Add a salt to the key derivation using the 'enc' program.
authorDr. Stephen Henson <steve@openssl.org>
Tue, 16 Nov 1999 02:49:25 +0000 (02:49 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Tue, 16 Nov 1999 02:49:25 +0000 (02:49 +0000)
CHANGES
apps/enc.c
doc/man/enc.pod

diff --git a/CHANGES b/CHANGES
index 574c3190add6340f7b362d919857d6bd236d986b..81942a0e7ae19fa3bf2b695ba59768fe24d048b8 100644 (file)
--- 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
index bce936a2fc6265aca37220c3f0d3b40841e807de..d033e380c4febf2e8acf3123ed2264d118500227 100644 (file)
@@ -65,6 +65,7 @@
 #include <openssl/evp.h>
 #include <openssl/objects.h>
 #include <openssl/x509.h>
+#include <openssl/rand.h>
 #ifndef NO_MD5
 #include <openssl/md5.h>
 #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; i<PKCS5_SALT_LEN; i++)
+                                       printf("%02X",salt[i]);
+                               printf("\n");
+                               }
                        if (cipher->key_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);
index 40b1c3ac1a67e37b11ecd96665bf56b825efc00a..d6875bcc5c70d6fbc245c929a315c596dd4ab341 100644 (file)
@@ -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<ALWAYS>
+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<filename>
 
+=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<openssl enc -ciphername>.
 
 A password will be prompted for to derive the key and IV if necessary.
 
+The B<-salt> option should B<ALWAYS> 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<enc> program only supports a fixed number of
 algorithms with certain parameters. So if, for example, you want to use RC2