diff --git a/lib/minisign/private_key.rb b/lib/minisign/private_key.rb index 7c57003..a6d0472 100644 --- a/lib/minisign/private_key.rb +++ b/lib/minisign/private_key.rb @@ -8,6 +8,13 @@ class PrivateKey :key_id, :public_key, :secret_key, :checksum # rubocop:disable Metrics/AbcSize + # rubocop:disable Layout/LineLength + + # Parse signing information from the minisign private key + # + # @param str [String] The minisign private key + # @example + # Minisign::PrivateKey.new('RWRTY0IyEf+yYa5eAX38PgdrI3TMxwy+3sgzpgcZWQXhOKqdf9sAAAACAAAAAAAAAEAAAAAAHe8Olzttgk6k5pZyT3CyCTcTAV0bLN3kq5CUqhLjqSdYZ6oEWs/S7ztaephS+/jwnuOElLBKkg3Sd56jzyvMwL4qStNUTyPDqckNjniw2SlowmHN8n5NnR47gvqjo96E+vakpw8v5PE=', 'password') def initialize(str, password = nil) contents = str.split("\n") bytes = Base64.decode64(contents.last).bytes @@ -19,8 +26,10 @@ def initialize(str, password = nil) kdf_output = derive_key(password, @kdf_salt, @kdf_opslimit, @kdf_memlimit) @key_id, @secret_key, @public_key, @checksum = xor(kdf_output, bytes[54..157]) end + # rubocop:enable Layout/LineLength # rubocop:enable Metrics/AbcSize + # @return [String] the used to xor the ed25519 keys def derive_key(password, kdf_salt, kdf_opslimit, kdf_memlimit) RbNaCl::PasswordHash.scrypt( password, @@ -31,17 +40,23 @@ def derive_key(password, kdf_salt, kdf_opslimit, kdf_memlimit) ).bytes end + # rubocop:disable Layout/LineLength + + # @return [Array<32 bit unsigned ints>] the byte array containing the key id, the secret and public ed25519 keys, and the checksum def xor(kdf_output, contents) + # rubocop:enable Layout/LineLength xored = kdf_output.each_with_index.map do |b, i| contents[i] ^ b end [xored[0..7], xored[8..39], xored[40..71], xored[72..103]] end + # @return [Ed25519::SigningKey] the ed25519 signing key def ed25519_signing_key Ed25519::SigningKey.new(@secret_key.pack('C*')) end + # @return [String] the signature in the .minisig format that can be written to a file. def sign(filename, message) signature = ed25519_signing_key.sign(blake2b512(message)) trusted_comment = "timestamp:#{Time.now.to_i}\tfile:#{filename}\thashed"