# HG changeset patch # User Bram Moolenaar # Date 1274448968 -7200 # Node ID c493d6bfde09997446ee92dc72a7e54abf3f24cc # Parent dde812fb22478c1fbd34d935ec466b2cd9869da4 A few more changes for encryption. Add test that encrypted file can be read. diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -2056,12 +2056,21 @@ A jump table for the options with a shor Method used for encryption when the buffer is written to a file: *pkzip* 0 PkZip compatible method. A weak kind of encryption. - backwards compatible with Vim 7.2 and older. + Backwards compatible with Vim 7.2 and older. *blowfish* - 1 Blowfish method. Strong encryption. Not compatible - with Vim 7.2 and older. + 1 Blowfish method. Strong encryption. Requires Vim 7.3 + or later, files can NOT be read by Vim 7.2 and older. + This adds a "seed" to the file, every time you write + the file the encrypted bytes will be different. + When reading an encrypted file 'cryptmethod' will be set automatically - to detected method for the file being read. + to the detected method of the file being read. Thus if you write it + without changing 'cryptmethod' the same method will be used. + Changing 'cryptmethod' does not mark the file as modified, you have to + explicitly write it when not making modifications. + Also see |:X|. + When a new encryption method is added in a later version of Vim, and + the current version does not recognize it, you will get *E821* . *'cscopepathcomp'* *'cspc'* diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt --- a/runtime/doc/todo.txt +++ b/runtime/doc/todo.txt @@ -30,16 +30,6 @@ be worked on, but only if you sponsor Vi *known-bugs* -------------------- Known bugs and current work ----------------------- -Crypt update: -- Make sure test71 fails when blowfish test fails. -- When not full match with magic, check for head and give warning about - unsupported crypt method. -- if 'enc' is ucs-2, does utf-8 to ucs-2 encoding always work for seed? - -After patch 7.2.407 a backslash before a newline is turned into a NUL. (Andy -Wokula, 2010 May 18) -No longer possible to insert a line break? Roll back the patch? - "g8" doesn't produce right value on NUL. Patch (Dominique Pelle, 2010 May 18) Include cabal and obj syntax files. (Vincent Berthoux, 2010 May 16) diff --git a/src/fileio.c b/src/fileio.c --- a/src/fileio.c +++ b/src/fileio.c @@ -33,13 +33,11 @@ #define SMBUFSIZE 256 /* size of emergency write buffer */ #ifdef FEAT_CRYPT -char crypt_magic_01[] = "VimCrypt~01!"; -char crypt_magic_02[] = "VimCrypt~02!"; +/* crypt_magic[0] is pkzip crypt, crypt_magic[1] is sha2+blowfish */ +static char *crypt_magic[] = {"VimCrypt~01!", "VimCrypt~02!"}; +static char crypt_magic_head[] = "VimCrypt~"; # define CRYPT_MAGIC_LEN 12 /* must be multiple of 4! */ - -/* crypt_magic[0] is pkzip crypt, crypt_magic[1] is sha2+blowfish */ -static char *crypt_magic[] = {crypt_magic_01, crypt_magic_02}; -static int crypt_seed_len[] = {0, 8}; +static int crypt_seed_len[] = {0, 8}; #define CRYPT_SEED_LEN_MAX 8 #endif @@ -61,7 +59,7 @@ static void check_marks_read __ARGS((voi #endif #ifdef FEAT_CRYPT static int get_crypt_method __ARGS((char *ptr, int len)); -static char_u *check_for_cryptkey __ARGS((char_u *cryptkey, char_u *ptr, long *sizep, long *filesizep, int newfile)); +static char_u *check_for_cryptkey __ARGS((char_u *cryptkey, char_u *ptr, long *sizep, long *filesizep, int newfile, int *did_ask)); #endif #ifdef UNIX static void set_file_time __ARGS((char_u *fname, time_t atime, time_t mtime)); @@ -253,6 +251,7 @@ readfile(fname, sfname, from, lines_to_s int skip_read = FALSE; #ifdef FEAT_CRYPT char_u *cryptkey = NULL; + int did_ask_for_key = FALSE; #endif int split = 0; /* number of split lines */ #define UNKNOWN 0x0fffffff /* file size is unknown */ @@ -1412,7 +1411,7 @@ retry: */ if (filesize == 0) cryptkey = check_for_cryptkey(cryptkey, ptr, &size, - &filesize, newfile); + &filesize, newfile, &did_ask_for_key); /* * Decrypt the read bytes. */ @@ -2811,6 +2810,11 @@ get_crypt_method(ptr, len) if (memcmp(ptr, crypt_magic[i], CRYPT_MAGIC_LEN) == 0) return i; } + + i = STRLEN(crypt_magic_head); + if (len >= i && memcmp(ptr, crypt_magic_head, i) == 0) + EMSG(_("E821: File is encrypted with unknown method")); + return -1; } @@ -2821,12 +2825,13 @@ get_crypt_method(ptr, len) * Return the (new) encryption key, NULL for no encryption. */ static char_u * -check_for_cryptkey(cryptkey, ptr, sizep, filesizep, newfile) +check_for_cryptkey(cryptkey, ptr, sizep, filesizep, newfile, did_ask) char_u *cryptkey; /* previous encryption key or NULL */ char_u *ptr; /* pointer to read bytes */ long *sizep; /* length of read bytes */ long *filesizep; /* nr of bytes used from file */ int newfile; /* editing a new buffer */ + int *did_ask; /* flag: whether already asked for key */ { int method = get_crypt_method((char *)ptr, *sizep); @@ -2836,7 +2841,7 @@ check_for_cryptkey(cryptkey, ptr, sizep, use_crypt_method = method; if (method > 0) (void)blowfish_self_test(); - if (cryptkey == NULL) + if (cryptkey == NULL && !*did_ask) { if (*curbuf->b_p_key) cryptkey = curbuf->b_p_key; @@ -2844,8 +2849,11 @@ check_for_cryptkey(cryptkey, ptr, sizep, { /* When newfile is TRUE, store the typed key in the 'key' * option and don't free it. bf needs hash of the key saved. - */ + * Don't ask for the key again when first time Enter was hit. + * Happens when retrying to detect encoding. */ cryptkey = get_crypt_key(newfile, FALSE); + *did_ask = TRUE; + /* check if empty key entered */ if (cryptkey != NULL && *cryptkey == NUL) { diff --git a/src/testdir/test71.in b/src/testdir/test71.in --- a/src/testdir/test71.in +++ b/src/testdir/test71.in @@ -2,10 +2,14 @@ Test for encryption. STARTTEST :so small.vim -:/^start of testfile/+1 -:let lines = getline('.', '$') -:new -:call append(0, lines) +:/^start of text/+1 +:let text_lines = getline('.', line('.') + 2) +:/^start of cm=0 bytes/+1 +:let cm0_bytes = getline('.', '.') +:/^start of cm=1 bytes/+1 +:let cm1_bytes = getline('.', '.') +:bwipe +:call append(0, text_lines) :$d :X foobar @@ -14,10 +18,11 @@ foobar :bwipe! :e Xtestfile foobar -:let dec1_lines = getline('.', '$') -:%s/^/2/ +:let cm0_read_back = getline('.', '$') :set key= :set cryptmethod=1 +:" If the blowfish test fails 'cryptmethod' will be 0 now. +:%s/^/\=&cryptmethod == 1 ? "OK " : "blowfish test failed "/ :X barfoo barfoo @@ -25,13 +30,46 @@ barfoo :bwipe! :e Xtestfile barfoo -:call append(0, dec1_lines) -:set key= +:let cm1_read_back = getline('.', '$') +:bwipe! +:set bin noeol key= +:call append(0, cm0_bytes) +:$d +:set fenc=latin1 +:w! Xtestfile +:bwipe! +:set nobin +:e Xtestfile +foofoo +:let cm0_read_bin = getline('.', '$') +:bwipe! +:set bin noeol key= +:call append(0, cm1_bytes) +:$d +:set fenc=latin1 +:w! Xtestfile +:bwipe! +:set nobin +:e Xtestfile +barbar +:call append(0, cm0_read_bin) +:call append(0, cm1_read_back) +:call append(0, cm0_read_back) +:set key= fenc=latin1 :w! test.out :qa! ENDTEST -start of testfile +start of text 01234567890123456789012345678901234567 line 2 foo bar blah line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +end of text + +start of cm=0 bytes +VimCrypt~01!lV'Þ}Mg ê£V©çE#3Ž2Ué— +end of cm=0 bytes + +start of cm=1 bytes +VimCrypt~02!¨Ò9ZšÙ¢èì”F¼èÃ[,ì”F¼ƒ€z¼Ö軂 y¾Ô( +end of cm=1 bytes diff --git a/src/testdir/test71.ok b/src/testdir/test71.ok --- a/src/testdir/test71.ok +++ b/src/testdir/test71.ok @@ -1,6 +1,10 @@ 01234567890123456789012345678901234567 line 2 foo bar blah line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -201234567890123456789012345678901234567 -2line 2 foo bar blah -2line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +OK 01234567890123456789012345678901234567 +OK line 2 foo bar blah +OK line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +1234567890 +aábbccddeëff +asdfasdfasdf +0001112223333