This library provides a way to easily handle arbitrary large integers.

This library provides the following operations :

  • addition, substraction, multiplication, division and modulo
  • bits operators (AND, OR, XOR, left and right shifts)
  • boolean operators
  • modular exponentiation (using montgomery algorithm)
  • modular inverse

Example

In this example, we use a 1024 bits long RSA key to encrypt and decrypt a message. We first encrypt the value 0x41 (65 in decimal) and then decrypt it. At the end, m should be equal to 0x41. The encryption is fast (0, 4 second) while the decryption is really slow. This code will take between 30 seconds and 2 minutes to execute depending on the compiler and optimization flags.

main.cpp

#include "mbed.h"
#include "BigInt.h"
#include <stdlib.h>
#include <stdio.h>

uint8_t modbits[] = {
0xd9, 0x4d, 0x88, 0x9e, 0x88, 0x85, 0x3d, 0xd8, 0x97, 0x69, 0xa1, 0x80, 0x15, 0xa0, 0xa2, 0xe6,
0xbf, 0x82, 0xbf, 0x35, 0x6f, 0xe1, 0x4f, 0x25, 0x1f, 0xb4, 0xf5, 0xe2, 0xdf, 0x0d, 0x9f, 0x9a,
0x94, 0xa6, 0x8a, 0x30, 0xc4, 0x28, 0xb3, 0x9e, 0x33, 0x62, 0xfb, 0x37, 0x79, 0xa4, 0x97, 0xec,
0xea, 0xea, 0x37, 0x10, 0x0f, 0x26, 0x4d, 0x7f, 0xb9, 0xfb, 0x1a, 0x97, 0xfb, 0xf6, 0x21, 0x13,
0x3d, 0xe5, 0x5f, 0xdc, 0xb9, 0xb1, 0xad, 0x0d, 0x7a, 0x31, 0xb3, 0x79, 0x21, 0x6d, 0x79, 0x25,
0x2f, 0x5c, 0x52, 0x7b, 0x9b, 0xc6, 0x3d, 0x83, 0xd4, 0xec, 0xf4, 0xd1, 0xd4, 0x5c, 0xbf, 0x84,
0x3e, 0x84, 0x74, 0xba, 0xbc, 0x65, 0x5e, 0x9b, 0xb6, 0x79, 0x9c, 0xba, 0x77, 0xa4, 0x7e, 0xaf,
0xa8, 0x38, 0x29, 0x64, 0x74, 0xaf, 0xc2, 0x4b, 0xeb, 0x9c, 0x82, 0x5b, 0x73, 0xeb, 0xf5, 0x49
};

uint8_t dbits[] = {
0x04, 0x7b, 0x9c, 0xfd, 0xe8, 0x43, 0x17, 0x6b, 0x88, 0x74, 0x1d, 0x68, 0xcf, 0x09, 0x69, 0x52,
0xe9, 0x50, 0x81, 0x31, 0x51, 0x05, 0x8c, 0xe4, 0x6f, 0x2b, 0x04, 0x87, 0x91, 0xa2, 0x6e, 0x50,
0x7a, 0x10, 0x95, 0x79, 0x3c, 0x12, 0xba, 0xe1, 0xe0, 0x9d, 0x82, 0x21, 0x3a, 0xd9, 0x32, 0x69,
0x28, 0xcf, 0x7c, 0x23, 0x50, 0xac, 0xb1, 0x9c, 0x98, 0xf1, 0x9d, 0x32, 0xd5, 0x77, 0xd6, 0x66,
0xcd, 0x7b, 0xb8, 0xb2, 0xb5, 0xba, 0x62, 0x9d, 0x25, 0xcc, 0xf7, 0x2a, 0x5c, 0xeb, 0x8a, 0x8d,
0xa0, 0x38, 0x90, 0x6c, 0x84, 0xdc, 0xdb, 0x1f, 0xe6, 0x77, 0xdf, 0xfb, 0x2c, 0x02, 0x9f, 0xd8,
0x92, 0x63, 0x18, 0xee, 0xde, 0x1b, 0x58, 0x27, 0x2a, 0xf2, 0x2b, 0xda, 0x5c, 0x52, 0x32, 0xbe,
0x06, 0x68, 0x39, 0x39, 0x8e, 0x42, 0xf5, 0x35, 0x2d, 0xf5, 0x88, 0x48, 0xad, 0xad, 0x11, 0xa1
};

int main() 
{
    BigInt e = 65537, mod, d;
    mod.importData(modbits, sizeof(modbits));
    d.importData(dbits, sizeof(dbits));

    BigInt c = modPow(0x41,e,mod);
    c.print();
    BigInt m = modPow(c,d,mod);
    m.print();
    printf("done\n");
    
    return 0;
}

Files at this revision

API Documentation at this revision

Comitter:
feb11
Date:
Sun Apr 06 08:12:52 2014 +0000
Parent:
23:002f471a973e
Child:
25:3d5c1f299da2
Commit message:
improved speed of modPow

Changed in this revision

BigInt.cpp Show annotated file Show diff for this revision Revisions of this file
BigInt.h Show annotated file Show diff for this revision Revisions of this file
--- a/BigInt.cpp	Mon Mar 10 21:59:19 2014 +0000
+++ b/BigInt.cpp	Sun Apr 06 08:12:52 2014 +0000
@@ -15,7 +15,12 @@
     0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000
 };
 
-static uint32_t num(const uint32_t a)
+static uint32_t BITS2[] =
+{
+    0x00FFFFFF, 0x0000FFFF, 0x00FFFFFF
+};
+
+static inline uint32_t num(const uint32_t a)
 {
     return a/4 + (a%4 ? 1:0); 
 }
@@ -539,14 +544,14 @@
     while(r > 0)
     {
         if(a.bits[j/32] & BITS[j%32])
-            result += b;
+            result.add(b);
         
         if(result.bits[0] & BITS[0])
-            result += m;
+            result.add(m);
      
         ++j; 
         --r;
-        result >>= 1;
+        result.shr();
     }
     
     if(result >= m)
@@ -579,6 +584,7 @@
     uint32_t j = 0; 
     while(j <= n)
     {
+        
         if(expn.bits[j/32] & BITS[j%32])
         {
             if(tmp.isValid())
@@ -589,6 +595,7 @@
         ++j;
         if(j <= n)  
             montA = montgomeryStep(montA, montA, modulus, r);
+        
     }
     
     // convert tmp to normal world
@@ -613,6 +620,50 @@
     printf("\n");
 }
 
+void BigInt::add(const BigInt &b)
+{
+    uint32_t al = num(size);
+    uint32_t bl = num(b.size);
+    uint32_t rsize = std::max(size, b.size) + 1;
+    size_t l = num(rsize);
+    
+    if(l > al)
+    {
+        bits = (uint32_t*)realloc(bits, sizeof(uint32_t)*l);
+        memset(&bits[al], 0, (l-al)*sizeof(uint32_t));
+        size = rsize;
+    }
+
+    uint32_t carry = 0;
+    for(int i = 0; i < l; ++i)
+    {
+        uint32_t tmpA = 0, tmpB = 0;
+        if(i < al)
+            tmpA = bits[i];
+        if(i < bl)
+            tmpB = b.bits[i];
+        bits[i] = tmpA + tmpB + carry;
+        carry = bits[i] < std::max(tmpA, tmpB);
+    }
+
+    trim();
+}
+
+void BigInt::shr()
+{
+    uint32_t lastBit = 0;
+    uint32_t tmp;
+    for(int i = num(size)-1; i >= 0; --i)
+    {
+        tmp = bits[i] & BITS[0];
+        bits[i] >>= 1;
+        bits[i] |= (lastBit ? BITS[31] : 0);
+        lastBit = tmp;
+    }
+
+    trim();
+}
+
 void BigInt::trim()
 {
     assert(isValid());
@@ -623,15 +674,12 @@
         newSize--;
     if(newSize == 0)
         newSize = 1;
-    if(num(newSize) < num(size))
+    uint32_t n = num(newSize);
+    if(n < num(size))
     {
-        uint32_t *tmp = new uint32_t[num(size)];
-        memcpy(tmp, bits, num(size)*sizeof(uint32_t));
-        delete[] bits;
-        bits = new uint32_t[num(newSize)];
-        memset(bits, 0, sizeof(uint32_t)*num(newSize));
-        memcpy(bits, tmp, newSize);
-        delete[] tmp;
+        bits = (uint32_t*)realloc(bits, n*sizeof(uint32_t));
+        if(newSize % 4 != 0)
+            bits[n-1] &= BITS2[newSize%4];
     }
     size = newSize; 
 }
@@ -651,4 +699,4 @@
     n += tmp2;
 
     return n;
-}
+}
\ No newline at end of file
--- a/BigInt.h	Mon Mar 10 21:59:19 2014 +0000
+++ b/BigInt.h	Sun Apr 06 08:12:52 2014 +0000
@@ -68,6 +68,10 @@
 
     private :
     
+        // fast operations
+        void add(const BigInt &b);
+        void shr();
+        
         void trim();  
         uint32_t numBits() const;    
      
@@ -79,4 +83,4 @@
 };
 
 
-#endif
+#endif
\ No newline at end of file