" " Allow direct editing of Encrypted files " " This is basically expanding the editing a GZip file example... " http://vimdoc.sourceforge.net/htmldoc/autocmd.html#gzip-example " OR " oreilly.com/library/view/linux-security-cookbook/0596003919/ch07s24.html " " However it does require the filter commands to read passwords directly " from the users terminal ("/dev/tty"). " "if (v:version < 702) " echohl ErrorMsg " "echo 'Vim Encrypt requires Vim version >= 7.2' " echohl None " finish "endif " WARNING: Vim's around 8.2 makes use of ANSI 'modifyOtherKeys' and may not " disable this mode when calling autocmd's. The 'echoraw()' commands below " can be used to disable/enable this mode before calling programs which may " request a password from the user. " For more information see https://github.com/vim/vim/issues/5617 " ------------------------------------------------------------------------- " Decrypt/Encrypt ".kpt" files using the "keepout" command. " This is a "openssl enc" file with a header containing the options used. " Can use "--key" and "--clear" to cache the decrypting password for later " use in re-encrypting the file. Preventing accidental password changes. " " Note "" is used as "%" changes betwene Read and Write if you are " in the same directory! That is in "/tmp" when using "ks -e" script. " augroup keepout autocmd! autocmd BufReadPre,FileReadPre *.kpt call s:EncPreRead() autocmd BufReadPost,FileReadPost *.kpt call s:EncPreDecrypt() autocmd BufReadPost,FileReadPost *.kpt '[,']!keepout -d --key 'vim-' autocmd BufReadPost,FileReadPost *.kpt call s:EncPostDecrypt() " autocmd BufWritePre,FileWritePre *.kpt call s:EncPreCrypt() autocmd BufWritePre,FileWritePre *.kpt '[,']!keepout --key 'vim-' autocmd BufWritePre,FileWritePre *.kpt call s:EncPostCrypt() autocmd BufWritePost,FileWritePost *.kpt call s:EncPostWrite() " autocmd BufDelete,VimLeave *.kpt set shell=/bin/sh autocmd BufDelete,VimLeave *.kpt !keepout --clear --key 'vim-' augroup END " Decrypt/Encrypt ".enc" files using the "encrypt" command. - OBSOLETE " " It is a PBKDF v2 (salt+count) aes-256-cbc encryption variant. " Updated to include "--keyname" to cache the decrypting password for later " use in re-encrypting the file. Preventing accidental password changes. " augroup enc autocmd! autocmd BufReadPre,FileReadPre *.enc call s:EncPreRead() autocmd BufReadPost,FileReadPost *.enc call s:EncPreDecrypt() autocmd BufReadPost,FileReadPost *.enc '[,']!encrypt -d --key 'vim-' autocmd BufReadPost,FileReadPost *.enc call s:EncPostDecrypt() " autocmd BufWritePre,FileWritePre *.enc call s:EncPreCrypt() autocmd BufWritePre,FileWritePre *.enc '[,']!encrypt --key 'vim-' autocmd BufWritePre,FileWritePre *.enc call s:EncPostCrypt() autocmd BufWritePost,FileWritePost *.enc call s:EncPostWrite() " autocmd BufDelete,VimLeave *.enc set shell=/bin/sh autocmd BufDelete,VimLeave *.enc !encrypt --clear --key 'vim-' augroup END " ----------------------------------------------------- " Other generic file encryption styles " Edit GPG encrypted files (.gpg) augroup gpg autocmd! autocmd BufReadPre,FileReadPre *.gpg call s:EncPreRead() autocmd BufReadPost,FileReadPost *.gpg call s:EncPreDecrypt() autocmd BufReadPost,FileReadPost *.gpg '[,']!gpg -o - autocmd BufReadPost,FileReadPost *.gpg call s:EncPostDecrypt() " autocmd BufWritePre,FileWritePre *.gpg call s:EncPreCrypt() autocmd BufWritePre,FileWritePre *.gpg '[,']!gpg -c --force-mdc -o - autocmd BufWritePre,FileWritePre *.gpg call s:EncPostCrypt() autocmd BufWritePost,FileWritePost *.gpg call s:EncPostWrite() augroup END " Edit Gzipped GPG encrypted files (.gpz) augroup gpz autocmd! autocmd BufReadPre,FileReadPre *.gpz call s:EncPreRead() autocmd BufReadPost,FileReadPost *.gpz call s:EncPreDecrypt() autocmd BufReadPost,FileReadPost *.gpz '[,']!gpg -o - | gzip -d autocmd BufReadPost,FileReadPost *.gpz call s:EncPostDecrypt() " autocmd BufWritePre,FileWritePre *.gpz call s:EncPreCrypt() autocmd BufWritePre,FileWritePre *.gpz '[,']!gzip | gpg -c --force-mdc -o - autocmd BufWritePre,FileWritePre *.gpz call s:EncPostCrypt() autocmd BufWritePost,FileWritePost *.gpz call s:EncPostWrite() augroup END " Edit PGP (v5) encrypted files (.pgp) augroup pgp autocmd! autocmd BufReadPre,FileReadPre *.pgp call s:EncPreRead() autocmd BufReadPost,FileReadPost *.pgp call s:EncPreDecrypt() autocmd BufReadPost,FileReadPost *.pgp '[,']!pgpv -f autocmd BufReadPost,FileReadPost *.pgp call s:EncPostDecrypt() " autocmd BufWritePre,FileWritePre *.pgp call s:EncPreCrypt() autocmd BufWritePre,FileWritePre *.pgp '[,']!pgpe -fc autocmd BufWritePre,FileWritePre *.pgp call s:EncPostCrypt() autocmd BufWritePost,FileWritePost *.pgp call s:EncPostWrite() augroup END " Edit Gziped PGP encrypted files (.pgz) augroup pgz autocmd! autocmd BufReadPre,FileReadPre *.pgz call s:EncPreRead() autocmd BufReadPost,FileReadPost *.pgz call s:EncPreDecrypt() autocmd BufReadPost,FileReadPost *.pgz '[,']!pgpv -f | gzip -d autocmd BufReadPost,FileReadPost *.pgz call s:EncPostDecrypt() " autocmd BufWritePre,FileWritePre *.pgz call s:EncPreCrypt() autocmd BufWritePre,FileWritePre *.pgz '[,']!gzip | pgpe -fc autocmd BufWritePre,FileWritePre *.pgz call s:EncPostCrypt() autocmd BufWritePost,FileWritePost *.pgz call s:EncPostWrite() augroup END " OpenSSL AES encryption (before version 1.1.0, with magic 'Salted__') " PBKDF v1.5 (salted) aes-256-cbc encrypted file " " OpenSSL after v1.1.1, has far to many option to have a 'standard'. " The "keepout" script (see above) provides a wrapped for "openssl" encryption, " that will save all the options used when encrypting a file. " augroup aes autocmd! autocmd BufReadPre,FileReadPre *.aes call s:EncPreRead() autocmd BufReadPost,FileReadPost *.aes call s:EncPreDecrypt() autocmd BufReadPost,FileReadPost *.aes '[,']!openssl aes-256-cbc -md md5 -d autocmd BufReadPost,FileReadPost *.aes call s:EncPostDecrypt() " autocmd BufWritePre,FileWritePre *.aes call s:EncPreCrypt() autocmd BufWritePre,FileWritePre *.aes '[,']!openssl aes-256-cbc -md md5 autocmd BufWritePre,FileWritePre *.aes call s:EncPostCrypt() autocmd BufWritePost,FileWritePost *.aes call s:EncPostWrite() augroup END " VERY Old OpenSSL Encryption (no file magic identifier) " PBKDF v1 (unsalted) or direct aes-256-cbc encrypted file " the option -md md5 should also be used, as this changedin v1.1.0 " This encryption is deterministic, generating the same output. " augroup ossl autocmd! autocmd BufReadPre,FileReadPre *.ossl call s:EncPreRead() autocmd BufReadPost,FileReadPost *.ossl call s:EncPreDecrypt() autocmd BufReadPost,FileReadPost *.ossl '[,']!openssl aes-256-cbc -nosalt -md md5 -d autocmd BufReadPost,FileReadPost *.ossl call s:EncPostDecrypt() " autocmd BufWritePre,FileWritePre *.ossl call s:EncPreCrypt() autocmd BufWritePre,FileWritePre *.ossl '[,']!openssl aes-256-cbc -nosalt -md5 autocmd BufWritePre,FileWritePre *.ossl call s:EncPostCrypt() autocmd BufWritePost,FileWritePost *.ossl call s:EncPostWrite() augroup END " ------------------------------------------------------------------------- " Functions called by the above, common to all binary encryption methods let s:EncDebugLevel = 0 let s:EncDebugFile = "enc.log" function s:EncDebug(level, text) if exists("s:EncDebugLevel") && s:EncDebugLevel >= a:level if exists("s:EncDebugFile") execute "redir >> " . s:EncDebugFile silent echo "Enc: " . a:text redir END else echo "Enc: " . a:text endif endif endfunction function s:SetShell() call s:EncDebug(2,">>>>>> Function SetShell()") " setup shell environment for unix and windows "let s:shellredirsave = &shellredir "let s:shellsave = &shell "let s:shelltempsave = &shelltemp let s:shell = '/bin/sh' let s:shellredir = ">" "let s:shellredir = ">%s 2>&1" let s:stderrredirnull = '2>/dev/null' " windows specic settings "let s:shell = &shell "let s:shellredir = '>' "let s:shellredir = '>%s' "let s:stderrredirnull = '2>nul' " check relevent vim settings "call s:EncDebug(3, "shellredirsave: " . s:shellredirsave) "call s:EncDebug(3, "shellsave: " . s:shellsave) "call s:EncDebug(3, "shelltempsave: " . s:shelltempsave) "call s:EncDebug(3, "shell: " . s:shell) "call s:EncDebug(3, "shellcmdflag: " . &shellcmdflag) "call s:EncDebug(3, "shellxquote: " . &shellxquote) "call s:EncDebug(3, "shellredir: " . s:shellredir) "call s:EncDebug(3, "stderrredirnull: " . s:stderrredirnull) "call s:EncDebug(3, "shell implementation: " . resolve(s:shell)) call s:EncDebug(2,"<<<<<< Leaving SetShell()") endfunction " --------------------------------------------- " --- File read requested --- " Prepare to read protected binary file " Do not save or cache anything! function s:EncPreRead() call s:EncDebug(2,">>>>>> Function EncPreRead()") " we don't want a swap file setl noswapfile " make no backup files setl nowritebackup " disable use of undo files setl noundofile " don't save anything in ~/.viminfo set viminfo= " no history set history=0 " don't swap alt screen on small amount of output set cmdheight=2 " now switch to binary mode, to read in binary data setl binary setl nofixeol set encoding=utf-8 set fileencoding=utf-8 call s:EncDebug(2,"<<<<<< Leaving EncPreRead()") endfunction " --- Binary/Encrypted file read in --- " prepare to convert to editable form function s:EncPreDecrypt() call s:EncDebug(2,">>>>>> Function EncPreDecrypt()") call s:SetShell() " disable modifyOtherKeys "call echoraw(&t_TE) call s:EncDebug(2,"<<<<<< Leaving EncPreDecrypt()") endfunction " --- Command to Convert/Decrypt to Plain Text --- " final preparations for file editing by user function s:EncPostDecrypt() call s:EncDebug(2,">>>>>> Function EncPostDecrypt()") "if (v:shell_error) " message could not be decrypted " echohl ErrorMsg " let blackhole = input("Message failed to decrypt! (Press ENTER)") " echohl None " " Only wipeout the buffer if we were creating one to start with. " " FileReadCmd just reads the content into the existing buffer " "if a:bufread " " silent bwipeout! " "endif " call s:EncDebug(2,"<<<<<< Leaving EncPostDecrypt()") " return "endif " text should now be editable set cmdheight& setl nobinary setl fixeol " enable modifyOtherKeys "call echoraw(&t_TI) "exe "doau BufReadPost ".expand("%:r") " refresh screen redraw! " In order to make :undo a no-op immediately after the buffer is read, " we need to do this dance with 'undolevels', ensuring there is a " undo change that we can then reset. Weird! let levels = &undolevels set undolevels=-1 silent 1s/^/X/|1s/^X// let &undolevels = levels " Mark the file as 'encrypted' for my personal "statusline" info bar " does not effect anything if you don't have that module let b:encflag=1 " call any autocmd for the file without the suffix "silent execute ':doautocmd BufReadPost ' . fnameescape(expand(':r')) call s:EncDebug(2,"<<<<<< Leaving EncPostDecrypt()") endfunction " --- User Edits File --- " then requests file write " Prepare file to be converted for write function s:EncPreCrypt() call s:EncDebug(2,">>>>>> Function EncPreCrypt()") " ensure binary mode is enabled, in preparation to encrypt buffer mark z setl binary setl nofixeol set cmdheight=2 call s:SetShell() " disable modifyOtherKeys "call echoraw(&t_TE) call s:EncDebug(2,"<<<<<< Leaving EncPreCrypt()") endfunction " --- Command to Convert/Encrypt File --- " Prepare to write binary file function s:EncPostCrypt() call s:EncDebug(2,">>>>>> Function EncPostCrypt()") " Ensure coding is appropriate for binary file save set cmdheight& set encoding=utf-8 set fileencoding=utf-8 " enable modifyOtherKeys "call echoraw(&t_TI) call s:EncDebug(2,"<<<<<< Leaving EncPostCrypt()") endfunction " --- The file is written --- " Return file to plain text for editing function s:EncPostWrite() call s:EncDebug(2,">>>>>> Function EncPostWrite()") " restore the file as it was before encrypted save! " and return cursor to the line user was on before save silent undo setl nobinary setl fixeol 'z call s:EncDebug(2,"<<<<<< Leaving EncPostWrite()") endfunction