Skip to content

Commit

Permalink
Handling COSE EC keys encoded without leading 0 bytes in coordinates (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
waltercacau authored Aug 12, 2024
1 parent fcde72f commit b997db1
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 1 deletion.
12 changes: 11 additions & 1 deletion lib/cose/key/ec2.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
23 changes: 23 additions & 0 deletions spec/cose/key/ec2_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit b997db1

Please sign in to comment.