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
Using Passphrase Callback in Ruby Gpgme
Insert Rows on Specific Line in a File
How to Mock Super in Ruby Using Rspec
Given a Url, How to Get Just the Domain
Web Page Scraping Gems/Tools Available in Ruby
"Dyld: Library Not Loaded", "Libruby.1.9.1.Dylib" When Calling "Mvim ." in the Command Line
What Regex How to Use to Get the Domain Name from a Url in Ruby
Floating Point Precision in Ruby on Rails Model Validations
Generating Excel Documents with Ruby
How to Convert PDF to Excel or CSV in Rails 4
Building a Simple Search Form in Rails
Differencebetween Unicorn and Unicorn_Rails
How to Get Error Messages from Ruby Threads
How to Define a Method in Ruby Using Splat and an Optional Hash at the Same Time
What Are the Meanings of the Hash Keys When Calling Objectspace.Count_Objects