diff --git a/lib/cose/key/ec2.rb b/lib/cose/key/ec2.rb index 8e97594..03372b8 100644 --- a/lib/cose/key/ec2.rb +++ b/lib/cose/key/ec2.rb @@ -11,6 +11,8 @@ class EC2 < CurveKey KTY_EC2 = 2 + ZERO_BYTE = "\0".b + def self.enforce_type(map) if map[LABEL_KTY] != KTY_EC2 raise "Not an EC2 key" @@ -68,7 +70,7 @@ def map def to_pkey if curve group = OpenSSL::PKey::EC::Group.new(curve.pkey_name) - public_key_bn = OpenSSL::BN.new("\x04" + x + y, 2) + public_key_bn = OpenSSL::BN.new("\x04" + pad_coordinate(group, x) + pad_coordinate(group, y), 2) public_key_point = OpenSSL::PKey::EC::Point.new(group, public_key_bn) # RFC5480 SubjectPublicKeyInfo @@ -113,6 +115,14 @@ def curve def self.keyword_arguments_for_initialize(map) super.merge(y: map[LABEL_Y]) end + + def pad_coordinate(group, coordinate) + coordinate_length = (group.degree + 7) / 8 + padding_required = coordinate_length - coordinate.length + return coordinate if padding_required <= 0 + + (ZERO_BYTE * padding_required) + coordinate + end end end end diff --git a/spec/cose/key/ec2_spec.rb b/spec/cose/key/ec2_spec.rb index a8f6c7a..d94b707 100644 --- a/spec/cose/key/ec2_spec.rb +++ b/spec/cose/key/ec2_spec.rb @@ -131,6 +131,29 @@ expect(pkey.public_key).to eq(original_pkey.public_key) expect(pkey.private_key).to eq(original_pkey.private_key) end + + it "works for an EC key that omits leading zero" do + # x was encoded omitting a leading zero. Before calling OpenSSL we must pad it. + x = ")\xC6`8\xBC\xEE\xF9*\xA4S\x9E\xA7\xFA'\xCE\xB9\x8D\x8C\xF7U\x06\xD8B\xB8\x8B\x9A\xF6\x9B\xC1\n\xCB".b + y = "Y\x9C\xD0+y<\xCB9Vk-\xC4\xEB\x87\xA7\xA1\xFA\xFEF\xAD\xD7\xA6\xB8\x84\xBEm[\xD7\xAEN\xD6w".b + original_key = COSE::Key::EC2.new( + kid: "id".b, + alg: -7, + key_ops: 1, + base_iv: "init-vector".b, + crv: 1, + x: x, + y: y, + ) + + pkey = original_key.to_pkey + key = COSE::Key::EC2.from_pkey(pkey) + + expect(pkey).to be_a(OpenSSL::PKey::EC) + expect(pkey.group.curve_name).to eq("prime256v1") + expect(key.x).to eq("\0".b + x) + expect(key.y).to eq(y) + end end describe "#serialize" do