]>
Commit | Line | Data |
---|---|---|
7a4b7691 PW |
1 | #ifndef _SECP256K1_ECDSA_IMPL_H_ |
2 | #define _SECP256K1_ECDSA_IMPL_H_ | |
3 | ||
4 | #include "../num.h" | |
5 | #include "../field.h" | |
6 | #include "../group.h" | |
7 | #include "../ecmult.h" | |
8 | #include "../ecdsa.h" | |
607884fc | 9 | |
d41e93a5 PW |
10 | void static secp256k1_ecdsa_sig_init(secp256k1_ecdsa_sig_t *r) { |
11 | secp256k1_num_init(&r->r); | |
12 | secp256k1_num_init(&r->s); | |
13 | } | |
14 | ||
15 | void static secp256k1_ecdsa_sig_free(secp256k1_ecdsa_sig_t *r) { | |
16 | secp256k1_num_free(&r->r); | |
17 | secp256k1_num_free(&r->s); | |
18 | } | |
19 | ||
764332d0 | 20 | int static secp256k1_ecdsa_pubkey_parse(secp256k1_ge_t *elem, const unsigned char *pub, int size) { |
607884fc | 21 | if (size == 33 && (pub[0] == 0x02 || pub[0] == 0x03)) { |
910d0de4 PW |
22 | secp256k1_fe_t x; |
23 | secp256k1_fe_set_b32(&x, pub+1); | |
764332d0 | 24 | secp256k1_ge_set_xo(elem, &x, pub[0] == 0x03); |
607884fc | 25 | } else if (size == 65 && (pub[0] == 0x04 || pub[0] == 0x06 || pub[0] == 0x07)) { |
d41e93a5 | 26 | secp256k1_fe_t x, y; |
910d0de4 PW |
27 | secp256k1_fe_set_b32(&x, pub+1); |
28 | secp256k1_fe_set_b32(&y, pub+33); | |
764332d0 | 29 | secp256k1_ge_set_xy(elem, &x, &y); |
910d0de4 | 30 | if ((pub[0] == 0x06 || pub[0] == 0x07) && secp256k1_fe_is_odd(&y) != (pub[0] == 0x07)) |
eb0be8ee | 31 | return 0; |
607884fc | 32 | } else { |
eb0be8ee | 33 | return 0; |
607884fc | 34 | } |
764332d0 | 35 | return secp256k1_ge_is_valid(elem); |
607884fc PW |
36 | } |
37 | ||
d41e93a5 PW |
38 | int static secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned char *sig, int size) { |
39 | if (sig[0] != 0x30) return 0; | |
607884fc | 40 | int lenr = sig[3]; |
d41e93a5 | 41 | if (5+lenr >= size) return 0; |
607884fc | 42 | int lens = sig[lenr+5]; |
d41e93a5 PW |
43 | if (sig[1] != lenr+lens+4) return 0; |
44 | if (lenr+lens+6 > size) return 0; | |
45 | if (sig[2] != 0x02) return 0; | |
46 | if (lenr == 0) return 0; | |
47 | if (sig[lenr+4] != 0x02) return 0; | |
48 | if (lens == 0) return 0; | |
49 | secp256k1_num_set_bin(&r->r, sig+4, lenr); | |
50 | secp256k1_num_set_bin(&r->s, sig+6+lenr, lens); | |
51 | return 1; | |
607884fc PW |
52 | } |
53 | ||
d41e93a5 PW |
54 | int static secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_ecdsa_sig_t *a) { |
55 | int lenR = (secp256k1_num_bits(&a->r) + 7)/8; | |
56 | if (lenR == 0 || secp256k1_num_get_bit(&a->r, lenR*8-1)) | |
0a07e62f | 57 | lenR++; |
d41e93a5 PW |
58 | int lenS = (secp256k1_num_bits(&a->s) + 7)/8; |
59 | if (lenS == 0 || secp256k1_num_get_bit(&a->s, lenS*8-1)) | |
0a07e62f PW |
60 | lenS++; |
61 | if (*size < 6+lenS+lenR) | |
d41e93a5 | 62 | return 0; |
0a07e62f PW |
63 | *size = 6 + lenS + lenR; |
64 | sig[0] = 0x30; | |
65 | sig[1] = 4 + lenS + lenR; | |
66 | sig[2] = 0x02; | |
67 | sig[3] = lenR; | |
d41e93a5 | 68 | secp256k1_num_get_bin(sig+4, lenR, &a->r); |
0a07e62f PW |
69 | sig[4+lenR] = 0x02; |
70 | sig[5+lenR] = lenS; | |
d41e93a5 PW |
71 | secp256k1_num_get_bin(sig+lenR+6, lenS, &a->s); |
72 | return 1; | |
0a07e62f PW |
73 | } |
74 | ||
764332d0 | 75 | int static secp256k1_ecdsa_sig_recompute(secp256k1_num_t *r2, const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_num_t *message) { |
d41e93a5 | 76 | const secp256k1_ge_consts_t *c = secp256k1_ge_consts; |
607884fc | 77 | |
d41e93a5 PW |
78 | if (secp256k1_num_is_neg(&sig->r) || secp256k1_num_is_neg(&sig->s)) |
79 | return 0; | |
80 | if (secp256k1_num_is_zero(&sig->r) || secp256k1_num_is_zero(&sig->s)) | |
81 | return 0; | |
82 | if (secp256k1_num_cmp(&sig->r, &c->order) >= 0 || secp256k1_num_cmp(&sig->s, &c->order) >= 0) | |
83 | return 0; | |
607884fc | 84 | |
d41e93a5 | 85 | int ret = 0; |
4adf6b2a PW |
86 | secp256k1_num_t sn, u1, u2; |
87 | secp256k1_num_init(&sn); | |
88 | secp256k1_num_init(&u1); | |
89 | secp256k1_num_init(&u2); | |
d41e93a5 PW |
90 | secp256k1_num_mod_inverse(&sn, &sig->s, &c->order); |
91 | secp256k1_num_mod_mul(&u1, &sn, message, &c->order); | |
92 | secp256k1_num_mod_mul(&u2, &sn, &sig->r, &c->order); | |
764332d0 PW |
93 | secp256k1_gej_t pubkeyj; secp256k1_gej_set_ge(&pubkeyj, pubkey); |
94 | secp256k1_gej_t pr; secp256k1_ecmult(&pr, &pubkeyj, &u2, &u1); | |
f11ff5be PW |
95 | if (!secp256k1_gej_is_infinity(&pr)) { |
96 | secp256k1_fe_t xr; secp256k1_gej_get_x(&xr, &pr); | |
910d0de4 PW |
97 | secp256k1_fe_normalize(&xr); |
98 | unsigned char xrb[32]; secp256k1_fe_get_b32(xrb, &xr); | |
d41e93a5 | 99 | secp256k1_num_set_bin(r2, xrb, 32); |
2f9e831d | 100 | secp256k1_num_mod(r2, &c->order); |
d41e93a5 | 101 | ret = 1; |
4adf6b2a PW |
102 | } |
103 | secp256k1_num_free(&sn); | |
104 | secp256k1_num_free(&u1); | |
105 | secp256k1_num_free(&u2); | |
106 | return ret; | |
607884fc PW |
107 | } |
108 | ||
764332d0 | 109 | int static secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_num_t *message) { |
4adf6b2a PW |
110 | secp256k1_num_t r2; |
111 | secp256k1_num_init(&r2); | |
d41e93a5 PW |
112 | int ret = 0; |
113 | ret = secp256k1_ecdsa_sig_recompute(&r2, sig, pubkey, message) && secp256k1_num_cmp(&sig->r, &r2) == 0; | |
4adf6b2a PW |
114 | secp256k1_num_free(&r2); |
115 | return ret; | |
607884fc PW |
116 | } |
117 | ||
d41e93a5 PW |
118 | int static secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *seckey, const secp256k1_num_t *message, const secp256k1_num_t *nonce) { |
119 | const secp256k1_ge_consts_t *c = secp256k1_ge_consts; | |
0a07e62f | 120 | |
f11ff5be | 121 | secp256k1_gej_t rp; |
d41e93a5 | 122 | secp256k1_ecmult_gen(&rp, nonce); |
910d0de4 | 123 | secp256k1_fe_t rx; |
f11ff5be | 124 | secp256k1_gej_get_x(&rx, &rp); |
0a07e62f | 125 | unsigned char b[32]; |
910d0de4 PW |
126 | secp256k1_fe_normalize(&rx); |
127 | secp256k1_fe_get_b32(b, &rx); | |
d41e93a5 | 128 | secp256k1_num_set_bin(&sig->r, b, 32); |
2f9e831d | 129 | secp256k1_num_mod(&sig->r, &c->order); |
4adf6b2a PW |
130 | secp256k1_num_t n; |
131 | secp256k1_num_init(&n); | |
d41e93a5 PW |
132 | secp256k1_num_mod_mul(&n, &sig->r, seckey, &c->order); |
133 | secp256k1_num_add(&n, &n, message); | |
2f9e831d | 134 | secp256k1_num_mod(&n, &c->order); |
d41e93a5 PW |
135 | secp256k1_num_mod_inverse(&sig->s, nonce, &c->order); |
136 | secp256k1_num_mod_mul(&sig->s, &sig->s, &n, &c->order); | |
4adf6b2a | 137 | secp256k1_num_free(&n); |
d41e93a5 PW |
138 | if (secp256k1_num_is_zero(&sig->s)) |
139 | return 0; | |
140 | if (secp256k1_num_is_odd(&sig->s)) | |
141 | secp256k1_num_sub(&sig->s, &c->order, &sig->s); | |
eb0be8ee | 142 | return 1; |
0a07e62f PW |
143 | } |
144 | ||
d41e93a5 PW |
145 | void static secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *r, const secp256k1_num_t *s) { |
146 | secp256k1_num_copy(&sig->r, r); | |
147 | secp256k1_num_copy(&sig->s, s); | |
607884fc | 148 | } |
7a4b7691 | 149 | |
42cccdaf PW |
150 | void static secp256k1_ecdsa_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, int *size, int compressed) { |
151 | secp256k1_fe_normalize(&elem->x); | |
152 | secp256k1_fe_normalize(&elem->y); | |
153 | secp256k1_fe_get_b32(&pub[1], &elem->x); | |
154 | if (compressed) { | |
155 | *size = 33; | |
156 | pub[0] = 0x02 | (secp256k1_fe_is_odd(&elem->y) ? 0x01 : 0x00); | |
157 | } else { | |
158 | *size = 65; | |
159 | pub[0] = 0x04; | |
160 | secp256k1_fe_get_b32(&pub[33], &elem->y); | |
161 | } | |
162 | } | |
163 | ||
7a4b7691 | 164 | #endif |