Codebase list libcryptx-perl / 69a245c
ECC added: verify_message_rfc7518, sign_message_rfc7518, curve2hash Karel Miko 8 years ago
7 changed file(s) with 309 addition(s) and 157 deletion(s). Raw diff Collapse all Expand all
447447 $curve = 'P-256' if $curve =~ /(secp256r1|nistp256|prime256v1)/;
448448 $curve = 'P-384' if $curve =~ /(secp384r1|nistp384)/;
449449 $curve = 'P-521' if $curve =~ /(secp521r1|nistp521)/;
450 if ($type eq 'private') {
450 if ($type && $type eq 'private') {
451451 return unless $kh->{pub_x} && $kh->{pub_y} && $kh->{k};
452452 for (qw/pub_x pub_y k/) {
453453 $kh->{$_} = "0$kh->{$_}" if length($kh->{$_}) % 2;
460460 encode_base64url(pack("H*", $kh->{pub_y})),
461461 encode_base64url(pack("H*", $kh->{k}));
462462 }
463 elsif ($type eq 'public') {
463 elsif ($type && $type eq 'public') {
464464 return unless $kh->{pub_x} && $kh->{pub_y};
465465 for (qw/pub_x pub_y/) {
466466 $kh->{$_} = "0$kh->{$_}" if length($kh->{$_}) % 2;
486486 }
487487 if ($key->{crv} && $key->{kty} && $key->{kty} eq "EC" && ($key->{d} || ($key->{x} && $key->{y}))) {
488488 # hash with items corresponding to JSON Web Key (JWK)
489 $key = {%$key}; # make a copy as we will modify it
489490 for (qw/x y d/) {
490491 $key->{$_} = eval { unpack("H*", decode_base64url($key->{$_})) } if exists $key->{$_};
491492 }
493494 return $self->_import_hex($key->{x}, $key->{y}, $key->{d}, $curve);
494495 }
495496 }
497 croak "FATAL: unexpected key hash";
496498 }
497499
498500 my $data;
567569 return $self->_sign($data_hash);
568570 }
569571
572 sub sign_message_rfc7518 {
573 my ($self, $data, $hash_name) = @_;
574 $hash_name ||= 'SHA1';
575 my $data_hash = digest_data($hash_name, $data);
576 return $self->_sign_rfc7518($data_hash);
577 }
578
570579 sub verify_message {
571580 my ($self, $sig, $data, $hash_name) = @_;
572581 $hash_name ||= 'SHA1';
574583 return $self->_verify($sig, $data_hash);
575584 }
576585
586 sub verify_message_rfc7518 {
587 my ($self, $sig, $data, $hash_name) = @_;
588 $hash_name ||= 'SHA1';
589 my $data_hash = digest_data($hash_name, $data);
590 return $self->_verify_rfc7518($sig, $data_hash);
591 }
592
577593 sub sign_hash {
578594 my ($self, $data_hash) = @_;
579595 return $self->_sign($data_hash);
582598 sub verify_hash {
583599 my ($self, $sig, $data_hash) = @_;
584600 return $self->_verify($sig, $data_hash);
601 }
602
603 sub curve2hash {
604 my $self = shift;
605 my $kh = $self->key2hash;
606 return {
607 prime => $kh->{curve_prime},
608 A => $kh->{curve_A},
609 B => $kh->{curve_B},
610 Gx => $kh->{curve_Gx},
611 Gy => $kh->{curve_Gy},
612 cofactor => $kh->{curve_cofactor},
613 order => $kh->{curve_order}
614 };
585615 }
586616
587617 ### FUNCTIONS
10351065
10361066 #NOTE: $hash_name can be 'SHA1' (DEFAULT), 'SHA256' or any other hash supported by Crypt::Digest
10371067
1068 =head2 sign_message_rfc7518
1069
1070 Same as L<sign_message|/sign_message> only the signature format is as defined by L<https://tools.ietf.org/html/rfc7518>
1071 (JWA - JSON Web Algorithms).
1072
10381073 =head2 verify_message
10391074
10401075 my $pk = Crypt::PK::ECC->new($pub_key_filename);
10431078 my $valid = $pub->verify_message($signature, $message, $hash_name);
10441079
10451080 #NOTE: $hash_name can be 'SHA1' (DEFAULT), 'SHA256' or any other hash supported by Crypt::Digest
1081
1082 =head2 verify_message_rfc7518
1083
1084 Same as L<verify_message|/verify_message> only the signature format is as defined by L<https://tools.ietf.org/html/rfc7518>
1085 (JWA - JSON Web Algorithms).
10461086
10471087 =head2 sign_hash
10481088
11041144 pub_y => "895D57E992D0A15F88D6680B27B701F615FCDC0F",
11051145 }
11061146
1147 =head2 curve2hash
1148
1149 my $crv = $pk->curve2hash;
1150
1151 # returns a hash that can be passed to: $pk->generate_key($crv)
1152 {
1153 A => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC",
1154 B => "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45",
1155 cofactor => 1,
1156 Gx => "4A96B5688EF573284664698968C38BB913CBFC82",
1157 Gy => "23A628553168947D59DCC912042351377AC5FB32",
1158 order => "0100000000000000000001F4C8F927AED3CA752257",
1159 prime => "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF",
1160 }
1161
11071162 =head1 FUNCTIONS
11081163
11091164 =head2 ecc_encrypt
22 use strict;
33 use warnings ;
44
5 our $VERSION = '0.023_2';
5 our $VERSION = '0.024';
66
77 require XSLoader;
88 XSLoader::load('CryptX', $VERSION);
271271
272272 SV *
273273 _sign(Crypt::PK::ECC self, SV * data)
274 ALIAS:
275 _sign_rfc7518 = 1
274276 CODE:
275277 {
276278 int rv;
281283
282284 data_ptr = (unsigned char *)SvPVbyte(data, data_len);
283285
284 rv = ecc_sign_hash(data_ptr, (unsigned long)data_len, buffer, &buffer_len,
285 &self->yarrow_prng_state, self->yarrow_prng_index,
286 &self->key);
286 if (ix == 1) {
287 rv = ecc_sign_hash_rfc7518(data_ptr, (unsigned long)data_len, buffer, &buffer_len,
288 &self->yarrow_prng_state, self->yarrow_prng_index,
289 &self->key);
290 }
291 else {
292 rv = ecc_sign_hash(data_ptr, (unsigned long)data_len, buffer, &buffer_len,
293 &self->yarrow_prng_state, self->yarrow_prng_index,
294 &self->key);
295 }
287296 if (rv != CRYPT_OK) croak("FATAL: ecc_sign_hash_ex failed: %s", error_to_string(rv));
288297 RETVAL = newSVpvn((char*)buffer, buffer_len);
289298 }
292301
293302 int
294303 _verify(Crypt::PK::ECC self, SV * sig, SV * data)
304 ALIAS:
305 _verify_rfc7518 = 1
295306 CODE:
296307 {
297308 int rv, stat;
304315 sig_ptr = (unsigned char *)SvPVbyte(sig, sig_len);
305316
306317 RETVAL = 1;
307 rv = ecc_verify_hash(sig_ptr, (unsigned long)sig_len, data_ptr, (unsigned long)data_len, &stat, &self->key);
318 if (ix == 1) {
319 rv = ecc_verify_hash_rfc7518(sig_ptr, (unsigned long)sig_len, data_ptr, (unsigned long)data_len, &stat, &self->key);
320 }
321 else {
322 rv = ecc_verify_hash(sig_ptr, (unsigned long)sig_len, data_ptr, (unsigned long)data_len, &stat, &self->key);
323 }
308324 if (rv != CRYPT_OK || stat != 1) RETVAL = 0;
309325 }
310326 OUTPUT:
5050 return CRYPT_INVALID_ARG;
5151 }
5252
53 /* XXX FIXME names can be different in some situations
5354 if (XSTRCMP(private_key->dp->name, public_key->dp->name) != 0) {
5455 return CRYPT_PK_TYPE_MISMATCH;
5556 }
56
57 */
5758 /* make new point */
5859 result = ltc_ecc_new_point();
5960 if (result == NULL) {
2020
2121 #ifdef LTC_MECC
2222
23 /**
24 Sign a message digest
25 @param in The message digest to sign
26 @param inlen The length of the digest
27 @param out [out] The destination for the signature
28 @param outlen [in/out] The max size and resulting size of the signature
29 @param prng An active PRNG state
30 @param wprng The index of the PRNG you wish to use
31 @param key A private ECC key
32 @return CRYPT_OK if successful
33 */
34 int ecc_sign_hash(const unsigned char *in, unsigned long inlen,
35 unsigned char *out, unsigned long *outlen,
36 prng_state *prng, int wprng, ecc_key *key)
23 int ecc_sign_hash_ex(const unsigned char *in, unsigned long inlen,
24 unsigned char *out, unsigned long *outlen,
25 prng_state *prng, int wprng, ecc_key *key, int sigformat)
3726 {
3827 ecc_key pubkey;
3928 void *r, *s, *e, *p;
11099 }
111100 }
112101
113 /* store as SEQUENCE { r, s -- integer } */
114 err = der_encode_sequence_multi(out, outlen,
115 LTC_ASN1_INTEGER, 1UL, r,
116 LTC_ASN1_INTEGER, 1UL, s,
117 LTC_ASN1_EOL, 0UL, NULL);
102 if (sigformat == 1) {
103 /* RFC7518 format */
104 if (*outlen < 2*pbytes) { err = CRYPT_MEM; goto errnokey; }
105 zeromem(out, 2*pbytes);
106 i = mp_unsigned_bin_size(r);
107 if ((err = mp_to_unsigned_bin(r, out + (pbytes - i))) != CRYPT_OK) goto errnokey;
108 i = mp_unsigned_bin_size(s);
109 if ((err = mp_to_unsigned_bin(s, out + (2*pbytes - i))) != CRYPT_OK) goto errnokey;
110 *outlen = 2*pbytes;
111 err = CRYPT_OK;
112 }
113 else {
114 /* store as ASN.1 SEQUENCE { r, s -- integer } */
115 err = der_encode_sequence_multi(out, outlen,
116 LTC_ASN1_INTEGER, 1UL, r,
117 LTC_ASN1_INTEGER, 1UL, s,
118 LTC_ASN1_EOL, 0UL, NULL);
119 }
118120 goto errnokey;
119121 error:
120122 ecc_free(&pubkey);
123125 return err;
124126 }
125127
128 /**
129 Sign a message digest
130 @param in The message digest to sign
131 @param inlen The length of the digest
132 @param out [out] The destination for the signature
133 @param outlen [in/out] The max size and resulting size of the signature
134 @param prng An active PRNG state
135 @param wprng The index of the PRNG you wish to use
136 @param key A private ECC key
137 @return CRYPT_OK if successful
138 */
139 int ecc_sign_hash(const unsigned char *in, unsigned long inlen,
140 unsigned char *out, unsigned long *outlen,
141 prng_state *prng, int wprng, ecc_key *key)
142 {
143 return ecc_sign_hash_ex(in, inlen, out, outlen, prng, wprng, key, 0);
144 }
145
146 /**
147 Sign a message digest in RFC7518 format
148 @param in The message digest to sign
149 @param inlen The length of the digest
150 @param out [out] The destination for the signature
151 @param outlen [in/out] The max size and resulting size of the signature
152 @param prng An active PRNG state
153 @param wprng The index of the PRNG you wish to use
154 @param key A private ECC key
155 @return CRYPT_OK if successful
156 */
157 int ecc_sign_hash_rfc7518(const unsigned char *in, unsigned long inlen,
158 unsigned char *out, unsigned long *outlen,
159 prng_state *prng, int wprng, ecc_key *key)
160 {
161 return ecc_sign_hash_ex(in, inlen, out, outlen, prng, wprng, key, 1);
162 }
163
126164 #endif
127165 /* $Source$ */
128166 /* $Revision$ */
2929 * v = X_x1 mod n
3030 * accept if v == r
3131 */
32
33 int ecc_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
34 const unsigned char *hash, unsigned long hashlen,
35 int *stat, ecc_key *key, int sigformat)
36 {
37 ecc_point *mG, *mQ;
38 void *r, *s, *v, *w, *u1, *u2, *e, *p, *m, *a;
39 void *mp;
40 int err;
41 unsigned long pbits, pbytes, i, shift_right;
42 unsigned char ch, buf[MAXBLOCKSIZE];
43
44 LTC_ARGCHK(sig != NULL);
45 LTC_ARGCHK(hash != NULL);
46 LTC_ARGCHK(stat != NULL);
47 LTC_ARGCHK(key != NULL);
48
49 /* default to invalid signature */
50 *stat = 0;
51 mp = NULL;
52
53 /* is the IDX valid ? */
54 if (ltc_ecc_is_valid_idx(key->idx) != 1) {
55 return CRYPT_PK_INVALID_TYPE;
56 }
57
58 /* allocate ints */
59 if ((err = mp_init_multi(&r, &s, &v, &w, &u1, &u2, &p, &e, &m, &a, NULL)) != CRYPT_OK) {
60 return CRYPT_MEM;
61 }
62
63 /* allocate points */
64 mG = ltc_ecc_new_point();
65 mQ = ltc_ecc_new_point();
66 if (mQ == NULL || mG == NULL) {
67 err = CRYPT_MEM;
68 goto error;
69 }
70
71 if (sigformat == 1) {
72 /* RFC7518 format */
73 if ((siglen % 2) == 1) {
74 err = CRYPT_INVALID_PACKET;
75 goto error;
76 }
77 i = siglen / 2;
78 if ((err = mp_read_unsigned_bin(r, (unsigned char *)sig, i)) != CRYPT_OK) goto error;
79 if ((err = mp_read_unsigned_bin(s, (unsigned char *)sig+i, i)) != CRYPT_OK) goto error;
80 }
81 else {
82 /* ASN.1 format */
83 if ((err = der_decode_sequence_multi(sig, siglen,
84 LTC_ASN1_INTEGER, 1UL, r,
85 LTC_ASN1_INTEGER, 1UL, s,
86 LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
87 goto error;
88 }
89 }
90
91 /* get the order */
92 if ((err = mp_read_radix(p, (char *)key->dp->order, 16)) != CRYPT_OK) { goto error; }
93
94 /* get the modulus */
95 if ((err = mp_read_radix(m, (char *)key->dp->prime, 16)) != CRYPT_OK) { goto error; }
96
97 /* get the a */
98 if ((err = mp_read_radix(a, (char *)key->dp->A, 16)) != CRYPT_OK) { goto error; }
99
100 /* check for zero */
101 if (mp_iszero(r) || mp_iszero(s) || mp_cmp(r, p) != LTC_MP_LT || mp_cmp(s, p) != LTC_MP_LT) {
102 err = CRYPT_INVALID_PACKET;
103 goto error;
104 }
105
106 /* read hash - truncate if needed */
107 pbits = mp_count_bits(p);
108 pbytes = (pbits+7) >> 3;
109 if (pbits > hashlen*8) {
110 if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, hashlen)) != CRYPT_OK) { goto error; }
111 }
112 else if (pbits % 8 == 0) {
113 if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, pbytes)) != CRYPT_OK) { goto error; }
114 }
115 else {
116 shift_right = 8 - pbits % 8;
117 for (i=0, ch=0; i<pbytes; i++) {
118 buf[i] = ch;
119 ch = (hash[i] << (8-shift_right));
120 buf[i] = buf[i] ^ (hash[i] >> shift_right);
121 }
122 if ((err = mp_read_unsigned_bin(e, (unsigned char *)buf, pbytes)) != CRYPT_OK) { goto error; }
123 }
124
125 /* w = s^-1 mod n */
126 if ((err = mp_invmod(s, p, w)) != CRYPT_OK) { goto error; }
127
128 /* u1 = ew */
129 if ((err = mp_mulmod(e, w, p, u1)) != CRYPT_OK) { goto error; }
130
131 /* u2 = rw */
132 if ((err = mp_mulmod(r, w, p, u2)) != CRYPT_OK) { goto error; }
133
134 /* find mG and mQ */
135 if ((err = mp_read_radix(mG->x, (char *)key->dp->Gx, 16)) != CRYPT_OK) { goto error; }
136 if ((err = mp_read_radix(mG->y, (char *)key->dp->Gy, 16)) != CRYPT_OK) { goto error; }
137 if ((err = mp_set(mG->z, 1)) != CRYPT_OK) { goto error; }
138
139 if ((err = mp_copy(key->pubkey.x, mQ->x)) != CRYPT_OK) { goto error; }
140 if ((err = mp_copy(key->pubkey.y, mQ->y)) != CRYPT_OK) { goto error; }
141 if ((err = mp_copy(key->pubkey.z, mQ->z)) != CRYPT_OK) { goto error; }
142
143 /* compute u1*mG + u2*mQ = mG */
144 if (ltc_mp.ecc_mul2add == NULL) {
145 if ((err = ltc_mp.ecc_ptmul(u1, mG, mG, a, m, 0)) != CRYPT_OK) { goto error; }
146 if ((err = ltc_mp.ecc_ptmul(u2, mQ, mQ, a, m, 0)) != CRYPT_OK) { goto error; }
147
148 /* find the montgomery mp */
149 if ((err = mp_montgomery_setup(m, &mp)) != CRYPT_OK) { goto error; }
150
151 /* add them */
152 if ((err = ltc_mp.ecc_ptadd(mQ, mG, mG, a, m, mp)) != CRYPT_OK) { goto error; }
153
154 /* reduce */
155 if ((err = ltc_mp.ecc_map(mG, m, mp)) != CRYPT_OK) { goto error; }
156 } else {
157 /* use Shamir's trick to compute u1*mG + u2*mQ using half of the doubles */
158 if ((err = ltc_mp.ecc_mul2add(mG, u1, mQ, u2, mG, a, m)) != CRYPT_OK) { goto error; }
159 }
160
161 /* v = X_x1 mod n */
162 if ((err = mp_mod(mG->x, p, v)) != CRYPT_OK) { goto error; }
163
164 /* does v == r */
165 if (mp_cmp(v, r) == LTC_MP_EQ) {
166 *stat = 1;
167 }
168
169 /* clear up and return */
170 err = CRYPT_OK;
171 error:
172 ltc_ecc_del_point(mG);
173 ltc_ecc_del_point(mQ);
174 mp_clear_multi(r, s, v, w, u1, u2, p, e, m, a, NULL);
175 if (mp != NULL) {
176 mp_montgomery_free(mp);
177 }
178 return err;
179 }
32180
33181 /**
34182 Verify an ECC signature
44192 const unsigned char *hash, unsigned long hashlen,
45193 int *stat, ecc_key *key)
46194 {
47 ecc_point *mG, *mQ;
48 void *r, *s, *v, *w, *u1, *u2, *e, *p, *m, *a;
49 void *mp;
50 int err;
51 unsigned long pbits, pbytes, i, shift_right;
52 unsigned char ch, buf[MAXBLOCKSIZE];
53
54 LTC_ARGCHK(sig != NULL);
55 LTC_ARGCHK(hash != NULL);
56 LTC_ARGCHK(stat != NULL);
57 LTC_ARGCHK(key != NULL);
58
59 /* default to invalid signature */
60 *stat = 0;
61 mp = NULL;
62
63 /* is the IDX valid ? */
64 if (ltc_ecc_is_valid_idx(key->idx) != 1) {
65 return CRYPT_PK_INVALID_TYPE;
66 }
67
68 /* allocate ints */
69 if ((err = mp_init_multi(&r, &s, &v, &w, &u1, &u2, &p, &e, &m, &a, NULL)) != CRYPT_OK) {
70 return CRYPT_MEM;
71 }
72
73 /* allocate points */
74 mG = ltc_ecc_new_point();
75 mQ = ltc_ecc_new_point();
76 if (mQ == NULL || mG == NULL) {
77 err = CRYPT_MEM;
78 goto error;
79 }
80
81 /* parse header */
82 if ((err = der_decode_sequence_multi(sig, siglen,
83 LTC_ASN1_INTEGER, 1UL, r,
84 LTC_ASN1_INTEGER, 1UL, s,
85 LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
86 goto error;
87 }
88
89 /* get the order */
90 if ((err = mp_read_radix(p, (char *)key->dp->order, 16)) != CRYPT_OK) { goto error; }
91
92 /* get the modulus */
93 if ((err = mp_read_radix(m, (char *)key->dp->prime, 16)) != CRYPT_OK) { goto error; }
94
95 /* get the a */
96 if ((err = mp_read_radix(a, (char *)key->dp->A, 16)) != CRYPT_OK) { goto error; }
97
98 /* check for zero */
99 if (mp_iszero(r) || mp_iszero(s) || mp_cmp(r, p) != LTC_MP_LT || mp_cmp(s, p) != LTC_MP_LT) {
100 err = CRYPT_INVALID_PACKET;
101 goto error;
102 }
103
104 /* read hash - truncate if needed */
105 pbits = mp_count_bits(p);
106 pbytes = (pbits+7) >> 3;
107 if (pbits > hashlen*8) {
108 if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, hashlen)) != CRYPT_OK) { goto error; }
109 }
110 else if (pbits % 8 == 0) {
111 if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, pbytes)) != CRYPT_OK) { goto error; }
112 }
113 else {
114 shift_right = 8 - pbits % 8;
115 for (i=0, ch=0; i<pbytes; i++) {
116 buf[i] = ch;
117 ch = (hash[i] << (8-shift_right));
118 buf[i] = buf[i] ^ (hash[i] >> shift_right);
119 }
120 if ((err = mp_read_unsigned_bin(e, (unsigned char *)buf, pbytes)) != CRYPT_OK) { goto error; }
121 }
122
123 /* w = s^-1 mod n */
124 if ((err = mp_invmod(s, p, w)) != CRYPT_OK) { goto error; }
125
126 /* u1 = ew */
127 if ((err = mp_mulmod(e, w, p, u1)) != CRYPT_OK) { goto error; }
128
129 /* u2 = rw */
130 if ((err = mp_mulmod(r, w, p, u2)) != CRYPT_OK) { goto error; }
131
132 /* find mG and mQ */
133 if ((err = mp_read_radix(mG->x, (char *)key->dp->Gx, 16)) != CRYPT_OK) { goto error; }
134 if ((err = mp_read_radix(mG->y, (char *)key->dp->Gy, 16)) != CRYPT_OK) { goto error; }
135 if ((err = mp_set(mG->z, 1)) != CRYPT_OK) { goto error; }
136
137 if ((err = mp_copy(key->pubkey.x, mQ->x)) != CRYPT_OK) { goto error; }
138 if ((err = mp_copy(key->pubkey.y, mQ->y)) != CRYPT_OK) { goto error; }
139 if ((err = mp_copy(key->pubkey.z, mQ->z)) != CRYPT_OK) { goto error; }
140
141 /* compute u1*mG + u2*mQ = mG */
142 if (ltc_mp.ecc_mul2add == NULL) {
143 if ((err = ltc_mp.ecc_ptmul(u1, mG, mG, a, m, 0)) != CRYPT_OK) { goto error; }
144 if ((err = ltc_mp.ecc_ptmul(u2, mQ, mQ, a, m, 0)) != CRYPT_OK) { goto error; }
145
146 /* find the montgomery mp */
147 if ((err = mp_montgomery_setup(m, &mp)) != CRYPT_OK) { goto error; }
148
149 /* add them */
150 if ((err = ltc_mp.ecc_ptadd(mQ, mG, mG, a, m, mp)) != CRYPT_OK) { goto error; }
151
152 /* reduce */
153 if ((err = ltc_mp.ecc_map(mG, m, mp)) != CRYPT_OK) { goto error; }
154 } else {
155 /* use Shamir's trick to compute u1*mG + u2*mQ using half of the doubles */
156 if ((err = ltc_mp.ecc_mul2add(mG, u1, mQ, u2, mG, a, m)) != CRYPT_OK) { goto error; }
157 }
158
159 /* v = X_x1 mod n */
160 if ((err = mp_mod(mG->x, p, v)) != CRYPT_OK) { goto error; }
161
162 /* does v == r */
163 if (mp_cmp(v, r) == LTC_MP_EQ) {
164 *stat = 1;
165 }
166
167 /* clear up and return */
168 err = CRYPT_OK;
169 error:
170 ltc_ecc_del_point(mG);
171 ltc_ecc_del_point(mQ);
172 mp_clear_multi(r, s, v, w, u1, u2, p, e, m, a, NULL);
173 if (mp != NULL) {
174 mp_montgomery_free(mp);
175 }
176 return err;
195 return ecc_verify_hash_ex(sig, siglen, hash, hashlen, stat, key, 0);
196 }
197
198 /**
199 Verify an ECC signature in RFC7518 format
200 @param sig The signature to verify
201 @param siglen The length of the signature (octets)
202 @param hash The hash (message digest) that was signed
203 @param hashlen The length of the hash (octets)
204 @param stat Result of signature, 1==valid, 0==invalid
205 @param key The corresponding public ECC key
206 @return CRYPT_OK if successful (even if the signature is not valid)
207 */
208 int ecc_verify_hash_rfc7518(const unsigned char *sig, unsigned long siglen,
209 const unsigned char *hash, unsigned long hashlen,
210 int *stat, ecc_key *key)
211 {
212 return ecc_verify_hash_ex(sig, siglen, hash, hashlen, stat, key, 1);
177213 }
178214
179215 #endif
1111 ok($k->is_private, 'is_private cryptx_priv_ecc1.der');
1212 is($k->size, 32, 'size');
1313 is(uc($k->key2hash->{pub_x}), 'C068B754877A4AB328A569BAC6D464A81B17E527D2D652572ABB11BDA3572D50', 'key2hash');
14 is(uc($k->curve2hash->{prime}), 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F', 'curve2hash');
1415
1516 $k = Crypt::PK::ECC->new('t/data/cryptx_priv_ecc2.der');
1617 ok($k, 'load cryptx_priv_ecc2.der');
7172 ok(length $sig > 60, 'sign_message ' . length($sig));
7273 ok($pu1->verify_message($sig, "message"), 'verify_message');
7374
75 my $sig_rfc7518 = $pr1->sign_message_rfc7518("message");
76 ok(length $sig_rfc7518 > 60, 'sign_message_rfc7518 ' . length($sig_rfc7518));
77 ok($pu1->verify_message_rfc7518($sig_rfc7518, "message"), 'verify_message_rfc7518');
78
7479 my $hash = pack("H*","04624fae618e9ad0c5e479f62e1420c71fff34dd");
7580 $sig = $pr1->sign_hash($hash, 'SHA1');
7681 ok(length $sig > 60, 'sign_hash ' . length($sig));
121126 ok($k->is_private, "is_private $priv");
122127 is($k->size, 32, "size $priv");
123128 is(uc($k->key2hash->{pub_x}), 'A01532A3C0900053DE60FBEFEFCCA58793301598D308B41E6F4E364E388C2711', "key2hash $priv");
129 is(uc($k->curve2hash->{prime}), 'FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF', "curve2hash $priv");
124130 }
125131
126132 for my $pub (qw/openssl_ec-short.pub.pem openssl_ec-short.pub.der/) {