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.
 
 
 
 
 

162 lines
5.3 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,"\n");
  61. fprintf(stderr," Ways to create points:\n");
  62. fprintf(stderr," [hex]: Point from point data as hex\n");
  63. fprintf(stderr," -e [hex]: Create point by hashing to curve using elligator\n");
  64. fprintf(stderr," base: Base point of curve\n");
  65. fprintf(stderr,"\n");
  66. fprintf(stderr," Operations:\n");
  67. fprintf(stderr," -n [point]: negative of point\n");
  68. fprintf(stderr," -s [scalar] * [point]: Hash to curve using elligator\n");
  69. fprintf(stderr," [point] + [point]: Add two poitns\n");
  70. fprintf(stderr,"\n");
  71. fprintf(stderr," NB: this is a debugging widget. It doesn't yet have order of operations.\n");
  72. fprintf(stderr," *** DON'T USE THIS UTILITY FOR ACTUAL CRYPTO! ***\n");
  73. fprintf(stderr," It's only for debugging!\n");
  74. fprintf(stderr,"\n");
  75. exit(-2);
  76. }
  77. template<typename Group> class Run {
  78. public:
  79. static void run() {
  80. uint8_t tmp[Group::Point::SER_BYTES];
  81. typename Group::Point a,b;
  82. typename Group::Scalar s;
  83. bool plus=false, empty=true, elligator=false, mul=false, scalar=false, scalarempty=true, neg=false;
  84. if (done || error) return;
  85. for (int i=1; i<g_argc && !error; i++) {
  86. bool point = false;
  87. if (!strcmp(g_argv[i],"-b") && ++i<g_argc) {
  88. if (atoi(g_argv[i]) == Group::bits()) continue;
  89. else return;
  90. } else if (!strcmp(g_argv[i],"+")) {
  91. if (elligator || scalar || empty) usage();
  92. plus = true;
  93. } else if (!strcmp(g_argv[i],"-n")) {
  94. neg = !neg;
  95. } else if (!strcmp(g_argv[i],"*")) {
  96. if (elligator || scalar || scalarempty) usage();
  97. mul = true;
  98. } else if (!strcmp(g_argv[i],"-s")) {
  99. if (elligator || scalar || !scalarempty) usage();
  100. scalar = true;
  101. } else if (!strcmp(g_argv[i],"-e")) {
  102. if (elligator || scalar) usage();
  103. elligator = true;
  104. } else if (!strcmp(g_argv[i],"base")) {
  105. if (elligator || scalar) usage();
  106. b = b.base();
  107. point = true;
  108. } else if ((strlen(g_argv[i]) == 2*sizeof(tmp)
  109. || ((scalar || elligator) && strlen(g_argv[i]) <= 2*sizeof(tmp)))
  110. && !(error=parsehex(tmp,sizeof(tmp),g_argv[i]))) {
  111. if (scalar) {
  112. s = Block(tmp,sizeof(tmp)); scalar=false; scalarempty=false;
  113. } else if (elligator) {
  114. point = true;
  115. b.set_to_hash(Block(tmp,sizeof(tmp))); elligator=false;
  116. } else if (DECAF_SUCCESS != b.decode(Block(tmp,sizeof(tmp)))) {
  117. fprintf(stderr,"Error: %s isn't in the group\n",g_argv[i]);
  118. error = -1;
  119. } else {
  120. point = true;
  121. }
  122. } else if (error || !empty) usage();
  123. if (point) {
  124. if (neg) { b = -b; neg = false; }
  125. if (mul) { b *= s; mul=false; }
  126. if (empty) { a = b; empty=false; }
  127. else if (plus) { a += b; plus=false; }
  128. else usage();
  129. }
  130. }
  131. if (!error && !empty) {
  132. a.serialize_into(tmp);
  133. printhex(tmp,sizeof(tmp));
  134. printf("\n");
  135. done = true;
  136. }
  137. }
  138. };
  139. int main(int argc, char **argv) {
  140. g_argc = argc;
  141. g_argv = argv;
  142. run_for_all_curves<Run>();
  143. if (!done) usage();
  144. return (error<0) ? -error : error;
  145. }