PKCS#7 Signing: How to get repeatable output for signing the same data
Tim Meusel
openssl at bastelfreak.de
Mon Oct 17 08:28:45 UTC 2022
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 at puppet ~ # ruby openssl.rb
encrypted: ["38b5cefb"]
decrypted: test
encrypted: ["38b5cefb"]
decrypted: test
root at puppet ~ # cat openssl.rb
#!/usr/bin/env ruby
require 'openssl'
def encrypt(content)
cipher = OpenSSL::Cipher::new("AES-128-CFB")
cipher.encrypt
iv ="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 at puppet ~ #
The complete original code:
https://github.com/binford2k/binford2k-node_encrypt/blob/main/lib/puppet_x/binford2k/node_encrypt.rb#L11-L55
My WIP patch:
https://github.com/binford2k/binford2k-node_encrypt/compare/main...bastelfreak:binford2k-node_encrypt:49675?expand=1
Cheers, Tim
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature
Type: application/pgp-signature
Size: 495 bytes
Desc: OpenPGP digital signature
URL: <https://mta.openssl.org/pipermail/openssl-users/attachments/20221017/0c1827b5/attachment.sig>
More information about the openssl-users
mailing list