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.
 
 
 
 
 

215 lines
7.9 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. static 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. static 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. static 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. static 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 encoding 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, div=false, torque=false,
  90. scalarempty=true, neg=false, einv=false, like_eddsa=false, like_x=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],"-C")) {
  109. like_x = true;
  110. } else if (!strcmp(g_argv[i],"-H")) {
  111. decoeff = true;
  112. } else if (!strcmp(g_argv[i],"-T")) {
  113. torque = true;
  114. } else if (!strcmp(g_argv[i],"*")) {
  115. if (elligator || scalar || scalarempty || div) usage();
  116. mul = true;
  117. } else if (!strcmp(g_argv[i],"/")) {
  118. if (elligator || scalar || scalarempty || mul) usage();
  119. div = true;
  120. } else if (!strcmp(g_argv[i],"-s")) {
  121. if (elligator || scalar || !scalarempty) usage();
  122. scalar = true;
  123. } else if (!strcmp(g_argv[i],"-e")) {
  124. if (elligator || scalar) usage();
  125. elligator = true;
  126. } else if (!strcmp(g_argv[i],"base")) {
  127. if (elligator || scalar) usage();
  128. b = b.base();
  129. point = true;
  130. } else if (!strcmp(g_argv[i],"identity")) {
  131. if (elligator || scalar) usage();
  132. b = b.identity();
  133. point = true;
  134. } else if ((strlen(g_argv[i]) == 2*sizeof(tmp)
  135. || ((scalar || elligator) && strlen(g_argv[i]) <= 2*sizeof(tmp)))
  136. && !(error=parsehex(tmp,sizeof(tmp),g_argv[i]))) {
  137. if (scalar) {
  138. s = Block(tmp,sizeof(tmp)); scalar=false; scalarempty=false;
  139. } else if (elligator) {
  140. point = true;
  141. b.set_to_hash(Block(tmp,sizeof(tmp))); elligator=false;
  142. } else if (DECAF_SUCCESS != b.decode(Block(tmp,sizeof(tmp)))) {
  143. fprintf(stderr,"Error: %s isn't in the group\n",g_argv[i]);
  144. error = -1;
  145. } else {
  146. point = true;
  147. }
  148. } else if (error || !empty) usage();
  149. if (point) {
  150. if (neg) { b = -b; neg = false; }
  151. if (div) { b /= s; div=false; }
  152. if (torque) { b = b.debugging_torque(); torque=false; }
  153. if (mul) { b *= s; mul=false; }
  154. if (empty) { a = b; empty=false; }
  155. else if (plus) { a += b; plus=false; }
  156. else usage();
  157. }
  158. }
  159. if (!error && !empty) {
  160. if (einv) {
  161. uint8_t buffer[Group::Point::HASH_BYTES];
  162. for (int h=0; h<1<<Group::Point::INVERT_ELLIGATOR_WHICH_BITS; h++) {
  163. if (DECAF_SUCCESS == a.invert_elligator(
  164. Buffer(buffer,sizeof(buffer)), h
  165. )) {
  166. printhex(buffer,sizeof(buffer));
  167. printf("\n");
  168. }
  169. }
  170. } else if (raw) {
  171. printhex((const uint8_t *)&a, sizeof(a));
  172. printf("\n");
  173. } else if (like_eddsa) {
  174. if (decoeff) a /= (Group::Point::EDDSA_ENCODE_RATIO);
  175. SecureBuffer b = a.mul_by_ratio_and_encode_like_eddsa();
  176. printhex(b.data(),b.size());
  177. printf("\n");
  178. } else if (like_x) {
  179. if (decoeff) a /= (Group::Point::LADDER_ENCODE_RATIO);
  180. SecureBuffer b = a.mul_by_ratio_and_encode_like_ladder();
  181. printhex(b.data(),b.size());
  182. printf("\n");
  183. } else {
  184. a.serialize_into(tmp);
  185. printhex(tmp,sizeof(tmp));
  186. printf("\n");
  187. }
  188. done = true;
  189. }
  190. }
  191. };
  192. int main(int argc, char **argv) {
  193. g_argc = argc;
  194. g_argv = argv;
  195. run_for_all_curves<Run>();
  196. if (!done) usage();
  197. return (error<0) ? -error : error;
  198. }