changeset 1302:7fd61e465bc6

Added implementation of Montgomery Exponentiation.
author Marc X. Makkes
date Mon, 19 Oct 2009 11:03:18 +0200
parents c44e2e1a9279
children deb7659465d2
files viff/montgomery_exponentiation.py
diffstat 1 files changed, 166 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/viff/montgomery_exponentiation.py	Mon Oct 19 11:03:18 2009 +0200
@@ -0,0 +1,166 @@
+# Copyright 2009 VIFF Development Team.
+#
+# This file is part of VIFF, the Virtual Ideal Functionality Framework.
+#
+# VIFF is free software: you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License (LGPL) as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# VIFF 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 Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with VIFF. If not, see <http://www.gnu.org/licenses/>.
+
+
+def sizeinbits(a):
+    acc = 0
+    while a != 0:
+        acc += 1
+        a = a >> 1
+    return acc
+
+
+def calc_r(n):
+    """Compute r."""
+    n_size = sizeinbits(n)
+    r = 2**(n_size+1)
+
+    while gcd(r, n) != 1:
+        r = r << 1
+		
+    return r
+
+
+def calc_r_r_inv(n):
+    """Compute r and r inverse."""
+    assert (n % 2) == 1, "n must be odd."
+    n_size = sizeinbits(n)
+    r = 2**(n_size+1)
+
+    while gcd(r, n) != 1:
+        r = r << 1
+		
+    return r, inversemod(r, n)
+
+
+def calc_np(n, r):
+    """Compute n'."""
+    assert (n % 2) == 1, "n must be odd."
+    n_prime = inversemod(n, r)
+    return r - n_prime 
+
+
+def inversemod(a, n):
+    g, x, y = xgcd(a, n)
+    if g != 1:
+        raise ZeroDivisionError, (a,n)
+    assert g == 1, "a must be coprime to n."
+    return x%n
+
+
+def gcd(a, b):                                       
+    if a < 0:  a = -a
+    if b < 0:  b = -b
+    if a == 0: return b
+    if b == 0: return a
+    while b != 0: 
+        (a, b) = (b, a%b)
+    return a
+
+
+def xgcd(a, b):
+    if a == 0 and b == 0: return (0, 0, 1)
+    if a == 0: return (abs(b), 0, b/abs(b))
+    if b == 0: return (abs(a), a/abs(a), 0)
+    x_sign = 1; y_sign = 1
+    if a < 0: a = -a; x_sign = -1
+    if b < 0: b = -b; y_sign = -1
+    x = 1; y = 0; r = 0; s = 1
+    while b != 0:
+        (c, q) = (a%b, a/b)
+        (a, b, r, s, x, y) = (b, c, x-q*r, y-q*s, r, s)
+    return (a, x*x_sign, y*y_sign)
+
+
+def montgomery_exponentiation_reduction(a, r , n ):
+    return (a * r) % n
+
+
+def montgomery_product(a, b, n_prime, size_of_r, r, n):
+    t = a * b 
+    m = (t * n_prime) & r -1
+    u = (t + m * n ) >> size_of_r - 1
+    if u >= n:
+        return u -n 
+    return u
+
+
+def montgomery_exponentiation(a, x, n, n_prime, r):
+    ah = (a * r) % n 
+    xh = r % n 
+    x_s = sizeinbits(x) - 1
+    px = 2**x_s
+    size_of_r = sizeinbits(r)
+    while px != 0:
+        t = xh * xh 
+        m = (t * n_prime) & r -1
+        u = (t + m * n ) >> size_of_r - 1
+        if u >= n:
+            xh = u - n 
+        else:
+            xh = u
+        if (px & x) > 0:
+            t = ah * xh 
+            m = (t * n_prime) & r - 1
+            u = (t + m * n ) >> size_of_r - 1
+            if u >= n:
+                xh =  u -n 
+            else:
+                xh = u
+	px = px >> 1
+
+    m = (xh * n_prime) & r - 1
+    u = (xh + m * n ) >> size_of_r - 1
+    if u >= n:
+        return u - n 
+    return u
+
+def montgomery_exponentiation2(a, x, n, n_prime,  r):
+    ah = (a * r) % n 
+    xh = r % n 
+    x_s = sizeinbits(x) - 1
+    px = 2**x_s
+    size_of_r = sizeinbits(r)
+    while px != 0:
+        xh = montgomery_product(xh, xh, n_prime, size_of_r, r, n)
+        if (px & x) > 0:
+            xh = montgomery_product(ah, xh, n_prime, size_of_r, r, n)
+	px = px >> 1
+
+    x  = montgomery_product(xh, 1, n_prime, size_of_r, r, n)
+    return x
+
+
+
+
+# n = 2328734783
+# r, r_inv = calc_r(n)
+# n_prime = calc_np(n, r) 
+
+if __name__ ==  '__main__':
+    n = 2328734783
+    r, r_inv = calc_r_r_inv(n)
+    n_prime = calc_np(n, r) 
+    a = 2987
+    x = 1093874
+    print montgomery_exponentiation(a, x, n, n_prime, r)
+    print pow(a, x, n)
+    print a**x % n
+
+
+
+