Skip to content

Commit

Permalink
recreate public key from private key
Browse files Browse the repository at this point in the history
  • Loading branch information
jshawl committed Feb 8, 2024
1 parent 8f9b5b4 commit 68431b2
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 7 deletions.
Binary file added .DS_Store
Binary file not shown.
11 changes: 8 additions & 3 deletions lib/minisign/private_key.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module Minisign
class PrivateKey
include Utils
attr_reader :signature_algorithm, :kdf_algorithm, :cksum_algorithm, :kdf_salt, :kdf_opslimit, :kdf_memlimit,
:key_id, :public_key, :secret_key, :checksum
:key_id, :ed25519_public_key, :secret_key, :checksum

# rubocop:disable Metrics/AbcSize
# rubocop:disable Layout/LineLength
Expand Down Expand Up @@ -35,7 +35,7 @@ def initialize(str, password = nil)
else
bytes[54..157]
end
@key_id, @secret_key, @public_key, @checksum = key_data(@key_data_bytes)
@key_id, @secret_key, @ed25519_public_key, @checksum = key_data(@key_data_bytes)
assert_keypair_match!
end
# rubocop:enable Layout/LineLength
Expand All @@ -44,7 +44,7 @@ def initialize(str, password = nil)

# @raise [RuntimeError] if the extracted public key does not match the derived public key
def assert_keypair_match!
raise 'Wrong password for that key' if @public_key != ed25519_signing_key.verify_key.to_bytes.bytes
raise 'Wrong password for that key' if @ed25519_public_key != ed25519_signing_key.verify_key.to_bytes.bytes
end

def key_data(bytes)
Expand All @@ -56,6 +56,11 @@ def ed25519_signing_key
Ed25519::SigningKey.new(@secret_key.pack('C*'))
end

def public_key
data = Base64.strict_encode64("Ed#{@key_id.pack('C*')}#{ed25519_signing_key.verify_key.to_bytes}")
Minisign::PublicKey.new(data)
end

# Sign a file/message
#
# @param filename [String] The filename to be used in the trusted comment section
Expand Down
2 changes: 1 addition & 1 deletion lib/minisign/public_key.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def initialize(str)
@public_key = @decoded[10..]
@verify_key = Ed25519::VerifyKey.new(@public_key)
@untrusted_comment = if parts.length == 1
"minisign public key #{key_id}\n#{key_data}\n"
"minisign public key #{key_id}"
else
parts.first.split('untrusted comment: ').last
end
Expand Down
8 changes: 8 additions & 0 deletions spec/minisign/key_pair_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,26 @@
keypair = Minisign::KeyPair.new
expect(keypair.private_key).to be_truthy
File.write('test/generated/new-unencrypted-keypair.key', keypair.private_key)
File.write('test/generated/new-unencrypted-keypair.pub', keypair.public_key)
expect(system(
'test/generated/minisign -Sm test/generated/.keep -s test/generated/new-unencrypted-keypair.key'
)).to be(true)
expect(system(
'test/generated/minisign -Vm test/generated/.keep -p test/generated/new-unencrypted-keypair.pub'
)).to be(true)
end
it 'generates a keypair with a password' do
keypair = Minisign::KeyPair.new('secret password')
expect(keypair.private_key).to be_truthy
File.write('test/generated/new-encrypted-keypair.key', keypair.private_key)
File.write('test/generated/new-encrypted-keypair.pub', keypair.public_key)
expect(system(
# rubocop:disable Layout/LineLength
"echo 'secret password' | test/generated/minisign -Sm test/generated/.keep -s test/generated/new-encrypted-keypair.key"
# rubocop:enable Layout/LineLength
)).to be(true)
expect(system(
'test/generated/minisign -Vm test/generated/.keep -p test/generated/new-encrypted-keypair.pub'
)).to be(true)
end
end
13 changes: 10 additions & 3 deletions spec/minisign/private_key_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@
end

it 'parses the public key' do
expect(@private_key.public_key).to eq([108, 35, 192, 26, 47, 128, 233, 165, 133, 38, 242, 5, 76, 55, 135, 40,
103, 72, 230, 43, 184, 117, 219, 37, 173, 250, 196, 122, 252, 174, 173, 140]) # rubocop:disable Layout/LineLength
key = @private_key.ed25519_public_key
expect(key).to eq([108, 35, 192, 26, 47, 128, 233, 165, 133, 38, 242, 5, 76, 55, 135, 40,
103, 72, 230, 43, 184, 117, 219, 37, 173, 250, 196, 122, 252, 174, 173, 140])
end

it 'parses the secret key' do
Expand All @@ -70,7 +71,7 @@
[69, 100],
@private_key.key_id,
@private_key.secret_key,
@private_key.public_key
@private_key.ed25519_public_key
].inject(&:+).pack('C*')

computed_checksum = blake2b256(key_data).bytes
Expand All @@ -80,6 +81,12 @@
it 'can be written to a file' do
expect(@private_key.to_s).to eq(File.read('test/minisign.key'))
end

it 'can recreate the public key from the private key' do
# remove the custom untrusted comment
original = File.read('test/minisign.pub').gsub(' yay', '')
expect(@private_key.public_key.to_s).to eq(original)
end
end

describe 'sign' do
Expand Down

0 comments on commit 68431b2

Please sign in to comment.