From fd699ac55f736e5b39b5fe3c244115e6b776eafa Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Tue, 16 Nov 1999 02:49:25 +0000 Subject: [PATCH] Add a salt to the key derivation using the 'enc' program. --- CHANGES | 5 ++ apps/enc.c | 121 +++++++++++++++++++++++++++++++++--------------- doc/man/enc.pod | 40 ++++++++++++---- 3 files changed, 121 insertions(+), 45 deletions(-) diff --git a/CHANGES b/CHANGES index 574c3190ad..81942a0e7a 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,11 @@ Changes between 0.9.4 and 0.9.5 [xx XXX 1999] + *) Add a salt to the key derivation routines in enc.c. This + forms the first 8 bytes of the encrypted file. Also add a + -S option to allow a salt to be input on the command line. + [Steve Henson] + *) New function X509_cmp(). Oddly enough there wasn't a function to compare two certificates. We do this by working out the SHA1 hash and comparing that. X509_cmp() will be needed by the trust diff --git a/apps/enc.c b/apps/enc.c index bce936a2fc..d033e380c4 100644 --- a/apps/enc.c +++ b/apps/enc.c @@ -65,6 +65,7 @@ #include #include #include +#include #ifndef NO_MD5 #include #endif @@ -86,10 +87,11 @@ int MAIN(int argc, char **argv) int bsize=BSIZE,verbose=0; int ret=1,inl; unsigned char key[24],iv[MD5_DIGEST_LENGTH]; + unsigned char salt[PKCS5_SALT_LEN]; char *str=NULL; - char *hkey=NULL,*hiv=NULL; + char *hkey=NULL,*hiv=NULL,*hsalt = NULL; int enc=1,printkey=0,i,base64=0; - int debug=0,olb64=0; + int debug=0,olb64=0,nosalt=1; const EVP_CIPHER *cipher=NULL,*c; char *inf=NULL,*outf=NULL; BIO *in=NULL,*out=NULL,*b64=NULL,*benc=NULL,*rbio=NULL,*wbio=NULL; @@ -136,8 +138,11 @@ int MAIN(int argc, char **argv) printkey=1; else if (strcmp(*argv,"-v") == 0) verbose=1; - else if ((strcmp(*argv,"-debug") == 0) || - (strcmp(*argv,"-d") == 0)) + else if (strcmp(*argv,"-salt") == 0) + nosalt=0; + else if (strcmp(*argv,"-nosalt") == 0) + nosalt=1; + else if (strcmp(*argv,"-debug") == 0) debug=1; else if (strcmp(*argv,"-P") == 0) printkey=2; @@ -194,6 +199,11 @@ int MAIN(int argc, char **argv) if (--argc < 1) goto bad; hkey= *(++argv); } + else if (strcmp(*argv,"-S") == 0) + { + if (--argc < 1) goto bad; + hsalt= *(++argv); + } else if (strcmp(*argv,"-iv") == 0) { if (--argc < 1) goto bad; @@ -386,11 +396,73 @@ bad: } } + + if (outf == NULL) + BIO_set_fp(out,stdout,BIO_NOCLOSE); + else + { + if (BIO_write_filename(out,outf) <= 0) + { + perror(outf); + goto end; + } + } + + rbio=in; + wbio=out; + + if (base64) + { + if ((b64=BIO_new(BIO_f_base64())) == NULL) + goto end; + if (debug) + { + BIO_set_callback(b64,BIO_debug_callback); + BIO_set_callback_arg(b64,bio_err); + } + if (olb64) + BIO_set_flags(b64,BIO_FLAGS_BASE64_NO_NL); + if (enc) + wbio=BIO_push(b64,wbio); + else + rbio=BIO_push(b64,rbio); + } + if (cipher != NULL) { if (str != NULL) { - EVP_BytesToKey(cipher,EVP_md5(),NULL, + /* Salt handling: if encrypting generate a salt and + * write to output BIO. If decrypting read salt from + * input BIO. + */ + unsigned char *sptr; + if(nosalt) sptr = NULL; + else { + if(enc) { + if(hsalt) { + if(!set_hex(hsalt,salt,PKCS5_SALT_LEN)) { + BIO_printf(bio_err, + "invalid hex salt value\n"); + goto end; + } + } else RAND_bytes(salt, PKCS5_SALT_LEN); + /* If -P option then don't bother writing */ + if((printkey != 2) && (BIO_write(wbio, + (unsigned char *) salt, + PKCS5_SALT_LEN) != PKCS5_SALT_LEN)) { + BIO_printf(bio_err,"error writing output file\n"); + goto end; + } + } else if(BIO_read(rbio, (unsigned char *)salt, + PKCS5_SALT_LEN) != PKCS5_SALT_LEN) { + BIO_printf(bio_err,"error reading input file\n"); + goto end; + } + sptr = salt; + } + + EVP_BytesToKey(cipher,EVP_md5(),sptr, (unsigned char *)str, strlen(str),1,key,iv); /* zero the complete buffer or the string @@ -424,6 +496,13 @@ bad: if (printkey) { + if (!nosalt) + { + printf("salt="); + for (i=0; ikey_len > 0) { printf("key="); @@ -446,38 +525,6 @@ bad: } } - - if (outf == NULL) - BIO_set_fp(out,stdout,BIO_NOCLOSE); - else - { - if (BIO_write_filename(out,outf) <= 0) - { - perror(outf); - goto end; - } - } - - rbio=in; - wbio=out; - - if (base64) - { - if ((b64=BIO_new(BIO_f_base64())) == NULL) - goto end; - if (debug) - { - BIO_set_callback(b64,BIO_debug_callback); - BIO_set_callback_arg(b64,bio_err); - } - if (olb64) - BIO_set_flags(b64,BIO_FLAGS_BASE64_NO_NL); - if (enc) - wbio=BIO_push(b64,wbio); - else - rbio=BIO_push(b64,rbio); - } - /* Only encrypt/decrypt as we write the file */ if (benc != NULL) wbio=BIO_push(benc,wbio); diff --git a/doc/man/enc.pod b/doc/man/enc.pod index 40b1c3ac1a..d6875bcc5c 100644 --- a/doc/man/enc.pod +++ b/doc/man/enc.pod @@ -40,6 +40,18 @@ the input filename, standard input by default. the output filename, standard output by default. +=item B<-salt> + +use a salt in the key derivation routines. This option should B +be used unless compatability with previous versions of OpenSSL or SSLeay +is required. This option is only present on OpenSSL versions 0.9.5 or +above. + +=item B<-nosalt> + +don't use a salt in the key derivation routines. This is the default for +compatability with previous versions of OpenSSL and SSLeay. + =item B<-e> encrypt the input data: this is the default. @@ -66,6 +78,11 @@ the password to derive the key from. read the password to derive the key from the first line of B +=item B<-S salt> + +the actual salt to use: this must be represented as a string comprised only +of hex digits. + =item B<-K key> the actual key to use: this must be represented as a string comprised only @@ -102,6 +119,16 @@ B. A password will be prompted for to derive the key and IV if necessary. +The B<-salt> option should B be used unless you want compatability +with previous versions of OpenSSL and SSLeay. + +Without the B<-salt> option it is possible to perform efficient dictionary +attacks on the password and to attack stream cipher encrypted data. The reason +for this is that without the salt the same password always generates the same +encryption key. When the salt is being used the first eight bytes of the +encrypted data are reserved for the salt: it is generated at random when +encrypting a file and read from the encrypted file when it is decrypted. + Some of the ciphers do not have large keys and others have security implications if not used correctly. A beginner is advised to just use a strong block cipher in CBC mode such as bf or des3. @@ -187,20 +214,20 @@ Decode the same file Encrypt a file using triple DES in CBC mode using a prompted password: - openssl des3 -in file.txt -out file.des3 + openssl des3 -salt -in file.txt -out file.des3 Decrypt a file using a supplied password: - openssl des3 -d -in file.des3 -out file.txt -k mypassword + openssl des3 -d -salt -in file.des3 -out file.txt -k mypassword Encrypt a file then base64 encode it (so it can be sent via mail for example) using Blowfish in CBC mode: - openssl bf -a -in file.txt -out file.bf + openssl bf -a -salt -in file.txt -out file.bf Base64 decode a file then decrypt it: - openssl bf -d -a -in file.bf -out file.txt + openssl bf -d -salt -a -in file.bf -out file.txt Decrypt some data using a supplied 40 bit RC4 key: @@ -210,10 +237,7 @@ Decrypt some data using a supplied 40 bit RC4 key: The B<-A> option when used with large files doesn't work properly. -The key derivation algorithm used is compatible with the SSLeay algorithm. It -is not very good: it uses unsalted MD5. - -There should be an option to allow a salt or iteration count to be included. +There should be an option to allow an iteration count to be included. Like the EVP library the B program only supports a fixed number of algorithms with certain parameters. So if, for example, you want to use RC2 -- GitLab