diff options
Diffstat (limited to 'core/src/main/java/org/spongycastle/math/raw/Mont256.java')
-rw-r--r-- | core/src/main/java/org/spongycastle/math/raw/Mont256.java | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/core/src/main/java/org/spongycastle/math/raw/Mont256.java b/core/src/main/java/org/spongycastle/math/raw/Mont256.java new file mode 100644 index 00000000..b90dcc5a --- /dev/null +++ b/core/src/main/java/org/spongycastle/math/raw/Mont256.java @@ -0,0 +1,152 @@ +package org.spongycastle.math.raw; + +public abstract class Mont256 +{ + private static final long M = 0xFFFFFFFFL; + + public static int inverse32(int x) + { + // assert (x & 1) == 1; + int z = x; // x.z == 1 mod 2**3 + z *= 2 - x * z; // x.z == 1 mod 2**6 + z *= 2 - x * z; // x.z == 1 mod 2**12 + z *= 2 - x * z; // x.z == 1 mod 2**24 + z *= 2 - x * z; // x.z == 1 mod 2**48 + // assert x * z == 1; + return z; + } + + public static void multAdd(int[] x, int[] y, int[] z, int[] m, int mInv32) + { + int z_8 = 0; + long y_0 = y[0] & M; + + for (int i = 0; i < 8; ++i) + { + long z_0 = z[0] & M; + long x_i = x[i] & M; + + long prod1 = x_i * y_0; + long carry = (prod1 & M) + z_0; + + long t = ((int)carry * mInv32) & M; + + long prod2 = t * (m[0] & M); + carry += (prod2 & M); + // assert (int)carry == 0; + carry = (carry >>> 32) + (prod1 >>> 32) + (prod2 >>> 32); + + for (int j = 1; j < 8; ++j) + { + prod1 = x_i * (y[j] & M); + prod2 = t * (m[j] & M); + + carry += (prod1 & M) + (prod2 & M) + (z[j] & M); + z[j - 1] = (int)carry; + carry = (carry >>> 32) + (prod1 >>> 32) + (prod2 >>> 32); + } + + carry += (z_8 & M); + z[7] = (int)carry; + z_8 = (int)(carry >>> 32); + } + + if (z_8 != 0 || Nat256.gte(z, m)) + { + Nat256.sub(z, m, z); + } + } + + public static void multAddXF(int[] x, int[] y, int[] z, int[] m) + { + // assert m[0] == M; + + int z_8 = 0; + long y_0 = y[0] & M; + + for (int i = 0; i < 8; ++i) + { + long x_i = x[i] & M; + + long carry = x_i * y_0 + (z[0] & M); + long t = carry & M; + carry = (carry >>> 32) + t; + + for (int j = 1; j < 8; ++j) + { + long prod1 = x_i * (y[j] & M); + long prod2 = t * (m[j] & M); + + carry += (prod1 & M) + (prod2 & M) + (z[j] & M); + z[j - 1] = (int)carry; + carry = (carry >>> 32) + (prod1 >>> 32) + (prod2 >>> 32); + } + + carry += (z_8 & M); + z[7] = (int)carry; + z_8 = (int)(carry >>> 32); + } + + if (z_8 != 0 || Nat256.gte(z, m)) + { + Nat256.sub(z, m, z); + } + } + + public static void reduce(int[] z, int[] m, int mInv32) + { + for (int i = 0; i < 8; ++i) + { + int z_0 = z[0]; + + long t = (z_0 * mInv32) & M; + + long carry = t * (m[0] & M) + (z_0 & M); + // assert (int)carry == 0; + carry >>>= 32; + + for (int j = 1; j < 8; ++j) + { + carry += t * (m[j] & M) + (z[j] & M); + z[j - 1] = (int)carry; + carry >>>= 32; + } + + z[7] = (int)carry; + // assert carry >>> 32 == 0; + } + + if (Nat256.gte(z, m)) + { + Nat256.sub(z, m, z); + } + } + + public static void reduceXF(int[] z, int[] m) + { + // assert m[0] == M; + + for (int i = 0; i < 8; ++i) + { + int z_0 = z[0]; + + long t = z_0 & M; + long carry = t; + + for (int j = 1; j < 8; ++j) + { + carry += t * (m[j] & M) + (z[j] & M); + z[j - 1] = (int)carry; + carry >>>= 32; + } + + z[7] = (int)carry; + // assert carry >>> 32 == 0; + } + + if (Nat256.gte(z, m)) + { + Nat256.sub(z, m, z); + } + } +} |