ed25519.c (3687B)
1 /* 2 Public domain by Andrew M. <liquidsun@gmail.com> 3 4 Ed25519 reference implementation using Ed25519-donna 5 */ 6 7 8 /* define ED25519_SUFFIX to have it appended to the end of each public function */ 9 #if !defined(ED25519_SUFFIX) 10 #define ED25519_SUFFIX 11 #endif 12 13 #define ED25519_FN3(fn,suffix) fn##suffix 14 #define ED25519_FN2(fn,suffix) ED25519_FN3(fn,suffix) 15 #define ED25519_FN(fn) ED25519_FN2(fn,ED25519_SUFFIX) 16 17 #include "ed25519-donna.h" 18 #include "ed25519.h" 19 #include "ed25519-randombytes.h" 20 #include "ed25519-hash.h" 21 22 /* 23 Generates a (extsk[0..31]) and aExt (extsk[32..63]) 24 */ 25 26 DONNA_INLINE static void 27 ed25519_extsk(hash_512bits extsk, const ed25519_secret_key sk) { 28 ed25519_hash(extsk, sk, 32); 29 extsk[0] &= 248; 30 extsk[31] &= 127; 31 extsk[31] |= 64; 32 } 33 34 static void 35 ed25519_hram(hash_512bits hram, const ed25519_signature RS, const ed25519_public_key pk, const unsigned char *m, size_t mlen) { 36 ed25519_hash_context ctx; 37 ed25519_hash_init(&ctx); 38 ed25519_hash_update(&ctx, RS, 32); 39 ed25519_hash_update(&ctx, pk, 32); 40 ed25519_hash_update(&ctx, m, mlen); 41 ed25519_hash_final(&ctx, hram); 42 } 43 44 void 45 ED25519_FN(ed25519_publickey) (const ed25519_secret_key sk, ed25519_public_key pk) { 46 bignum256modm a; 47 ge25519 ALIGN(16) A; 48 hash_512bits extsk; 49 50 /* A = aB */ 51 ed25519_extsk(extsk, sk); 52 expand256_modm(a, extsk, 32); 53 ge25519_scalarmult_base_niels(&A, ge25519_niels_base_multiples, a); 54 ge25519_pack(pk, &A); 55 } 56 57 58 void 59 ED25519_FN(ed25519_sign) (const unsigned char *m, size_t mlen, const ed25519_secret_key sk, const ed25519_public_key pk, ed25519_signature RS) { 60 ed25519_hash_context ctx; 61 bignum256modm r, S, a; 62 ge25519 ALIGN(16) R; 63 hash_512bits extsk, hashr, hram; 64 65 ed25519_extsk(extsk, sk); 66 67 /* r = H(aExt[32..64], m) */ 68 ed25519_hash_init(&ctx); 69 ed25519_hash_update(&ctx, extsk + 32, 32); 70 ed25519_hash_update(&ctx, m, mlen); 71 ed25519_hash_final(&ctx, hashr); 72 expand256_modm(r, hashr, 64); 73 74 /* R = rB */ 75 ge25519_scalarmult_base_niels(&R, ge25519_niels_base_multiples, r); 76 ge25519_pack(RS, &R); 77 78 /* S = H(R,A,m).. */ 79 ed25519_hram(hram, RS, pk, m, mlen); 80 expand256_modm(S, hram, 64); 81 82 /* S = H(R,A,m)a */ 83 expand256_modm(a, extsk, 32); 84 mul256_modm(S, S, a); 85 86 /* S = (r + H(R,A,m)a) */ 87 add256_modm(S, S, r); 88 89 /* S = (r + H(R,A,m)a) mod L */ 90 contract256_modm(RS + 32, S); 91 } 92 93 int 94 ED25519_FN(ed25519_sign_open) (const unsigned char *m, size_t mlen, const ed25519_public_key pk, const ed25519_signature RS) { 95 ge25519 ALIGN(16) R, A; 96 hash_512bits hash; 97 bignum256modm hram, S; 98 unsigned char checkR[32]; 99 100 if ((RS[63] & 224) || !ge25519_unpack_negative_vartime(&A, pk)) 101 return -1; 102 103 /* hram = H(R,A,m) */ 104 ed25519_hram(hash, RS, pk, m, mlen); 105 expand256_modm(hram, hash, 64); 106 107 /* S */ 108 expand256_modm(S, RS + 32, 32); 109 110 /* SB - H(R,A,m)A */ 111 ge25519_double_scalarmult_vartime(&R, &A, hram, S); 112 ge25519_pack(checkR, &R); 113 114 /* check that R = SB - H(R,A,m)A */ 115 return ed25519_verify(RS, checkR, 32) ? 0 : -1; 116 } 117 118 #include "ed25519-donna-batchverify.h" 119 120 /* 121 Fast Curve25519 basepoint scalar multiplication 122 */ 123 124 void 125 ED25519_FN(curved25519_scalarmult_basepoint) (curved25519_key pk, const curved25519_key e) { 126 curved25519_key ec; 127 bignum256modm s; 128 bignum25519 ALIGN(16) yplusz, zminusy; 129 ge25519 ALIGN(16) p; 130 size_t i; 131 132 /* clamp */ 133 for (i = 0; i < 32; i++) ec[i] = e[i]; 134 ec[0] &= 248; 135 ec[31] &= 127; 136 ec[31] |= 64; 137 138 expand_raw256_modm(s, ec); 139 140 /* scalar * basepoint */ 141 ge25519_scalarmult_base_niels(&p, ge25519_niels_base_multiples, s); 142 143 /* u = (y + z) / (z - y) */ 144 curve25519_add(yplusz, p.y, p.z); 145 curve25519_sub(zminusy, p.z, p.y); 146 curve25519_recip(zminusy, zminusy); 147 curve25519_mul(yplusz, yplusz, zminusy); 148 curve25519_contract(pk, yplusz); 149 }