#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
+#include <openssl/rand.h>
#ifndef NO_MD5
#include <openssl/md5.h>
#endif
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;
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;
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;
}
}
+
+ 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
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=");
}
}
-
- 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);
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.
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
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.
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:
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