How to Refactor Openssl Pkcs5_Keyivgen in Ruby

How do I refactor OpenSSL pkcs5_keyivgen in ruby?

Was trying to solve this problem, but I think there is no easy solution or i just can't see one). Pkcs5_keyivgen() is deprecated and implements non-standard pass key derivation for AES 256.

From this docs and this source code

Pkcs5_keyivgen (pass, SALT = nil, num = 2048, digest = "MD5") -> nil 

Generates some key and IV from salt and pass. No salt in your case. Generation method is defined in v1.5 PKCS #5 (deprecated)

So you are looking for "Password Based Key Derivation Function". PBKDF1

Pkcs5_keyivgen() function calls EVP_BytesToKey() from Openssl and EVP_BytesToKey() generates key bytes for larger key size in a non-standard way

So MD5 generates hash of size EVP_MAX_MD_SIZE (16 + 20) // 16 for MD5

But AES key(32) + IV(16) sizes > EVP_MAX_MD_SIZE, so AES 256 will need multiple hashes to generate random key and IV. Here is source code of algorithm in C

And here is nice pseudo-code explanation of the EVP_BytesToKey()

If you really want to re-implement PBKDF1 here is also RTC2898 standard for PBKDF1
But i don't think that it is a good idea to implement crypto yourself

How to resolve deprecation warnings for OpenSSL::Cipher::Cipher#encrypt

Due to the implicit type conversion in Ruby, older Ruby allows people use PBE (Password-Based Encryption) in a totally wrong way. The newer one fixes that so the warning is a good thing.

Your example shows exactly the problem. Triple-DES requires 24-byte key material (including parity) but you only provided 6 bytes. Your key material will be repeated to make up the deficit, that resulted in a less secure key.

The correct way to do this is to generate key and IV (initial vector) with PKCS5, which use complicated hashing and iteration to make the key much more secure.

Ruby provides following sample code. pass is your key and you can use any hardcoded value for salt.

puts "--Encrypting--"
des = OpenSSL::Cipher::Cipher.new(alg)
des.pkcs5_keyivgen(pass, salt)
des.encrypt
cipher = des.update(text)
cipher << des.final
puts %(encrypted text: #{cipher.inspect})
puts

puts "--Decrypting--"
des = OpenSSL::Cipher::Cipher.new(alg)
des.pkcs5_keyivgen(pass, salt)
des.decrypt
out = des.update(cipher)
out << des.final
puts %(decrypted text: "#{out}")
puts

Clarifying the EVP_BytesToKey() function in OpenSSL

It means what it says. PKCS5 version 1.5 assumes that the number of key bytes plus the number of IV bytes is less than or equal to the size of the hash function output. PKCS5 version version 2 fixes these issues but it came out after the EVP_BytesToKey function was defined, so EVP_BytesToKey generates key bytes for larger key size in a non-standard way.


OpenSSL 1.1.0c changed the digest algorithm used in some internal components. Formerly, MD5 was used, and 1.1.0 switched to SHA256. Be careful the change is not affecting you in both EVP_BytesToKey and commands like openssl enc.



Related Topics



Leave a reply



Submit