Add simpleid-1.0.5
diff --git a/simpleid/www/bignum.inc.php b/simpleid/www/bignum.inc.php
new file mode 100644
index 0000000..78fefd7
--- /dev/null
+++ b/simpleid/www/bignum.inc.php
@@ -0,0 +1,286 @@
+<?php
+/*
+ * SimpleID
+ *
+ * Copyright (C) Kelvin Mo 2009
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * 
+ * $Id$
+ */
+
+/**
+ * Abstraction library for multiple precision mathematics.  This file uses either
+ * the GNU Multiple Precision Arithmic Libary (GMP) if it is installed, or the
+ * default BCMath library if it is not installed.
+ *
+ * @package simpleid
+ * @filesource
+ */
+
+ 
+if (function_exists('gmp_init')) {
+    /**
+     * Defines whether the GMP library is available.
+     */
+    define('BIGNUM_GMP', true);
+} else {
+    /** @ignore */
+    define('BIGNUM_GMP', false);
+}
+
+/**
+ * Returns whether either the GMP or the BCMath library is installed.  If neither
+ * of these libraries are installed, the functions in this file will not work.
+ *
+ * @return bool true if either GMP or BCMath is installed.
+ */ 
+function bignum_loaded() {
+    return (function_exists('gmp_init') || function_exists('bcadd'));
+}
+
+/**
+ * Creates a bignum.
+ *
+ * @param mixed $str An integer, a string in base 2 to 36, or a byte stream in base 256
+ * @param int $base an integer between 2 and 36, or 256
+ * @return resource a bignum
+ */
+function bignum_new($str, $base = 10) {
+    switch ($base) {
+        case 10:
+            if (BIGNUM_GMP) {
+                return gmp_init($str, 10);
+            } else {
+                return $str;
+            }
+            break;
+        case 256:
+            $bytes = array_merge(unpack('C*', $str));
+
+            $num = bignum_new(0);
+      
+            foreach ($bytes as $byte) {
+                $num = bignum_mul($num, 256);
+                $num = bignum_add($num, bignum_new($byte));
+            }
+            return $num;
+            break;
+        default:
+            if (!is_integer($base) || ($base < 2) || ($base > 36)) return FALSE;
+
+            $num = bignum_new(0);
+
+            for ($i = 0; $i < strlen($str); $i++) {
+                $num = bignum_mul($num, $base);
+                $num = bignum_add($num, bignum_new(base_convert($str[$i], $base, 10)));
+            }
+            return $num;
+    }
+
+    return FALSE;
+}
+
+/**
+ * Converts a bignum into a string representation (base 2 to 36) or a byte stream
+ * (base 256)
+ *
+ * @param resource $num the bignum
+ * @param int $base an integer between 2 and 36, or 256
+ * @return string the converted bignum
+ */
+function bignum_val($num, $base = 10) {
+    switch ($base) {
+        case 10:
+            if (BIGNUM_GMP) {
+                $base10 = gmp_strval($num, 10);
+            } else {
+                $base10 = $num;
+            }
+
+            return $base10;
+            break;
+    
+        case 256:
+            $cmp = bignum_cmp($num, 0);
+            if ($cmp < 0) {
+                return FALSE;
+            }
+    
+            if ($cmp == 0) {
+                return "\x00";
+            }
+    
+            $bytes = array();
+      
+            while (bignum_cmp($num, 0) > 0) {
+                array_unshift($bytes, bignum_mod($num, 256));
+                $num = bignum_div($num, 256);
+            }
+      
+            if ($bytes && ($bytes[0] > 127)) {
+                array_unshift($bytes, 0);
+            }
+      
+            $byte_stream = '';
+            foreach ($bytes as $byte) {
+                $byte_stream .= pack('C', $byte);
+            }
+      
+            return $byte_stream;
+            break;
+        default:
+            if (!is_integer($base) || ($base < 2) || ($base > 36)) return FALSE;
+
+            $cmp = bignum_cmp($num, 0);
+            if ($cmp < 0) {
+                return FALSE;
+            }
+    
+            if ($cmp == 0) {
+                return "0";
+            }
+
+            $str = '';
+            while (bignum_cmp($num, 0) > 0) {
+                $r = intval(bignum_val(bignum_mod($num, $base)));
+                $str = base_convert($r, 10, $base) . $str;
+                $num = bignum_div($num, $base);
+            }
+ 
+            return $str;
+    }
+    
+    return FALSE;
+}
+
+/**
+ * Adds two bignums
+ *
+ * @param resource $a
+ * @param resource $b
+ * @return resource a bignum representing a + b
+ */
+function bignum_add($a, $b) {
+    if (BIGNUM_GMP) {
+        return gmp_add($a, $b);
+    } else {
+        return bcadd($a, $b);
+    }
+}
+
+/**
+ * Multiplies two bignums
+ *
+ * @param resource $a
+ * @param resource $b
+ * @return resource a bignum representing a * b
+ */
+function bignum_mul($a, $b) {
+    if (BIGNUM_GMP) {
+        return gmp_mul($a, $b);
+    } else {
+        return bcmul($a, $b);
+    }
+}
+
+/**
+ * Divides two bignums
+ *
+ * @param resource $a
+ * @param resource $b
+ * @return resource a bignum representing a / b
+ */
+function bignum_div($a, $b) {
+    if (BIGNUM_GMP) {
+        return gmp_div($a, $b);
+    } else {
+        return bcdiv($a, $b);
+    }
+}
+
+/**
+ * Raise base to power exp
+ *
+ * @param resource $base the base
+ * @param mixed $exp the exponent, as an integer or a bignum
+ * @return resource a bignum representing base ^ exp
+ */
+function bignum_pow($base, $exp) {
+    if (BIGNUM_GMP) {
+        if (is_resource($exp) && (get_resource_type($exp) == 'gmp')) $exp = gmp_intval($exp);
+        return gmp_pow($base, $exp);
+    } else {
+        return bcpow($base, $exp);
+    }
+}
+
+/**
+ * Returns n modulo d
+ *
+ * @param resource $n
+ * @param resource $d
+ * @return resource a bignum representing n mod d
+ */
+function bignum_mod($n, $d) {
+    if (BIGNUM_GMP) {
+        return gmp_mod($n, $d);
+    } else {
+        return bcmod($n, $d);
+    }
+}
+
+/**
+ * Raise a number into power with modulo
+ *
+ * @param resource $base the base
+ * @param resource $exp the exponent
+ * @param resource $mod the modulo
+ * @return resource a bignum representing base ^ exp mod mod
+ */
+function bignum_powmod($base, $exp, $mod) {
+    if (BIGNUM_GMP) {
+        return gmp_powm($base, $exp, $mod);
+    } elseif (function_exists('bcpowmod')) {
+        return bcpowmod($base, $exp, $mod);
+    } else {
+        $square = bignum_mod($base, $mod);
+        $result = 1;
+        while (bignum_cmp($exp, 0) > 0) {
+            if (bignum_mod($exp, 2)) {
+                $result = bignum_mod(bignum_mul($result, $square), $mod);
+            }
+            $square = bignum_mod(bignum_mul($square, $square), $mod);
+            $exp = bignum_div($exp, 2);
+        }
+        return $result;
+    }
+}
+
+/**
+ * Compares two bignum
+ *
+ * @param resource $a
+ * @param resource $b
+ * @return int positive value if a > b, zero if a = b and a negative value if a < b
+ */
+function bignum_cmp($a, $b) {
+    if (BIGNUM_GMP) {
+        return gmp_cmp($a, $b);
+    } else {
+        return bccomp($a, $b);
+    }
+}
+?>