@@ -23,6 +23,15 @@ AwEHoUQDQgAEqIVYZVLCrPZHGHjP17CTW0/+D9Lfw0EkjqF7xB4FivAxzic30tMM
23234GF+hR6Dxh71Z50VGGdldkkDXZCnTNnoXQ==
2424-----END EC PRIVATE KEY-----'
2525
26+ // P-256 key whose private scalar starts with 0x00, so OpenSSL's
27+ // `BN_bn2binpad(num_bytes)` returns 31 bytes instead of 32. This
28+ // exercises the leading-zero padding in `ecdsa_key_from_xy_d`.
29+ const short_d_p256_private_pem = '-----BEGIN EC PRIVATE KEY-----
30+ MHcCAQEEIACZmEw0q8iipb0amaNiobX/wwn6PoIKUatErMY2Dd4+oAoGCCqGSM49
31+ AwEHoUQDQgAE/z/OBheMT6mCKDapfETr56tkYLOrnQh+ZL293+IqXsJ+iMZgYe0/
32+ WHaZhZfCu1OKUWayaVEkvb7j0o3uUfw+OQ==
33+ -----END EC PRIVATE KEY-----'
34+
2635fn key_test_b26_components () Components {
2736 return Components{
2837 method: 'POST'
@@ -103,6 +112,35 @@ fn test_from_pem_ecdsa_p256_public_verifies_rfc_b24_reference() {
103112 'sig-b24' , pub_key)!
104113}
105114
115+ fn test_from_pem_ecdsa_p256_pads_short_private_scalar () {
116+ // Regression: a P-256 PEM whose `d` has a leading zero byte must
117+ // still produce a 96-byte (x||y||d) key and sign successfully.
118+ priv := Key.from_pem (short_d_p256_ private_pem)!
119+ assert priv.algorithm == .ecdsa_p256_ sha256
120+ assert priv.is_private
121+ assert priv.bytes.len == 96
122+ c := Components{
123+ method: 'POST'
124+ target_uri: 'https://example.com/'
125+ }
126+ p := SignatureParams{
127+ components: ['@method' , '@target-uri' ]
128+ created: 1
129+ }
130+ out := sign (c, p, priv, 'sig1' )!
131+ verify (c, out.signature_input, out.signature, 'sig1' , priv)!
132+ }
133+
134+ fn test_pad_left_pads_to_width_and_rejects_overflow () {
135+ assert pad_left ([u8 (0x01 )], 4 )! == [u8 (0x00 ), 0x00 , 0x00 , 0x01 ]
136+ assert pad_left ([u8 (0x01 ), 0x02 , 0x03 , 0x04 ], 4 )! == [u8 (0x01 ), 0x02 , 0x03 , 0x04 ]
137+ if _ := pad_left ([u8 (0x01 ), 0x02 , 0x03 , 0x04 , 0x05 ], 4 ) {
138+ assert false , 'must reject scalars wider than the curve'
139+ } else {
140+ assert err is MalformedMessage
141+ }
142+ }
143+
106144fn test_from_pem_rejects_garbage () {
107145 if _ := Key.from_pem ('not a PEM block' ) {
108146 assert false , 'must reject non-PEM input'
0 commit comments