Ed25519.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. /*
  2. * Copyright (c) 2022, stelar7 <dudedbz@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Random.h>
  7. #include <LibCrypto/Curves/Curve25519.h>
  8. #include <LibCrypto/Curves/Ed25519.h>
  9. #include <LibCrypto/Hash/SHA2.h>
  10. namespace Crypto::Curves {
  11. // https://datatracker.ietf.org/doc/html/rfc8032#section-5.1.5
  12. ErrorOr<ByteBuffer> Ed25519::generate_private_key()
  13. {
  14. // The private key is 32 octets (256 bits, corresponding to b) of
  15. // cryptographically secure random data. See [RFC4086] for a discussion
  16. // about randomness.
  17. auto buffer = TRY(ByteBuffer::create_uninitialized(key_size()));
  18. fill_with_random(buffer);
  19. return buffer;
  20. }
  21. // https://datatracker.ietf.org/doc/html/rfc8032#section-5.1.5
  22. ErrorOr<ByteBuffer> Ed25519::generate_public_key(ReadonlyBytes private_key)
  23. {
  24. // The 32-byte public key is generated by the following steps.
  25. // 1. Hash the 32-byte private key using SHA-512, storing the digest in a 64-octet large buffer, denoted h.
  26. // Only the lower 32 bytes are used for generating the public key.
  27. auto digest = Crypto::Hash::SHA512::hash(private_key);
  28. // NOTE: we do these steps in the opposite order (since its easier to modify s)
  29. // 3. Interpret the buffer as the little-endian integer, forming a secret scalar s.
  30. memcpy(s, digest.data, 32);
  31. // 2. Prune the buffer:
  32. // The lowest three bits of the first octet are cleared,
  33. s[0] &= 0xF8;
  34. // the highest bit of the last octet is cleared,
  35. s[31] &= 0x7F;
  36. // and the second highest bit of the last octet is set.
  37. s[31] |= 0x40;
  38. // Perform a fixed-base scalar multiplication [s]B.
  39. point_multiply_scalar(&sb, s, &BASE_POINT);
  40. // 4. The public key A is the encoding of the point [s]B.
  41. // First, encode the y-coordinate (in the range 0 <= y < p) as a little-endian string of 32 octets.
  42. // The most significant bit of the final octet is always zero.
  43. // To form the encoding of the point [s]B, copy the least significant bit of the x coordinate
  44. // to the most significant bit of the final octet. The result is the public key.
  45. auto public_key = TRY(ByteBuffer::create_uninitialized(key_size()));
  46. encode_point(&sb, public_key.data());
  47. return public_key;
  48. }
  49. // https://datatracker.ietf.org/doc/html/rfc8032#section-5.1.6
  50. ErrorOr<ByteBuffer> Ed25519::sign(ReadonlyBytes public_key, ReadonlyBytes private_key, ReadonlyBytes message)
  51. {
  52. // 1. Hash the private key, 32 octets, using SHA-512.
  53. // Let h denote the resulting digest.
  54. auto h = Crypto::Hash::SHA512::hash(private_key);
  55. // Construct the secret scalar s from the first half of the digest,
  56. memcpy(s, h.data, 32);
  57. // NOTE: This is done later in step 4, but we can also do it here.
  58. s[0] &= 0xF8;
  59. s[31] &= 0x7F;
  60. s[31] |= 0x40;
  61. // and the corresponding public key A, as described in the previous section.
  62. // NOTE: The public key A is taken as input to this function.
  63. // Let prefix denote the second half of the hash digest, h[32],...,h[63].
  64. memcpy(p, h.data + 32, 32);
  65. // 2. Compute SHA-512(dom2(F, C) || p || PH(M)), where M is the message to be signed.
  66. Crypto::Hash::SHA512 hash;
  67. // NOTE: dom2(F, C) is a blank octet string when signing or verifying Ed25519
  68. hash.update(p, 32);
  69. // NOTE: PH(M) = M
  70. hash.update(message.data(), message.size());
  71. // Interpret the 64-octet digest as a little-endian integer r.
  72. // For efficiency, do this by first reducing r modulo L, the group order of B.
  73. auto digest = hash.digest();
  74. barrett_reduce(r, digest.data);
  75. // 3. Compute the point [r]B.
  76. point_multiply_scalar(&rb, r, &BASE_POINT);
  77. auto R = TRY(ByteBuffer::create_uninitialized(32));
  78. // Let the string R be the encoding of this point
  79. encode_point(&rb, R.data());
  80. // 4. Compute SHA512(dom2(F, C) || R || A || PH(M)),
  81. // NOTE: We can reuse hash here, since digest() calls reset()
  82. // NOTE: dom2(F, C) is a blank octet string when signing or verifying Ed25519
  83. hash.update(R.data(), R.size());
  84. // NOTE: A == public_key
  85. hash.update(public_key.data(), public_key.size());
  86. // NOTE: PH(M) = M
  87. hash.update(message.data(), message.size());
  88. digest = hash.digest();
  89. // and interpret the 64-octet digest as a little-endian integer k.
  90. memcpy(k, digest.data, 64);
  91. // 5. Compute S = (r + k * s) mod L. For efficiency, again reduce k modulo L first.
  92. barrett_reduce(p, k);
  93. multiply(k, k + 32, p, s, 32);
  94. barrett_reduce(p, k);
  95. add(s, p, r, 32);
  96. // modular reduction
  97. auto reduced_s = TRY(ByteBuffer::create_uninitialized(32));
  98. auto is_negative = subtract(p, s, Curve25519::BASE_POINT_L_ORDER, 32);
  99. select(reduced_s.data(), p, s, is_negative, 32);
  100. // 6. Form the signature of the concatenation of R (32 octets) and the little-endian encoding of S
  101. // (32 octets; the three most significant bits of the final octet are always zero).
  102. auto signature = TRY(ByteBuffer::copy(R));
  103. signature.append(reduced_s);
  104. return signature;
  105. }
  106. // https://datatracker.ietf.org/doc/html/rfc8032#section-5.1.7
  107. bool Ed25519::verify(ReadonlyBytes public_key, ReadonlyBytes signature, ReadonlyBytes message)
  108. {
  109. auto not_valid = false;
  110. // 1. To verify a signature on a message M using public key A,
  111. // with F being 0 for Ed25519ctx, 1 for Ed25519ph, and if Ed25519ctx or Ed25519ph is being used, C being the context
  112. // first split the signature into two 32-octet halves.
  113. // If any of the decodings fail (including S being out of range), the signature is invalid.
  114. // NOTE: We dont care about F, since we dont implement Ed25519ctx or Ed25519PH
  115. // NOTE: C is the internal state, so its not a parameter
  116. auto half_signature_size = signature_size() / 2;
  117. // Decode the first half as a point R
  118. memcpy(r, signature.data(), half_signature_size);
  119. // and the second half as an integer S, in the range 0 <= s < L.
  120. memcpy(s, signature.data() + half_signature_size, half_signature_size);
  121. // NOTE: Ed25519 and Ed448 signatures are not malleable due to the verification check that decoded S is smaller than l.
  122. // Without this check, one can add a multiple of l into a scalar part and still pass signature verification,
  123. // resulting in malleable signatures.
  124. auto is_negative = subtract(p, s, Curve25519::BASE_POINT_L_ORDER, half_signature_size);
  125. not_valid |= 1 ^ is_negative;
  126. // Decode the public key A as point A'.
  127. not_valid |= decode_point(&ka, public_key.data());
  128. // 2. Compute SHA512(dom2(F, C) || R || A || PH(M)), and interpret the 64-octet digest as a little-endian integer k.
  129. Crypto::Hash::SHA512 hash;
  130. // NOTE: dom2(F, C) is a blank octet string when signing or verifying Ed25519
  131. hash.update(r, half_signature_size);
  132. // NOTE: A == public_key
  133. hash.update(public_key.data(), key_size());
  134. // NOTE: PH(M) = M
  135. hash.update(message.data(), message.size());
  136. auto digest = hash.digest();
  137. auto k = digest.data;
  138. // 3. Check the group equation [8][S]B = [8]R + [8][k]A'.
  139. // It's sufficient, but not required, to instead check [S]B = R + [k]A'.
  140. // NOTE: For efficiency, do this by first reducing k modulo L.
  141. barrett_reduce(k, k);
  142. // NOTE: We check [S]B - [k]A' == R
  143. Curve25519::modular_subtract(ka.x, Curve25519::ZERO, ka.x);
  144. Curve25519::modular_subtract(ka.t, Curve25519::ZERO, ka.t);
  145. point_multiply_scalar(&sb, s, &BASE_POINT);
  146. point_multiply_scalar(&ka, k, &ka);
  147. point_add(&ka, &sb, &ka);
  148. encode_point(&ka, p);
  149. not_valid |= compare(p, r, half_signature_size);
  150. return !not_valid;
  151. }
  152. void Ed25519::point_double(Ed25519Point* result, Ed25519Point const* point)
  153. {
  154. Curve25519::modular_square(a, point->x);
  155. Curve25519::modular_square(b, point->y);
  156. Curve25519::modular_square(c, point->z);
  157. Curve25519::modular_add(c, c, c);
  158. Curve25519::modular_add(e, a, b);
  159. Curve25519::modular_add(f, point->x, point->y);
  160. Curve25519::modular_square(f, f);
  161. Curve25519::modular_subtract(f, e, f);
  162. Curve25519::modular_subtract(g, a, b);
  163. Curve25519::modular_add(h, c, g);
  164. Curve25519::modular_multiply(result->x, f, h);
  165. Curve25519::modular_multiply(result->y, e, g);
  166. Curve25519::modular_multiply(result->z, g, h);
  167. Curve25519::modular_multiply(result->t, e, f);
  168. }
  169. void Ed25519::point_multiply_scalar(Ed25519Point* result, u8 const* scalar, Ed25519Point const* point)
  170. {
  171. // Set U to the neutral element (0, 1, 1, 0)
  172. Curve25519::set(u.x, 0);
  173. Curve25519::set(u.y, 1);
  174. Curve25519::set(u.z, 1);
  175. Curve25519::set(u.t, 0);
  176. for (i32 i = Curve25519::BITS - 1; i >= 0; i--) {
  177. u8 b = (scalar[i / 8] >> (i % 8)) & 1;
  178. // Compute U = 2 * U
  179. point_double(&u, &u);
  180. // Compute V = U + P
  181. point_add(&v, &u, point);
  182. // If b is set, then U = V
  183. Curve25519::select(u.x, u.x, v.x, b);
  184. Curve25519::select(u.y, u.y, v.y, b);
  185. Curve25519::select(u.z, u.z, v.z, b);
  186. Curve25519::select(u.t, u.t, v.t, b);
  187. }
  188. Curve25519::copy(result->x, u.x);
  189. Curve25519::copy(result->y, u.y);
  190. Curve25519::copy(result->z, u.z);
  191. Curve25519::copy(result->t, u.t);
  192. }
  193. // https://datatracker.ietf.org/doc/html/rfc8032#section-5.1.2
  194. void Ed25519::encode_point(Ed25519Point* point, u8* data)
  195. {
  196. // Retrieve affine representation
  197. Curve25519::modular_multiply_inverse(point->z, point->z);
  198. Curve25519::modular_multiply(point->x, point->x, point->z);
  199. Curve25519::modular_multiply(point->y, point->y, point->z);
  200. Curve25519::set(point->z, 1);
  201. Curve25519::modular_multiply(point->t, point->x, point->y);
  202. // First, encode the y-coordinate (in the range 0 <= y < p) as a little-endian string of 32 octets.
  203. // The most significant bit of the final octet is always zero.
  204. Curve25519::export_state(point->y, data);
  205. // To form the encoding of the point [s]B,
  206. // copy the least significant bit of the x coordinate to the most significant bit of the final octet.
  207. data[31] |= (point->x[0] & 1) << 7;
  208. }
  209. void Ed25519::barrett_reduce(u8* result, u8 const* input)
  210. {
  211. // Barrett reduction b = 2^8 && k = 32
  212. u8 is_negative;
  213. u8 u[33];
  214. u8 v[33];
  215. multiply(NULL, u, input + 31, Curve25519::BARRETT_REDUCTION_QUOTIENT, 33);
  216. multiply(v, NULL, u, Curve25519::BASE_POINT_L_ORDER, 33);
  217. subtract(u, input, v, 33);
  218. is_negative = subtract(v, u, Curve25519::BASE_POINT_L_ORDER, 33);
  219. select(u, v, u, is_negative, 33);
  220. is_negative = subtract(v, u, Curve25519::BASE_POINT_L_ORDER, 33);
  221. select(u, v, u, is_negative, 33);
  222. copy(result, u, 32);
  223. }
  224. void Ed25519::multiply(u8* result_low, u8* result_high, u8 const* a, u8 const* b, u8 n)
  225. {
  226. // Comba's algorithm
  227. u32 temp = 0;
  228. for (u32 i = 0; i < n; i++) {
  229. for (u32 j = 0; j <= i; j++) {
  230. temp += (uint16_t)a[j] * b[i - j];
  231. }
  232. if (result_low != NULL) {
  233. result_low[i] = temp & 0xFF;
  234. }
  235. temp >>= 8;
  236. }
  237. if (result_high != NULL) {
  238. for (u32 i = n; i < (2 * n); i++) {
  239. for (u32 j = i + 1 - n; j < n; j++) {
  240. temp += (uint16_t)a[j] * b[i - j];
  241. }
  242. result_high[i - n] = temp & 0xFF;
  243. temp >>= 8;
  244. }
  245. }
  246. }
  247. void Ed25519::add(u8* result, u8 const* a, u8 const* b, u8 n)
  248. {
  249. // Compute R = A + B
  250. u16 temp = 0;
  251. for (u8 i = 0; i < n; i++) {
  252. temp += a[i];
  253. temp += b[i];
  254. result[i] = temp & 0xFF;
  255. temp >>= 8;
  256. }
  257. }
  258. u8 Ed25519::subtract(u8* result, u8 const* a, u8 const* b, u8 n)
  259. {
  260. i16 temp = 0;
  261. // Compute R = A - B
  262. for (i8 i = 0; i < n; i++) {
  263. temp += a[i];
  264. temp -= b[i];
  265. result[i] = temp & 0xFF;
  266. temp >>= 8;
  267. }
  268. // Return 1 if the result of the subtraction is negative
  269. return temp & 1;
  270. }
  271. void Ed25519::select(u8* r, u8 const* a, u8 const* b, u8 c, u8 n)
  272. {
  273. u8 mask = c - 1;
  274. for (u8 i = 0; i < n; i++) {
  275. r[i] = (a[i] & mask) | (b[i] & ~mask);
  276. }
  277. }
  278. // https://datatracker.ietf.org/doc/html/rfc8032#section-5.1.3
  279. u32 Ed25519::decode_point(Ed25519Point* point, u8 const* data)
  280. {
  281. u32 u[8];
  282. u32 v[8];
  283. u32 ret;
  284. u64 temp = 19;
  285. // 1. First, interpret the string as an integer in little-endian representation.
  286. // Bit 255 of this number is the least significant bit of the x-coordinate and denote this value x_0.
  287. u8 x0 = data[31] >> 7;
  288. // The y-coordinate is recovered simply by clearing this bit.
  289. Curve25519::import_state(point->y, data);
  290. point->y[7] &= 0x7FFFFFFF;
  291. // Compute U = Y + 19
  292. for (u32 i = 0; i < 8; i++) {
  293. temp += point->y[i];
  294. u[i] = temp & 0xFFFFFFFF;
  295. temp >>= 32;
  296. }
  297. // If the resulting value is >= p, decoding fails.
  298. ret = (u[7] >> 31) & 1;
  299. // 2. To recover the x-coordinate, the curve equation implies x^2 = (y^2 - 1) / (d y^2 + 1) (mod p).
  300. // The denominator is always non-zero mod p.
  301. // Let u = y^2 - 1 and v = d * y^2 + 1
  302. Curve25519::modular_square(v, point->y);
  303. Curve25519::modular_subtract_single(u, v, 1);
  304. Curve25519::modular_multiply(v, v, Curve25519::CURVE_D);
  305. Curve25519::modular_add_single(v, v, 1);
  306. // 3. Compute u = sqrt(u / v)
  307. ret |= Curve25519::modular_square_root(u, u, v);
  308. // If x = 0, and x_0 = 1, decoding fails.
  309. ret |= (Curve25519::compare(u, Curve25519::ZERO) ^ 1) & x0;
  310. // 4. Finally, use the x_0 bit to select the right square root.
  311. Curve25519::modular_subtract(v, Curve25519::ZERO, u);
  312. Curve25519::select(point->x, u, v, (x0 ^ u[0]) & 1);
  313. Curve25519::set(point->z, 1);
  314. Curve25519::modular_multiply(point->t, point->x, point->y);
  315. // Return 0 if the point has been successfully decoded, else 1
  316. return ret;
  317. }
  318. void Ed25519::point_add(Ed25519Point* result, Ed25519Point const* p, Ed25519Point const* q)
  319. {
  320. // Compute R = P + Q
  321. Curve25519::modular_add(c, p->y, p->x);
  322. Curve25519::modular_add(d, q->y, q->x);
  323. Curve25519::modular_multiply(a, c, d);
  324. Curve25519::modular_subtract(c, p->y, p->x);
  325. Curve25519::modular_subtract(d, q->y, q->x);
  326. Curve25519::modular_multiply(b, c, d);
  327. Curve25519::modular_multiply(c, p->z, q->z);
  328. Curve25519::modular_add(c, c, c);
  329. Curve25519::modular_multiply(d, p->t, q->t);
  330. Curve25519::modular_multiply(d, d, Curve25519::CURVE_D_2);
  331. Curve25519::modular_add(e, a, b);
  332. Curve25519::modular_subtract(f, a, b);
  333. Curve25519::modular_add(g, c, d);
  334. Curve25519::modular_subtract(h, c, d);
  335. Curve25519::modular_multiply(result->x, f, h);
  336. Curve25519::modular_multiply(result->y, e, g);
  337. Curve25519::modular_multiply(result->z, g, h);
  338. Curve25519::modular_multiply(result->t, e, f);
  339. }
  340. u8 Ed25519::compare(u8 const* a, u8 const* b, u8 n)
  341. {
  342. u8 mask = 0;
  343. for (u32 i = 0; i < n; i++) {
  344. mask |= a[i] ^ b[i];
  345. }
  346. // Return 0 if A = B, else 1
  347. return ((u8)(mask | (~mask + 1))) >> 7;
  348. }
  349. void Ed25519::copy(u8* a, u8 const* b, u32 n)
  350. {
  351. for (u32 i = 0; i < n; i++) {
  352. a[i] = b[i];
  353. }
  354. }
  355. }