------------------------------------------------------------------------------- Using OpenSSL for encryption and key generation This command has a lot of features, from random data generators, password hashing, encrypting data and files, hash checksums, through to encrypted SSL connections to remote systems. Help http://www.madboa.com/geek/openssl/#encrypt-simple Otherwise for a list of encryption types use... openssl list-cipher-commands ------------------------------------------------------------------------------- Encrypt a file # encrypt file.txt to file.enc using 256-bit AES in CBC mode openssl enc -aes-256-cbc -salt -in file.txt -out file.enc # the same, only the output is base64 encoded for say e-mail. # -a = base64 as appropriate for encryption direction openssl enc -aes-256-cbc -a -salt -in file.txt -out file.enc Decrypt a file # decrypt binary file.enc openssl enc -d -aes-256-cbc -salt -in file.enc # decrypt base64-encoded version openssl enc -d -aes-256-cbc -a -salt -in file.enc WARNING: This uses the fast PBKDF1.5 password to key function. It does not use the slower more modern PBKDF2 method (see below). As such it is prone to brute force dictionary attacks, even with salting. See "Password to Key" below. ------------------------------------------------------------------------------- Salt The 'salt' is a random 8 byte string that is stored with the encrypted file so that every time you encrypt a file with a specific password or key the resulting file will be different. Salt is turned on by default! To identify the use of a salt, openssl also adds the file magic "Salted__" to the start of the encrypted data stream. For example... echo "data" | openssl aes-256-cbc -pass pass:keyvar | dd bs=1 count=16 Salted__........ Where the '.' is the 8 byte salt charcaters, after that the encrypted data blocks Data length = 8 (magic) + 8 salted + 16 (one data block, padded) -- If no salt (-nosalt) is used then no file magic identifier, or salt is used. This is the (old method, PBKDF1 just pure AES encryption of data). As such a fixed password/file will always produce the same encrypted result (in this case one block, or 16 bytes) echo "data" | openssl aes-256-cbc -a -pass pass:keyvar -nosalt YQl6Zg03yi87w54gUPba5g== Thus to use the encryption as a 'hashing' function you should not use a salt WARNING: To decode a '-nosalt' encryption, you need -nosalt when decrypting The -salt is now the default mode. -- PBKDF2 - iterative password hashing This not only needs a salt, but count of the number of times the hashing function in applied. This cound should be large enough to make brute force passward hashing very difficult. Only one hashing sequence is used, with both the Key and IV beting extracted from the results. ------------------------------------------------------------------------------- Password to Encryption Key OpenSSL generates the actual encryption key (generally a Hash and a IV) from the user supplied password, plus some other 'public' data in a 'hashing function'. The other 'public' data is usally a 'salt' which is used to make a pre-prepared 'dictionary' attack usless. This comes from some encryption configuration data (along with the encryption method, data locations etc) which is typically part of, or close to, the encrypted data. For aes-128 Key = MD5(passwd + salt) IV = MD5(Key + Password + Salt) Note that this password hashing function is simple (and thus fast) It does not provide any protection in the form of a slow variable hash. For aes-256 the key size is 32 so a longer sequence is needed Hash0 = '' Hash1 = MD5(Hash0 + Password + Salt) Hash2 = MD5(Hash1 + Password + Salt) Hash3 = MD5(Hash2 + Password + Salt) Hash4 = MD5(Hash3 + Password + Salt) ... The hash is then split to generate the 'Key' and 'IV' needed to decrypt. Key = Hash1 + Hash2 IV = Hash3 See EVP_BytesToKey() function http://www.openssl.org/docs/crypto/EVP_BytesToKey.html A different hash could be used, with the sequence continuing until enough bits have been hashed to set both Key + IV in sequence. The better function to use however is PKCS5_PBKDF2_HMAC_SHA1() which implements the newer iteritive hash function. This interates a couple of thousand times (count given with salt) so the computer needs at least a couple of seconds to convert the given ( Password + Salt + Count ), into the ( Key + IV ). This makes brute force attacks very slow and time consuming, making such attacks impractical. While this function is in the openssl library, it is not in the openssl command. However a trivial program "pbkdf2.c" can make the function avilable to external scripting programs. ASIDE: PKCS5 Password based encryption #5 PBKDF2 is the iterative hashing method to derive Key and IV HMAC-SHA1 hashing function used for PBKDF ------------------------------------------------------------------------------- Passphrase handling in OpenSSL From command line... -pass pass:mySillyPassword From file -pass file:/path/to/secret/password.txt From File descriptor -pass fd:N From stdin -pass stdin Only the last two methods can be deemed to be 'secure' from other users on the machine it is run on. The thrid can be secure using named pipes, but only if the named pipe is secure. Watch out for newlines! ------------------------------------------------------------------------------- Error Interpretation from log... sshd[31784]: error: RSA_public_decrypt failed: error:0407006A:lib(4):func(112):reason(106) look up openssl errstr 0407006A error:0407006A:rsa routines:RSA_padding_check_PKCS1_type_1: block type is not 01 The RSA_padding_add_PKCS1_type_1(3) manpage then says... block methods for signatures ------------------------------------------------------------------------------- Random Data Generation # write 128 random bytes of base64-encoded data to stdout openssl rand -base64 128 # write 1024 bytes of binary random data to a file openssl rand -out random-data.bin 1024 # seed openssl with semi-random bytes from browser cache cd $(find ~/.mozilla/firefox -type d -name Cache | head -n 1) openssl rand -rand $(find . -type f -printf '%f:') -base64 1024 # get 32 bytes from /dev/urandom and base64 encode them head -c 32 /dev/urandom | openssl enc -base64 ------------------------------------------------------------------------------- Checksums and Hashing # This is exactly like "md5sum" but with different output openssl dgst -md5 filename MD5(filename)= 81eda7985e99d28acd6d286aa0e13e07 # This is exactly like "sha1sum" but with different output openssl dgst -sha1 filename SHA1(filename)= e4eabc78894e2c204d788521812497e021f45c08 You can also output the hash as -binary or -hex (default) Unfortunateally you can not output it in base64. But you can pipe it back into openssl to convert to base64 echo -n "$text" | openssl dgst -md5 -binary | openssl enc -base64 4cuww4ea+DRyRvEsVZqGtQ== (the echo is a bash builtin, so from a script "text" is not visible in the process list. You can convert that into a 22 character random filename... echo -n "text" | openssl dgst -sha1 -binary | dd bs=1 skip=2 count=18 2>/dev/null | openssl enc -base64 | tr '+/' ',-' oIyrM,ccAsZR28g6R00yxnbq This filename is similar to what use generated by EncFS but it is NOT the same scheme that EncFS uses, which includes a checksum. :-( NOTE: "openssl" command and "hashalot" does not implement iterative hashing as per the PBKDF2 (RFC 2898) algorithm (Password-Based Key Derivation Function v2) ------------------------------------------------------------------------------- Unix Password handling # Generate the old UNIX des encrypted password # Give previously encrypted password as -salt for testing openssl passwd # generate md5 encrypted password openssl passwd -1 ------------------------------------------------------------------------------- SSL conection to a remote server To talk to the wever via HTTPS using 'openssl'... =======8<-------- :::prompt:::> openssl s_client -connect www.cit.gu.edu.au:443 CONNECTED(00000003) ...lots of output about server and its certificate... --- HEAD / HTTP/1.0 <- You type this for the doc <- and a blank line HTTP/1.1 200 OK Date: Tue, 27 Oct 2009 05:23:53 GMT Server: Apache/2.0.52 (CentOS) Accept-Ranges: bytes Content-Length: 1532 Connection: close Content-Type: text/html; charset=iso-8859-1 closed =======8<-------- For SMTP (mail) # port 25/TLS; use same syntax for port 587 openssl s_client -connect remote.host:25 -starttls smtp # port 465/SSL openssl s_client -connect remote.host:465 Other servers # https: HTTP over SSL openssl s_client -connect remote.host:443 # ldaps: LDAP over SSL openssl s_client -connect remote.host:636 # imaps: IMAP over SSL openssl s_client -connect remote.host:993 # pop3s: POP-3 over SSL openssl s_client -connect remote.host:995 ------------------------------------------------------------------------------- Setup a HTTPS server This is not recommended, and a certificate should be provided. # the -www option will sent back an HTML-formatted status page # to any HTTP clients that request a page openssl s_server -cert mycert.pem -www # the -WWW option "emulates a simple web server. Pages will be # resolved relative to the current directory." This example # is listening on the https port, rather than the default # port 4433 openssl s_server -accept 443 -cert mycert.pem -WWW -------------------------------------------------------------------------------