You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

201 lines
7.1 KiB

  1. /**
  2. * @file ristretto.cxx
  3. * @author Mike Hamburg
  4. *
  5. * @copyright
  6. * Copyright (c) 2015 Cryptography Research, Inc. \n
  7. * Released under the MIT License. See LICENSE.txt for license information.
  8. *
  9. * @brief Ristretto implementation widget
  10. */
  11. #include <decaf.hxx>
  12. #include <stdio.h>
  13. using namespace decaf;
  14. inline int hexi(char c) {
  15. if (c >= '0' && c <= '9') return c-'0';
  16. if (c >= 'a' && c <= 'f') return c-'a'+0xa;
  17. if (c >= 'A' && c <= 'F') return c-'A'+0xa;
  18. return -1;
  19. }
  20. int parsehex(uint8_t *out, size_t sizeof_out, const char *hex) {
  21. size_t l = strlen(hex);
  22. if (l%2 != 0) {
  23. fprintf(stderr,"String should be hex, but has odd length\n: %s\n", hex);
  24. return -1;
  25. } else if (l/2 > sizeof_out) {
  26. fprintf(stderr,"Argument is too long: %s\n", hex);
  27. return -1;
  28. }
  29. memset(out,0,sizeof_out);
  30. int ret1,ret2;
  31. for (size_t i=0; i<l/2; i++) {
  32. if ( (ret1 = hexi(hex[2*i ])) < 0
  33. || (ret2 = hexi(hex[2*i+1])) < 0) {
  34. fprintf(stderr,"Invalid hex %s\n",hex);
  35. return -1;
  36. }
  37. out[i] = ret1*16+ret2;
  38. }
  39. return 0;
  40. }
  41. void printhex(const uint8_t *in, size_t sizeof_in) {
  42. for (; sizeof_in > 0; in++,sizeof_in--) {
  43. printf("%02x",*in);
  44. }
  45. }
  46. static int g_argc = 0;
  47. static char **g_argv = NULL;
  48. static int error = 0;
  49. static int done = 0;
  50. void usage() {
  51. const char *me=g_argv[0];
  52. if (!me) me = "ristretto";
  53. for (unsigned i=0; g_argv[0][i]; i++) {
  54. if (g_argv[0][i] == '/' && g_argv[0][i+1] != 0 && g_argv[0][i+1] != '/') {
  55. me = &g_argv[0][i];
  56. }
  57. }
  58. fprintf(stderr,"Usage: %s [points] [operations] ...\n", me);
  59. fprintf(stderr," -b 255|448: Set which group to use (sometimes inferred from lengths)\n");
  60. fprintf(stderr," -E: Display output as Elligator inverses\n");
  61. fprintf(stderr," -D: Display output in EdDSA format (times clearing ratio)\n");
  62. fprintf(stderr," -R: Display raw xyzt\n");
  63. //fprintf(stderr," -C: Display output in X[25519|448] format\n");
  64. fprintf(stderr," -H: ... divide by clearing ratio first\n");
  65. fprintf(stderr,"\n");
  66. fprintf(stderr," Ways to create points:\n");
  67. fprintf(stderr," [hex]: Point from point data as hex\n");
  68. fprintf(stderr," -e [hex]: Create point by hashing to curve using elligator\n");
  69. fprintf(stderr," base: Base point of curve\n");
  70. fprintf(stderr," identity: Identity point of curve\n");
  71. fprintf(stderr,"\n");
  72. fprintf(stderr," Operations:\n");
  73. fprintf(stderr," -n [point]: negative of point\n");
  74. fprintf(stderr," -s [scalar] * [point]: Hash to curve using elligator\n");
  75. fprintf(stderr," [point] + [point]: Add two points\n");
  76. fprintf(stderr,"\n");
  77. fprintf(stderr," NB: this is a debugging widget. It doesn't yet have order of operations.\n");
  78. fprintf(stderr," *** DON'T USE THIS UTILITY FOR ACTUAL CRYPTO! ***\n");
  79. fprintf(stderr," It's only for debugging!\n");
  80. fprintf(stderr,"\n");
  81. exit(-2);
  82. }
  83. template<typename Group> class Run {
  84. public:
  85. static void run() {
  86. uint8_t tmp[Group::Point::SER_BYTES];
  87. typename Group::Point a,b;
  88. typename Group::Scalar s;
  89. bool plus=false, empty=true, elligator=false, mul=false, scalar=false,
  90. scalarempty=true, neg=false, einv=false, like_eddsa=false, decoeff=false, raw=false;
  91. if (done || error) return;
  92. for (int i=1; i<g_argc && !error; i++) {
  93. bool point = false;
  94. if (!strcmp(g_argv[i],"-b") && ++i<g_argc) {
  95. if (atoi(g_argv[i]) == Group::bits()) continue;
  96. else return;
  97. } else if (!strcmp(g_argv[i],"+")) {
  98. if (elligator || scalar || empty) usage();
  99. plus = true;
  100. } else if (!strcmp(g_argv[i],"-n")) {
  101. neg = !neg;
  102. } else if (!strcmp(g_argv[i],"-E")) {
  103. einv = true;
  104. } else if (!strcmp(g_argv[i],"-R")) {
  105. raw = true;
  106. } else if (!strcmp(g_argv[i],"-D")) {
  107. like_eddsa = true;
  108. } else if (!strcmp(g_argv[i],"-H")) {
  109. decoeff = true;
  110. } else if (!strcmp(g_argv[i],"*")) {
  111. if (elligator || scalar || scalarempty) usage();
  112. mul = true;
  113. } else if (!strcmp(g_argv[i],"-s")) {
  114. if (elligator || scalar || !scalarempty) usage();
  115. scalar = true;
  116. } else if (!strcmp(g_argv[i],"-e")) {
  117. if (elligator || scalar) usage();
  118. elligator = true;
  119. } else if (!strcmp(g_argv[i],"base")) {
  120. if (elligator || scalar) usage();
  121. b = b.base();
  122. point = true;
  123. } else if (!strcmp(g_argv[i],"identity")) {
  124. if (elligator || scalar) usage();
  125. b = b.identity();
  126. point = true;
  127. } else if ((strlen(g_argv[i]) == 2*sizeof(tmp)
  128. || ((scalar || elligator) && strlen(g_argv[i]) <= 2*sizeof(tmp)))
  129. && !(error=parsehex(tmp,sizeof(tmp),g_argv[i]))) {
  130. if (scalar) {
  131. s = Block(tmp,sizeof(tmp)); scalar=false; scalarempty=false;
  132. } else if (elligator) {
  133. point = true;
  134. b.set_to_hash(Block(tmp,sizeof(tmp))); elligator=false;
  135. } else if (DECAF_SUCCESS != b.decode(Block(tmp,sizeof(tmp)))) {
  136. fprintf(stderr,"Error: %s isn't in the group\n",g_argv[i]);
  137. error = -1;
  138. } else {
  139. point = true;
  140. }
  141. } else if (error || !empty) usage();
  142. if (point) {
  143. if (neg) { b = -b; neg = false; }
  144. if (mul) { b *= s; mul=false; }
  145. if (empty) { a = b; empty=false; }
  146. else if (plus) { a += b; plus=false; }
  147. else usage();
  148. }
  149. }
  150. if (!error && !empty) {
  151. if (decoeff) a /= (Group::EDDSA_RATIO);
  152. if (einv) {
  153. uint8_t buffer[Group::Point::HASH_BYTES];
  154. for (int h=0; h<1<<Group::Point::INVERT_ELLIGATOR_WHICH_BITS; h++) {
  155. if (DECAF_SUCCESS == a.invert_elligator(
  156. Buffer(buffer,sizeof(buffer)), h
  157. )) {
  158. printhex(buffer,sizeof(buffer));
  159. printf("\n");
  160. }
  161. }
  162. } else if (raw) {
  163. printhex((const uint8_t *)&a, sizeof(a));
  164. printf("\n");
  165. } else if (like_eddsa) {
  166. SecureBuffer b = a.mul_by_cofactor_and_encode_like_eddsa();
  167. printhex(b.data(),b.size());
  168. printf("\n");
  169. } else {
  170. a.serialize_into(tmp);
  171. printhex(tmp,sizeof(tmp));
  172. printf("\n");
  173. }
  174. done = true;
  175. }
  176. }
  177. };
  178. int main(int argc, char **argv) {
  179. g_argc = argc;
  180. g_argv = argv;
  181. run_for_all_curves<Run>();
  182. if (!done) usage();
  183. return (error<0) ? -error : error;
  184. }