v2 / vlib / crypto / ecdsa / util_test.v
198 lines · 174 sloc · 7.89 KB · e2e5cf8db56f3562c7baa735061690be936bdf3e
Raw
1// vtest build: present_openssl? && !(openbsd && gcc) && !(sanitize-memory-clang || docker-ubuntu-musl)
2module ecdsa
3
4import encoding.hex
5import crypto.pem
6import crypto.sha1
7import crypto.sha512
8
9// This material wss generated with https://emn178.github.io/online-tools/ecdsa/key-generator
10// with curve SECG secp384r1 aka NIST P-384
11const privatekey_sample = '-----BEGIN PRIVATE KEY-----
12MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDAwzj2iiJZaxgk/C6mp
13oVskdr6j7akl4bPB8JRnT1J5XNbLPK/iNd/BW+xUJEj/pxWhZANiAAT4/euEWRPV
149cdhtjcKlwF2HrFMLvgxAXFx+01UPfMQ9XOj/85qUhVq1jXraSyDy5FYF28UW4dn
1504xVeRuPBbCFxc/uqYj2s5ItHcAZSV3L5sGlXadPfTqoIjCBQAx44k8=
16-----END PRIVATE KEY-----'
17
18const public_key_sample = '-----BEGIN PUBLIC KEY-----
19MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE+P3rhFkT1fXHYbY3CpcBdh6xTC74MQFx
20cftNVD3zEPVzo//OalIVatY162ksg8uRWBdvFFuHZ9OMVXkbjwWwhcXP7qmI9rOS
21LR3AGUldy+bBpV2nT306qCIwgUAMeOJP
22-----END PUBLIC KEY-----'
23
24// Message tobe signed and verified
25const message_tobe_signed = 'Example of ECDSA with P-384'.bytes()
26// Message signature created with SHA384 digest with associated above key
27const expected_signature = hex.decode('3066023100b08f6ec77bb319fdb7bce55a2714d7e79cc645d834ee539d8903cfcc88c6fa90df1558856cb840b2dd82e82cd89d7046023100d9d482ca8a6545a3b081fbdd4bb9643a2b4eda4e21fd624833216596032471faae646891f8d2f0bbb86b796c36d3c390')!
28
29fn test_load_pubkey_from_der_serialized_bytes() ! {
30 block, _ := pem.decode(public_key_sample) or { panic(err) }
31 pbkey := pubkey_from_bytes(block.data)!
32
33 // .with_no_hash currently changed to have same behaviour with .with_recommended_hash
34 status_without_hashed := pbkey.verify(message_tobe_signed, expected_signature,
35 hash_config: .with_no_hash
36 )!
37 assert status_without_hashed == true
38
39 // expected signature was comes from hashed message with sha384
40 status_with_hashed := pbkey.verify(message_tobe_signed, expected_signature)!
41 assert status_with_hashed == true
42 pbkey.free()
43}
44
45fn test_for_pubkey_bytes() ! {
46 // material generated with online ecdsa generator https://emn178.github.io/online-tools/ecdsa/key-generator/
47 pv := '62e998bea8a15f52ff0b76cf3fe281cfcd8042ce4479b6e652ca7b5a36f6fb40'
48 pb := '0421af184ac64c8a13e66c65d4f1ad31677edeaa97af791aef73b66ea26d1623a411f67b6c4d842ba22fa39d1216bd64acef00a1b924ac11a10af679ac3a7eb2fd'
49 pvkey := new_key_from_seed(hex.decode(pv)!)!
50
51 assert pvkey.bytes()!.hex() == pv
52 pbkey := pvkey.public_key()!
53 assert pbkey.bytes()!.hex() == pb
54 pbkey.free()
55 pvkey.free()
56}
57
58// above pem-formatted private key read with
59// `$openssl ec -in vlib/crypto/ecdsa/example.pem -text -param_out -check`
60// produces following result:
61// ```codeblock
62// read EC key
63// Private-Key: (384 bit)
64// priv:
65// 30:ce:3d:a2:88:96:5a:c6:09:3f:0b:a9:a9:a1:5b:
66// 24:76:be:a3:ed:a9:25:e1:b3:c1:f0:94:67:4f:52:
67// 79:5c:d6:cb:3c:af:e2:35:df:c1:5b:ec:54:24:48:
68// ff:a7:15
69// pub:
70// 04:f8:fd:eb:84:59:13:d5:f5:c7:61:b6:37:0a:97:
71// 01:76:1e:b1:4c:2e:f8:31:01:71:71:fb:4d:54:3d:
72// f3:10:f5:73:a3:ff:ce:6a:52:15:6a:d6:35:eb:69:
73// 2c:83:cb:91:58:17:6f:14:5b:87:67:d3:8c:55:79:
74// 1b:8f:05:b0:85:c5:cf:ee:a9:88:f6:b3:92:2d:1d:
75// c0:19:49:5d:cb:e6:c1:a5:5d:a7:4f:7d:3a:a8:22:
76// 30:81:40:0c:78:e2:4f
77// ASN1 OID: secp384r1
78// NIST CURVE: P-384
79// EC Key valid.
80// writing EC key
81// -----BEGIN EC PRIVATE KEY-----
82// MIGkAgEBBDAwzj2iiJZaxgk/C6mpoVskdr6j7akl4bPB8JRnT1J5XNbLPK/iNd/B
83// W+xUJEj/pxWgBwYFK4EEACKhZANiAAT4/euEWRPV9cdhtjcKlwF2HrFMLvgxAXFx
84// +01UPfMQ9XOj/85qUhVq1jXraSyDy5FYF28UW4dn04xVeRuPBbCFxc/uqYj2s5It
85// HcAZSV3L5sGlXadPfTqoIjCBQAx44k8=
86// -----END EC PRIVATE KEY-----
87// ```
88fn test_load_privkey_from_string_sign_and_verify() ! {
89 pvkey := privkey_from_string(privatekey_sample)!
90 expected_pvkey_bytes := '30ce3da288965ac6093f0ba9a9a15b2476bea3eda925e1b3c1f094674f52795cd6cb3cafe235dfc15bec542448ffa715'
91 assert pvkey.bytes()!.hex() == expected_pvkey_bytes
92
93 // public key part
94 pbkey := pvkey.public_key()!
95 pbkey_bytes := pbkey.bytes()!
96 expected_pubkey_bytes := '04f8fdeb845913d5f5c761b6370a9701761eb14c2ef831017171fb4d543df310f573a3ffce6a52156ad635eb692c83cb9158176f145b8767d38c55791b8f05b085c5cfeea988f6b3922d1dc019495dcbe6c1a55da74f7d3aa8223081400c78e24f'
97 assert pbkey_bytes.hex() == expected_pubkey_bytes
98
99 // lets sign the message with default hash, ie, sha384
100 signature := pvkey.sign(message_tobe_signed)!
101
102 verified := pbkey.verify(message_tobe_signed, signature)!
103 assert verified == true
104 pvkey.free()
105 pbkey.free()
106}
107
108fn test_load_pubkey_from_string_and_used_for_verifying() ! {
109 pbkey := pubkey_from_string(public_key_sample)!
110 pbkey_bytes := pbkey.bytes()!
111 expected_pubkey_bytes := '04f8fdeb845913d5f5c761b6370a9701761eb14c2ef831017171fb4d543df310f573a3ffce6a52156ad635eb692c83cb9158176f145b8767d38c55791b8f05b085c5cfeea988f6b3922d1dc019495dcbe6c1a55da74f7d3aa8223081400c78e24f'
112 assert pbkey_bytes.hex() == expected_pubkey_bytes
113
114 // expected signature was comes from hashed message with sha384
115 status_with_hashed := pbkey.verify(message_tobe_signed, expected_signature)!
116 assert status_with_hashed == true
117 pbkey.free()
118}
119
120// test for loading privat key from unsupported curve should fail.
121fn test_load_privkey_from_string_with_unsupported_curve() ! {
122 // generated with openssl ecparam -name secp192k1 -genkey -noout -out key.pem
123 key := '-----BEGIN EC PRIVATE KEY-----
124MFwCAQEEGDHV+WhJL2UjUhgMLh52k0RJjRebtu4HvqAHBgUrgQQAH6E0AzIABFyF
125UHhnmmVRraSwrVkPdYIeXhH/Ob4+8OLcwrQBMv4RXsD1GVFsgkvEYDTEb/vnMA==
126-----END EC PRIVATE KEY-----'
127 _ := privkey_from_string(key) or {
128 assert err == error('Unsupported group')
129 return
130 }
131}
132
133fn test_key_signing_verifying_with_custom_hash() ! {
134 // privatekey_sample was P-384 key
135 pvkey := privkey_from_string(privatekey_sample)!
136 // public key part
137 pbkey := pvkey.public_key()!
138 pbk := pubkey_from_string(public_key_sample)!
139
140 // lets sign the message with default hash, ie, sha384
141 signature := pvkey.sign(message_tobe_signed)!
142 verified := pbkey.verify(message_tobe_signed, signature)!
143 assert verified == true
144
145 // Use the bigger custom hash
146 opt0 := SignerOpts{
147 hash_config: .with_custom_hash
148 allow_custom_hash: true
149 custom_hash: sha512.new()
150 }
151 // online-generated signature with sha512 digest with the same params from https://emn178.github.io/online-tools/ecdsa/sign/
152 online_sign0 :=
153 hex.decode('3066023100b54b479b64961481074c4200a9dec83fb8a42bb7db53cf97f1da131504a058ead85d0a9e4e32be14098bc9b4d1a5a8dd023100f9c7de178a286329103f684d1eab1ccfe359c65a41a1459d7f535b703c57048f25931b1670ab4ec7a812d94c69063522')!
154 // library generated signature
155 sign0 := pvkey.sign(message_tobe_signed, opt0)!
156 v00 := pbkey.verify(message_tobe_signed, sign0, opt0)!
157 // this own signature should assert into true
158 assert v00 == true
159
160 // verify online-generated signature
161 v01 := pbkey.verify(message_tobe_signed, online_sign0, opt0)!
162 assert v01 == true
163
164 // with public_key_sample key
165 v02 := pbk.verify(message_tobe_signed, sign0, opt0)!
166 assert v02 == true
167 v03 := pbk.verify(message_tobe_signed, online_sign0, opt0)!
168 assert v03 == true
169
170 // Use smaller custom hash
171 opt1 := SignerOpts{
172 hash_config: .with_custom_hash
173 allow_custom_hash: true
174 allow_smaller_size: true
175 custom_hash: sha1.new()
176 }
177 // online-generated signature with SHA1 digest
178 online_sign1 :=
179 hex.decode('306602310084299d8a70bf512c25cd2b79ae36509572f2bd6f198baeee074683578a70b4af8008e1cf451a2df1a887cf43daff4eea023100dceb267fe5037025c2af9f37911e05a36cbe666dd90fd6904020b5db056e86f25f9439a0ccb443d113b174cab6e2ad61')!
180 // library generated signature
181 sign1 := pvkey.sign(message_tobe_signed, opt1)!
182 verified1 := pbkey.verify(message_tobe_signed, sign1, opt1)!
183 // this own signature should assert into true
184 assert verified1 == true
185 // verify online-generated signature
186 verified11 := pbkey.verify(message_tobe_signed, online_sign1, opt1)!
187 assert verified11 == true
188
189 // verify with public_key_sample key
190 v11 := pbk.verify(message_tobe_signed, sign1, opt1)!
191 assert v11 == true
192 v12 := pbk.verify(message_tobe_signed, online_sign1, opt1)!
193 assert v12 == true
194
195 pvkey.free()
196 pbkey.free()
197 pbk.free()
198}
199