Hi!I maintain a Ruby script that does PKCS#7 signing and afterwards some enryption with AES-128-CFB. A trimmed down version:
certpath = '/tmp/cert.pem' keypath = '/tmp/key/pem' data = 'teststring' key = OpenSSL::PKey::RSA.new(File.read(keypath), '1234') cert = OpenSSL::X509::Certificate.new(File.read(certpath)) signed = OpenSSL::PKCS7::sign(cert, key, data, [], OpenSSL::PKCS7::BINARY) cipher = OpenSSL::Cipher::new("AES-128-CFB") iv_len = cipher.iv_len key_len = cipher.key_len fqdn_rand = Digest::SHA256.hexdigest([destination,data.length].join(':')) iv_seed, key_seed = fqdn_rand.partition(/.{32}/)[1,2] iv = iv_seed.unpack('a2'*key_len).map{|x| x.hex}.pack('c'*key_len) key = key_seed.unpack('a2'*key_len).map{|x| x.hex}.pack('c'*key_len) cipher.encrypt cipher.iv=(iv) cipher.key=(key)OpenSSL::PKCS7::encrypt([target], signed.to_der, cipher, OpenSSL::PKCS7::BINARY).to_s
I pulled the AES encryption into a testscript and that's indeed repeatable (script at the end of the email). I did some tests and noticed that the initial signing doesn't produce repeatable output:
signed = OpenSSL::PKCS7::sign(cert, key, data, [], OpenSSL::PKCS7::BINARY)I did some googling and that told me the signing date/timestamp is part of the output, which would explain why it doesn't produce the same output when I run it twice. Now to my actual questions: * Is the different output caused by a changing signing time and/or something else?
* Do you know if I can pass the signingtime to manipulate it?I know that this isn't a Ruby mailinglist, but the ruby-openssl bindings and the documentation are generated from the C code and were not very helpful (for people not knowing C/not knowing a lot about OpenSSL/PKCS#7). Maybe you've some thoughts.
Why am I doing this?Roughly explained, the script is executed every 30 minutes for a lot of content, then the previous PKCS#7 output is pulled from a database, compared, and if the new script output is different, the DB is updated. This is stupid in many ways, but I cannot change that short-term. As a workarond, we would like to update the script to produce repeatable output. I know that this weakens the security, but we need to reduce the database load from the many reoccurring updates.
my AES testing: root@puppet ~ # ruby openssl.rb encrypted: ["38b5cefb"] decrypted: test encrypted: ["38b5cefb"] decrypted: test root@puppet ~ # cat openssl.rb #!/usr/bin/env ruby require 'openssl' def encrypt(content) cipher = OpenSSL::Cipher::new("AES-128-CFB") cipher.encryptiv ="00000000000000000000000000000001".unpack('a2'*16).map{|x| x.hex}.pack('c'*16)
cipher.iv=(iv)key = "7ffb8032dff33aef9aa92e9ac96239d3".unpack('a2'*16).map{|x| x.hex}.pack('c'*16)
cipher.key=(key) output = cipher.update(content) output << cipher.final puts "encrypted: #{output.unpack('H*')}\n" puts "decrypted: #{decrypt(output, iv, key)}\n" end def decrypt(content, iv, key) cipher = OpenSSL::Cipher::new("AES-128-CFB") cipher.decrypt cipher.iv=(iv) cipher.key=(key) output = cipher.update(content) output << cipher.final output end encrypt 'test' encrypt 'test' root@puppet ~ # The complete original code: https://github.com/binford2k/binford2k-node_encrypt/blob/main/lib/puppet_x/binford2k/node_encrypt.rb#L11-L55My WIP patch: https://github.com/binford2k/binford2k-node_encrypt/compare/main...bastelfreak:binford2k-node_encrypt:49675?expand=1
Cheers, Tim
Attachment:
OpenPGP_signature
Description: OpenPGP digital signature