Browse Source

support base 64 for GMP

Patrick Pelletier 14 years ago
parent
commit
3fbccfcb5c
1 changed files with 38 additions and 2 deletions
  1. 38 2
      src/math/gmp_desc.c

+ 38 - 2
src/math/gmp_desc.c

@@ -138,13 +138,49 @@ static int twoexpt(void *a, int n)
 
 /* ---- conversions ---- */
 
+static const char rmap[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
+
 /* read ascii string */
 static int read_radix(void *a, const char *b, int radix)
 {
+   int ret;
    LTC_ARGCHK(a != NULL);
    LTC_ARGCHK(b != NULL);
-   mpz_set_str(a, b, radix);
-   return CRYPT_OK;
+   if (radix == 64) {
+      /* Sadly, GMP only supports radixes up to 62, but we need 64.
+       * So, although this is not the most elegant or efficient way,
+       * let's just convert the base 64 string (6 bits per digit) to
+       * an octal string (3 bits per digit) that's twice as long. */
+      char c, *tmp, *q;
+      const char *p;
+      int i;
+      tmp = XMALLOC (1 + 2 * strlen (b));
+      if (tmp == NULL) {
+         return CRYPT_MEM;
+      }
+      p = b;
+      q = tmp;
+      while ((c = *p++) != 0) {
+         for (i = 0; i < 64; i++) {
+            if (c == rmap[i])
+               break;
+         }
+         if (i == 64) {
+            XFREE (tmp);
+            // printf ("c = '%c'\n", c);
+            return CRYPT_ERROR;
+         }
+         *q++ = '0' + (i / 8);
+         *q++ = '0' + (i % 8);
+      }
+      *q = 0;
+      ret = mpz_set_str(a, tmp, 8);
+      // printf ("ret = %d for '%s'\n", ret, tmp);
+      XFREE (tmp);
+   } else {
+      ret = mpz_set_str(a, b, radix);
+   }
+   return (ret == 0 ? CRYPT_OK : CRYPT_ERROR);
 }
 
 /* write one */