edsign.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /* Edwards curve signature system
  2. * Daniel Beer <dlbeer@gmail.com>, 22 Apr 2014
  3. *
  4. * This file is in the public domain.
  5. */
  6. #include "ed25519.h"
  7. #include "sha512.h"
  8. #include "fprime.h"
  9. #include "edsign.h"
  10. #define EXPANDED_SIZE 64
  11. static const uint8_t ed25519_order[FPRIME_SIZE] = {
  12. 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
  13. 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
  14. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  15. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10
  16. };
  17. static void expand_key(uint8_t *expanded, const uint8_t *secret)
  18. {
  19. struct sha512_state s;
  20. sha512_init(&s);
  21. sha512_add(&s, secret, EDSIGN_SECRET_KEY_SIZE);
  22. sha512_final(&s, expanded);
  23. ed25519_prepare(expanded);
  24. }
  25. static uint8_t upp(struct ed25519_pt *p, const uint8_t *packed)
  26. {
  27. uint8_t x[F25519_SIZE];
  28. uint8_t y[F25519_SIZE];
  29. uint8_t ok = ed25519_try_unpack(x, y, packed);
  30. ed25519_project(p, x, y);
  31. return ok;
  32. }
  33. static void pp(uint8_t *packed, const struct ed25519_pt *p)
  34. {
  35. uint8_t x[F25519_SIZE];
  36. uint8_t y[F25519_SIZE];
  37. ed25519_unproject(x, y, p);
  38. ed25519_pack(packed, x, y);
  39. }
  40. static void sm_pack(uint8_t *r, const uint8_t *k)
  41. {
  42. struct ed25519_pt p;
  43. ed25519_smult(&p, &ed25519_base, k);
  44. pp(r, &p);
  45. }
  46. void edsign_sec_to_pub(void *pub, const void *secret)
  47. {
  48. uint8_t expanded[EXPANDED_SIZE];
  49. expand_key(expanded, secret);
  50. sm_pack(pub, expanded);
  51. }
  52. static void save_hash(struct sha512_state *s, uint8_t *out)
  53. {
  54. void *hash;
  55. hash = sha512_final_get(s);
  56. fprime_from_bytes(out, hash, SHA512_HASH_SIZE, ed25519_order);
  57. }
  58. static void generate_k(uint8_t *k, const uint8_t *kgen_key,
  59. const uint8_t *message, size_t len)
  60. {
  61. struct sha512_state s;
  62. sha512_init(&s);
  63. sha512_add(&s, kgen_key, 32);
  64. sha512_add(&s, message, len);
  65. save_hash(&s, k);
  66. }
  67. static void hash_message(uint8_t *z, const uint8_t *r, const uint8_t *a,
  68. const uint8_t *m, size_t len)
  69. {
  70. struct sha512_state s;
  71. sha512_init(&s);
  72. sha512_add(&s, r, 32);
  73. sha512_add(&s, a, 32);
  74. sha512_add(&s, m, len);
  75. save_hash(&s, z);
  76. }
  77. void edsign_sign(uint8_t *signature, const uint8_t *pub,
  78. const uint8_t *secret,
  79. const uint8_t *message, size_t len)
  80. {
  81. uint8_t expanded[EXPANDED_SIZE];
  82. uint8_t e[FPRIME_SIZE];
  83. uint8_t s[FPRIME_SIZE];
  84. uint8_t k[FPRIME_SIZE];
  85. uint8_t z[FPRIME_SIZE];
  86. expand_key(expanded, secret);
  87. /* Generate k and R = kB */
  88. generate_k(k, expanded + 32, message, len);
  89. sm_pack(signature, k);
  90. /* Compute z = H(R, A, M) */
  91. hash_message(z, signature, pub, message, len);
  92. /* Obtain e */
  93. fprime_from_bytes(e, expanded, 32, ed25519_order);
  94. /* Compute s = ze + k */
  95. fprime_mul(s, z, e, ed25519_order);
  96. fprime_add(s, k, ed25519_order);
  97. memcpy(signature + 32, s, 32);
  98. }
  99. void edsign_verify_init(struct edsign_verify_state *st, const void *sig,
  100. const void *pub)
  101. {
  102. sha512_init(&st->sha);
  103. sha512_add(&st->sha, sig, 32);
  104. sha512_add(&st->sha, pub, 32);
  105. }
  106. bool edsign_verify(struct edsign_verify_state *st, const void *sig, const void *pub)
  107. {
  108. struct ed25519_pt p;
  109. struct ed25519_pt q;
  110. uint8_t lhs[F25519_SIZE];
  111. uint8_t rhs[F25519_SIZE];
  112. uint8_t z[FPRIME_SIZE];
  113. uint8_t ok = 1;
  114. /* Compute z = H(R, A, M) */
  115. save_hash(&st->sha, z);
  116. /* sB = (ze + k)B = ... */
  117. sm_pack(lhs, sig + 32);
  118. /* ... = zA + R */
  119. ok &= upp(&p, pub);
  120. ed25519_smult(&p, &p, z);
  121. ok &= upp(&q, sig);
  122. ed25519_add(&p, &p, &q);
  123. pp(rhs, &p);
  124. /* Equal? */
  125. return ok & f25519_eq(lhs, rhs);
  126. }