diff --git a/.classpath b/.classpath deleted file mode 100644 index 8ffbfb4..0000000 --- a/.classpath +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/.gitignore b/.gitignore index 6e9468a..5987f1e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,9 @@ classes/ doc/ dist/ - +.idea/ +.settings/ +*.iml +.classpath +.project +target/ diff --git a/.project b/.project deleted file mode 100644 index d6da668..0000000 --- a/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - zrtp4j.git - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - diff --git a/README.txt b/README.txt index 0a3e1f9..d46dc1c 100644 --- a/README.txt +++ b/README.txt @@ -26,33 +26,6 @@ the following hash and crypto algorithms: - AES - Diffie-Hellman (DH) -The crypto part of the library was copied from BouncyCastle crypto library. -Only the Diffie-Hellman part was modified to a new BigIntegerCrypto -implementation which is also part of this package. - -BigIntegerCrypto re-uses the GNU BigInteger implementation and adds -some crypto specific enhancements: - -- don't use the GMP library if installed on the system. While this - may reduce performance it gives us full control of the data (no - copying between Java and C) - -- Add a method to clear the contents / data of the big integer. The - application can use this function to clear data in case this big - integer was used as a private key. Some applications may stay in - emory for a long time (for example communication applications) and - thus it is important to be able to clear secret data if it is not - longer used. Otherwise a malicious person could be able to do - memory analysis to find some key material. - -- Clear temporary data produced during calculations. Some big integer - calculation produce and use temporary data. BigIntegerCrypto clears - these temporary data to avoid data leakage. The tag "crypto:" - identifies these modifications. - -Otherwise BigIntegerCrypto behaves in the same way as the normal -BigInteger. - The source distribution contains a short Java file that tests the availability of the mentioned algorithms and support classes. diff --git a/build.xml b/build.xml deleted file mode 100644 index 27984ce..0000000 --- a/build.xml +++ /dev/null @@ -1,142 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/legal/LICENSE-bouncycastle.txt b/legal/LICENSE-bouncycastle.txt deleted file mode 100755 index 17ef6db..0000000 --- a/legal/LICENSE-bouncycastle.txt +++ /dev/null @@ -1,19 +0,0 @@ - -License - -Copyright (c) 2000 - 2008 The Legion Of The Bouncy Castle (http://www.bouncycastle.org) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software -and associated documentation files (the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, publish, distribute, -sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or -substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING -BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/lib/bccontrib-1.0-SNAPSHOT.jar b/lib/bccontrib-1.0-SNAPSHOT.jar deleted file mode 100644 index 719078e..0000000 Binary files a/lib/bccontrib-1.0-SNAPSHOT.jar and /dev/null differ diff --git a/lib/bcprov-jdk15on-148.jar b/lib/bcprov-jdk15on-148.jar deleted file mode 100644 index 3fcb136..0000000 Binary files a/lib/bcprov-jdk15on-148.jar and /dev/null differ diff --git a/lib/jmf.jar b/lib/jmf.jar deleted file mode 100644 index f2a8c4d..0000000 Binary files a/lib/jmf.jar and /dev/null differ diff --git a/lib/junit-3.8.1.jar b/lib/junit-3.8.1.jar deleted file mode 100644 index 674d71e..0000000 Binary files a/lib/junit-3.8.1.jar and /dev/null differ diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..be03a51 --- /dev/null +++ b/pom.xml @@ -0,0 +1,182 @@ + + 4.0.0 + + com.github.wernerd + zrtp4j + 4.1.0-SNAPSHOT + bundle + ZRTP for Java library + + zrtp4j + https://github.com/wernerd/zrtp4j + + + + wernerd + Werner Dittmann + Werner.Dittmann@t-online.de + + + + + UTF-8 + + + + + org.bouncycastle + bcprov-jdk15on + 1.52 + + + javax.media + jmf + 2.1.1e + true + + + + + src + src + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.0 + + 1.7 + 1.7 + + + + + org.apache.felix + maven-bundle-plugin + 3.2.0 + true + + + + GPL-3+ with Classpath-Exception + gnu.java.zrtp.*,!demo + !demo,gnu.java.zrtp.annotations + + + + + + + + + release-prepare + + + performRelease + true + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + + attach-javadocs + + jar + + + + + + + + + release + + + performRelease + true + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.3 + true + + ossrh + https://oss.sonatype.org/ + true + + + + + + + + doclint-java8-disable + + [1.8,) + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + -Xdoclint:none + + + + + + + + + + ossrh + https://oss.sonatype.org/content/repositories/snapshots + + + ossrh + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + diff --git a/src/demo/CryptoTestPureLW.java b/src/demo/CryptoTestPureLW.java index 0e984f7..244df7e 100644 --- a/src/demo/CryptoTestPureLW.java +++ b/src/demo/CryptoTestPureLW.java @@ -2,30 +2,26 @@ import gnu.java.zrtp.ZrtpConstants; -import gnu.java.bigintcrypto.BigIntegerCrypto; - -import java.util.Random; +import java.math.BigInteger; +import java.security.SecureRandom; import java.util.Arrays; -import org.bouncycastle.cryptozrtp.generators.DHBasicKeyPairGenerator; -import org.bouncycastle.cryptozrtp.params.DHKeyGenerationParameters; -import org.bouncycastle.cryptozrtp.AsymmetricCipherKeyPair; +import org.bouncycastle.crypto.AsymmetricCipherKeyPair; import org.bouncycastle.crypto.DataLengthException; import org.bouncycastle.crypto.InvalidCipherTextException; -//import org.bouncycastle.cryptozrtp.InvalidCipherTextException; -import org.bouncycastle.cryptozrtp.agreement.DHBasicAgreement; -import org.bouncycastle.cryptozrtp.params.DHPublicKeyParameters; +import org.bouncycastle.crypto.agreement.DHBasicAgreement; import org.bouncycastle.crypto.digests.SHA256Digest; +import org.bouncycastle.crypto.generators.DHBasicKeyPairGenerator; import org.bouncycastle.crypto.macs.HMac; +import org.bouncycastle.crypto.params.DHKeyGenerationParameters; +import org.bouncycastle.crypto.params.DHPublicKeyParameters; import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.crypto.BufferedBlockCipher; import org.bouncycastle.crypto.modes.CFBBlockCipher; import org.bouncycastle.crypto.engines.AESFastEngine; import org.bouncycastle.crypto.params.ParametersWithIV; -import org.bouncycastle.crypto.prng.RandomGenerator; -import org.jitsi.bccontrib.prng.FortunaGenerator; import gnu.java.zrtp.utils.ZrtpUtils; @@ -62,9 +58,10 @@ public class CryptoTestPureLW { byte[] dataToSecure = dataAsText.getBytes(); boolean testProvider() { - byte[] rnd = new byte[256]; - new Random().nextBytes(rnd); - RandomGenerator secRand = new FortunaGenerator(rnd); + byte[] rnd = new byte[256]; + SecureRandom secRand = new SecureRandom(); + secRand.nextBytes(rnd); + /* * Test and check DH key agreement */ @@ -86,7 +83,7 @@ boolean testProvider() { // get B party's public key DHPublicKeyParameters tmp = (DHPublicKeyParameters) myKeyPairLwB.getPublic(); - BigIntegerCrypto y = tmp.getY(); // and the big int value of it + BigInteger y = tmp.getY(); // and the big int value of it // System.out.println("B public length: " + y.toByteArray().length); @@ -95,7 +92,7 @@ boolean testProvider() { // calculate the secret value of A party, using B party's value dhContextLwA = new DHBasicAgreement(); dhContextLwA.init(myKeyPairLwA.getPrivate()); - BigIntegerCrypto resultLwA = dhContextLwA.calculateAgreement(new DHPublicKeyParameters(y, ZrtpConstants.specDh3k)); + BigInteger resultLwA = dhContextLwA.calculateAgreement(new DHPublicKeyParameters(y, ZrtpConstants.specDh3k)); // get A party's public key @@ -109,7 +106,7 @@ boolean testProvider() { // then calculate the secret value of A party, using B party's value dhContextLwB = new DHBasicAgreement(); dhContextLwB.init(myKeyPairLwB.getPrivate()); - BigIntegerCrypto resultLwB = dhContextLwB.calculateAgreement(new DHPublicKeyParameters(y, ZrtpConstants.specDh3k)); + BigInteger resultLwB = dhContextLwB.calculateAgreement(new DHPublicKeyParameters(y, ZrtpConstants.specDh3k)); byte[] lwByteA = adjustKey(resultLwA); byte[] lwByteB = adjustKey(resultLwB); @@ -187,7 +184,7 @@ boolean testProvider() { return true; } - byte[] adjustKey(BigIntegerCrypto in) { + byte[] adjustKey(BigInteger in) { byte[] inBytes = in.toByteArray(); // check for leading zero byte if public key resulted in negative // value. BigIntegerCrypto adds a leading zero to drop the negative sign bit diff --git a/src/djb/Curve25519.java b/src/djb/Curve25519.java deleted file mode 100644 index 35f018b..0000000 --- a/src/djb/Curve25519.java +++ /dev/null @@ -1,903 +0,0 @@ -/* Ported from C to Java by Dmitry Skiba [sahn0], 23/02/08. - * Original: http://cds.xs4all.nl:8081/ecdh/ - */ -/* Generic 64-bit integer implementation of Curve25519 ECDH - * Written by Matthijs van Duin, 200608242056 - * Public domain. - * - * Based on work by Daniel J Bernstein, http://cr.yp.to/ecdh.html - */ -package djb; - -public class Curve25519 { - - /* key size */ - public static final int KEY_SIZE = 32; - - /* 0 */ - public static final byte[] ZERO = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - - /* the prime 2^255-19 */ - public static final byte[] PRIME = { - (byte)237, (byte)255, (byte)255, (byte)255, - (byte)255, (byte)255, (byte)255, (byte)255, - (byte)255, (byte)255, (byte)255, (byte)255, - (byte)255, (byte)255, (byte)255, (byte)255, - (byte)255, (byte)255, (byte)255, (byte)255, - (byte)255, (byte)255, (byte)255, (byte)255, - (byte)255, (byte)255, (byte)255, (byte)255, - (byte)255, (byte)255, (byte)255, (byte)127 - }; - - /* group order (a prime near 2^252+2^124) */ - public static final byte[] ORDER = { - (byte)237, (byte)211, (byte)245, (byte)92, - (byte)26, (byte)99, (byte)18, (byte)88, - (byte)214, (byte)156, (byte)247, (byte)162, - (byte)222, (byte)249, (byte)222, (byte)20, - (byte)0, (byte)0, (byte)0, (byte)0, - (byte)0, (byte)0, (byte)0, (byte)0, - (byte)0, (byte)0, (byte)0, (byte)0, - (byte)0, (byte)0, (byte)0, (byte)16 - }; - - /********* KEY AGREEMENT *********/ - - /* Private key clamping - * k [out] your private key for key agreement - * k [in] 32 random bytes - */ - public static void clamp(byte[] k) { - k[31] &= 0x7F; - k[31] |= 0x40; - k[ 0] &= 0xF8; - } - - /* Key-pair generation - * P [out] your public key, 32 bytes - * s [out] your private key for signing - * k [out] your private key for key agreement, 32 bytes - * k [in] 32 random bytes, 32 bytes - * s may be NULL if you don't care - * - * WARNING: if s is not NULL, this function has data-dependent timing */ - public static void keygen(byte[] P, byte[] s, byte[] k) { - clamp(k); - core(P, s, k, null); - } - - /* Key agreement - * Z [out] shared secret (needs hashing before use) - * k [in] your private key for key agreement - * P [in] peer's public key - */ - public static void curve(byte[] Z, byte[] k, byte[] P) { - core(Z, null, k, P); - } - - /********* DIGITAL SIGNATURES *********/ - - /* deterministic EC-KCDSA - * - * s is the private key for signing - * P is the corresponding public key - * Z is the context data (signer public key or certificate, etc) - * - * signing: - * - * m = hash(Z, message) - * x = hash(m, s) - * keygen25519(Y, NULL, x); - * r = hash(Y); - * h = m XOR r - * sign25519(v, h, x, s); - * - * output (v,r) as the signature - * - * verification: - * - * m = hash(Z, message); - * h = m XOR r - * verify25519(Y, v, h, P) - * - * confirm r == hash(Y) - * - * It would seem to me that it would be simpler to have the signer directly do - * h = hash(m, Y) and send that to the recipient instead of r, who can verify - * the signature by checking h == hash(m, Y). If there are any problems with - * such a scheme, please let me know. - * - * Also, EC-KCDSA (like most DS algorithms) picks x random, which is a waste of - * perfectly good entropy, but does allow Y to be calculated in advance of (or - * parallel to) hashing the message. - */ - - /* Signature generation primitive, calculates (x-h)s mod q - * v [out] signature value - * h [in] signature hash (of message, signature pub key, and context data) - * x [in] signature private key - * s [in] private key for signing - * returns true on success, false on failure (use different x or h) - */ - public static boolean sign(byte[] v, byte[] h, byte[] x, byte[] s) { - /* v = (x - h) s mod q */ - byte[] tmp1=new byte[65]; - byte[] tmp2=new byte[33]; - int w; - int i; - for (i = 0; i < 32; i++) - v[i] = 0; - i = mula_small(v, x, 0, h, 32, -1); - mula_small(v, v, 0, ORDER, 32, (15-v[31])/16); - mula32(tmp1, v, s, 32, 1); - divmod(tmp2, tmp1, 64, ORDER, 32); - for (w = 0, i = 0; i < 32; i++) - w |= v[i] = tmp1[i]; - return w != 0; - } - - /* Signature verification primitive, calculates Y = vP + hG - * Y [out] signature public key - * v [in] signature value - * h [in] signature hash - * P [in] public key - */ - public static void verify(byte[] Y, byte[] v, byte[] h, byte[] P) { - /* Y = v abs(P) + h G */ - byte[] d=new byte[32]; - long10[] - p=new long10[]{new long10(),new long10()}, - s=new long10[]{new long10(),new long10()}, - yx=new long10[]{new long10(),new long10(),new long10()}, - yz=new long10[]{new long10(),new long10(),new long10()}, - t1=new long10[]{new long10(),new long10(),new long10()}, - t2=new long10[]{new long10(),new long10(),new long10()}; - - int vi = 0, hi = 0, di = 0, nvh=0, i, j, k; - - /* set p[0] to G and p[1] to P */ - - set(p[0], 9); - unpack(p[1], P); - - /* set s[0] to P+G and s[1] to P-G */ - - /* s[0] = (Py^2 + Gy^2 - 2 Py Gy)/(Px - Gx)^2 - Px - Gx - 486662 */ - /* s[1] = (Py^2 + Gy^2 + 2 Py Gy)/(Px - Gx)^2 - Px - Gx - 486662 */ - - x_to_y2(t1[0], t2[0], p[1]); /* t2[0] = Py^2 */ - sqrt(t1[0], t2[0]); /* t1[0] = Py or -Py */ - j = is_negative(t1[0]); /* ... check which */ - t2[0]._0 += 39420360; /* t2[0] = Py^2 + Gy^2 */ - mul(t2[1], BASE_2Y, t1[0]);/* t2[1] = 2 Py Gy or -2 Py Gy */ - sub(t1[j], t2[0], t2[1]); /* t1[0] = Py^2 + Gy^2 - 2 Py Gy */ - add(t1[1-j], t2[0], t2[1]);/* t1[1] = Py^2 + Gy^2 + 2 Py Gy */ - cpy(t2[0], p[1]); /* t2[0] = Px */ - t2[0]._0 -= 9; /* t2[0] = Px - Gx */ - sqr(t2[1], t2[0]); /* t2[1] = (Px - Gx)^2 */ - recip(t2[0], t2[1], 0); /* t2[0] = 1/(Px - Gx)^2 */ - mul(s[0], t1[0], t2[0]); /* s[0] = t1[0]/(Px - Gx)^2 */ - sub(s[0], s[0], p[1]); /* s[0] = t1[0]/(Px - Gx)^2 - Px */ - s[0]._0 -= 9 + 486662; /* s[0] = X(P+G) */ - mul(s[1], t1[1], t2[0]); /* s[1] = t1[1]/(Px - Gx)^2 */ - sub(s[1], s[1], p[1]); /* s[1] = t1[1]/(Px - Gx)^2 - Px */ - s[1]._0 -= 9 + 486662; /* s[1] = X(P-G) */ - mul_small(s[0], s[0], 1); /* reduce s[0] */ - mul_small(s[1], s[1], 1); /* reduce s[1] */ - - - /* prepare the chain */ - for (i = 0; i < 32; i++) { - vi = (vi >> 8) ^ (v[i] & 0xFF) ^ ((v[i] & 0xFF) << 1); - hi = (hi >> 8) ^ (h[i] & 0xFF) ^ ((h[i] & 0xFF) << 1); - nvh = ~(vi ^ hi); - di = (nvh & (di & 0x80) >> 7) ^ vi; - di ^= nvh & (di & 0x01) << 1; - di ^= nvh & (di & 0x02) << 1; - di ^= nvh & (di & 0x04) << 1; - di ^= nvh & (di & 0x08) << 1; - di ^= nvh & (di & 0x10) << 1; - di ^= nvh & (di & 0x20) << 1; - di ^= nvh & (di & 0x40) << 1; - d[i] = (byte)di; - } - - di = ((nvh & (di & 0x80) << 1) ^ vi) >> 8; - - /* initialize state */ - set(yx[0], 1); - cpy(yx[1], p[di]); - cpy(yx[2], s[0]); - set(yz[0], 0); - set(yz[1], 1); - set(yz[2], 1); - - /* y[0] is (even)P + (even)G - * y[1] is (even)P + (odd)G if current d-bit is 0 - * y[1] is (odd)P + (even)G if current d-bit is 1 - * y[2] is (odd)P + (odd)G - */ - - vi = 0; - hi = 0; - - /* and go for it! */ - for (i = 32; i--!=0; ) { - vi = (vi << 8) | (v[i] & 0xFF); - hi = (hi << 8) | (h[i] & 0xFF); - di = (di << 8) | (d[i] & 0xFF); - - for (j = 8; j--!=0; ) { - mont_prep(t1[0], t2[0], yx[0], yz[0]); - mont_prep(t1[1], t2[1], yx[1], yz[1]); - mont_prep(t1[2], t2[2], yx[2], yz[2]); - - k = ((vi ^ vi >> 1) >> j & 1) - + ((hi ^ hi >> 1) >> j & 1); - mont_dbl(yx[2], yz[2], t1[k], t2[k], yx[0], yz[0]); - - k = (di >> j & 2) ^ ((di >> j & 1) << 1); - mont_add(t1[1], t2[1], t1[k], t2[k], yx[1], yz[1], - p[di >> j & 1]); - - mont_add(t1[2], t2[2], t1[0], t2[0], yx[2], yz[2], - s[((vi ^ hi) >> j & 2) >> 1]); - } - } - - k = (vi & 1) + (hi & 1); - recip(t1[0], yz[k], 0); - mul(t1[1], yx[k], t1[0]); - - pack(t1[1], Y); - } - - /////////////////////////////////////////////////////////////////////////// - - /* sahn0: - * Using this class instead of long[10] to avoid bounds checks. */ - private static final class long10 { - public long10() {} - public long10( - long _0, long _1, long _2, long _3, long _4, - long _5, long _6, long _7, long _8, long _9) - { - this._0=_0; this._1=_1; this._2=_2; - this._3=_3; this._4=_4; this._5=_5; - this._6=_6; this._7=_7; this._8=_8; - this._9=_9; - } - public long _0,_1,_2,_3,_4,_5,_6,_7,_8,_9; - } - - /********************* radix 2^8 math *********************/ - - private static void cpy32(byte[] d, final byte[] s) { - int i; - for (i = 0; i < 32; i++) - d[i] = s[i]; - } - - /* p[m..n+m-1] = q[m..n+m-1] + z * x */ - /* n is the size of x */ - /* n+m is the size of p and q */ - private static int mula_small(byte[] p,byte[] q,int m,byte[] x,int n,int z) { - int v=0; - for (int i=0;i>=8; - } - return v; - } - - /* p += x * y * z where z is a small integer - * x is size 32, y is size t, p is size 32+t - * y is allowed to overlap with p+32 if you don't care about the upper half */ - private static int mula32(byte[] p, byte[] x, byte[] y, int t, int z) { - final int n = 31; - int w = 0; - int i = 0; - for (; i < t; i++) { - int zy = z * (y[i] & 0xFF); - w += mula_small(p, p, i, x, n, zy) + - (p[i+n] & 0xFF) + zy * (x[n] & 0xFF); - p[i+n] = (byte)w; - w >>= 8; - } - p[i+n] = (byte)(w + (p[i+n] & 0xFF)); - return w >> 8; - } - - /* divide r (size n) by d (size t), returning quotient q and remainder r - * quotient is size n-t+1, remainder is size t - * requires t > 0 && d[t-1] != 0 - * requires that r[-1] and d[-1] are valid memory locations - * q may overlap with r+t */ - private static void divmod(byte[] q, byte[] r, int n, byte[] d, int t) { - int rn = 0; - int dt = ((d[t-1] & 0xFF) << 8); - if (t>1) { - dt |= (d[t-2] & 0xFF); - } - while (n-- >= t) { - int z = (rn << 16) | ((r[n] & 0xFF) << 8); - if (n>0) { - z |= (r[n-1] & 0xFF); - } - z/=dt; - rn += mula_small(r,r, n-t+1, d, t, -z); - q[n-t+1] = (byte)((z + rn) & 0xFF); /* rn is 0 or -1 (underflow) */ - mula_small(r,r, n-t+1, d, t, -rn); - rn = (r[n] & 0xFF); - r[n] = 0; - } - r[t-1] = (byte)rn; - } - - private static int numsize(byte[] x,int n) { - while (n--!=0 && x[n]==0) - ; - return n+1; - } - - /* Returns x if a contains the gcd, y if b. - * Also, the returned buffer contains the inverse of a mod b, - * as 32-byte signed. - * x and y must have 64 bytes space for temporary use. - * requires that a[-1] and b[-1] are valid memory locations */ - private static byte[] egcd32(byte[] x,byte[] y,byte[] a,byte[] b) { - int an, bn = 32, qn, i; - for (i = 0; i < 32; i++) - x[i] = y[i] = 0; - x[0] = 1; - an = numsize(a, 32); - if (an==0) - return y; /* division by zero */ - byte[] temp=new byte[32]; - while (true) { - qn = bn - an + 1; - divmod(temp, b, bn, a, an); - bn = numsize(b, bn); - if (bn==0) - return x; - mula32(y, x, temp, qn, -1); - - qn = an - bn + 1; - divmod(temp, a, an, b, bn); - an = numsize(a, an); - if (an==0) - return y; - mula32(x, y, temp, qn, -1); - } - } - - /********************* radix 2^25.5 GF(2^255-19) math *********************/ - - private static final int P25=33554431; /* (1 << 25) - 1 */ - private static final int P26=67108863; /* (1 << 26) - 1 */ - - /* Convert to internal format from little-endian byte format */ - private static void unpack(long10 x, final byte[] m) { - x._0 = ((m[0] & 0xFF)) | ((m[1] & 0xFF))<<8 | - (m[2] & 0xFF)<<16 | ((m[3] & 0xFF)& 3)<<24; - x._1 = ((m[3] & 0xFF)&~ 3)>>2 | (m[4] & 0xFF)<<6 | - (m[5] & 0xFF)<<14 | ((m[6] & 0xFF)& 7)<<22; - x._2 = ((m[6] & 0xFF)&~ 7)>>3 | (m[7] & 0xFF)<<5 | - (m[8] & 0xFF)<<13 | ((m[9] & 0xFF)&31)<<21; - x._3 = ((m[9] & 0xFF)&~31)>>5 | (m[10] & 0xFF)<<3 | - (m[11] & 0xFF)<<11 | ((m[12] & 0xFF)&63)<<19; - x._4 = ((m[12] & 0xFF)&~63)>>6 | (m[13] & 0xFF)<<2 | - (m[14] & 0xFF)<<10 | (m[15] & 0xFF) <<18; - x._5 = (m[16] & 0xFF) | (m[17] & 0xFF)<<8 | - (m[18] & 0xFF)<<16 | ((m[19] & 0xFF)& 1)<<24; - x._6 = ((m[19] & 0xFF)&~ 1)>>1 | (m[20] & 0xFF)<<7 | - (m[21] & 0xFF)<<15 | ((m[22] & 0xFF)& 7)<<23; - x._7 = ((m[22] & 0xFF)&~ 7)>>3 | (m[23] & 0xFF)<<5 | - (m[24] & 0xFF)<<13 | ((m[25] & 0xFF)&15)<<21; - x._8 = ((m[25] & 0xFF)&~15)>>4 | (m[26] & 0xFF)<<4 | - (m[27] & 0xFF)<<12 | ((m[28] & 0xFF)&63)<<20; - x._9 = ((m[28] & 0xFF)&~63)>>6 | (m[29] & 0xFF)<<2 | - (m[30] & 0xFF)<<10 | (m[31] & 0xFF) <<18; - } - - /* Check if reduced-form input >= 2^255-19 */ - private static boolean is_overflow(final long10 x) { - return ( - ((x._0 > P26-19)) && - ((x._1 & x._3 & x._5 & x._7 & x._9) == P25) && - ((x._2 & x._4 & x._6 & x._8) == P26) - ) || (x._9 > P25); - } - - /* Convert from internal format to little-endian byte format. The - * number must be in a reduced form which is output by the following ops: - * unpack, mul, sqr - * set -- if input in range 0 .. P25 - * If you're unsure if the number is reduced, first multiply it by 1. */ - private static void pack(final long10 x, final byte[] m) { - int ld = 0, ud = 0; - long t; - ld = (is_overflow(x)?1:0) - ((x._9 < 0)?1:0); - ud = ld * -(P25+1); - ld *= 19; - t = ld + x._0 + (x._1 << 26); - m[ 0] = (byte)t; - m[ 1] = (byte)(t >> 8); - m[ 2] = (byte)(t >> 16); - m[ 3] = (byte)(t >> 24); - t = (t >> 32) + (x._2 << 19); - m[ 4] = (byte)t; - m[ 5] = (byte)(t >> 8); - m[ 6] = (byte)(t >> 16); - m[ 7] = (byte)(t >> 24); - t = (t >> 32) + (x._3 << 13); - m[ 8] = (byte)t; - m[ 9] = (byte)(t >> 8); - m[10] = (byte)(t >> 16); - m[11] = (byte)(t >> 24); - t = (t >> 32) + (x._4 << 6); - m[12] = (byte)t; - m[13] = (byte)(t >> 8); - m[14] = (byte)(t >> 16); - m[15] = (byte)(t >> 24); - t = (t >> 32) + x._5 + (x._6 << 25); - m[16] = (byte)t; - m[17] = (byte)(t >> 8); - m[18] = (byte)(t >> 16); - m[19] = (byte)(t >> 24); - t = (t >> 32) + (x._7 << 19); - m[20] = (byte)t; - m[21] = (byte)(t >> 8); - m[22] = (byte)(t >> 16); - m[23] = (byte)(t >> 24); - t = (t >> 32) + (x._8 << 12); - m[24] = (byte)t; - m[25] = (byte)(t >> 8); - m[26] = (byte)(t >> 16); - m[27] = (byte)(t >> 24); - t = (t >> 32) + ((x._9 + ud) << 6); - m[28] = (byte)t; - m[29] = (byte)(t >> 8); - m[30] = (byte)(t >> 16); - m[31] = (byte)(t >> 24); - } - - /* Copy a number */ - private static void cpy(long10 out, long10 in) { - out._0=in._0; out._1=in._1; - out._2=in._2; out._3=in._3; - out._4=in._4; out._5=in._5; - out._6=in._6; out._7=in._7; - out._8=in._8; out._9=in._9; - } - - /* Set a number to value, which must be in range -185861411 .. 185861411 */ - private static void set(long10 out, int in) { - out._0=in; out._1=0; - out._2=0; out._3=0; - out._4=0; out._5=0; - out._6=0; out._7=0; - out._8=0; out._9=0; - } - - /* Add/subtract two numbers. The inputs must be in reduced form, and the - * output isn't, so to do another addition or subtraction on the output, - * first multiply it by one to reduce it. */ - private static void add(long10 xy, long10 x, long10 y) { - xy._0 = x._0 + y._0; xy._1 = x._1 + y._1; - xy._2 = x._2 + y._2; xy._3 = x._3 + y._3; - xy._4 = x._4 + y._4; xy._5 = x._5 + y._5; - xy._6 = x._6 + y._6; xy._7 = x._7 + y._7; - xy._8 = x._8 + y._8; xy._9 = x._9 + y._9; - } - private static void sub(long10 xy, long10 x, long10 y) { - xy._0 = x._0 - y._0; xy._1 = x._1 - y._1; - xy._2 = x._2 - y._2; xy._3 = x._3 - y._3; - xy._4 = x._4 - y._4; xy._5 = x._5 - y._5; - xy._6 = x._6 - y._6; xy._7 = x._7 - y._7; - xy._8 = x._8 - y._8; xy._9 = x._9 - y._9; - } - - /* Multiply a number by a small integer in range -185861411 .. 185861411. - * The output is in reduced form, the input x need not be. x and xy may point - * to the same buffer. */ - private static long10 mul_small(long10 xy, long10 x, long y) { - long t; - t = (x._8*y); - xy._8 = (t & ((1 << 26) - 1)); - t = (t >> 26) + (x._9*y); - xy._9 = (t & ((1 << 25) - 1)); - t = 19 * (t >> 25) + (x._0*y); - xy._0 = (t & ((1 << 26) - 1)); - t = (t >> 26) + (x._1*y); - xy._1 = (t & ((1 << 25) - 1)); - t = (t >> 25) + (x._2*y); - xy._2 = (t & ((1 << 26) - 1)); - t = (t >> 26) + (x._3*y); - xy._3 = (t & ((1 << 25) - 1)); - t = (t >> 25) + (x._4*y); - xy._4 = (t & ((1 << 26) - 1)); - t = (t >> 26) + (x._5*y); - xy._5 = (t & ((1 << 25) - 1)); - t = (t >> 25) + (x._6*y); - xy._6 = (t & ((1 << 26) - 1)); - t = (t >> 26) + (x._7*y); - xy._7 = (t & ((1 << 25) - 1)); - t = (t >> 25) + xy._8; - xy._8 = (t & ((1 << 26) - 1)); - xy._9 += (t >> 26); - return xy; - } - - /* Multiply two numbers. The output is in reduced form, the inputs need not - * be. */ - private static long10 mul(long10 xy, long10 x, long10 y) { - /* sahn0: - * Using local variables to avoid class access. - * This seem to improve performance a bit... - */ - long - x_0=x._0,x_1=x._1,x_2=x._2,x_3=x._3,x_4=x._4, - x_5=x._5,x_6=x._6,x_7=x._7,x_8=x._8,x_9=x._9; - long - y_0=y._0,y_1=y._1,y_2=y._2,y_3=y._3,y_4=y._4, - y_5=y._5,y_6=y._6,y_7=y._7,y_8=y._8,y_9=y._9; - long t; - t = (x_0*y_8) + (x_2*y_6) + (x_4*y_4) + (x_6*y_2) + - (x_8*y_0) + 2 * ((x_1*y_7) + (x_3*y_5) + - (x_5*y_3) + (x_7*y_1)) + 38 * - (x_9*y_9); - xy._8 = (t & ((1 << 26) - 1)); - t = (t >> 26) + (x_0*y_9) + (x_1*y_8) + (x_2*y_7) + - (x_3*y_6) + (x_4*y_5) + (x_5*y_4) + - (x_6*y_3) + (x_7*y_2) + (x_8*y_1) + - (x_9*y_0); - xy._9 = (t & ((1 << 25) - 1)); - t = (x_0*y_0) + 19 * ((t >> 25) + (x_2*y_8) + (x_4*y_6) - + (x_6*y_4) + (x_8*y_2)) + 38 * - ((x_1*y_9) + (x_3*y_7) + (x_5*y_5) + - (x_7*y_3) + (x_9*y_1)); - xy._0 = (t & ((1 << 26) - 1)); - t = (t >> 26) + (x_0*y_1) + (x_1*y_0) + 19 * ((x_2*y_9) - + (x_3*y_8) + (x_4*y_7) + (x_5*y_6) + - (x_6*y_5) + (x_7*y_4) + (x_8*y_3) + - (x_9*y_2)); - xy._1 = (t & ((1 << 25) - 1)); - t = (t >> 25) + (x_0*y_2) + (x_2*y_0) + 19 * ((x_4*y_8) - + (x_6*y_6) + (x_8*y_4)) + 2 * (x_1*y_1) - + 38 * ((x_3*y_9) + (x_5*y_7) + - (x_7*y_5) + (x_9*y_3)); - xy._2 = (t & ((1 << 26) - 1)); - t = (t >> 26) + (x_0*y_3) + (x_1*y_2) + (x_2*y_1) + - (x_3*y_0) + 19 * ((x_4*y_9) + (x_5*y_8) + - (x_6*y_7) + (x_7*y_6) + - (x_8*y_5) + (x_9*y_4)); - xy._3 = (t & ((1 << 25) - 1)); - t = (t >> 25) + (x_0*y_4) + (x_2*y_2) + (x_4*y_0) + 19 * - ((x_6*y_8) + (x_8*y_6)) + 2 * ((x_1*y_3) + - (x_3*y_1)) + 38 * - ((x_5*y_9) + (x_7*y_7) + (x_9*y_5)); - xy._4 = (t & ((1 << 26) - 1)); - t = (t >> 26) + (x_0*y_5) + (x_1*y_4) + (x_2*y_3) + - (x_3*y_2) + (x_4*y_1) + (x_5*y_0) + 19 * - ((x_6*y_9) + (x_7*y_8) + (x_8*y_7) + - (x_9*y_6)); - xy._5 = (t & ((1 << 25) - 1)); - t = (t >> 25) + (x_0*y_6) + (x_2*y_4) + (x_4*y_2) + - (x_6*y_0) + 19 * (x_8*y_8) + 2 * ((x_1*y_5) + - (x_3*y_3) + (x_5*y_1)) + 38 * - ((x_7*y_9) + (x_9*y_7)); - xy._6 = (t & ((1 << 26) - 1)); - t = (t >> 26) + (x_0*y_7) + (x_1*y_6) + (x_2*y_5) + - (x_3*y_4) + (x_4*y_3) + (x_5*y_2) + - (x_6*y_1) + (x_7*y_0) + 19 * ((x_8*y_9) + - (x_9*y_8)); - xy._7 = (t & ((1 << 25) - 1)); - t = (t >> 25) + xy._8; - xy._8 = (t & ((1 << 26) - 1)); - xy._9 += (t >> 26); - return xy; - } - - /* Square a number. Optimization of mul25519(x2, x, x) */ - private static long10 sqr(long10 x2, long10 x) { - long - x_0=x._0,x_1=x._1,x_2=x._2,x_3=x._3,x_4=x._4, - x_5=x._5,x_6=x._6,x_7=x._7,x_8=x._8,x_9=x._9; - long t; - t = (x_4*x_4) + 2 * ((x_0*x_8) + (x_2*x_6)) + 38 * - (x_9*x_9) + 4 * ((x_1*x_7) + (x_3*x_5)); - x2._8 = (t & ((1 << 26) - 1)); - t = (t >> 26) + 2 * ((x_0*x_9) + (x_1*x_8) + (x_2*x_7) + - (x_3*x_6) + (x_4*x_5)); - x2._9 = (t & ((1 << 25) - 1)); - t = 19 * (t >> 25) + (x_0*x_0) + 38 * ((x_2*x_8) + - (x_4*x_6) + (x_5*x_5)) + 76 * ((x_1*x_9) - + (x_3*x_7)); - x2._0 = (t & ((1 << 26) - 1)); - t = (t >> 26) + 2 * (x_0*x_1) + 38 * ((x_2*x_9) + - (x_3*x_8) + (x_4*x_7) + (x_5*x_6)); - x2._1 = (t & ((1 << 25) - 1)); - t = (t >> 25) + 19 * (x_6*x_6) + 2 * ((x_0*x_2) + - (x_1*x_1)) + 38 * (x_4*x_8) + 76 * - ((x_3*x_9) + (x_5*x_7)); - x2._2 = (t & ((1 << 26) - 1)); - t = (t >> 26) + 2 * ((x_0*x_3) + (x_1*x_2)) + 38 * - ((x_4*x_9) + (x_5*x_8) + (x_6*x_7)); - x2._3 = (t & ((1 << 25) - 1)); - t = (t >> 25) + (x_2*x_2) + 2 * (x_0*x_4) + 38 * - ((x_6*x_8) + (x_7*x_7)) + 4 * (x_1*x_3) + 76 * - (x_5*x_9); - x2._4 = (t & ((1 << 26) - 1)); - t = (t >> 26) + 2 * ((x_0*x_5) + (x_1*x_4) + (x_2*x_3)) - + 38 * ((x_6*x_9) + (x_7*x_8)); - x2._5 = (t & ((1 << 25) - 1)); - t = (t >> 25) + 19 * (x_8*x_8) + 2 * ((x_0*x_6) + - (x_2*x_4) + (x_3*x_3)) + 4 * (x_1*x_5) + - 76 * (x_7*x_9); - x2._6 = (t & ((1 << 26) - 1)); - t = (t >> 26) + 2 * ((x_0*x_7) + (x_1*x_6) + (x_2*x_5) + - (x_3*x_4)) + 38 * (x_8*x_9); - x2._7 = (t & ((1 << 25) - 1)); - t = (t >> 25) + x2._8; - x2._8 = (t & ((1 << 26) - 1)); - x2._9 += (t >> 26); - return x2; - } - - /* Calculates a reciprocal. The output is in reduced form, the inputs need not - * be. Simply calculates y = x^(p-2) so it's not too fast. */ - /* When sqrtassist is true, it instead calculates y = x^((p-5)/8) */ - private static void recip(long10 y, long10 x, int sqrtassist) { - long10 - t0=new long10(), - t1=new long10(), - t2=new long10(), - t3=new long10(), - t4=new long10(); - int i; - /* the chain for x^(2^255-21) is straight from djb's implementation */ - sqr(t1, x); /* 2 == 2 * 1 */ - sqr(t2, t1); /* 4 == 2 * 2 */ - sqr(t0, t2); /* 8 == 2 * 4 */ - mul(t2, t0, x); /* 9 == 8 + 1 */ - mul(t0, t2, t1); /* 11 == 9 + 2 */ - sqr(t1, t0); /* 22 == 2 * 11 */ - mul(t3, t1, t2); /* 31 == 22 + 9 - == 2^5 - 2^0 */ - sqr(t1, t3); /* 2^6 - 2^1 */ - sqr(t2, t1); /* 2^7 - 2^2 */ - sqr(t1, t2); /* 2^8 - 2^3 */ - sqr(t2, t1); /* 2^9 - 2^4 */ - sqr(t1, t2); /* 2^10 - 2^5 */ - mul(t2, t1, t3); /* 2^10 - 2^0 */ - sqr(t1, t2); /* 2^11 - 2^1 */ - sqr(t3, t1); /* 2^12 - 2^2 */ - for (i = 1; i < 5; i++) { - sqr(t1, t3); - sqr(t3, t1); - } /* t3 */ /* 2^20 - 2^10 */ - mul(t1, t3, t2); /* 2^20 - 2^0 */ - sqr(t3, t1); /* 2^21 - 2^1 */ - sqr(t4, t3); /* 2^22 - 2^2 */ - for (i = 1; i < 10; i++) { - sqr(t3, t4); - sqr(t4, t3); - } /* t4 */ /* 2^40 - 2^20 */ - mul(t3, t4, t1); /* 2^40 - 2^0 */ - for (i = 0; i < 5; i++) { - sqr(t1, t3); - sqr(t3, t1); - } /* t3 */ /* 2^50 - 2^10 */ - mul(t1, t3, t2); /* 2^50 - 2^0 */ - sqr(t2, t1); /* 2^51 - 2^1 */ - sqr(t3, t2); /* 2^52 - 2^2 */ - for (i = 1; i < 25; i++) { - sqr(t2, t3); - sqr(t3, t2); - } /* t3 */ /* 2^100 - 2^50 */ - mul(t2, t3, t1); /* 2^100 - 2^0 */ - sqr(t3, t2); /* 2^101 - 2^1 */ - sqr(t4, t3); /* 2^102 - 2^2 */ - for (i = 1; i < 50; i++) { - sqr(t3, t4); - sqr(t4, t3); - } /* t4 */ /* 2^200 - 2^100 */ - mul(t3, t4, t2); /* 2^200 - 2^0 */ - for (i = 0; i < 25; i++) { - sqr(t4, t3); - sqr(t3, t4); - } /* t3 */ /* 2^250 - 2^50 */ - mul(t2, t3, t1); /* 2^250 - 2^0 */ - sqr(t1, t2); /* 2^251 - 2^1 */ - sqr(t2, t1); /* 2^252 - 2^2 */ - if (sqrtassist!=0) { - mul(y, x, t2); /* 2^252 - 3 */ - } else { - sqr(t1, t2); /* 2^253 - 2^3 */ - sqr(t2, t1); /* 2^254 - 2^4 */ - sqr(t1, t2); /* 2^255 - 2^5 */ - mul(y, t1, t0); /* 2^255 - 21 */ - } - } - - /* checks if x is "negative", requires reduced input */ - private static int is_negative(long10 x) { - return (int)(((is_overflow(x) || (x._9 < 0))?1:0) ^ (x._0 & 1)); - } - - /* a square root */ - private static void sqrt(long10 x, long10 u) { - long10 v=new long10(), t1=new long10(), t2=new long10(); - add(t1, u, u); /* t1 = 2u */ - recip(v, t1, 1); /* v = (2u)^((p-5)/8) */ - sqr(x, v); /* x = v^2 */ - mul(t2, t1, x); /* t2 = 2uv^2 */ - t2._0--; /* t2 = 2uv^2-1 */ - mul(t1, v, t2); /* t1 = v(2uv^2-1) */ - mul(x, u, t1); /* x = uv(2uv^2-1) */ - } - - /********************* Elliptic curve *********************/ - - /* y^2 = x^3 + 486662 x^2 + x over GF(2^255-19) */ - - /* t1 = ax + az - * t2 = ax - az */ - private static void mont_prep(long10 t1, long10 t2, long10 ax, long10 az) { - add(t1, ax, az); - sub(t2, ax, az); - } - - /* A = P + Q where - * X(A) = ax/az - * X(P) = (t1+t2)/(t1-t2) - * X(Q) = (t3+t4)/(t3-t4) - * X(P-Q) = dx - * clobbers t1 and t2, preserves t3 and t4 */ - private static void mont_add(long10 t1, long10 t2, long10 t3, long10 t4,long10 ax, long10 az, long10 dx) { - mul(ax, t2, t3); - mul(az, t1, t4); - add(t1, ax, az); - sub(t2, ax, az); - sqr(ax, t1); - sqr(t1, t2); - mul(az, t1, dx); - } - - /* B = 2 * Q where - * X(B) = bx/bz - * X(Q) = (t3+t4)/(t3-t4) - * clobbers t1 and t2, preserves t3 and t4 */ - private static void mont_dbl(long10 t1, long10 t2, long10 t3, long10 t4,long10 bx, long10 bz) { - sqr(t1, t3); - sqr(t2, t4); - mul(bx, t1, t2); - sub(t2, t1, t2); - mul_small(bz, t2, 121665); - add(t1, t1, bz); - mul(bz, t1, t2); - } - - /* Y^2 = X^3 + 486662 X^2 + X - * t is a temporary */ - private static void x_to_y2(long10 t, long10 y2, long10 x) { - sqr(t, x); - mul_small(y2, x, 486662); - add(t, t, y2); - t._0++; - mul(y2, t, x); - } - - /* P = kG and s = sign(P)/k */ - private static void core(byte[] Px, byte[] s, final byte[] k, final byte[] Gx) { - long10 - dx=new long10(), - t1=new long10(), - t2=new long10(), - t3=new long10(), - t4=new long10(); - long10[] - x=new long10[]{new long10(),new long10()}, - z=new long10[]{new long10(),new long10()}; - int i, j; - - /* unpack the base */ - if (Gx!=null) - unpack(dx, Gx); - else - set(dx, 9); - - /* 0G = point-at-infinity */ - set(x[0], 1); - set(z[0], 0); - - /* 1G = G */ - cpy(x[1], dx); - set(z[1], 1); - - for (i = 32; i--!=0; ) { - if (i==0) { - i=0; - } - for (j = 8; j--!=0; ) { - /* swap arguments depending on bit */ - int bit1 = (k[i] & 0xFF) >> j & 1; - int bit0 = ~(k[i] & 0xFF) >> j & 1; - long10 ax = x[bit0]; - long10 az = z[bit0]; - long10 bx = x[bit1]; - long10 bz = z[bit1]; - - /* a' = a + b */ - /* b' = 2 b */ - mont_prep(t1, t2, ax, az); - mont_prep(t3, t4, bx, bz); - mont_add(t1, t2, t3, t4, ax, az, dx); - mont_dbl(t1, t2, t3, t4, bx, bz); - } - } - - recip(t1, z[0], 0); - mul(dx, x[0], t1); - pack(dx, Px); - - /* calculate s such that s abs(P) = G .. assumes G is std base point */ - if (s!=null) { - x_to_y2(t2, t1, dx); /* t1 = Py^2 */ - recip(t3, z[1], 0); /* where Q=P+G ... */ - mul(t2, x[1], t3); /* t2 = Qx */ - add(t2, t2, dx); /* t2 = Qx + Px */ - t2._0 += 9 + 486662; /* t2 = Qx + Px + Gx + 486662 */ - dx._0 -= 9; /* dx = Px - Gx */ - sqr(t3, dx); /* t3 = (Px - Gx)^2 */ - mul(dx, t2, t3); /* dx = t2 (Px - Gx)^2 */ - sub(dx, dx, t1); /* dx = t2 (Px - Gx)^2 - Py^2 */ - dx._0 -= 39420360; /* dx = t2 (Px - Gx)^2 - Py^2 - Gy^2 */ - mul(t1, dx, BASE_R2Y); /* t1 = -Py */ - if (is_negative(t1)!=0) /* sign is 1, so just copy */ - cpy32(s, k); - else /* sign is -1, so negate */ - mula_small(s, ORDER_TIMES_8, 0, k, 32, -1); - - /* reduce s mod q - * (is this needed? do it just in case, it's fast anyway) */ - //divmod((dstptr) t1, s, 32, order25519, 32); - - /* take reciprocal of s mod q */ - byte[] temp1=new byte[32]; - byte[] temp2=new byte[64]; - byte[] temp3=new byte[64]; - cpy32(temp1, ORDER); - cpy32(s, egcd32(temp2, temp3, s, temp1)); - if ((s[31] & 0x80)!=0) - mula_small(s, s, 0, ORDER, 32, 1); - } - } - - /* smallest multiple of the order that's >= 2^255 */ - private static final byte[] ORDER_TIMES_8 = { - (byte)104, (byte)159, (byte)174, (byte)231, - (byte)210, (byte)24, (byte)147, (byte)192, - (byte)178, (byte)230, (byte)188, (byte)23, - (byte)245, (byte)206, (byte)247, (byte)166, - (byte)0, (byte)0, (byte)0, (byte)0, - (byte)0, (byte)0, (byte)0, (byte)0, - (byte)0, (byte)0, (byte)0, (byte)0, - (byte)0, (byte)0, (byte)0, (byte)128 - }; - - /* constants 2Gy and 1/(2Gy) */ - private static final long10 BASE_2Y = new long10( - 39999547, 18689728, 59995525, 1648697, 57546132, - 24010086, 19059592, 5425144, 63499247, 16420658 - ); - private static final long10 BASE_R2Y = new long10( - 5744, 8160848, 4790893, 13779497, 35730846, - 12541209, 49101323, 30047407, 40071253, 6226132 - ); -} diff --git a/src/gnu/java/bigintcrypto/BigIntegerCrypto.java b/src/gnu/java/bigintcrypto/BigIntegerCrypto.java deleted file mode 100755 index c11687d..0000000 --- a/src/gnu/java/bigintcrypto/BigIntegerCrypto.java +++ /dev/null @@ -1,2340 +0,0 @@ -/* java.bigintcrypto.BigIntegerCrypto -- Arbitary precision integers for - * crypto applications, for example Diffie-Hellman key agreements. - * -Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007, 2009 Free Software Foundation, Inc. - -This file is part of GNU ZRTP4J - -GNU ZRTP4J 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 3, or (at your option) -any later version. - -GNU ZRTP4J 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 GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package gnu.java.bigintcrypto; - -import java.lang.StringBuffer; -import gnu.java.math.MPN; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.util.Random; -import java.util.Arrays; - -import org.bouncycastle.crypto.prng.RandomGenerator; - -/** - * Crypto-aware big integer implementation. - * - * This implememtation re-uses the GNU classpath BigInteger implementation - * and modifies/enhances it to be more "crypto-aware. - * - * Some crypto specific enhancements: - * - * Written using on-line Java Platform 1.2 API Specification, as well as - * "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998) and - * "Applied Cryptography, Second Edition" by Bruce Schneier (Wiley, 1996). - * - * Based primarily on IntNum.java BitOps.java by Per Bothner (per@bothner.com) - * (found in Kawa 1.6.62). - * - * @author Werner Dittmann (werner.dittmann@t-online.de) - * @date March 21, 2009 - * - * @author Warren Levy (warrenl@cygnus.com) - * @date December 20, 1999. - * @status believed complete and correct. - */ -public class BigIntegerCrypto extends Number implements - Comparable { - - // private static final Logger log = - // Logger.getLogger(BigInteger.class.getName()); - - /** - * All integers are stored in 2's-complement form. If words == null, the - * ival is the value of this BigInteger. Otherwise, the first ival elements - * of words make the value of this BigInteger, stored in little-endian - * order, 2's-complement form. - */ - private transient int ival; - - private transient int[] words; - - private byte[] magnitude; - - private int signum; - - private static final long serialVersionUID = -3877199389772696545L; - - /** - * We pre-allocate integers in the range minFixNum..maxFixNum. Note that we - * must at least preallocate 0, 1, and 10. - */ - private static final int minFixNum = -100; - - private static final int maxFixNum = 1024; - - private static final int numFixNum = maxFixNum - minFixNum + 1; - - private static final BigIntegerCrypto[] smallFixNums; - - static { - smallFixNums = new BigIntegerCrypto[numFixNum]; - for (int i = numFixNum; --i >= 0;) - smallFixNums[i] = new BigIntegerCrypto(i + minFixNum); - - ZERO = smallFixNums[-minFixNum]; - ONE = smallFixNums[1 - minFixNum]; - TEN = smallFixNums[10 - minFixNum]; - } - - /** - * The constant zero as a BigInteger. - * - * @since 1.2 - */ - public static final BigIntegerCrypto ZERO; - - /** - * The constant one as a BigInteger. - * - * @since 1.2 - */ - public static final BigIntegerCrypto ONE; - - /** - * The constant ten as a BigInteger. - * - * @since 1.5 - */ - public static final BigIntegerCrypto TEN; - - /* Rounding modes: */ - private static final int FLOOR = 1; - - private static final int CEILING = 2; - - private static final int TRUNCATE = 3; - - private static final int ROUND = 4; - - /** - * When checking the probability of primes, it is most efficient to first - * check the factoring of small primes, so we'll use this array. - */ - private static final int[] primes = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, - 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, - 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, - 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, - 241, 251 }; - - /** HAC (Handbook of Applied Cryptography), Alfred Menezes & al. Table 4.4. */ - private static final int[] k = { 100, 150, 200, 250, 300, 350, 400, 500, - 600, 800, 1250, Integer.MAX_VALUE }; - - private static final int[] t = { 27, 18, 15, 12, 9, 8, 7, 6, 5, 4, 3, 2 }; - - private BigIntegerCrypto() { - super(); - } - - /* Create a new (non-shared) BigInteger, and initialize to an int. */ - private BigIntegerCrypto(int value) { - super(); - - ival = value; - } - - public BigIntegerCrypto(String s, int radix) { - this(); - - int len = s.length(); - int i, digit; - boolean negative; - byte[] bytes; - char ch = s.charAt(0); - if (ch == '-') { - negative = true; - i = 1; - bytes = new byte[len - 1]; - } else { - negative = false; - i = 0; - bytes = new byte[len]; - } - int byte_len = 0; - for (; i < len; i++) { - ch = s.charAt(i); - digit = Character.digit(ch, radix); - if (digit < 0) - throw new NumberFormatException( - "Invalid character at position #" + i); - bytes[byte_len++] = (byte) digit; - } - - BigIntegerCrypto result; - // Testing (len < MPN.chars_per_word(radix)) would be more accurate, - // but slightly more expensive, for little practical gain. - if (len <= 15 && radix <= 16) - result = valueOf(Long.parseLong(s, radix)); - else - result = valueOf(bytes, byte_len, negative, radix); - - Arrays.fill(bytes, (byte)0); // crypto: delete temporary content - this.ival = result.ival; - this.words = result.words; - } - - public BigIntegerCrypto(String val) { - this(val, 10); - } - - /* Create a new possibly shared BigInteger, and initialize from a byte array. */ - public BigIntegerCrypto(byte[] val) { - this(); - - if (val == null || val.length < 1) - throw new NumberFormatException(); - - words = byteArrayToIntArray(val, val[0] < 0 ? -1 : 0); - BigIntegerCrypto result = make(words, words.length); - this.ival = result.ival; - this.words = result.words; - } - - public BigIntegerCrypto(int signum, byte[] magnitude) { - this(); - - if (magnitude == null || signum > 1 || signum < -1) - throw new NumberFormatException(); - - if (signum == 0) { - int i; - for (i = magnitude.length - 1; i >= 0 && magnitude[i] == 0; --i) - ; - if (i >= 0) - throw new NumberFormatException(); - return; - } - - // Magnitude is always positive, so don't ever pass a sign of -1. - words = byteArrayToIntArray(magnitude, 0); - BigIntegerCrypto result = make(words, words.length); - this.ival = result.ival; - this.words = result.words; - - if (signum < 0) - setNegative(); - } - - public BigIntegerCrypto(int numBits, Random rnd) { - this(); - - if (numBits < 0) - throw new IllegalArgumentException(); - - init(numBits, rnd); - } - - public BigIntegerCrypto(int numBits, RandomGenerator rnd) { - this(); - - if (numBits < 0) - throw new IllegalArgumentException(); - - init(numBits, rnd); - } - private void init(int numBits, Random rnd) { - int highbits = numBits & 31; - // minimum number of bytes to store the above number of bits - int highBitByteCount = (highbits + 7) / 8; - // number of bits to discard from the last byte - int discardedBitCount = highbits % 8; - if (discardedBitCount != 0) - discardedBitCount = 8 - discardedBitCount; - byte[] highBitBytes = new byte[highBitByteCount]; - if (highbits > 0) { - rnd.nextBytes(highBitBytes); - highbits = (highBitBytes[highBitByteCount - 1] & 0xFF) >>> discardedBitCount; - for (int i = highBitByteCount - 2; i >= 0; i--) - highbits = (highbits << 8) | (highBitBytes[i] & 0xFF); - } - int nwords = numBits / 32; - - while (highbits == 0 && nwords > 0) { - highbits = rnd.nextInt(); - --nwords; - } - if (nwords == 0 && highbits >= 0) { - ival = highbits; - } else { - ival = highbits < 0 ? nwords + 2 : nwords + 1; - words = new int[ival]; - words[nwords] = highbits; - while (--nwords >= 0) - words[nwords] = rnd.nextInt(); - } - } - - private void init(int numBits, RandomGenerator rnd) { - int highbits = numBits & 31; - // minimum number of bytes to store the above number of bits - int highBitByteCount = (highbits + 7) / 8; - // number of bits to discard from the last byte - int discardedBitCount = highbits % 8; - if (discardedBitCount != 0) - discardedBitCount = 8 - discardedBitCount; - byte[] highBitBytes = new byte[highBitByteCount]; - if (highbits > 0) { - rnd.nextBytes(highBitBytes); - highbits = (highBitBytes[highBitByteCount - 1] & 0xFF) >>> discardedBitCount; - for (int i = highBitByteCount - 2; i >= 0; i--) - highbits = (highbits << 8) | (highBitBytes[i] & 0xFF); - } - int nwords = numBits / 32; - - byte tmpBytes[] = new byte[4]; - while (highbits == 0 && nwords > 0) { - rnd.nextBytes(tmpBytes); - highbits = (byte)tmpBytes[0]; - highbits |= tmpBytes[1] << 8; - highbits |= tmpBytes[2] << 16; - highbits |= tmpBytes[3] << 24; - --nwords; - } - if (nwords == 0 && highbits >= 0) { - ival = highbits; - } else { - ival = highbits < 0 ? nwords + 2 : nwords + 1; - words = new int[ival]; - words[nwords] = highbits; - while (--nwords >= 0) { - rnd.nextBytes(tmpBytes); - words[nwords] = (byte)tmpBytes[0]; - words[nwords] |= tmpBytes[1] << 8; - words[nwords] |= tmpBytes[2] << 16; - words[nwords] |= tmpBytes[3] << 24; - } - } - } - - public BigIntegerCrypto(int bitLength, int certainty, Random rnd) { - this(); - - BigIntegerCrypto result = new BigIntegerCrypto(); - while (true) { - result.init(bitLength, rnd); - result = result.setBit(bitLength - 1); - if (result.isProbablePrime(certainty)) - break; - } - - this.ival = result.ival; - this.words = result.words; - } - - public BigIntegerCrypto(int bitLength, int certainty, RandomGenerator rnd) { - this(); - - BigIntegerCrypto result = new BigIntegerCrypto(); - while (true) { - result.init(bitLength, rnd); - result = result.setBit(bitLength - 1); - if (result.isProbablePrime(certainty)) - break; - } - - this.ival = result.ival; - this.words = result.words; - } - /** - * Clear content and reset to a zero BigIntegerCrypto. - * - * Clear all allocated data (overwrite with 0) and reset this - * BigIntegerCrypto to zero. - * - * This method clears the content of real big integers only and does - * not clear predefined "small" big integers and small constants. - * - * Crypto: enhancement. - */ - public void zeroize() { - if (words != null) { - Arrays.fill(words, 0); - words = null; - ival = 0; - } - } - - /** - * Return a BigInteger that is bitLength bits long with a probability < - * 2^-100 of being composite. - * - * @param bitLength - * length in bits of resulting number - * @param rnd - * random number generator to use - * @throws ArithmeticException - * if bitLength < 2 - * @since 1.4 - */ - public static BigIntegerCrypto probablePrime(int bitLength, Random rnd) { - if (bitLength < 2) - throw new ArithmeticException(); - - return new BigIntegerCrypto(bitLength, 100, rnd); - } - - /** Return a (possibly-shared) BigInteger with a given long value. */ - public static BigIntegerCrypto valueOf(long val) { - if (val >= minFixNum && val <= maxFixNum) - return smallFixNums[(int) val - minFixNum]; - int i = (int)val; - if (i == val) - return new BigIntegerCrypto(i); - BigIntegerCrypto result = alloc(2); - result.ival = 2; - result.words[0] = i; - result.words[1] = (int) (val >> 32); - return result; - } - - /** - * Make a canonicalized BigInteger from an array of words. The array may be - * reused (without copying). - */ - private static BigIntegerCrypto make(int[] words, int len) { - if (words == null) - return valueOf(len); - len = BigIntegerCrypto.wordsNeeded(words, len); - if (len <= 1) - return len == 0 ? ZERO : valueOf(words[0]); - BigIntegerCrypto num = new BigIntegerCrypto(); - num.words = words; - num.ival = len; - return num; - } - - /** Convert a big-endian byte array to a little-endian array of words. */ - private static int[] byteArrayToIntArray(byte[] bytes, int sign) { - // Determine number of words needed. - int[] words = new int[bytes.length / 4 + 1]; - int nwords = words.length; - - // Create a int out of modulo 4 high order bytes. - int bptr = 0; - int word = sign; - for (int i = bytes.length % 4; i > 0; --i, bptr++) - word = (word << 8) | (bytes[bptr] & 0xff); - words[--nwords] = word; - - // Elements remaining in byte[] are a multiple of 4. - while (nwords > 0) - words[--nwords] = bytes[bptr++] << 24 - | (bytes[bptr++] & 0xff) << 16 - | (bytes[bptr++] & 0xff) << 8 | (bytes[bptr++] & 0xff); - return words; - } - - /** - * Allocate a new non-shared BigInteger. - * - * @param nwords - * number of words to allocate - */ - private static BigIntegerCrypto alloc(int nwords) { - BigIntegerCrypto result = new BigIntegerCrypto(); - if (nwords > 1) - result.words = new int[nwords]; - return result; - } - - /** - * Change words.length to nwords. We allow words.length to be upto nwords+2 - * without reallocating. - */ - private void realloc(int nwords) { - if (nwords == 0) { - if (words != null) { - if (ival > 0) { - ival = words[0]; - words[0] = 0; // crypto: clear old content - } - words = null; - } - } else if (words == null || words.length < nwords - || words.length > nwords + 2) { - int[] new_words = new int[nwords]; - if (words == null) { - new_words[0] = ival; - ival = 1; - } else { - if (nwords < ival) - ival = nwords; - System.arraycopy(words, 0, new_words, 0, ival); - Arrays.fill(words, 0); // crypto: clear old content - } - words = new_words; - } - } - - private boolean isNegative() { - return (words == null ? ival : words[ival - 1]) < 0; - } - - public int signum() { - - if (ival == 0 && words == null) - return 0; - int top = words == null ? ival : words[ival - 1]; - return top < 0 ? -1 : 1; - } - - private static int compareTo(BigIntegerCrypto x, BigIntegerCrypto y) { - if (x.words == null && y.words == null) - return x.ival < y.ival ? -1 : x.ival > y.ival ? 1 : 0; - boolean x_negative = x.isNegative(); - boolean y_negative = y.isNegative(); - if (x_negative != y_negative) - return x_negative ? -1 : 1; - int x_len = x.words == null ? 1 : x.ival; - int y_len = y.words == null ? 1 : y.ival; - if (x_len != y_len) - return (x_len > y_len) != x_negative ? 1 : -1; - return MPN.cmp(x.words, y.words, x_len); - } - - /** @since 1.2 */ - public int compareTo(BigIntegerCrypto val) { - return compareTo(this, val); - } - - public BigIntegerCrypto min(BigIntegerCrypto val) { - return compareTo(this, val) < 0 ? this : val; - } - - public BigIntegerCrypto max(BigIntegerCrypto val) { - return compareTo(this, val) > 0 ? this : val; - } - - private boolean isZero() { - return words == null && ival == 0; - } - - private boolean isOne() { - return words == null && ival == 1; - } - - /** - * Calculate how many words are significant in words[0:len-1]. Returns the - * least value x such that x>0 && words[0:x-1]==words[0:len-1], when words - * is viewed as a 2's complement integer. - */ - private static int wordsNeeded(int[] words, int len) { - int i = len; - if (i > 0) { - int word = words[--i]; - if (word == -1) { - while (i > 0 && (word = words[i - 1]) < 0) { - i--; - if (word != -1) - break; - } - } else { - while (word == 0 && i > 0 && (word = words[i - 1]) >= 0) - i--; - } - } - return i + 1; - } - - private BigIntegerCrypto canonicalize() { - if (words != null - && (ival = BigIntegerCrypto.wordsNeeded(words, ival)) <= 1) { - if (ival == 1) - ival = words[0]; - Arrays.fill(words, 0); // crypto: clear old contents - words = null; - } - if (words == null && ival >= minFixNum && ival <= maxFixNum) - return smallFixNums[ival - minFixNum]; - return this; - } - - /** Add two ints, yielding a BigInteger. */ - private static BigIntegerCrypto add(int x, int y) { - return valueOf((long) x + (long) y); - } - - /** Add a BigInteger and an int, yielding a new BigInteger. */ - private static BigIntegerCrypto add(BigIntegerCrypto x, int y) { - if (x.words == null) - return BigIntegerCrypto.add(x.ival, y); - BigIntegerCrypto result = new BigIntegerCrypto(0); - result.setAdd(x, y); - return result.canonicalize(); - } - - /** - * Set this to the sum of x and y. OK if x==this. - */ - private void setAdd(BigIntegerCrypto x, int y) { - if (x.words == null) { - set((long) x.ival + (long) y); - return; - } - int len = x.ival; - realloc(len + 1); - long carry = y; - for (int i = 0; i < len; i++) { - carry += (x.words[i] & 0xffffffffL); - words[i] = (int) carry; - carry >>= 32; - } - if (x.words[len - 1] < 0) - carry--; - words[len] = (int) carry; - ival = wordsNeeded(words, len + 1); - } - - /** Destructively add an int to this. */ - private void setAdd(int y) { - setAdd(this, y); - } - - /** Destructively set the value of this to a long. */ - private void set(long y) { - int i = (int) y; - if (i == y) { - ival = i; - if (words != null) - Arrays.fill(words, 0); - words = null; - } else { - realloc(2); - words[0] = i; - words[1] = (int) (y >> 32); - ival = 2; - } - } - - /** - * Destructively set the value of this to the given words. The words array - * is reused, not copied. - */ - private void set(int[] words, int length) { - this.ival = length; - if (this.words != null) { - Arrays.fill(this.words, 0); // crypto: clear old contents - } - this.words = words; - } - - /** Destructively set the value of this to that of y. */ - private void set(BigIntegerCrypto y) { - if (y.words == null) - set(y.ival); - else if (this != y) { - realloc(y.ival); // TODO: allocate int[y.ival] directly - System.arraycopy(y.words, 0, words, 0, y.ival); - ival = y.ival; - } - } - - /** Add two BigIntegers, yielding their sum as another BigInteger. */ - private static BigIntegerCrypto add(BigIntegerCrypto x, BigIntegerCrypto y, - int k) { - if (x.words == null && y.words == null) - return valueOf((long) k * (long) y.ival + x.ival); - if (k != 1) { - if (k == -1) - y = BigIntegerCrypto.neg(y); - else - y = BigIntegerCrypto.times(y, valueOf(k)); - } - if (x.words == null) - return BigIntegerCrypto.add(y, x.ival); - if (y.words == null) - return BigIntegerCrypto.add(x, y.ival); - // Both are big - if (y.ival > x.ival) { // Swap so x is longer then y. - BigIntegerCrypto tmp = x; - x = y; - y = tmp; - } - BigIntegerCrypto result = alloc(x.ival + 1); - int i = y.ival; - long carry = MPN.add_n(result.words, x.words, y.words, i); - long y_ext = y.words[i - 1] < 0 ? 0xffffffffL : 0; - for (; i < x.ival; i++) { - carry += (x.words[i] & 0xffffffffL) + y_ext; - result.words[i] = (int) carry; - carry >>>= 32; - } - if (x.words[i - 1] < 0) - y_ext--; - result.words[i] = (int) (carry + y_ext); - result.ival = i + 1; - return result.canonicalize(); - } - - public BigIntegerCrypto add(BigIntegerCrypto val) { - return add(this, val, 1); - } - - public BigIntegerCrypto subtract(BigIntegerCrypto val) { - return add(this, val, -1); - } - - private static BigIntegerCrypto times(BigIntegerCrypto x, int y) { - if (y == 0) - return ZERO; - if (y == 1) - return x; - int[] xwords = x.words; - int xlen = x.ival; - if (xwords == null) - return valueOf((long) xlen * (long) y); - boolean negative; - BigIntegerCrypto result = BigIntegerCrypto.alloc(xlen + 1); - if (xwords[xlen - 1] < 0) { - negative = true; - negate(result.words, xwords, xlen); - xwords = result.words; - } else - negative = false; - if (y < 0) { - negative = !negative; - y = -y; - } - result.words[xlen] = MPN.mul_1(result.words, xwords, xlen, y); - result.ival = xlen + 1; - if (negative) - result.setNegative(); - return result.canonicalize(); - } - - private static BigIntegerCrypto times(BigIntegerCrypto x, BigIntegerCrypto y) { - if (y.words == null) - return times(x, y.ival); - if (x.words == null) - return times(y, x.ival); - boolean negative = false; - int[] xwords; - int[] ywords; - int xlen = x.ival; - int ylen = y.ival; - if (x.isNegative()) { - negative = true; - xwords = new int[xlen]; - negate(xwords, x.words, xlen); - } else { - negative = false; - xwords = x.words; - } - if (y.isNegative()) { - negative = !negative; - ywords = new int[ylen]; - negate(ywords, y.words, ylen); - } else - ywords = y.words; - // Swap if x is shorter then y. - if (xlen < ylen) { - int[] twords = xwords; - xwords = ywords; - ywords = twords; - int tlen = xlen; - xlen = ylen; - ylen = tlen; - } - BigIntegerCrypto result = BigIntegerCrypto.alloc(xlen + ylen); - MPN.mul(result.words, xwords, xlen, ywords, ylen); - - if (!(xwords == x.words || ywords == x.words)) { // crypto: delete temp content - Arrays.fill(xwords, 0); - xwords = null; - } - if (!(ywords == y.words || xwords == y.words)) { // crypto: delete temp content - Arrays.fill(ywords, 0); - ywords = null; - } - result.ival = xlen + ylen; - if (negative) - result.setNegative(); - return result.canonicalize(); - } - - public BigIntegerCrypto multiply(BigIntegerCrypto y) { - return times(this, y); - } - - private static void divide(long x, long y, BigIntegerCrypto quotient, - BigIntegerCrypto remainder, int rounding_mode) { - boolean xNegative, yNegative; - if (x < 0) { - xNegative = true; - if (x == Long.MIN_VALUE) { - divide(valueOf(x), valueOf(y), quotient, remainder, - rounding_mode); - return; - } - x = -x; - } else - xNegative = false; - - if (y < 0) { - yNegative = true; - if (y == Long.MIN_VALUE) { - if (rounding_mode == TRUNCATE) { // x != Long.Min_VALUE implies - // abs(x) < abs(y) - if (quotient != null) - quotient.set(0); - if (remainder != null) - remainder.set(x); - } else - divide(valueOf(x), valueOf(y), quotient, remainder, - rounding_mode); - return; - } - y = -y; - } else - yNegative = false; - - long q = x / y; - long r = x % y; - boolean qNegative = xNegative ^ yNegative; - - boolean add_one = false; - if (r != 0) { - switch (rounding_mode) { - case TRUNCATE: - break; - case CEILING: - case FLOOR: - if (qNegative == (rounding_mode == FLOOR)) - add_one = true; - break; - case ROUND: - add_one = r > ((y - (q & 1)) >> 1); - break; - } - } - if (quotient != null) { - if (add_one) - q++; - if (qNegative) - q = -q; - quotient.set(q); - } - if (remainder != null) { - // The remainder is by definition: X-Q*Y - if (add_one) { - // Subtract the remainder from Y. - r = y - r; - // In this case, abs(Q*Y) > abs(X). - // So sign(remainder) = -sign(X). - xNegative = !xNegative; - } else { - // If !add_one, then: abs(Q*Y) <= abs(X). - // So sign(remainder) = sign(X). - } - if (xNegative) - r = -r; - remainder.set(r); - } - } - - /** - * Divide two integers, yielding quotient and remainder. - * - * @param x - * the numerator in the division - * @param y - * the denominator in the division - * @param quotient - * is set to the quotient of the result (iff quotient!=null) - * @param remainder - * is set to the remainder of the result (iff remainder!=null) - * @param rounding_mode - * one of FLOOR, CEILING, TRUNCATE, or ROUND. - */ - private static void divide(BigIntegerCrypto x, BigIntegerCrypto y, - BigIntegerCrypto quotient, BigIntegerCrypto remainder, - int rounding_mode) { - if ((x.words == null || x.ival <= 2) - && (y.words == null || y.ival <= 2)) { - long x_l = x.longValue(); - long y_l = y.longValue(); - if (x_l != Long.MIN_VALUE && y_l != Long.MIN_VALUE) { - divide(x_l, y_l, quotient, remainder, rounding_mode); - return; - } - } - - boolean xNegative = x.isNegative(); - boolean yNegative = y.isNegative(); - boolean qNegative = xNegative ^ yNegative; - - int ylen = y.words == null ? 1 : y.ival; - int[] ywords = new int[ylen]; - y.getAbsolute(ywords); - while (ylen > 1 && ywords[ylen - 1] == 0) - ylen--; - - int xlen = x.words == null ? 1 : x.ival; - int[] xwords = new int[xlen + 2]; - x.getAbsolute(xwords); - while (xlen > 1 && xwords[xlen - 1] == 0) - xlen--; - - int qlen, rlen; - - int cmpval = MPN.cmp(xwords, xlen, ywords, ylen); - if (cmpval < 0) // abs(x) < abs(y) - { // quotient = 0; remainder = num. - int[] rwords = xwords; - xwords = ywords; - ywords = rwords; - rlen = xlen; - qlen = 1; - xwords[0] = 0; - } else if (cmpval == 0) // abs(x) == abs(y) - { - xwords[0] = 1; - qlen = 1; // quotient = 1 - ywords[0] = 0; - rlen = 1; // remainder = 0; - } else if (ylen == 1) { - qlen = xlen; - // Need to leave room for a word of leading zeros if dividing by 1 - // and the dividend has the high bit set. It might be safe to - // increment qlen in all cases, but it certainly is only necessary - // in the following case. - if (ywords[0] == 1 && xwords[xlen - 1] < 0) - qlen++; - rlen = 1; - ywords[0] = MPN.divmod_1(xwords, xwords, xlen, ywords[0]); - } else // abs(x) > abs(y) - { - // Normalize the denominator, i.e. make its most significant bit set - // by - // shifting it normalization_steps bits to the left. Also shift the - // numerator the same number of steps (to keep the quotient the - // same!). - - int nshift = MPN.count_leading_zeros(ywords[ylen - 1]); - if (nshift != 0) { - // Shift up the denominator setting the most significant bit of - // the most significant word. - MPN.lshift(ywords, 0, ywords, ylen, nshift); - - // Shift up the numerator, possibly introducing a new most - // significant word. - int x_high = MPN.lshift(xwords, 0, xwords, xlen, nshift); - xwords[xlen++] = x_high; - } - - if (xlen == ylen) - xwords[xlen++] = 0; - MPN.divide(xwords, xlen, ywords, ylen); - rlen = ylen; - MPN.rshift0(ywords, xwords, 0, rlen, nshift); - - qlen = xlen + 1 - ylen; - if (quotient != null) { - for (int i = 0; i < qlen; i++) - xwords[i] = xwords[i + ylen]; - } - } - - if (ywords[rlen - 1] < 0) { - ywords[rlen] = 0; - rlen++; - } - - // Now the quotient is in xwords, and the remainder is in ywords. - - boolean add_one = false; - if (rlen > 1 || ywords[0] != 0) { // Non-zero remainder i.e. in-exact - // quotient. - switch (rounding_mode) { - case TRUNCATE: - break; - case CEILING: - case FLOOR: - if (qNegative == (rounding_mode == FLOOR)) - add_one = true; - break; - case ROUND: - // int cmp = compareTo(remainder<<1, abs(y)); - BigIntegerCrypto tmp = remainder == null ? new BigIntegerCrypto() - : remainder; - tmp.set(ywords, rlen); - tmp = shift(tmp, 1); - if (yNegative) - tmp.setNegative(); - int cmp = compareTo(tmp, y); - // Now cmp == compareTo(sign(y)*(remainder<<1), y) - if (yNegative) - cmp = -cmp; - add_one = (cmp == 1) || (cmp == 0 && (xwords[0] & 1) != 0); - } - } - if (quotient != null) { - quotient.set(xwords, qlen); - if (qNegative) { - if (add_one) // -(quotient + 1) == ~(quotient) - quotient.setInvert(); - else - quotient.setNegative(); - } else if (add_one) - quotient.setAdd(1); - } - if (remainder != null) { - // The remainder is by definition: X-Q*Y - remainder.set(ywords, rlen); - if (add_one) { - // Subtract the remainder from Y: - // abs(R) = abs(Y) - abs(orig_rem) = -(abs(orig_rem) - abs(Y)). - BigIntegerCrypto tmp; - if (y.words == null) { - tmp = remainder; - tmp - .set(yNegative ? ywords[0] + y.ival : ywords[0] - - y.ival); - } else - tmp = BigIntegerCrypto - .add(remainder, y, yNegative ? 1 : -1); - // Now tmp <= 0. - // In this case, abs(Q) = 1 + floor(abs(X)/abs(Y)). - // Hence, abs(Q*Y) > abs(X). - // So sign(remainder) = -sign(X). - if (xNegative) - remainder.setNegative(tmp); - else - remainder.set(tmp); - if (tmp != remainder) { - tmp.zeroize(); // crypto: clear temp data - } - } else { - // If !add_one, then: abs(Q*Y) <= abs(X). - // So sign(remainder) = sign(X). - if (xNegative) - remainder.setNegative(); - } - } - } - - public BigIntegerCrypto divide(BigIntegerCrypto val) { - if (val.isZero()) - throw new ArithmeticException("divisor is zero"); - - BigIntegerCrypto quot = new BigIntegerCrypto(); - divide(this, val, quot, null, TRUNCATE); - return quot.canonicalize(); - } - - public BigIntegerCrypto remainder(BigIntegerCrypto val) { - if (val.isZero()) - throw new ArithmeticException("divisor is zero"); - - BigIntegerCrypto rem = new BigIntegerCrypto(); - divide(this, val, null, rem, TRUNCATE); - return rem.canonicalize(); - } - - public BigIntegerCrypto[] divideAndRemainder(BigIntegerCrypto val) { - if (val.isZero()) - throw new ArithmeticException("divisor is zero"); - - BigIntegerCrypto[] result = new BigIntegerCrypto[2]; - result[0] = new BigIntegerCrypto(); - result[1] = new BigIntegerCrypto(); - divide(this, val, result[0], result[1], TRUNCATE); - result[0].canonicalize(); - result[1].canonicalize(); - return result; - } - - public BigIntegerCrypto mod(BigIntegerCrypto m) { - if (m.isNegative() || m.isZero()) - throw new ArithmeticException("non-positive modulus"); - - BigIntegerCrypto rem = new BigIntegerCrypto(); - divide(this, m, null, rem, FLOOR); - return rem.canonicalize(); - } - - /** - * Calculate the integral power of a BigInteger. - * - * @param exponent - * the exponent (must be non-negative) - */ - public BigIntegerCrypto pow(int exponent) { - if (exponent <= 0) { - if (exponent == 0) - return ONE; - throw new ArithmeticException("negative exponent"); - } - - if (isZero()) - return this; - int plen = words == null ? 1 : ival; // Length of pow2. - int blen = ((bitLength() * exponent) >> 5) + 2 * plen; - boolean negative = isNegative() && (exponent & 1) != 0; - int[] pow2 = new int[blen]; - int[] rwords = new int[blen]; - int[] work = new int[blen]; - getAbsolute(pow2); // pow2 = abs(this); - int rlen = 1; - rwords[0] = 1; // rwords = 1; - for (;;) // for (i = 0; ; i++) - { - // pow2 == this**(2**i) - // prod = this**(sum(j=0..i-1, (exponent>>j)&1)) - if ((exponent & 1) != 0) { // r *= pow2 - MPN.mul(work, pow2, plen, rwords, rlen); - int[] temp = work; - work = rwords; - rwords = temp; - rlen += plen; - while (rwords[rlen - 1] == 0) - rlen--; - } - exponent >>= 1; - if (exponent == 0) - break; - // pow2 *= pow2; - MPN.mul(work, pow2, plen, pow2, plen); - int[] temp = work; - work = pow2; - pow2 = temp; // swap to avoid a copy - plen *= 2; - while (pow2[plen - 1] == 0) - plen--; - } - if (rwords[rlen - 1] < 0) - rlen++; - if (negative) - negate(rwords, rwords, rlen); - // crypto: make(...) could return another biginteger if rwords is # - // small. In that case clear rwords before leaving the method. - BigIntegerCrypto ret = BigIntegerCrypto.make(rwords, rlen); - return ret; - } - - private static int[] euclidInv(int a, int b, int prevDiv) { - if (b == 0) - throw new ArithmeticException("not invertible"); - - if (b == 1) - // Success: values are indeed invertible! - // Bottom of the recursion reached; start unwinding. - return new int[] { -prevDiv, 1 }; - - int[] xy = euclidInv(b, a % b, a / b); // Recursion happens here. - a = xy[0]; // use our local copy of 'a' as a work var - xy[0] = a * -prevDiv + xy[1]; - xy[1] = a; - return xy; - } - - private static void euclidInv(BigIntegerCrypto a, BigIntegerCrypto b, - BigIntegerCrypto prevDiv, BigIntegerCrypto[] xy) { - if (b.isZero()) - throw new ArithmeticException("not invertible"); - - if (b.isOne()) { - // Success: values are indeed invertible! - // Bottom of the recursion reached; start unwinding. - xy[0] = neg(prevDiv); - xy[1] = ONE; - return; - } - - // Recursion happens in the following conditional! - - // If a just contains an int, then use integer math for the rest. - if (a.words == null) { - int[] xyInt = euclidInv(b.ival, a.ival % b.ival, a.ival / b.ival); - xy[0] = new BigIntegerCrypto(xyInt[0]); - xy[1] = new BigIntegerCrypto(xyInt[1]); - } else { - BigIntegerCrypto rem = new BigIntegerCrypto(); - BigIntegerCrypto quot = new BigIntegerCrypto(); - divide(a, b, quot, rem, FLOOR); - // quot and rem may not be in canonical form. ensure - rem.canonicalize(); - quot.canonicalize(); - euclidInv(b, rem, quot, xy); - } - - BigIntegerCrypto t = xy[0]; - xy[0] = add(xy[1], times(t, prevDiv), -1); - xy[1] = t; - } - - public BigIntegerCrypto modInverse(BigIntegerCrypto y) { - if (y.isNegative() || y.isZero()) - throw new ArithmeticException("non-positive modulo"); - - // Degenerate cases. - if (y.isOne()) - return ZERO; - if (isOne()) - return ONE; - - // Use Euclid's algorithm as in gcd() but do this recursively - // rather than in a loop so we can use the intermediate results as we - // unwind from the recursion. - // Used http://www.math.nmsu.edu/~crypto/EuclideanAlgo.html as - // reference. - BigIntegerCrypto result = new BigIntegerCrypto(); - boolean swapped = false; - - if (y.words == null) { - // The result is guaranteed to be less than the modulus, y (which is - // an int), so simplify this by working with the int result of this - // modulo y. Also, if this is negative, make it positive via modulo - // math. Note that BigInteger.mod() must be used even if this is - // already an int as the % operator would provide a negative result - // if - // this is negative, BigInteger.mod() never returns negative values. - int xval = (words != null || isNegative()) ? mod(y).ival : ival; - int yval = y.ival; - - // Swap values so x > y. - if (yval > xval) { - int tmp = xval; - xval = yval; - yval = tmp; - swapped = true; - } - // Normally, the result is in the 2nd element of the array, but - // if originally x < y, then x and y were swapped and the result - // is in the 1st element of the array. - result.ival = euclidInv(yval, xval % yval, xval / yval)[swapped ? 0 - : 1]; - - // Result can't be negative, so make it positive by adding the - // original modulus, y.ival (not the possibly "swapped" yval). - if (result.ival < 0) - result.ival += y.ival; - } else { - // As above, force this to be a positive value via modulo math. - BigIntegerCrypto x = isNegative() ? this.mod(y) : this; - - // Swap values so x > y. - if (x.compareTo(y) < 0) { - result = x; - x = y; - y = result; // use 'result' as a work var - swapped = true; - } - // As above (for ints), result will be in the 2nd element unless - // the original x and y were swapped. - BigIntegerCrypto rem = new BigIntegerCrypto(); - BigIntegerCrypto quot = new BigIntegerCrypto(); - divide(x, y, quot, rem, FLOOR); - // quot and rem may not be in canonical form. ensure - rem.canonicalize(); - quot.canonicalize(); - BigIntegerCrypto[] xy = new BigIntegerCrypto[2]; - euclidInv(y, rem, quot, xy); - result = swapped ? xy[0] : xy[1]; - - // Result can't be negative, so make it positive by adding the - // original modulus, y (which is now x if they were swapped). - if (result.isNegative()) - result = add(result, swapped ? x : y, 1); - } - - return result; - } - - public BigIntegerCrypto modPow(BigIntegerCrypto exponent, BigIntegerCrypto m) { - if (m.isNegative() || m.isZero()) - throw new ArithmeticException("non-positive modulo"); - - if (exponent.isNegative()) - return modInverse(m).modPow(exponent.negate(), m); - if (exponent.isOne()) - return mod(m); - - // To do this naively by first raising this to the power of exponent - // and then performing modulo m would be extremely expensive, especially - // for very large numbers. The solution is found in Number Theory - // where a combination of partial powers and moduli can be done easily. - // - // We'll use the algorithm for Additive Chaining which can be found on - // p. 244 of "Applied Cryptography, Second Edition" by Bruce Schneier. - BigIntegerCrypto s = ONE; - BigIntegerCrypto t = this; - BigIntegerCrypto u = exponent; - - while (!u.isZero()) { - if (u.and(ONE).isOne()) - s = times(s, t).mod(m); - u = u.shiftRight(1); - t = times(t, t).mod(m); - } - - return s; - } - - /** Calculate Greatest Common Divisor for non-negative ints. */ - private static int gcd(int a, int b) { - // Euclid's algorithm, copied from libg++. - int tmp; - if (b > a) { - tmp = a; - a = b; - b = tmp; - } - for (;;) { - if (b == 0) - return a; - if (b == 1) - return b; - tmp = b; - b = a % b; - a = tmp; - } - } - - public BigIntegerCrypto gcd(BigIntegerCrypto y) { - int xval = ival; - int yval = y.ival; - if (words == null) { - if (xval == 0) - return abs(y); - if (y.words == null && xval != Integer.MIN_VALUE - && yval != Integer.MIN_VALUE) { - if (xval < 0) - xval = -xval; - if (yval < 0) - yval = -yval; - return valueOf(gcd(xval, yval)); - } - xval = 1; - } - if (y.words == null) { - if (yval == 0) - return abs(this); - yval = 1; - } - int len = (xval > yval ? xval : yval) + 1; - int[] xwords = new int[len]; - int[] ywords = new int[len]; - getAbsolute(xwords); - y.getAbsolute(ywords); - len = MPN.gcd(xwords, ywords, len); - - BigIntegerCrypto result = new BigIntegerCrypto(0); - result.ival = len; - result.words = xwords; - return result.canonicalize(); - } - - /** - *

- * Returns true if this BigInteger is probably prime, - * false if it's definitely composite. If - * certainty is <= 0, true is - * returned. - *

- * - * @param certainty - * a measure of the uncertainty that the caller is willing to - * tolerate: if the call returns true the - * probability that this BigInteger is prime exceeds - * (1 - 1/2certainty). The execution time - * of this method is proportional to the value of this parameter. - * @return true if this BigInteger is probably prime, - * false if it's definitely composite. - */ - public boolean isProbablePrime(int certainty) { - if (certainty < 1) - return true; - - /** - * We'll use the Rabin-Miller algorithm for doing a probabilistic - * primality test. It is fast, easy and has faster decreasing odds of a - * composite passing than with other tests. This means that this method - * will actually have a probability much greater than the 1 - - * .5^certainty specified in the JCL (p. 117), but I don't think anyone - * will complain about better performance with greater certainty. - * - * The Rabin-Miller algorithm can be found on pp. 259-261 of "Applied - * Cryptography, Second Edition" by Bruce Schneier. - */ - - // First rule out small prime factors - BigIntegerCrypto rem = new BigIntegerCrypto(); - int i; - for (i = 0; i < primes.length; i++) { - if (words == null && ival == primes[i]) - return true; - - divide(this, smallFixNums[primes[i] - minFixNum], null, rem, - TRUNCATE); - if (rem.canonicalize().isZero()) - return false; - } - - // Now perform the Rabin-Miller test. - - // Set b to the number of times 2 evenly divides (this - 1). - // I.e. 2^b is the largest power of 2 that divides (this - 1). - BigIntegerCrypto pMinus1 = add(this, -1); - int b = pMinus1.getLowestSetBit(); - - // Set m such that this = 1 + 2^b * m. - BigIntegerCrypto m = pMinus1.divide(valueOf(2L).pow(b)); - - // The HAC (Handbook of Applied Cryptography), Alfred Menezes & al. Note - // 4.49 (controlling the error probability) gives the number of trials - // for an error probability of 1/2**80, given the number of bits in the - // number to test. we shall use these numbers as is if/when 'certainty' - // is less or equal to 80, and twice as much if it's greater. - int bits = this.bitLength(); - for (i = 0; i < k.length; i++) - if (bits <= k[i]) - break; - int trials = t[i]; - if (certainty > 80) - trials *= 2; - BigIntegerCrypto z; - for (int t = 0; t < trials; t++) { - // The HAC (Handbook of Applied Cryptography), Alfred Menezes & al. - // Remark 4.28 states: "...A strategy that is sometimes employed - // is to fix the bases a to be the first few primes instead of - // choosing them at random. - z = smallFixNums[primes[t] - minFixNum].modPow(m, this); - if (z.isOne() || z.equals(pMinus1)) - continue; // Passes the test; may be prime. - - for (i = 0; i < b;) { - if (z.isOne()) { - return false; - } - i++; - if (z.equals(pMinus1)) - break; // Passes the test; may be prime. - - z = z.modPow(valueOf(2), this); - } - - if (i == b && !z.equals(pMinus1)) { - return false; - } - } - return true; - } - - private void setInvert() { - if (words == null) - ival = ~ival; - else { - for (int i = ival; --i >= 0;) - words[i] = ~words[i]; - } - } - - private void setShiftLeft(BigIntegerCrypto x, int count) { - int[] xwords; - int xlen; - if (x.words == null) { - if (count < 32) { - set((long) x.ival << count); - return; - } - xwords = new int[1]; - xwords[0] = x.ival; - xlen = 1; - } else { - xwords = x.words; - xlen = x.ival; - } - int word_count = count >> 5; - count &= 31; - int new_len = xlen + word_count; - if (count == 0) { - realloc(new_len); - for (int i = xlen; --i >= 0;) - words[i + word_count] = xwords[i]; - } else { - new_len++; - realloc(new_len); - int shift_out = MPN.lshift(words, word_count, xwords, xlen, count); - count = 32 - count; - words[new_len - 1] = (shift_out << count) >> count; // sign-extend. - } - ival = new_len; - for (int i = word_count; --i >= 0;) - words[i] = 0; - } - - private void setShiftRight(BigIntegerCrypto x, int count) { - if (x.words == null) - set(count < 32 ? x.ival >> count : x.ival < 0 ? -1 : 0); - else if (count == 0) - set(x); - else { - boolean neg = x.isNegative(); - int word_count = count >> 5; - count &= 31; - int d_len = x.ival - word_count; - if (d_len <= 0) - set(neg ? -1 : 0); - else { - if (words == null || words.length < d_len) - realloc(d_len); - MPN.rshift0(words, x.words, word_count, d_len, count); - ival = d_len; - if (neg) - words[d_len - 1] |= -2 << (31 - count); - } - } - } - - private void setShift(BigIntegerCrypto x, int count) { - if (count > 0) - setShiftLeft(x, count); - else - setShiftRight(x, -count); - } - - private static BigIntegerCrypto shift(BigIntegerCrypto x, int count) { - if (x.words == null) { - if (count <= 0) - return valueOf(count > -32 ? x.ival >> (-count) - : x.ival < 0 ? -1 : 0); - if (count < 32) - return valueOf((long) x.ival << count); - } - if (count == 0) - return x; - BigIntegerCrypto result = new BigIntegerCrypto(0); - result.setShift(x, count); - return result.canonicalize(); - } - - public BigIntegerCrypto shiftLeft(int n) { - if (n == 0) - return this; - - return shift(this, n); - } - - public BigIntegerCrypto shiftRight(int n) { - if (n == 0) - return this; - - return shift(this, -n); - } - - private void format(int radix, StringBuffer buffer) { - if (words == null) - buffer.append(Integer.toString(ival, radix)); - else if (ival <= 2) - buffer.append(Long.toString(longValue(), radix)); - else { - boolean neg = isNegative(); - int[] work; - if (neg || radix != 16) { - work = new int[ival]; - getAbsolute(work); - } else - work = words; - int len = ival; - - if (radix == 16) { - if (neg) - buffer.append('-'); - int buf_start = buffer.length(); - for (int i = len; --i >= 0;) { - int word = work[i]; - for (int j = 8; --j >= 0;) { - int hex_digit = (word >> (4 * j)) & 0xF; - // Suppress leading zeros: - if (hex_digit > 0 || buffer.length() > buf_start) - buffer.append(Character.forDigit(hex_digit, 16)); - } - } - } else { - int i = buffer.length(); - for (;;) { - int digit = MPN.divmod_1(work, work, len, radix); - buffer.append(Character.forDigit(digit, radix)); - while (len > 0 && work[len - 1] == 0) - len--; - if (len == 0) - break; - } - if (neg) - buffer.append('-'); - /* Reverse buffer. */ - int j = buffer.length() - 1; - while (i < j) { - char tmp = buffer.charAt(i); - buffer.setCharAt(i, buffer.charAt(j)); - buffer.setCharAt(j, tmp); - i++; - j--; - } - } - } - } - - public String toString() { - return toString(10); - } - - public String toString(int radix) { - - if (words == null) - return Integer.toString(ival, radix); - if (ival <= 2) - return Long.toString(longValue(), radix); - int buf_size = ival * (MPN.chars_per_word(radix) + 1); - StringBuffer buffer = new StringBuffer(buf_size); - format(radix, buffer); - return buffer.toString(); - } - - public int intValue() { - if (words == null) - return ival; - return words[0]; - } - - public long longValue() { - if (words == null) - return ival; - if (ival == 1) - return words[0]; - return ((long) words[1] << 32) + (words[0] & 0xffffffffL); - } - - public int hashCode() { - // FIXME: May not match hashcode of JDK. - return words == null ? ival : (words[0] + words[ival - 1]); - } - - /* Assumes x and y are both canonicalized. */ - private static boolean equals(BigIntegerCrypto x, BigIntegerCrypto y) { - - if (x.words == null && y.words == null) - return x.ival == y.ival; - if (x.words == null || y.words == null || x.ival != y.ival) - return false; - for (int i = x.ival; --i >= 0;) { - if (x.words[i] != y.words[i]) - return false; - } - return true; - } - - /* Assumes this and obj are both canonicalized. */ - public boolean equals(Object obj) { - if (!(obj instanceof BigIntegerCrypto)) - return false; - return equals(this, (BigIntegerCrypto) obj); - } - - private static BigIntegerCrypto valueOf(byte[] digits, int byte_len, - boolean negative, int radix) { - int chars_per_word = MPN.chars_per_word(radix); - int[] words = new int[byte_len / chars_per_word + 1]; - int size = MPN.set_str(words, digits, byte_len, radix); - if (size == 0) - return ZERO; - if (words[size - 1] < 0) - words[size++] = 0; - if (negative) - negate(words, words, size); - return make(words, size); - } - - public double doubleValue() { - if (words == null) - return ival; - if (ival <= 2) - return longValue(); - if (isNegative()) - return neg(this).roundToDouble(0, true, false); - return roundToDouble(0, false, false); - } - - public float floatValue() { - return (float) doubleValue(); - } - - /** - * Return true if any of the lowest n bits are one. (false if n is - * negative). - */ - private boolean checkBits(int n) { - if (n <= 0) - return false; - if (words == null) - return n > 31 || ((ival & ((1 << n) - 1)) != 0); - int i; - for (i = 0; i < (n >> 5); i++) - if (words[i] != 0) - return true; - return (n & 31) != 0 && (words[i] & ((1 << (n & 31)) - 1)) != 0; - } - - /** - * Convert a semi-processed BigInteger to double. Number must be - * non-negative. Multiplies by a power of two, applies sign, and converts to - * double, with the usual java rounding. - * - * @param exp - * power of two, positive or negative, by which to multiply - * @param neg - * true if negative - * @param remainder - * true if the BigInteger is the result of a truncating division - * that had non-zero remainder. To ensure proper rounding in this - * case, the BigInteger must have at least 54 bits. - */ - private double roundToDouble(int exp, boolean neg, boolean remainder) { - // Compute length. - int il = bitLength(); - - // Exponent when normalized to have decimal point directly after - // leading one. This is stored excess 1023 in the exponent bit field. - exp += il - 1; - - // Gross underflow. If exp == -1075, we let the rounding - // computation determine whether it is minval or 0 (which are just - // 0x0000 0000 0000 0001 and 0x0000 0000 0000 0000 as bit - // patterns). - if (exp < -1075) - return neg ? -0.0 : 0.0; - - // gross overflow - if (exp > 1023) - return neg ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY; - - // number of bits in mantissa, including the leading one. - // 53 unless it's denormalized - int ml = (exp >= -1022 ? 53 : 53 + exp + 1022); - - // Get top ml + 1 bits. The extra one is for rounding. - long m; - int excess_bits = il - (ml + 1); - if (excess_bits > 0) - m = ((words == null) ? ival >> excess_bits : MPN.rshift_long(words, - ival, excess_bits)); - else - m = longValue() << (-excess_bits); - - // Special rounding for maxval. If the number exceeds maxval by - // any amount, even if it's less than half a step, it overflows. - if (exp == 1023 && ((m >> 1) == (1L << 53) - 1)) { - if (remainder || checkBits(il - ml)) - return neg ? Double.NEGATIVE_INFINITY - : Double.POSITIVE_INFINITY; - else - return neg ? -Double.MAX_VALUE : Double.MAX_VALUE; - } - - // Normal round-to-even rule: round up if the bit dropped is a one, and - // the bit above it or any of the bits below it is a one. - if ((m & 1) == 1 - && ((m & 2) == 2 || remainder || checkBits(excess_bits))) { - m += 2; - // Check if we overflowed the mantissa - if ((m & (1L << 54)) != 0) { - exp++; - // renormalize - m >>= 1; - } - // Check if a denormalized mantissa was just rounded up to a - // normalized one. - else if (ml == 52 && (m & (1L << 53)) != 0) - exp++; - } - - // Discard the rounding bit - m >>= 1; - - long bits_sign = neg ? (1L << 63) : 0; - exp += 1023; - long bits_exp = (exp <= 0) ? 0 : ((long) exp) << 52; - long bits_mant = m & ~(1L << 52); - return Double.longBitsToDouble(bits_sign | bits_exp | bits_mant); - } - - /** - * Copy the abolute value of this into an array of words. Assumes - * words.length >= (this.words == null ? 1 : this.ival). Result is - * zero-extended, but need not be a valid 2's complement number. - */ - private void getAbsolute(int[] words) { - int len; - if (this.words == null) { - len = 1; - words[0] = this.ival; - } else { - len = this.ival; - for (int i = len; --i >= 0;) - words[i] = this.words[i]; - } - if (words[len - 1] < 0) - negate(words, words, len); - for (int i = words.length; --i > len;) - words[i] = 0; - } - - /** - * Set dest[0:len-1] to the negation of src[0:len-1]. Return true if - * overflow (i.e. if src is -2**(32*len-1)). Ok for src==dest. - */ - private static boolean negate(int[] dest, int[] src, int len) { - long carry = 1; - boolean negative = src[len - 1] < 0; - for (int i = 0; i < len; i++) { - carry += ((~src[i]) & 0xffffffffL); - dest[i] = (int) carry; - carry >>= 32; - } - return (negative && dest[len - 1] < 0); - } - - /** - * Destructively set this to the negative of x. It is OK if x==this. - */ - private void setNegative(BigIntegerCrypto x) { - int len = x.ival; - if (x.words == null) { - if (len == Integer.MIN_VALUE) - set(-(long) len); - else - set(-len); - return; - } - realloc(len + 1); - if (negate(words, x.words, len)) - words[len++] = 0; - ival = len; - } - - /** Destructively negate this. */ - private void setNegative() { - setNegative(this); - } - - private static BigIntegerCrypto abs(BigIntegerCrypto x) { - return x.isNegative() ? neg(x) : x; - } - - public BigIntegerCrypto abs() { - return abs(this); - } - - private static BigIntegerCrypto neg(BigIntegerCrypto x) { - if (x.words == null && x.ival != Integer.MIN_VALUE) - return valueOf(-x.ival); - BigIntegerCrypto result = new BigIntegerCrypto(0); - result.setNegative(x); - return result.canonicalize(); - } - - public BigIntegerCrypto negate() { - return neg(this); - } - - /** - * Calculates ceiling(log2(this < 0 ? -this : this+1)) See Common Lisp: the - * Language, 2nd ed, p. 361. - */ - public int bitLength() { - if (words == null) - return MPN.intLength(ival); - return MPN.intLength(words, ival); - } - - public byte[] toByteArray() { - if (signum() == 0) - return new byte[1]; - - // Determine number of bytes needed. The method bitlength returns - // the size without the sign bit, so add one bit for that and then - // add 7 more to emulate the ceil function using integer math. - byte[] bytes = new byte[(bitLength() + 1 + 7) / 8]; - int nbytes = bytes.length; - - int wptr = 0; - int word; - - // Deal with words array until one word or less is left to process. - // If BigInteger is an int, then it is in ival and nbytes will be <= 4. - while (nbytes > 4) { - word = words[wptr++]; - for (int i = 4; i > 0; --i, word >>= 8) - bytes[--nbytes] = (byte) word; - } - - // Deal with the last few bytes. If BigInteger is an int, use ival. - word = (words == null) ? ival : words[wptr]; - for (; nbytes > 0; word >>= 8) - bytes[--nbytes] = (byte) word; - - return bytes; - } - - /** - * Return the boolean opcode (for bitOp) for swapped operands. I.e. - * bitOp(swappedOp(op), x, y) == bitOp(op, y, x). - */ - private static int swappedOp(int op) { - return "\000\001\004\005\002\003\006\007\010\011\014\015\012\013\016\017" - .charAt(op); - } - - /** Do one the the 16 possible bit-wise operations of two BigIntegers. */ - private static BigIntegerCrypto bitOp(int op, BigIntegerCrypto x, - BigIntegerCrypto y) { - switch (op) { - case 0: - return ZERO; - case 1: - return x.and(y); - case 3: - return x; - case 5: - return y; - case 15: - return valueOf(-1); - } - BigIntegerCrypto result = new BigIntegerCrypto(); - setBitOp(result, op, x, y); - return result.canonicalize(); - } - - /** Do one the the 16 possible bit-wise operations of two BigIntegers. */ - private static void setBitOp(BigIntegerCrypto result, int op, - BigIntegerCrypto x, BigIntegerCrypto y) { - if ((y.words != null) && (x.words == null || x.ival < y.ival)) { - BigIntegerCrypto temp = x; - x = y; - y = temp; - op = swappedOp(op); - } - int xi; - int yi; - int xlen, ylen; - if (y.words == null) { - yi = y.ival; - ylen = 1; - } else { - yi = y.words[0]; - ylen = y.ival; - } - if (x.words == null) { - xi = x.ival; - xlen = 1; - } else { - xi = x.words[0]; - xlen = x.ival; - } - if (xlen > 1) - result.realloc(xlen); - int[] w = result.words; - int i = 0; - // Code for how to handle the remainder of x. - // 0: Truncate to length of y. - // 1: Copy rest of x. - // 2: Invert rest of x. - int finish = 0; - int ni; - switch (op) { - case 0: // clr - ni = 0; - break; - case 1: // and - for (;;) { - ni = xi & yi; - if (i + 1 >= ylen) - break; - w[i++] = ni; - xi = x.words[i]; - yi = y.words[i]; - } - if (yi < 0) - finish = 1; - break; - case 2: // andc2 - for (;;) { - ni = xi & ~yi; - if (i + 1 >= ylen) - break; - w[i++] = ni; - xi = x.words[i]; - yi = y.words[i]; - } - if (yi >= 0) - finish = 1; - break; - case 3: // copy x - ni = xi; - finish = 1; // Copy rest - break; - case 4: // andc1 - for (;;) { - ni = ~xi & yi; - if (i + 1 >= ylen) - break; - w[i++] = ni; - xi = x.words[i]; - yi = y.words[i]; - } - if (yi < 0) - finish = 2; - break; - case 5: // copy y - for (;;) { - ni = yi; - if (i + 1 >= ylen) - break; - w[i++] = ni; - xi = x.words[i]; - yi = y.words[i]; - } - break; - case 6: // xor - for (;;) { - ni = xi ^ yi; - if (i + 1 >= ylen) - break; - w[i++] = ni; - xi = x.words[i]; - yi = y.words[i]; - } - finish = yi < 0 ? 2 : 1; - break; - case 7: // ior - for (;;) { - ni = xi | yi; - if (i + 1 >= ylen) - break; - w[i++] = ni; - xi = x.words[i]; - yi = y.words[i]; - } - if (yi >= 0) - finish = 1; - break; - case 8: // nor - for (;;) { - ni = ~(xi | yi); - if (i + 1 >= ylen) - break; - w[i++] = ni; - xi = x.words[i]; - yi = y.words[i]; - } - if (yi >= 0) - finish = 2; - break; - case 9: // eqv [exclusive nor] - for (;;) { - ni = ~(xi ^ yi); - if (i + 1 >= ylen) - break; - w[i++] = ni; - xi = x.words[i]; - yi = y.words[i]; - } - finish = yi >= 0 ? 2 : 1; - break; - case 10: // c2 - for (;;) { - ni = ~yi; - if (i + 1 >= ylen) - break; - w[i++] = ni; - xi = x.words[i]; - yi = y.words[i]; - } - break; - case 11: // orc2 - for (;;) { - ni = xi | ~yi; - if (i + 1 >= ylen) - break; - w[i++] = ni; - xi = x.words[i]; - yi = y.words[i]; - } - if (yi < 0) - finish = 1; - break; - case 12: // c1 - ni = ~xi; - finish = 2; - break; - case 13: // orc1 - for (;;) { - ni = ~xi | yi; - if (i + 1 >= ylen) - break; - w[i++] = ni; - xi = x.words[i]; - yi = y.words[i]; - } - if (yi >= 0) - finish = 2; - break; - case 14: // nand - for (;;) { - ni = ~(xi & yi); - if (i + 1 >= ylen) - break; - w[i++] = ni; - xi = x.words[i]; - yi = y.words[i]; - } - if (yi < 0) - finish = 2; - break; - default: - case 15: // set - ni = -1; - break; - } - // Here i==ylen-1; w[0]..w[i-1] have the correct result; - // and ni contains the correct result for w[i+1]. - if (i + 1 == xlen) - finish = 0; - switch (finish) { - case 0: - if (i == 0 && w == null) { - result.ival = ni; - return; - } - w[i++] = ni; - break; - case 1: - w[i] = ni; - while (++i < xlen) - w[i] = x.words[i]; - break; - case 2: - w[i] = ni; - while (++i < xlen) - w[i] = ~x.words[i]; - break; - } - result.ival = i; - } - - /** Return the logical (bit-wise) "and" of a BigInteger and an int. */ - private static BigIntegerCrypto and(BigIntegerCrypto x, int y) { - if (x.words == null) - return valueOf(x.ival & y); - if (y >= 0) - return valueOf(x.words[0] & y); - int len = x.ival; - int[] words = new int[len]; - words[0] = x.words[0] & y; - while (--len > 0) - words[len] = x.words[len]; - return make(words, x.ival); - } - - /** Return the logical (bit-wise) "and" of two BigIntegers. */ - public BigIntegerCrypto and(BigIntegerCrypto y) { - if (y.words == null) - return and(this, y.ival); - else if (words == null) - return and(y, ival); - - BigIntegerCrypto x = this; - if (ival < y.ival) { - BigIntegerCrypto temp = this; - x = y; - y = temp; - } - int i; - int len = y.isNegative() ? x.ival : y.ival; - int[] words = new int[len]; - for (i = 0; i < y.ival; i++) - words[i] = x.words[i] & y.words[i]; - for (; i < len; i++) - words[i] = x.words[i]; - return make(words, len); - } - - /** Return the logical (bit-wise) "(inclusive) or" of two BigIntegers. */ - public BigIntegerCrypto or(BigIntegerCrypto y) { - return bitOp(7, this, y); - } - - /** Return the logical (bit-wise) "exclusive or" of two BigIntegers. */ - public BigIntegerCrypto xor(BigIntegerCrypto y) { - return bitOp(6, this, y); - } - - /** Return the logical (bit-wise) negation of a BigInteger. */ - public BigIntegerCrypto not() { - return bitOp(12, this, ZERO); - } - - public BigIntegerCrypto andNot(BigIntegerCrypto val) { - return and(val.not()); - } - - public BigIntegerCrypto clearBit(int n) { - if (n < 0) - throw new ArithmeticException(); - - return and(ONE.shiftLeft(n).not()); - } - - public BigIntegerCrypto setBit(int n) { - if (n < 0) - throw new ArithmeticException(); - - return or(ONE.shiftLeft(n)); - } - - public boolean testBit(int n) { - if (n < 0) - throw new ArithmeticException(); - - return !and(ONE.shiftLeft(n)).isZero(); - } - - public BigIntegerCrypto flipBit(int n) { - if (n < 0) - throw new ArithmeticException(); - - return xor(ONE.shiftLeft(n)); - } - - public int getLowestSetBit() { - if (isZero()) - return -1; - - if (words == null) - return MPN.findLowestBit(ival); - else - return MPN.findLowestBit(words); - } - - // bit4count[I] is number of '1' bits in I. - private static final byte[] bit4_count = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, - 3, 2, 3, 3, 4 }; - - private static int bitCount(int i) { - int count = 0; - while (i != 0) { - count += bit4_count[i & 15]; - i >>>= 4; - } - return count; - } - - private static int bitCount(int[] x, int len) { - int count = 0; - while (--len >= 0) - count += bitCount(x[len]); - return count; - } - - /** - * Count one bits in a BigInteger. If argument is negative, count zero bits - * instead. - */ - public int bitCount() { - int i, x_len; - int[] x_words = words; - if (x_words == null) { - x_len = 1; - i = bitCount(ival); - } else { - x_len = ival; - i = bitCount(x_words, x_len); - } - return isNegative() ? x_len * 32 - i : i; - } - - private void readObject(ObjectInputStream s) throws IOException, - ClassNotFoundException { - s.defaultReadObject(); - if (magnitude.length == 0 || signum == 0) { - this.ival = 0; - this.words = null; - } else { - words = byteArrayToIntArray(magnitude, signum < 0 ? -1 : 0); - Arrays.fill(magnitude, (byte)0); // crypto: clear temporary content - BigIntegerCrypto result = make(words, words.length); - this.ival = result.ival; - this.words = result.words; - } - } - - private void writeObject(ObjectOutputStream s) throws IOException { - signum = signum(); - magnitude = signum == 0 ? new byte[0] : toByteArray(); - s.defaultWriteObject(); - Arrays.fill(magnitude, (byte)0); // crypto: clear temporary content - magnitude = null; // not needed anymore - } - - // inner class(es) - // .......................................................... - -} diff --git a/src/gnu/java/bigintcrypto/test/BigIntCryptoDHTest.java b/src/gnu/java/bigintcrypto/test/BigIntCryptoDHTest.java deleted file mode 100755 index 7f3fd0e..0000000 --- a/src/gnu/java/bigintcrypto/test/BigIntCryptoDHTest.java +++ /dev/null @@ -1,63 +0,0 @@ -package gnu.java.bigintcrypto.test; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -import java.security.SecureRandom; - -/** - * Class to test and check required crypto algorithms. - * - */ -public class BigIntCryptoDHTest { - - // The DH prime for DH3k (3072 bit) as defined in RFC 3526 - public static final BigIntegerCrypto P3072 = new BigIntegerCrypto( -// 1 2 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 24 bytes per line - "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + // 0 - "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + // 1 - "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + // 2 - "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + // 3 - "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + // 4 - "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + // 5 - "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + // 6 - "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + // 7 - "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" + // 8 - "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + // 9 - "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" + // 10 - "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + // 11 - "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" + // 12 - "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + // 13 - "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" + // 14 - "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF", 16); // 15, total = 24 * 16 = 384 - - // DH generator 2 - public static final BigIntegerCrypto two = BigIntegerCrypto.valueOf(2); - - private SecureRandom secRand = new SecureRandom(); - - - public void testManyPub() { - BigIntegerCrypto x; - - for (int i = 0; i < 20; i++) { - - do { - x = new BigIntegerCrypto(256, 0, secRand); - } while (x.equals(BigIntegerCrypto.ZERO)); - - two.modPow(x, P3072); - System.out.print(i + " "); - } - } - - public static void main(String[] args) { - - BigIntCryptoDHTest ct = new BigIntCryptoDHTest(); - ct.testManyPub(); - - System.out.println("Test done"); - System.exit(0); - } - -} diff --git a/src/gnu/java/bigintcrypto/test/BigIntegerCryptoTest.java b/src/gnu/java/bigintcrypto/test/BigIntegerCryptoTest.java deleted file mode 100755 index a7b689a..0000000 --- a/src/gnu/java/bigintcrypto/test/BigIntegerCryptoTest.java +++ /dev/null @@ -1,555 +0,0 @@ -/** - * Copyright (C) 2006-2008 Werner Dittmann - * - * 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 3 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, see . - * - * Authors: Werner Dittmann - */ - -package gnu.java.bigintcrypto.test; - -/** - * The test class for BigIntegerCrypto. - * - * This class contains tests for BigIntegerCrypto. Mos tests were copied - * from various sources, for example BouncyCastle. - * - * Now they are in a Junit compliant framework. - * - * @author Werner Dittmann - */ - - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -import java.security.SecureRandom; - -import junit.framework.Test; -import junit.framework.TestCase; -import junit.framework.TestSuite; - - - -public class BigIntegerCryptoTest - extends TestCase -{ - private static BigIntegerCrypto VALUE1 = new BigIntegerCrypto("1234"); - private static BigIntegerCrypto VALUE2 = new BigIntegerCrypto("1234567890"); - private static BigIntegerCrypto VALUE3 = new BigIntegerCrypto("12345678901234567890123"); - - - protected static SecureRandom r = new SecureRandom(); - - java.math.BigInteger[] intsToTest = { - new java.math.BigInteger("0"), - new java.math.BigInteger("1"), - new java.math.BigInteger("2"), - new java.math.BigInteger("8"), - new java.math.BigInteger("9"), - new java.math.BigInteger("10"), - new java.math.BigInteger("11"), - new java.math.BigInteger("12"), - new java.math.BigInteger("21"), - new java.math.BigInteger("1000000"), - new java.math.BigInteger("123456789"), - new java.math.BigInteger("10203040506070809"), - new java.math.BigInteger("111111111111"), - new java.math.BigInteger("222222222222"), - new java.math.BigInteger(256, r), - new java.math.BigInteger(256, r), - new java.math.BigInteger(256, r), - new java.math.BigInteger(256, r), - new java.math.BigInteger(256, r) - }; - - BigIntegerCrypto[] myBigInts; - - java.math.BigInteger[] dividends = { - new java.math.BigInteger(81, r), - new java.math.BigInteger(100, r), - new java.math.BigInteger(190, r), - new java.math.BigInteger(200, r), - new java.math.BigInteger(256, r) - }; - - java.math.BigInteger[] divisors = { - new java.math.BigInteger(77, r), - new java.math.BigInteger(111, r), - new java.math.BigInteger(179, r), - new java.math.BigInteger(193, r), - new java.math.BigInteger(203, r) - }; - - BigIntegerCrypto[] myDividends; - BigIntegerCrypto[] myDivisors; - - /** - * Default constructor for test class BigIntegerTest - */ - public BigIntegerCryptoTest() - { - // This is here because it doesn't need to be - // re-run once per test: BigIntegers are immutable. - myBigInts = new BigIntegerCrypto[intsToTest.length]; - for (int x = 0; x < myBigInts.length; x++) { - myBigInts[x] = new BigIntegerCrypto(intsToTest[x].toString()); - } - - myDividends = new BigIntegerCrypto[dividends.length]; - myDivisors = new BigIntegerCrypto[divisors.length]; - - for (int i = 0; i < dividends.length; i++) { - myDividends[i] = new BigIntegerCrypto(dividends[i].toString()); - myDivisors[i] = new BigIntegerCrypto(divisors[i].toString()); - } - } - - /** - * Sets up the test fixture. - * - * Called before every test case method. - */ - protected void setUp() - { - } - - /** - * Tears down the test fixture. - * - * Called after every test case method. - */ - protected void tearDown() - { - } - - - public String getName() - { - return "BigIntegerCrypto"; - } - - public void testClearBit() - { - BigIntegerCrypto value = VALUE1.clearBit(3); - BigIntegerCrypto result = new BigIntegerCrypto("1234"); - - if (!value.equals(result)) - { - fail("clearBit - expected: " + result + " got: " + value); - } - - value = VALUE2.clearBit(3); - result = new BigIntegerCrypto("1234567890"); - - if (!value.equals(result)) - { - fail("clearBit - expected: " + result + " got: " + value); - } - - value = VALUE3.clearBit(3); - result = new BigIntegerCrypto("12345678901234567890115"); - - if (!value.equals(result)) - { - fail("clearBit - expected: " + result + " got: " + value); - } - - value = VALUE2.clearBit(55); - result = new BigIntegerCrypto("1234567890"); - - if (!value.equals(result)) - { - fail("clearBit - expected: " + result + " got: " + value); - } - - value = VALUE3.clearBit(55); - result = new BigIntegerCrypto("12345642872437548926155"); - - if (!value.equals(result)) - { - fail("clearBit - expected: " + result + " got: " + value); - } - } - - public void testFlipBit() - { - BigIntegerCrypto value = VALUE1.flipBit(3); - BigIntegerCrypto result = new BigIntegerCrypto("1242"); - - if (!value.equals(result)) - { - fail("flipBit - expected: " + result + " got: " + value); - } - - value = VALUE2.flipBit(3); - result = new BigIntegerCrypto("1234567898"); - - if (!value.equals(result)) - { - fail("flipBit - expected: " + result + " got: " + value); - } - - value = VALUE3.flipBit(3); - result = new BigIntegerCrypto("12345678901234567890115"); - - if (!value.equals(result)) - { - fail("flipBit - expected: " + result + " got: " + value); - } - - value = VALUE2.flipBit(55); - result = new BigIntegerCrypto("36028798253531858"); - - if (!value.equals(result)) - { - fail("flipBit - expected: " + result + " got: " + value); - } - - value = VALUE3.flipBit(55); - result = new BigIntegerCrypto("12345642872437548926155"); - - if (!value.equals(result)) - { - fail("flipBit - expected: " + result + " got: " + value); - } - } - - public void testSetBit() - { - BigIntegerCrypto value = VALUE1.setBit(3); - BigIntegerCrypto result = new BigIntegerCrypto("1242"); - - if (!value.equals(result)) - { - fail("setBit - expected: " + result + " got: " + value); - } - - value = VALUE2.setBit(3); - result = new BigIntegerCrypto("1234567898"); - - if (!value.equals(result)) - { - fail("setBit - expected: " + result + " got: " + value); - } - - value = VALUE3.setBit(3); - result = new BigIntegerCrypto("12345678901234567890123"); - - if (!value.equals(result)) - { - fail("setBit - expected: " + result + " got: " + value); - } - - value = VALUE2.setBit(55); - result = new BigIntegerCrypto("36028798253531858"); - - if (!value.equals(result)) - { - fail("setBit - expected: " + result + " got: " + value); - } - - value = VALUE3.setBit(55); - result = new BigIntegerCrypto("12345678901234567890123"); - - if (!value.equals(result)) - { - fail("setBit - expected: " + result + " got: " + value); - } - } - - public void testXor() - { - BigIntegerCrypto value = VALUE1.xor(VALUE2); - BigIntegerCrypto result = new BigIntegerCrypto("1234568704"); - - if (!value.equals(result)) - { - fail("xor - expected: " + result + " got: " + value); - } - - value = VALUE1.xor(VALUE3); - result = new BigIntegerCrypto("12345678901234567888921"); - - if (!value.equals(result)) - { - fail("xor - expected: " + result + " got: " + value); - } - - value = VALUE3.xor(VALUE1); - result = new BigIntegerCrypto("12345678901234567888921"); - - if (!value.equals(result)) - { - fail("xor - expected: " + result + " got: " + value); - } - - value = VALUE2.xor(new BigIntegerCrypto("-1")); - result = new BigIntegerCrypto("-1234567891"); - - if (!value.equals(result)) - { - fail("xor - expected: " + result + " got: " + value); - } - - value = VALUE3.xor(VALUE3); - result = new BigIntegerCrypto("0"); - - if (!value.equals(result)) - { - fail("xor - expected: " + result + " got: " + value); - } - } - - public void testPerform() - { - BigIntegerCrypto n1, n2, r1; - - // test division where the difference in bit length of the dividend and divisor is 32 bits - n1 = new BigIntegerCrypto("54975581388"); - n2 = new BigIntegerCrypto("10"); - r1 = n1.divide(n2); - if (!r1.toString(10).equals("5497558138")) - { - fail("BigIntegerCrypto: failed Divide Test"); - } - - // two's complement test - byte[] zeroBytes = BigIntegerCrypto.ZERO.toByteArray(); - byte[] oneBytes = BigIntegerCrypto.ONE.toByteArray(); - byte[] minusOneBytes = BigIntegerCrypto.ONE.negate().toByteArray(); - - BigIntegerCrypto zero = new BigIntegerCrypto(zeroBytes); - if (!zero.equals(BigIntegerCrypto.ZERO)) - { - fail("Failed constructing zero"); - } - - BigIntegerCrypto one = new BigIntegerCrypto(oneBytes); - if (!one.equals(BigIntegerCrypto.ONE)) - { - fail("Failed constructing one"); - } - - BigIntegerCrypto minusOne = new BigIntegerCrypto(minusOneBytes); - if (!minusOne.equals(BigIntegerCrypto.ONE.negate())) - { - fail("Failed constructing minus one"); - } - - SecureRandom random = new SecureRandom(); - byte[] randomBytes = new byte[100]; - for (int i=0; i < 100; i++) - { - random.nextBytes(randomBytes); - BigIntegerCrypto bcInt = new BigIntegerCrypto(randomBytes); - BigIntegerCrypto bcInt2 = new BigIntegerCrypto(bcInt.toByteArray()); - if (!bcInt.equals(bcInt2)) - { - fail("Failed constructing random value " + i); - } - -// java.math.BigIntegerCrypto jdkInt = new java.math.BigIntegerCrypto(randomBytes); -// byte[] bcBytes = bcInt.toByteArray(); -// byte[] jdkBytes = jdkInt.toByteArray(); -// if (!arrayEquals(bcBytes, jdkBytes)) -// { -// fail(""Failed constructing random value " + i); -// } - } - } - - - public void testMultiply() { - - // The following tests copied from: - // Copyright (C) 2004 David Gilbert - - // Mauve 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, or (at your option) - // any later version. - - // Mauve 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 Mauve; see the file COPYING. If not, write to - // the Free Software Foundation, 59 Temple Place - Suite 330, - // Boston, MA 02111-1307, USA. */ - - // modifications to use JUnit by: Werner Dittmann - - // some really simple cases - BigIntegerCrypto p1 = new BigIntegerCrypto("1"); - BigIntegerCrypto p2 = new BigIntegerCrypto("2"); - BigIntegerCrypto m1 = new BigIntegerCrypto("-1"); - BigIntegerCrypto m2 = new BigIntegerCrypto("-2"); - - assertTrue(p1.multiply(p2).equals(p2)); - assertTrue(p1.multiply(m2).equals(m2)); - assertTrue(m1.multiply(p2).equals(m2)); - assertTrue(m1.multiply(m2).equals(p2)); - - // some bigger numbers - BigIntegerCrypto bp1 = new BigIntegerCrypto("12345678901234567890123456789012345678901234567890"); - BigIntegerCrypto bp2 = new BigIntegerCrypto("987654321098765432198765"); - BigIntegerCrypto bm1 = new BigIntegerCrypto("-12345678901234567890123456789012345678901234567890"); - BigIntegerCrypto bm2 = new BigIntegerCrypto("-987654321098765432198765"); - BigIntegerCrypto resultp = new BigIntegerCrypto("12193263113702179523715891618930089161893008916189178958987793067366655850"); - BigIntegerCrypto resultm = new BigIntegerCrypto("-12193263113702179523715891618930089161893008916189178958987793067366655850"); - - assert(bp1.multiply(bp2).equals(resultp)); - assertTrue(bp1.multiply(bm2).equals(resultm)); - assertTrue(bm1.multiply(bp2).equals(resultm)); - assertTrue(bm1.multiply(bm2).equals(resultp)); - - // check null argument - boolean pass = false; - try - { - p1.multiply(null); - } - catch (NullPointerException e) - { - pass = true; - } - assertTrue(pass); - } - - - /* - * The next tests use the setup done in the constructor and compare - * the results of BigIntegerCrypto to the standard BigInteger package. - * - * These tests were copied from Zachary Kurmas (package/project not - * known to me) and modified to use the BigIntegerCrypto and the published - * API, not the internal API. - */ - public void testToString() { - for (int x = 0; x < intsToTest.length; x++) { - assertEquals("toString failed", intsToTest[x].toString(), - myBigInts[x].toString()); - } - } - - public void testEquals() { - for (int x = 0; x < intsToTest.length; x++) { - for (int y = 0; y < intsToTest.length; y++) { - boolean observed = myBigInts[x].equals(myBigInts[y]); - boolean expected = intsToTest[x].equals(intsToTest[y]); - - assertEquals("Equals failed comparing " + intsToTest[x] - + " and " + intsToTest[y], expected, observed); - } // end for y - } // end for x - } // end testEquals - - public void testLessThan() { - for (int x = 0; x < intsToTest.length; x++) { - for (int y = 0; y < intsToTest.length; y++) { - boolean observed = myBigInts[x].compareTo(myBigInts[y]) < 0; - boolean expected = intsToTest[x].compareTo(intsToTest[y]) < 0; - - assertEquals("lessThan failed comparing " + intsToTest[x] - + " and " + intsToTest[y], expected, observed); - } // end for y - } // end for x - } // end test - - protected void tAdd_helper(int a, int b) { - java.math.BigInteger expected = intsToTest[a].add(intsToTest[b]); - BigIntegerCrypto observed = myBigInts[a].add(myBigInts[b]); - assertEquals("Failure adding " + a + " and " + b, expected.toString(), - observed.toString()); - } - - public void testAdd() { - for (int x = 0; x < intsToTest.length; x++) { - for (int y = 0; y < intsToTest.length; y++) { - tAdd_helper(x, y); - } - } - } - - protected void tMult_helper(int a, int b) { - java.math.BigInteger expected = intsToTest[a].multiply(intsToTest[b]); - BigIntegerCrypto observed = myBigInts[a].multiply(myBigInts[b]); - assertEquals("Failure multiplying " + a + " and " + b, expected - .toString(), observed.toString()); - } - - public void testMultiply1() { - for (int x = 0; x < intsToTest.length; x++) { - for (int y = 0; y < intsToTest.length; y++) { - tMult_helper(x, y); - } - } - } - - protected void tDiv_helper(int a, int b) { - java.math.BigInteger expected = dividends[a].divide(divisors[b]); - BigIntegerCrypto observed = myDividends[a].divide(myDivisors[b]); - assertEquals("Failure dividing " + a + " and " + b, expected - .toString(), observed.toString()); - } - - public void testDivision() { - for (int x = 0; x < dividends.length; x++) { - for (int y = 0; y < divisors.length; y++) { - tDiv_helper(x, y); - } - } - } - - protected void tDivRem_helper(int a, int b) { - java.math.BigInteger expected[] = dividends[a] - .divideAndRemainder(divisors[b]); - BigIntegerCrypto observed[] = myDividends[a] - .divideAndRemainder(myDivisors[b]); - assertEquals("Failure dividing " + a + " and " + b, expected[0] - .toString(), observed[0].toString()); - assertEquals("Failure dividing " + a + " and " + b, expected[1] - .toString(), observed[1].toString()); - } - - public void testDivisionReminder() { - for (int x = 0; x < dividends.length; x++) { - for (int y = 0; y < divisors.length; y++) { - tDivRem_helper(x, y); - } - } - } - - /** - * JUnit suite

- * - * @return a junit test suite - */ - public static Test suite() { - return new TestSuite(BigIntegerCryptoTest.class); - } - - /** - * Main method

- * - * @param args - * command line args - */ - public static void main(String[] args) { - junit.textui.TestRunner.run(suite()); - } -} - diff --git a/src/gnu/java/bigintcrypto/test/BigIntegerTest.java b/src/gnu/java/bigintcrypto/test/BigIntegerTest.java deleted file mode 100755 index aaa92e0..0000000 --- a/src/gnu/java/bigintcrypto/test/BigIntegerTest.java +++ /dev/null @@ -1,334 +0,0 @@ -package gnu.java.bigintcrypto.test; - -import java.math.BigInteger; - -import java.security.SecureRandom; - - -import junit.framework.Test; -import junit.framework.TestCase; -import junit.framework.TestSuite; - -public class BigIntegerTest - extends TestCase -{ - private static BigInteger VALUE1 = new BigInteger("1234"); - private static BigInteger VALUE2 = new BigInteger("1234567890"); - private static BigInteger VALUE3 = new BigInteger("12345678901234567890123"); - - public String getName() - { - return "BigInteger"; - } - - public void testClearBit() - { - BigInteger value = VALUE1.clearBit(3); - BigInteger result = new BigInteger("1234"); - - if (!value.equals(result)) - { - fail("clearBit - expected: " + result + " got: " + value); - } - - value = VALUE2.clearBit(3); - result = new BigInteger("1234567890"); - - if (!value.equals(result)) - { - fail("clearBit - expected: " + result + " got: " + value); - } - - value = VALUE3.clearBit(3); - result = new BigInteger("12345678901234567890115"); - - if (!value.equals(result)) - { - fail("clearBit - expected: " + result + " got: " + value); - } - - value = VALUE2.clearBit(55); - result = new BigInteger("1234567890"); - - if (!value.equals(result)) - { - fail("clearBit - expected: " + result + " got: " + value); - } - - value = VALUE3.clearBit(55); - result = new BigInteger("12345642872437548926155"); - - if (!value.equals(result)) - { - fail("clearBit - expected: " + result + " got: " + value); - } - } - - public void testFlipBit() - { - BigInteger value = VALUE1.flipBit(3); - BigInteger result = new BigInteger("1242"); - - if (!value.equals(result)) - { - fail("flipBit - expected: " + result + " got: " + value); - } - - value = VALUE2.flipBit(3); - result = new BigInteger("1234567898"); - - if (!value.equals(result)) - { - fail("flipBit - expected: " + result + " got: " + value); - } - - value = VALUE3.flipBit(3); - result = new BigInteger("12345678901234567890115"); - - if (!value.equals(result)) - { - fail("flipBit - expected: " + result + " got: " + value); - } - - value = VALUE2.flipBit(55); - result = new BigInteger("36028798253531858"); - - if (!value.equals(result)) - { - fail("flipBit - expected: " + result + " got: " + value); - } - - value = VALUE3.flipBit(55); - result = new BigInteger("12345642872437548926155"); - - if (!value.equals(result)) - { - fail("flipBit - expected: " + result + " got: " + value); - } - } - - public void testSetBit() - { - BigInteger value = VALUE1.setBit(3); - BigInteger result = new BigInteger("1242"); - - if (!value.equals(result)) - { - fail("setBit - expected: " + result + " got: " + value); - } - - value = VALUE2.setBit(3); - result = new BigInteger("1234567898"); - - if (!value.equals(result)) - { - fail("setBit - expected: " + result + " got: " + value); - } - - value = VALUE3.setBit(3); - result = new BigInteger("12345678901234567890123"); - - if (!value.equals(result)) - { - fail("setBit - expected: " + result + " got: " + value); - } - - value = VALUE2.setBit(55); - result = new BigInteger("36028798253531858"); - - if (!value.equals(result)) - { - fail("setBit - expected: " + result + " got: " + value); - } - - value = VALUE3.setBit(55); - result = new BigInteger("12345678901234567890123"); - - if (!value.equals(result)) - { - fail("setBit - expected: " + result + " got: " + value); - } - } - - public void testXor() - { - BigInteger value = VALUE1.xor(VALUE2); - BigInteger result = new BigInteger("1234568704"); - - if (!value.equals(result)) - { - fail("xor - expected: " + result + " got: " + value); - } - - value = VALUE1.xor(VALUE3); - result = new BigInteger("12345678901234567888921"); - - if (!value.equals(result)) - { - fail("xor - expected: " + result + " got: " + value); - } - - value = VALUE3.xor(VALUE1); - result = new BigInteger("12345678901234567888921"); - - if (!value.equals(result)) - { - fail("xor - expected: " + result + " got: " + value); - } - - value = VALUE2.xor(new BigInteger("-1")); - result = new BigInteger("-1234567891"); - - if (!value.equals(result)) - { - fail("xor - expected: " + result + " got: " + value); - } - - value = VALUE3.xor(VALUE3); - result = new BigInteger("0"); - - if (!value.equals(result)) - { - fail("xor - expected: " + result + " got: " + value); - } - } - - public void testPerform() - { - BigInteger n1, n2, r1; - - // test division where the difference in bit length of the dividend and divisor is 32 bits - n1 = new BigInteger("54975581388"); - n2 = new BigInteger("10"); - r1 = n1.divide(n2); - if (!r1.toString(10).equals("5497558138")) - { - fail("BigInteger: failed Divide Test"); - } - - // two's complement test - byte[] zeroBytes = BigInteger.ZERO.toByteArray(); - byte[] oneBytes = BigInteger.ONE.toByteArray(); - byte[] minusOneBytes = BigInteger.ONE.negate().toByteArray(); - - BigInteger zero = new BigInteger(zeroBytes); - if (!zero.equals(BigInteger.ZERO)) - { - fail("Failed constructing zero"); - } - - BigInteger one = new BigInteger(oneBytes); - if (!one.equals(BigInteger.ONE)) - { - fail("Failed constructing one"); - } - - BigInteger minusOne = new BigInteger(minusOneBytes); - if (!minusOne.equals(BigInteger.ONE.negate())) - { - fail("Failed constructing minus one"); - } - - SecureRandom random = new SecureRandom(); - byte[] randomBytes = new byte[100]; - for (int i=0; i < 100; i++) - { - random.nextBytes(randomBytes); - BigInteger bcInt = new BigInteger(randomBytes); - BigInteger bcInt2 = new BigInteger(bcInt.toByteArray()); - if (!bcInt.equals(bcInt2)) - { - fail("Failed constructing random value " + i); - } - -// java.math.BigInteger jdkInt = new java.math.BigInteger(randomBytes); -// byte[] bcBytes = bcInt.toByteArray(); -// byte[] jdkBytes = jdkInt.toByteArray(); -// if (!arrayEquals(bcBytes, jdkBytes)) -// { -// fail(""Failed constructing random value " + i); -// } - } - } - - - public void testMultiply() { - - // The following tests copied from: - // Copyright (C) 2004 David Gilbert - - // Mauve 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, or (at your option) - // any later version. - - // Mauve 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 Mauve; see the file COPYING. If not, write to - // the Free Software Foundation, 59 Temple Place - Suite 330, - // Boston, MA 02111-1307, USA. */ - - // modified to use Junit by: Werner Dittmann - - // some really simple cases - BigInteger p1 = new BigInteger("1"); - BigInteger p2 = new BigInteger("2"); - BigInteger m1 = new BigInteger("-1"); - BigInteger m2 = new BigInteger("-2"); - - assertTrue(p1.multiply(p2).equals(p2)); - assertTrue(p1.multiply(m2).equals(m2)); - assertTrue(m1.multiply(p2).equals(m2)); - assertTrue(m1.multiply(m2).equals(p2)); - - // some bigger numbers - BigInteger bp1 = new BigInteger("12345678901234567890123456789012345678901234567890"); - BigInteger bp2 = new BigInteger("987654321098765432198765"); - BigInteger bm1 = new BigInteger("-12345678901234567890123456789012345678901234567890"); - BigInteger bm2 = new BigInteger("-987654321098765432198765"); - BigInteger resultp = new BigInteger("12193263113702179523715891618930089161893008916189178958987793067366655850"); - BigInteger resultm = new BigInteger("-12193263113702179523715891618930089161893008916189178958987793067366655850"); - - assert(bp1.multiply(bp2).equals(resultp)); - assertTrue(bp1.multiply(bm2).equals(resultm)); - assertTrue(bm1.multiply(bp2).equals(resultm)); - assertTrue(bm1.multiply(bm2).equals(resultp)); - - // check null argument - boolean pass = false; - try - { - p1.multiply(null); - } - catch (NullPointerException e) - { - pass = true; - } - assertTrue(pass); - } - - - /** - * JUnit suite

- * - * @return a junit test suite - */ - public static Test suite() { - return new TestSuite(BigIntegerTest.class); - } - - /** - * Main method

- * - * @param args - * command line args - */ - public static void main(String[] args) { - junit.textui.TestRunner.run(suite()); - } -} - diff --git a/src/gnu/java/math/MPN.java b/src/gnu/java/math/MPN.java deleted file mode 100755 index 3228d43..0000000 --- a/src/gnu/java/math/MPN.java +++ /dev/null @@ -1,771 +0,0 @@ -/* gnu.java.math.MPN - Copyright (C) 1999, 2000, 2001, 2004 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath 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, or (at your option) -any later version. - -GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -// Included from Kawa 1.6.62 with permission of the author, -// Per Bothner . - -package gnu.java.math; - -/** This contains various low-level routines for unsigned bigints. - * The interfaces match the mpn interfaces in gmp, - * so it should be easy to replace them with fast native functions - * that are trivial wrappers around the mpn_ functions in gmp - * (at least on platforms that use 32-bit "limbs"). - */ - -public class MPN -{ - /** Add x[0:size-1] and y, and write the size least - * significant words of the result to dest. - * Return carry, either 0 or 1. - * All values are unsigned. - * This is basically the same as gmp's mpn_add_1. */ - public static int add_1 (int[] dest, int[] x, int size, int y) - { - long carry = y & 0xffffffffL; - for (int i = 0; i < size; i++) - { - carry += (x[i] & 0xffffffffL); - dest[i] = (int) carry; - carry >>= 32; - } - return (int) carry; - } - - /** Add x[0:len-1] and y[0:len-1] and write the len least - * significant words of the result to dest[0:len-1]. - * All words are treated as unsigned. - * @return the carry, either 0 or 1 - * This function is basically the same as gmp's mpn_add_n. - */ - public static int add_n (int dest[], int[] x, int[] y, int len) - { - long carry = 0; - for (int i = 0; i < len; i++) - { - carry += (x[i] & 0xffffffffL) - + (y[i] & 0xffffffffL); - dest[i] = (int) carry; - carry >>>= 32; - } - return (int) carry; - } - - /** Subtract Y[0:size-1] from X[0:size-1], and write - * the size least significant words of the result to dest[0:size-1]. - * Return borrow, either 0 or 1. - * This is basically the same as gmp's mpn_sub_n function. - */ - - public static int sub_n (int[] dest, int[] X, int[] Y, int size) - { - int cy = 0; - for (int i = 0; i < size; i++) - { - int y = Y[i]; - int x = X[i]; - y += cy; /* add previous carry to subtrahend */ - // Invert the high-order bit, because: (unsigned) X > (unsigned) Y - // iff: (int) (X^0x80000000) > (int) (Y^0x80000000). - cy = (y^0x80000000) < (cy^0x80000000) ? 1 : 0; - y = x - y; - cy += (y^0x80000000) > (x ^ 0x80000000) ? 1 : 0; - dest[i] = y; - } - return cy; - } - - /** Multiply x[0:len-1] by y, and write the len least - * significant words of the product to dest[0:len-1]. - * Return the most significant word of the product. - * All values are treated as if they were unsigned - * (i.e. masked with 0xffffffffL). - * OK if dest==x (not sure if this is guaranteed for mpn_mul_1). - * This function is basically the same as gmp's mpn_mul_1. - */ - - public static int mul_1 (int[] dest, int[] x, int len, int y) - { - long yword = y & 0xffffffffL; - long carry = 0; - for (int j = 0; j < len; j++) - { - carry += (x[j] & 0xffffffffL) * yword; - dest[j] = (int) carry; - carry >>>= 32; - } - return (int) carry; - } - - /** - * Multiply x[0:xlen-1] and y[0:ylen-1], and - * write the result to dest[0:xlen+ylen-1]. - * The destination has to have space for xlen+ylen words, - * even if the result might be one limb smaller. - * This function requires that xlen >= ylen. - * The destination must be distinct from either input operands. - * All operands are unsigned. - * This function is basically the same gmp's mpn_mul. */ - - public static void mul (int[] dest, - int[] x, int xlen, - int[] y, int ylen) - { - dest[xlen] = MPN.mul_1 (dest, x, xlen, y[0]); - - for (int i = 1; i < ylen; i++) - { - long yword = y[i] & 0xffffffffL; - long carry = 0; - for (int j = 0; j < xlen; j++) - { - carry += (x[j] & 0xffffffffL) * yword - + (dest[i+j] & 0xffffffffL); - dest[i+j] = (int) carry; - carry >>>= 32; - } - dest[i+xlen] = (int) carry; - } - } - - /* Divide (unsigned long) N by (unsigned int) D. - * Returns (remainder << 32)+(unsigned int)(quotient). - * Assumes (unsigned int)(N>>32) < (unsigned int)D. - * Code transcribed from gmp-2.0's mpn_udiv_w_sdiv function. - */ - public static long udiv_qrnnd (long N, int D) - { - long q, r; - long a1 = N >>> 32; - long a0 = N & 0xffffffffL; - if (D >= 0) - { - if (a1 < ((D - a1 - (a0 >>> 31)) & 0xffffffffL)) - { - /* dividend, divisor, and quotient are nonnegative */ - q = N / D; - r = N % D; - } - else - { - /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */ - long c = N - ((long) D << 31); - /* Divide (c1*2^32 + c0) by d */ - q = c / D; - r = c % D; - /* Add 2^31 to quotient */ - q += 1 << 31; - } - } - else - { - long b1 = D >>> 1; /* d/2, between 2^30 and 2^31 - 1 */ - //long c1 = (a1 >> 1); /* A/2 */ - //int c0 = (a1 << 31) + (a0 >> 1); - long c = N >>> 1; - if (a1 < b1 || (a1 >> 1) < b1) - { - if (a1 < b1) - { - q = c / b1; - r = c % b1; - } - else /* c1 < b1, so 2^31 <= (A/2)/b1 < 2^32 */ - { - c = ~(c - (b1 << 32)); - q = c / b1; /* (A/2) / (d/2) */ - r = c % b1; - q = (~q) & 0xffffffffL; /* (A/2)/b1 */ - r = (b1 - 1) - r; /* r < b1 => new r >= 0 */ - } - r = 2 * r + (a0 & 1); - if ((D & 1) != 0) - { - if (r >= q) { - r = r - q; - } else if (q - r <= (D & 0xffffffffL)) { - r = r - q + D; - q -= 1; - } else { - r = r - q + D + D; - q -= 2; - } - } - } - else /* Implies c1 = b1 */ - { /* Hence a1 = d - 1 = 2*b1 - 1 */ - if (a0 >= ((-D) & 0xffffffffL)) - { - q = -1; - r = a0 + D; - } - else - { - q = -2; - r = a0 + D + D; - } - } - } - - return (r << 32) | (q & 0xFFFFFFFFl); - } - - /** Divide divident[0:len-1] by (unsigned int)divisor. - * Write result into quotient[0:len-1. - * Return the one-word (unsigned) remainder. - * OK for quotient==dividend. - */ - - public static int divmod_1 (int[] quotient, int[] dividend, - int len, int divisor) - { - int i = len - 1; - long r = dividend[i]; - if ((r & 0xffffffffL) >= (divisor & 0xffffffffL)) - r = 0; - else - { - quotient[i--] = 0; - r <<= 32; - } - - for (; i >= 0; i--) - { - int n0 = dividend[i]; - r = (r & ~0xffffffffL) | (n0 & 0xffffffffL); - r = udiv_qrnnd (r, divisor); - quotient[i] = (int) r; - } - return (int)(r >> 32); - } - - /* Subtract x[0:len-1]*y from dest[offset:offset+len-1]. - * All values are treated as if unsigned. - * @return the most significant word of - * the product, minus borrow-out from the subtraction. - */ - public static int submul_1 (int[] dest, int offset, int[] x, int len, int y) - { - long yl = y & 0xffffffffL; - int carry = 0; - int j = 0; - do - { - long prod = (x[j] & 0xffffffffL) * yl; - int prod_low = (int) prod; - int prod_high = (int) (prod >> 32); - prod_low += carry; - // Invert the high-order bit, because: (unsigned) X > (unsigned) Y - // iff: (int) (X^0x80000000) > (int) (Y^0x80000000). - carry = ((prod_low ^ 0x80000000) < (carry ^ 0x80000000) ? 1 : 0) - + prod_high; - int x_j = dest[offset+j]; - prod_low = x_j - prod_low; - if ((prod_low ^ 0x80000000) > (x_j ^ 0x80000000)) - carry++; - dest[offset+j] = prod_low; - } - while (++j < len); - return carry; - } - - /** Divide zds[0:nx] by y[0:ny-1]. - * The remainder ends up in zds[0:ny-1]. - * The quotient ends up in zds[ny:nx]. - * Assumes: nx>ny. - * (int)y[ny-1] < 0 (i.e. most significant bit set) - */ - - public static void divide (int[] zds, int nx, int[] y, int ny) - { - // This is basically Knuth's formulation of the classical algorithm, - // but translated from in scm_divbigbig in Jaffar's SCM implementation. - - // Correspondance with Knuth's notation: - // Knuth's u[0:m+n] == zds[nx:0]. - // Knuth's v[1:n] == y[ny-1:0] - // Knuth's n == ny. - // Knuth's m == nx-ny. - // Our nx == Knuth's m+n. - - // Could be re-implemented using gmp's mpn_divrem: - // zds[nx] = mpn_divrem (&zds[ny], 0, zds, nx, y, ny). - - int j = nx; - do - { // loop over digits of quotient - // Knuth's j == our nx-j. - // Knuth's u[j:j+n] == our zds[j:j-ny]. - int qhat; // treated as unsigned - if (zds[j]==y[ny-1]) - qhat = -1; // 0xffffffff - else - { - long w = (((long)(zds[j])) << 32) + (zds[j-1] & 0xffffffffL); - qhat = (int) udiv_qrnnd (w, y[ny-1]); - } - if (qhat != 0) - { - int borrow = submul_1 (zds, j - ny, y, ny, qhat); - int save = zds[j]; - long num = (save&0xffffffffL) - (borrow&0xffffffffL); - while (num != 0) - { - qhat--; - long carry = 0; - for (int i = 0; i < ny; i++) - { - carry += (zds[j-ny+i] & 0xffffffffL) - + (y[i] & 0xffffffffL); - zds[j-ny+i] = (int) carry; - carry >>>= 32; - } - zds[j] += carry; - num = carry - 1; - } - } - zds[j] = qhat; - } while (--j >= ny); - } - - /** Number of digits in the conversion base that always fits in a word. - * For example, for base 10 this is 9, since 10**9 is the - * largest number that fits into a words (assuming 32-bit words). - * This is the same as gmp's __mp_bases[radix].chars_per_limb. - * @param radix the base - * @return number of digits */ - public static int chars_per_word (int radix) - { - if (radix < 10) - { - if (radix < 8) - { - if (radix <= 2) - return 32; - else if (radix == 3) - return 20; - else if (radix == 4) - return 16; - else - return 18 - radix; - } - else - return 10; - } - else if (radix < 12) - return 9; - else if (radix <= 16) - return 8; - else if (radix <= 23) - return 7; - else if (radix <= 40) - return 6; - // The following are conservative, but we don't care. - else if (radix <= 256) - return 4; - else - return 1; - } - - /** Count the number of leading zero bits in an int. */ - public static int count_leading_zeros (int i) - { - if (i == 0) - return 32; - int count = 0; - for (int k = 16; k > 0; k = k >> 1) { - int j = i >>> k; - if (j == 0) - count += k; - else - i = j; - } - return count; - } - - public static int set_str (int dest[], byte[] str, int str_len, int base) - { - int size = 0; - if ((base & (base - 1)) == 0) - { - // The base is a power of 2. Read the input string from - // least to most significant character/digit. */ - - int next_bitpos = 0; - int bits_per_indigit = 0; - for (int i = base; (i >>= 1) != 0; ) bits_per_indigit++; - int res_digit = 0; - - for (int i = str_len; --i >= 0; ) - { - int inp_digit = str[i]; - res_digit |= inp_digit << next_bitpos; - next_bitpos += bits_per_indigit; - if (next_bitpos >= 32) - { - dest[size++] = res_digit; - next_bitpos -= 32; - res_digit = inp_digit >> (bits_per_indigit - next_bitpos); - } - } - - if (res_digit != 0) - dest[size++] = res_digit; - } - else - { - // General case. The base is not a power of 2. - int indigits_per_limb = MPN.chars_per_word (base); - int str_pos = 0; - - while (str_pos < str_len) - { - int chunk = str_len - str_pos; - if (chunk > indigits_per_limb) - chunk = indigits_per_limb; - int res_digit = str[str_pos++]; - int big_base = base; - - while (--chunk > 0) - { - res_digit = res_digit * base + str[str_pos++]; - big_base *= base; - } - - int cy_limb; - if (size == 0) - cy_limb = res_digit; - else - { - cy_limb = MPN.mul_1 (dest, dest, size, big_base); - cy_limb += MPN.add_1 (dest, dest, size, res_digit); - } - if (cy_limb != 0) - dest[size++] = cy_limb; - } - } - return size; - } - - /** Compare x[0:size-1] with y[0:size-1], treating them as unsigned integers. - * @result -1, 0, or 1 depending on if x<y, x==y, or x>y. - * This is basically the same as gmp's mpn_cmp function. - */ - public static int cmp (int[] x, int[] y, int size) - { - while (--size >= 0) - { - int x_word = x[size]; - int y_word = y[size]; - if (x_word != y_word) - { - // Invert the high-order bit, because: - // (unsigned) X > (unsigned) Y iff - // (int) (X^0x80000000) > (int) (Y^0x80000000). - return (x_word ^ 0x80000000) > (y_word ^0x80000000) ? 1 : -1; - } - } - return 0; - } - - /** - * Compare x[0:xlen-1] with y[0:ylen-1], treating them as unsigned integers. - * - * @return -1, 0, or 1 depending on if x<y, x==y, or x>y. - */ - public static int cmp (int[] x, int xlen, int[] y, int ylen) - { - return xlen > ylen ? 1 : xlen < ylen ? -1 : cmp (x, y, xlen); - } - - /** - * Shift x[x_start:x_start+len-1] count bits to the "right" - * (i.e. divide by 2**count). - * Store the len least significant words of the result at dest. - * The bits shifted out to the right are returned. - * OK if dest==x. - * Assumes: 0 < count < 32 - */ - public static int rshift (int[] dest, int[] x, int x_start, - int len, int count) - { - int count_2 = 32 - count; - int low_word = x[x_start]; - int retval = low_word << count_2; - int i = 1; - for (; i < len; i++) - { - int high_word = x[x_start+i]; - dest[i-1] = (low_word >>> count) | (high_word << count_2); - low_word = high_word; - } - dest[i-1] = low_word >>> count; - return retval; - } - - /** - * Shift x[x_start:x_start+len-1] count bits to the "right" - * (i.e. divide by 2**count). - * Store the len least significant words of the result at dest. - * OK if dest==x. - * Assumes: 0 <= count < 32 - * Same as rshift, but handles count==0 (and has no return value). - */ - public static void rshift0 (int[] dest, int[] x, int x_start, - int len, int count) - { - if (count > 0) - rshift(dest, x, x_start, len, count); - else - for (int i = 0; i < len; i++) - dest[i] = x[i + x_start]; - } - - /** Return the long-truncated value of right shifting. - * @param x a two's-complement "bignum" - * @param len the number of significant words in x - * @param count the shift count - * @return (long)(x[0..len-1] >> count). - */ - public static long rshift_long (int[] x, int len, int count) - { - int wordno = count >> 5; - count &= 31; - int sign = x[len-1] < 0 ? -1 : 0; - int w0 = wordno >= len ? sign : x[wordno]; - wordno++; - int w1 = wordno >= len ? sign : x[wordno]; - if (count != 0) - { - wordno++; - int w2 = wordno >= len ? sign : x[wordno]; - w0 = (w0 >>> count) | (w1 << (32-count)); - w1 = (w1 >>> count) | (w2 << (32-count)); - } - return ((long)w1 << 32) | (w0 & 0xffffffffL); - } - - /* Shift x[0:len-1] left by count bits, and store the len least - * significant words of the result in dest[d_offset:d_offset+len-1]. - * Return the bits shifted out from the most significant digit. - * Assumes 0 < count < 32. - * OK if dest==x. - */ - - public static int lshift (int[] dest, int d_offset, - int[] x, int len, int count) - { - int count_2 = 32 - count; - int i = len - 1; - int high_word = x[i]; - int retval = high_word >>> count_2; - d_offset++; - while (--i >= 0) - { - int low_word = x[i]; - dest[d_offset+i] = (high_word << count) | (low_word >>> count_2); - high_word = low_word; - } - dest[d_offset+i] = high_word << count; - return retval; - } - - /** Return least i such that word & (1<<i). Assumes word!=0. */ - - public static int findLowestBit (int word) - { - int i = 0; - while ((word & 0xF) == 0) - { - word >>= 4; - i += 4; - } - if ((word & 3) == 0) - { - word >>= 2; - i += 2; - } - if ((word & 1) == 0) - i += 1; - return i; - } - - /** Return least i such that words & (1<<i). Assumes there is such an i. */ - - public static int findLowestBit (int[] words) - { - for (int i = 0; ; i++) - { - if (words[i] != 0) - return 32 * i + findLowestBit (words[i]); - } - } - - /** Calculate Greatest Common Divisior of x[0:len-1] and y[0:len-1]. - * Assumes both arguments are non-zero. - * Leaves result in x, and returns len of result. - * Also destroys y (actually sets it to a copy of the result). */ - - public static int gcd (int[] x, int[] y, int len) - { - int i, word; - // Find sh such that both x and y are divisible by 2**sh. - for (i = 0; ; i++) - { - word = x[i] | y[i]; - if (word != 0) - { - // Must terminate, since x and y are non-zero. - break; - } - } - int initShiftWords = i; - int initShiftBits = findLowestBit (word); - // Logically: sh = initShiftWords * 32 + initShiftBits - - // Temporarily devide both x and y by 2**sh. - len -= initShiftWords; - MPN.rshift0 (x, x, initShiftWords, len, initShiftBits); - MPN.rshift0 (y, y, initShiftWords, len, initShiftBits); - - int[] odd_arg; /* One of x or y which is odd. */ - int[] other_arg; /* The other one can be even or odd. */ - if ((x[0] & 1) != 0) - { - odd_arg = x; - other_arg = y; - } - else - { - odd_arg = y; - other_arg = x; - } - - for (;;) - { - // Shift other_arg until it is odd; this doesn't - // affect the gcd, since we divide by 2**k, which does not - // divide odd_arg. - for (i = 0; other_arg[i] == 0; ) i++; - if (i > 0) - { - int j; - for (j = 0; j < len-i; j++) - other_arg[j] = other_arg[j+i]; - for ( ; j < len; j++) - other_arg[j] = 0; - } - i = findLowestBit(other_arg[0]); - if (i > 0) - MPN.rshift (other_arg, other_arg, 0, len, i); - - // Now both odd_arg and other_arg are odd. - - // Subtract the smaller from the larger. - // This does not change the result, since gcd(a-b,b)==gcd(a,b). - i = MPN.cmp(odd_arg, other_arg, len); - if (i == 0) - break; - if (i > 0) - { // odd_arg > other_arg - MPN.sub_n (odd_arg, odd_arg, other_arg, len); - // Now odd_arg is even, so swap with other_arg; - int[] tmp = odd_arg; odd_arg = other_arg; other_arg = tmp; - } - else - { // other_arg > odd_arg - MPN.sub_n (other_arg, other_arg, odd_arg, len); - } - while (odd_arg[len-1] == 0 && other_arg[len-1] == 0) - len--; - } - if (initShiftWords + initShiftBits > 0) - { - if (initShiftBits > 0) - { - int sh_out = MPN.lshift (x, initShiftWords, x, len, initShiftBits); - if (sh_out != 0) - x[(len++)+initShiftWords] = sh_out; - } - else - { - for (i = len; --i >= 0;) - x[i+initShiftWords] = x[i]; - } - for (i = initShiftWords; --i >= 0; ) - x[i] = 0; - len += initShiftWords; - } - return len; - } - - public static int intLength (int i) - { - return 32 - count_leading_zeros (i < 0 ? ~i : i); - } - - /** Calcaulte the Common Lisp "integer-length" function. - * Assumes input is canonicalized: len==BigInteger.wordsNeeded(words,len) */ - public static int intLength (int[] words, int len) - { - len--; - return intLength (words[len]) + 32 * len; - } - - /* DEBUGGING: - public static void dprint (BigInteger x) - { - if (x.words == null) - System.err.print(Long.toString((long) x.ival & 0xffffffffL, 16)); - else - dprint (System.err, x.words, x.ival); - } - public static void dprint (int[] x) { dprint (System.err, x, x.length); } - public static void dprint (int[] x, int len) { dprint (System.err, x, len); } - public static void dprint (java.io.PrintStream ps, int[] x, int len) - { - ps.print('('); - for (int i = 0; i < len; i++) - { - if (i > 0) - ps.print (' '); - ps.print ("#x" + Long.toString ((long) x[i] & 0xffffffffL, 16)); - } - ps.print(')'); - } - */ -} diff --git a/src/gnu/java/zrtp/ZRtp.java b/src/gnu/java/zrtp/ZRtp.java index 46b3a23..3519b6f 100644 --- a/src/gnu/java/zrtp/ZRtp.java +++ b/src/gnu/java/zrtp/ZRtp.java @@ -19,12 +19,11 @@ package gnu.java.zrtp; -import gnu.java.bigintcrypto.BigIntegerCrypto; import gnu.java.zrtp.ZrtpConstants.SupportedSASTypes; import gnu.java.zrtp.packets.*; import gnu.java.zrtp.utils.Base32; import gnu.java.zrtp.utils.EmojiBase32; -import gnu.java.zrtp.utils.ZrtpFortuna; +import gnu.java.zrtp.utils.ZrtpSecureRandom; import gnu.java.zrtp.utils.ZrtpUtils; import gnu.java.zrtp.zidfile.ZidFile; import gnu.java.zrtp.zidfile.ZidRecord; @@ -34,12 +33,13 @@ import org.bouncycastle.crypto.macs.HMac; import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.crypto.params.ParametersWithIV; -import org.bouncycastle.cryptozrtp.AsymmetricCipherKeyPair; -import org.bouncycastle.cryptozrtp.params.DHPublicKeyParameters; -import org.bouncycastle.cryptozrtp.params.Djb25519PublicKeyParameters; -import org.bouncycastle.cryptozrtp.params.ECPublicKeyParameters; -import org.bouncycastle.mathzrtp.ec.ECPoint; +import org.bouncycastle.crypto.AsymmetricCipherKeyPair; +import org.bouncycastle.crypto.params.DHPublicKeyParameters; +import org.bouncycastle.crypto.params.ECPublicKeyParameters; +import org.bouncycastle.math.ec.ECPoint; +import java.math.BigInteger; +import java.security.SecureRandom; import java.util.Arrays; import java.util.EnumSet; @@ -129,7 +129,7 @@ static class HelloPacketVersion { private AsymmetricCipherKeyPair ecKeyPair = null; - private ZrtpFortuna secRand; + private SecureRandom secRand; /** * The computed DH shared secret @@ -449,7 +449,7 @@ public ZRtp(byte[] myZid, ZrtpCallback cb, String id, ZrtpConfigure config, bool */ public ZRtp(byte[] myZid, ZrtpCallback cb, String id, ZrtpConfigure config, boolean mitmMode, boolean sasSignSupport) { - secRand = ZrtpFortuna.getInstance(); + secRand = ZrtpSecureRandom.getInstance(); configureAlgos = config; enableMitmEnrollment = config.isTrustedMitM(); @@ -1304,17 +1304,16 @@ private boolean fillPubKey() { } } // Here produce the ECDH stuff - else if (pubKey == ZrtpConstants.SupportedPubKeys.EC25 || pubKey == ZrtpConstants.SupportedPubKeys.EC38) { + else if (pubKey == ZrtpConstants.SupportedPubKeys.EC25 + || pubKey == ZrtpConstants.SupportedPubKeys.EC38 + || pubKey == ZrtpConstants.SupportedPubKeys.E255) { ecKeyPair = pubKey.keyPairGen.generateKeyPair(); - byte[] encoded = ((ECPublicKeyParameters) ecKeyPair.getPublic()).getQ().getEncoded(); + byte[] encoded = ((ECPublicKeyParameters) ecKeyPair.getPublic()).getQ() + .getEncoded(pubKey == ZrtpConstants.SupportedPubKeys.E255); pubKeyBytes = new byte[pubKey.pubKeySize]; System.arraycopy(encoded, 1, pubKeyBytes, 0, pubKey.pubKeySize); } - else if (pubKey == ZrtpConstants.SupportedPubKeys.E255) { - ecKeyPair = pubKey.keyPairGen.generateKeyPair(); - pubKeyBytes = ((Djb25519PublicKeyParameters)ecKeyPair.getPublic()).getP(); - } else { return false; } @@ -1559,7 +1558,7 @@ protected ZrtpPacketDHPart prepareDHPart2(ZrtpPacketDHPart dhPart1, ZrtpCodes.Zr // generate the resonpder's public key from the pvr data and the key // specs, then compute the shared secret. - BigIntegerCrypto pvrBigInt = new BigIntegerCrypto(1, pvrBytes); + BigInteger pvrBigInt = new BigInteger(1, pvrBytes); if (!checkPubKey(pvrBigInt, pubKey)) { errMsg[0] = ZrtpCodes.ZrtpErrorCodes.DHErrorWrongPV; return null; @@ -1567,32 +1566,24 @@ protected ZrtpPacketDHPart prepareDHPart2(ZrtpPacketDHPart dhPart1, ZrtpCodes.Zr pubKey.dhContext.init(dhKeyPair.getPrivate()); DHPublicKeyParameters pvr = new DHPublicKeyParameters(pvrBigInt, pubKey.specDh); dhSize = pubKey.pubKeySize; - BigIntegerCrypto bi = pubKey.dhContext.calculateAgreement(pvr); + BigInteger bi = pubKey.dhContext.calculateAgreement(pvr); DHss = bi.toByteArray(); - pubKey.dhContext.clear(); - bi.zeroize(); // clear secret big integer data } // Here produce the ECDH stuff - else if (pubKey == ZrtpConstants.SupportedPubKeys.EC25 || pubKey == ZrtpConstants.SupportedPubKeys.EC38) { + else if (pubKey == ZrtpConstants.SupportedPubKeys.EC25 + || pubKey == ZrtpConstants.SupportedPubKeys.EC38 + || pubKey == ZrtpConstants.SupportedPubKeys.E255) { byte[] encoded = new byte[pvrBytes.length + 1]; - encoded[0] = 0x04; // uncompressed + encoded[0] = (byte)(pubKey == ZrtpConstants.SupportedPubKeys.E255 + ? 0x02 // compressed, i.e. X only + : 0x04); // uncompressed System.arraycopy(pvrBytes, 0, encoded, 1, pvrBytes.length); ECPoint point = pubKey.curve.decodePoint(encoded); dhSize = pubKey.pubKeySize / 2; pubKey.dhContext.init(ecKeyPair.getPrivate()); - BigIntegerCrypto bi = pubKey.dhContext.calculateAgreement(new ECPublicKeyParameters(point, null)); - DHss = bi.toByteArray(); - pubKey.dhContext.clear(); - bi.zeroize(); // clear secret big integer data - } - else if (pubKey == ZrtpConstants.SupportedPubKeys.E255) { - dhSize = pubKey.pubKeySize; - pubKey.dhContext.init(ecKeyPair.getPrivate()); - BigIntegerCrypto bi = pubKey.dhContext.calculateAgreement(new Djb25519PublicKeyParameters(pvrBytes)); + BigInteger bi = pubKey.dhContext.calculateAgreement(new ECPublicKeyParameters(point, null)); DHss = bi.toByteArray(); - pubKey.dhContext.clear(); - bi.zeroize(); // clear secret big integer data } else { errMsg[0] = ZrtpCodes.ZrtpErrorCodes.CriticalSWError; @@ -1682,7 +1673,7 @@ protected ZrtpPacketConfirm prepareConfirm1(ZrtpPacketDHPart dhPart2, ZrtpCodes. // generate the resonpder's public key from the pvi data and the key // specs, then compute the shared secret. - BigIntegerCrypto pviBigInt = new BigIntegerCrypto(1, pviBytes); + BigInteger pviBigInt = new BigInteger(1, pviBytes); if (!checkPubKey(pviBigInt, pubKey)) { errMsg[0] = ZrtpCodes.ZrtpErrorCodes.DHErrorWrongPV; return null; @@ -1690,32 +1681,24 @@ protected ZrtpPacketConfirm prepareConfirm1(ZrtpPacketDHPart dhPart2, ZrtpCodes. pubKey.dhContext.init(dhKeyPair.getPrivate()); DHPublicKeyParameters pvi = new DHPublicKeyParameters(pviBigInt, pubKey.specDh); dhSize = pubKey.pubKeySize; - BigIntegerCrypto bi = pubKey.dhContext.calculateAgreement(pvi); + BigInteger bi = pubKey.dhContext.calculateAgreement(pvi); DHss = bi.toByteArray(); - pubKey.dhContext.clear(); - bi.zeroize(); // clear secret big integer data } // Here produce the ECDH stuff - else if (pubKey == ZrtpConstants.SupportedPubKeys.EC25 || pubKey == ZrtpConstants.SupportedPubKeys.EC38) { + else if (pubKey == ZrtpConstants.SupportedPubKeys.EC25 + || pubKey == ZrtpConstants.SupportedPubKeys.EC38 + || pubKey == ZrtpConstants.SupportedPubKeys.E255) { byte[] encoded = new byte[pviBytes.length + 1]; - encoded[0] = 0x04; // uncompressed + encoded[0] = (byte)(pubKey == ZrtpConstants.SupportedPubKeys.E255 + ? 0x02 // compressed, i.e. X only + : 0x04); // uncompressed System.arraycopy(pviBytes, 0, encoded, 1, pviBytes.length); ECPoint pubPoint = pubKey.curve.decodePoint(encoded); dhSize = pubKey.pubKeySize / 2; pubKey.dhContext.init(ecKeyPair.getPrivate()); - BigIntegerCrypto bi = pubKey.dhContext.calculateAgreement(new ECPublicKeyParameters(pubPoint, null)); - DHss = bi.toByteArray(); - pubKey.dhContext.clear(); - bi.zeroize(); // clear secret big integer data - } - else if (pubKey == ZrtpConstants.SupportedPubKeys.E255) { - dhSize = pubKey.pubKeySize; - pubKey.dhContext.init(ecKeyPair.getPrivate()); - BigIntegerCrypto bi = pubKey.dhContext.calculateAgreement(new Djb25519PublicKeyParameters(pviBytes)); + BigInteger bi = pubKey.dhContext.calculateAgreement(new ECPublicKeyParameters(pubPoint, null)); DHss = bi.toByteArray(); - pubKey.dhContext.clear(); - bi.zeroize(); // clear secret big integer data } else { errMsg[0] = ZrtpCodes.ZrtpErrorCodes.CriticalSWError; @@ -3091,8 +3074,8 @@ else if (ZrtpUtils.byteArrayCompare(rs2IDi, dhPart.getRs2Id(), 8) == 0) { Arrays.fill(s0, (byte) 0); } - private boolean checkPubKey(BigIntegerCrypto pvr, ZrtpConstants.SupportedPubKeys dhtype) { - if (pvr.equals(BigIntegerCrypto.ONE)) { + private boolean checkPubKey(BigInteger pvr, ZrtpConstants.SupportedPubKeys dhtype) { + if (pvr.equals(BigInteger.ONE)) { return false; } if (dhtype == ZrtpConstants.SupportedPubKeys.DH2K) { diff --git a/src/gnu/java/zrtp/ZrtpConstants.java b/src/gnu/java/zrtp/ZrtpConstants.java index ea5aead..b2a2819 100644 --- a/src/gnu/java/zrtp/ZrtpConstants.java +++ b/src/gnu/java/zrtp/ZrtpConstants.java @@ -19,26 +19,25 @@ package gnu.java.zrtp; -import gnu.java.bigintcrypto.BigIntegerCrypto; -import gnu.java.zrtp.utils.ZrtpFortuna; - +import gnu.java.zrtp.utils.ZrtpSecureRandom; import org.bouncycastle.asn1.sec.SECNamedCurves; import org.bouncycastle.asn1.x9.X9ECParameters; import org.bouncycastle.crypto.BufferedBlockCipher; +import org.bouncycastle.crypto.ec.CustomNamedCurves; import org.bouncycastle.crypto.engines.AESFastEngine; import org.bouncycastle.crypto.engines.TwofishEngine; import org.bouncycastle.crypto.modes.CFBBlockCipher; -import org.bouncycastle.cryptozrtp.AsymmetricCipherKeyPairGenerator; -import org.bouncycastle.cryptozrtp.BasicAgreement; -import org.bouncycastle.cryptozrtp.agreement.Djb25519DHBasicAgreement; -import org.bouncycastle.cryptozrtp.agreement.ECDHBasicAgreement; -import org.bouncycastle.cryptozrtp.generators.Djb25519KeyPairGenerator; -import org.bouncycastle.cryptozrtp.params.*; -import org.bouncycastle.cryptozrtp.agreement.DHBasicAgreement; -import org.bouncycastle.cryptozrtp.generators.DHBasicKeyPairGenerator; -import org.bouncycastle.cryptozrtp.generators.ECKeyPairGenerator; -import org.bouncycastle.mathzrtp.ec.ECCurve; +import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator; +import org.bouncycastle.crypto.BasicAgreement; +import org.bouncycastle.crypto.agreement.ECDHBasicAgreement; +import org.bouncycastle.crypto.params.*; +import org.bouncycastle.crypto.agreement.DHBasicAgreement; +import org.bouncycastle.crypto.generators.DHBasicKeyPairGenerator; +import org.bouncycastle.crypto.generators.ECKeyPairGenerator; +import org.bouncycastle.math.ec.ECCurve; + +import java.math.BigInteger; /** * @author Werner Dittmann @@ -313,20 +312,22 @@ public enum SupportedSymAlgos { public static final X9ECParameters x9Ec25 = SECNamedCurves.getByName("secp256r1"); public static final X9ECParameters x9Ec38 = SECNamedCurves.getByName("secp384r1"); + public static final X9ECParameters curve25519 = CustomNamedCurves.getByName("Curve25519"); public enum SupportedPubKeys { EC25(ec25, 64, new ECKeyGenerationParameters(new ECDomainParameters(x9Ec25.getCurve(), x9Ec25.getG(), x9Ec25.getN(), x9Ec25.getH(), - x9Ec25.getSeed()), ZrtpFortuna.getInstance())), + x9Ec25.getSeed()), ZrtpSecureRandom.getInstance())), EC38(ec38, 96, new ECKeyGenerationParameters(new ECDomainParameters(x9Ec38.getCurve(), x9Ec38.getG(), x9Ec38.getN(), x9Ec38.getH(), - x9Ec38.getSeed()), ZrtpFortuna.getInstance())), - - E255(e255, 32, new Djb25519KeyGenerationParameters(ZrtpFortuna.getInstance())), + x9Ec38.getSeed()), ZrtpSecureRandom.getInstance())), + E255(e255, 32, new ECKeyGenerationParameters(new ECDomainParameters(curve25519.getCurve(), + curve25519.getG(), curve25519.getN(), curve25519.getH(), + curve25519.getSeed()), ZrtpSecureRandom.getInstance())), - DH2K(dh2k, 256, new DHKeyGenerationParameters(ZrtpFortuna.getInstance(), + DH2K(dh2k, 256, new DHKeyGenerationParameters(ZrtpSecureRandom.getInstance(), specDh2k)), - DH3K(dh3k, 384, new DHKeyGenerationParameters(ZrtpFortuna.getInstance(), + DH3K(dh3k, 384, new DHKeyGenerationParameters(ZrtpSecureRandom.getInstance(), specDh3k)), MULT(mult); @@ -380,17 +381,6 @@ public enum SupportedPubKeys { } curve = null; } - - SupportedPubKeys(byte[] nm, int size, Djb25519KeyGenerationParameters djbdh) { - name = nm; - pubKeySize = size; - keyPairGen = new Djb25519KeyPairGenerator(); - keyPairGen.init(djbdh); - dhContext = new Djb25519DHBasicAgreement(); - curve = null; - - specDh = null; - } } public enum SupportedSASTypes { @@ -427,7 +417,7 @@ public enum SupportedAuthAlgos { // The Diffie-Helman constants as defined in the ZRTP specification // The DH prime for DH2k (2048 bit) as defined in RFC 3526 - public static final BigIntegerCrypto P2048 = new BigIntegerCrypto( + public static final BigInteger P2048 = new BigInteger( // 1 2 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 24 bytes per line "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + // 0 @@ -444,7 +434,7 @@ public enum SupportedAuthAlgos { // The DH prime for DH3k (3072 bit) as defined in RFC 3526 - public static final BigIntegerCrypto P3072 = new BigIntegerCrypto( + public static final BigInteger P3072 = new BigInteger( // 1 2 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 24 bytes per line "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + // 0 @@ -493,10 +483,10 @@ public enum SupportedAuthAlgos { "FFFFFFFFFFFFFFFF", 16); // Total = 8 + 24 * 21 = 512 *** */ // DH generator 2 - public static final BigIntegerCrypto two = BigIntegerCrypto.valueOf(2); + public static final BigInteger two = BigInteger.valueOf(2); - public static final BigIntegerCrypto P2048MinusOne = P2048.subtract(BigIntegerCrypto.ONE); - public static final BigIntegerCrypto P3072MinusOne = P3072.subtract(BigIntegerCrypto.ONE); + public static final BigInteger P2048MinusOne = P2048.subtract(BigInteger.ONE); + public static final BigInteger P3072MinusOne = P3072.subtract(BigInteger.ONE); // public static final BigIntegerCrypto P4096MinusOne = P4096.subtract(BigIntegerCrypto.ONE); public static final DHParameters specDh2k = new DHParameters(ZrtpConstants.P2048, diff --git a/src/gnu/java/zrtp/jmf/transform/TransformConnector.java b/src/gnu/java/zrtp/jmf/transform/TransformConnector.java index ee97e31..be0d602 100755 --- a/src/gnu/java/zrtp/jmf/transform/TransformConnector.java +++ b/src/gnu/java/zrtp/jmf/transform/TransformConnector.java @@ -104,7 +104,7 @@ public TransformConnector(SessionAddress localAddr, TransformEngine engine) } catch (SocketException e) { - throw new InvalidSessionAddressException(); + throw new InvalidSessionAddressException(e.getMessage()); } } diff --git a/src/gnu/java/zrtp/jmf/transform/srtp/SRTCPCryptoContext.java b/src/gnu/java/zrtp/jmf/transform/srtp/SRTCPCryptoContext.java index e76688d..9eff9e5 100644 --- a/src/gnu/java/zrtp/jmf/transform/srtp/SRTCPCryptoContext.java +++ b/src/gnu/java/zrtp/jmf/transform/srtp/SRTCPCryptoContext.java @@ -33,8 +33,7 @@ import org.bouncycastle.crypto.digests.SHA1Digest; import org.bouncycastle.crypto.macs.*; import org.bouncycastle.crypto.params.KeyParameter; -import org.jitsi.bccontrib.macs.SkeinMac; -import org.jitsi.bccontrib.params.ParametersForSkein; +import org.bouncycastle.crypto.params.SkeinParameters; import org.bouncycastle.crypto.BlockCipher; import org.bouncycastle.crypto.Mac; @@ -242,9 +241,9 @@ public SRTCPCryptoContext(long ssrcIn, break; case SRTPPolicy.SKEIN_AUTHENTICATION: - mac = new SkeinMac(); authKey = new byte[policy.getAuthKeyLength()]; tagStore = new byte[policy.getAuthTagLength()]; + mac = new SkeinMac(SkeinMac.SKEIN_512, authKey.length * 8); break; default: @@ -606,8 +605,7 @@ public void deriveSrtcpKeys() { case SRTPPolicy.SKEIN_AUTHENTICATION: // Skein MAC uses number of bits as MAC size, not just bytes - ParametersForSkein pfs = new ParametersForSkein(new KeyParameter(authKey), - ParametersForSkein.Skein512, tagStore.length*8); + SkeinParameters pfs = new SkeinParameters.Builder().setKey(authKey).build(); mac.init(pfs); break; } diff --git a/src/gnu/java/zrtp/jmf/transform/srtp/SRTPCryptoContext.java b/src/gnu/java/zrtp/jmf/transform/srtp/SRTPCryptoContext.java index be09276..706ec85 100755 --- a/src/gnu/java/zrtp/jmf/transform/srtp/SRTPCryptoContext.java +++ b/src/gnu/java/zrtp/jmf/transform/srtp/SRTPCryptoContext.java @@ -33,13 +33,12 @@ import org.bouncycastle.crypto.digests.SHA1Digest; import org.bouncycastle.crypto.macs.*; import org.bouncycastle.crypto.params.KeyParameter; -import org.jitsi.bccontrib.macs.SkeinMac; -import org.jitsi.bccontrib.params.ParametersForSkein; import org.bouncycastle.crypto.BlockCipher; import org.bouncycastle.crypto.Mac; import org.bouncycastle.crypto.engines.AESFastEngine; import org.bouncycastle.crypto.engines.TwofishEngine; +import org.bouncycastle.crypto.params.SkeinParameters; /** @@ -272,9 +271,9 @@ public SRTPCryptoContext(long ssrcIn, int rocIn, long kdr, break; case SRTPPolicy.SKEIN_AUTHENTICATION: - mac = new SkeinMac(); authKey = new byte[policy.getAuthKeyLength()]; tagStore = new byte[policy.getAuthTagLength()]; + mac = new SkeinMac(SkeinMac.SKEIN_512, tagStore.length * 8); break; default: @@ -662,8 +661,7 @@ public void deriveSrtpKeys(long index) { case SRTPPolicy.SKEIN_AUTHENTICATION: // Skein MAC uses number of bits as MAC size, not just bytes - ParametersForSkein pfs = new ParametersForSkein(new KeyParameter(authKey), - ParametersForSkein.Skein512, tagStore.length*8); + SkeinParameters pfs = new SkeinParameters.Builder().setKey(authKey).build(); mac.init(pfs); break; } diff --git a/src/gnu/java/zrtp/packets/ZrtpPacketDHPart.java b/src/gnu/java/zrtp/packets/ZrtpPacketDHPart.java index 67ba1b2..bf2cd3c 100755 --- a/src/gnu/java/zrtp/packets/ZrtpPacketDHPart.java +++ b/src/gnu/java/zrtp/packets/ZrtpPacketDHPart.java @@ -19,9 +19,9 @@ package gnu.java.zrtp.packets; -import djb.Curve25519; import gnu.java.zrtp.ZrtpConstants; import gnu.java.zrtp.utils.ZrtpUtils; +import org.bouncycastle.math.ec.custom.djb.Curve25519; /** @@ -117,7 +117,7 @@ else if (pkt == ZrtpConstants.SupportedPubKeys.EC38) { dhLength = 96; } else if (pkt == ZrtpConstants.SupportedPubKeys.E255) { - dhLength = Curve25519.KEY_SIZE; + dhLength = 32; //or new Curve25519().getBitLength()/8 } else return; diff --git a/src/gnu/java/zrtp/utils/FortunaGenerator.java b/src/gnu/java/zrtp/utils/FortunaGenerator.java new file mode 100644 index 0000000..01c824d --- /dev/null +++ b/src/gnu/java/zrtp/utils/FortunaGenerator.java @@ -0,0 +1,490 @@ +package gnu.java.zrtp.utils; + +import java.util.Arrays; + +import org.bouncycastle.crypto.Digest; +import org.bouncycastle.crypto.BlockCipher; +import org.bouncycastle.crypto.digests.SHA256Digest; +import org.bouncycastle.crypto.engines.AESFastEngine; +import org.bouncycastle.crypto.params.KeyParameter; +import org.bouncycastle.crypto.prng.RandomGenerator; + +/** + * The Fortuna random number generator. + *

+ * This class is a modified variant of the original Fortuna generator in GNU + * Classpath (see note below). The class now uses the Bouncycastle hash and + * cipher classes and provides a Bouncycastle compliant interface. + *

+ * Fortuna is a continuously-seeded pseudo-random number generator (PRNG) + * and is composed of two major pieces: the entropy accumulator and the + * generator function. The former takes in random bits and incorporates them + * into the generator's state. The latter takes this base entropy and generates + * pseudo-random bits from it. + *

+ * Here an example how to use the FortunaGenerator (pseudo code): + * + *

+ * ...
+ *     new Random().nextBytes(firstSeed)  // get some random data
+ *     FortunaGenerator fg = new FortunaGenerator(firstSeed);
+ *     ...
+ *     
+ *     fg.nextBytes(randomData)
+ *     ...
+ *     fg.addSeedMaterial(entropyData)
+ * 
+ * 
+ * + * After some time the application has done its work and exits. To enable + * a fast restart of the FortunaGenerator you may store the seed status + * and initialize the FortunaGenerator with this seed the next time. For + * example: + * + *
+ * ... // use FortunaGenerator
+ *     seedStatus = fg.getSeedStatus()
+ *     
+ *     // save seed status somewhere
+ *     // exit application
+ * ...
+ *     // restart application
+ *     if (saved seed status available) 
+ *         read seed status data
+ *         FortunaGenerator fg = new FortunaGenerator()
+ *         fg.setSeedStatus(seed status data)
+ *     // alternatively you can do 
+ *         FortunaGenerator = new FortunaGenerator(seed status data)
+ *     // use FortunaGenerator
+ * 
+ * 
+ * + * There are some things users of this class must be aware of: + *
+ *
Adding Random Data
+ *
This class does not do any polling of random sources, but rather provides + * an interface for adding entropy data (additional seed). Applications that use + * this code must provide this mechanism. We use this design because an + * application writer who knows the system he is targeting is in a better + * position to judge what random data is available.
+ *
Storing the Seed
+ *
This class implements functions to read and restore the seed in such a + * way that it returns a 64 byte seed byte array to the application, and sets it + * back again when the application sets the seed status again. This is the + * extent of seed file management, however, and those using this class are + * encouraged to think deeply about when, how often, and where to store the + * seed.
+ *
+ *

+ * References: + *

    + *
  • Niels Ferguson and Bruce Schneier, Practical Cryptography, pp. + * 155--184. Wiley Publishing, Indianapolis. (2003 Niels Ferguson and Bruce + * Schneier). ISBN 0-471-22357-3.
  • + *
+ * + * I did some small enhancements of the re-seed loop that, otherwise the + * algorithms were not touched. + *

+ * License: the Bouncycastle license applies to this file. Also notice the GNU + * Classpath license exception (see below). + *

+ * Copyright (C) 2010 Werner Dittmann (Werner.Dittmann@t-online.de)
+ * Copyright (C) 2004, 2006 Free Software Foundation, Inc. + * + */ + +/* + * Copyright note of the original Fortuna source. Not that THIS file is not + * longer part of GNU Classpath. + * + * Fortuna.java -- The Fortuna PRNG. +Copyright (C) 2004, 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath 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. + +GNU Classpath 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 GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +public class FortunaGenerator implements RandomGenerator { + + private static final int SEED_FILE_SIZE = 64; + private static final int NUM_POOLS = 32; + private static final int MIN_POOL_SIZE = 64; + private final Generator generator; + private final Digest[] pools; + private long lastReseed = 0; + private int pool = 0; + private int pool0Count = 0; + private int reseedCount = 0; + private boolean initialized = false; + + /** A temporary buffer to serve random bytes. */ + private byte[] buffer; + + /** The index into buffer of where the next byte will come from. */ + protected int ndx = 0; + + public FortunaGenerator() { + this(null); + } + + public FortunaGenerator(byte[] seed) { + generator = new Generator(new AESFastEngine(), new SHA256Digest()); + pools = new Digest[NUM_POOLS]; + for (int i = 0; i < NUM_POOLS; i++) + pools[i] = new SHA256Digest(); + buffer = new byte[256]; + if (seed != null) { + generator.init(seed); + fillBlock(); + initialized = true; + } + } + + private void fillBlock() { + if (pool0Count >= MIN_POOL_SIZE + && System.currentTimeMillis() - lastReseed > 100) + { + long powerOfTwo = 1; + reseedCount++; + byte[] randomBytes = new byte[pools[0].getDigestSize()]; + for (int i = 0; i < NUM_POOLS; i++) { + if (i == 0 || reseedCount % powerOfTwo == 0) { + pools[i].doFinal(randomBytes, 0); + generator.addRandomBytes(randomBytes, 0, randomBytes.length); + } + else + break; + + powerOfTwo <<= 1; + } + lastReseed = System.currentTimeMillis(); + pool0Count = 0; + } + generator.nextBytes(buffer, 0, buffer.length); + } + + /** + * Get new random data. + *

+ * This functions fills a byte buffer with new random data. + * + * @param out the buffer that receives the random data + */ + public void nextBytes(byte[] out) { + nextBytes(out, 0, out.length); + } + + /** + * Get new random data. + *

+ * This functions returns new random data. + * + * @param out the buffer that receives the random data + * @param offset offset into the buffer + * @param length number of random bytes + */ + public void nextBytes(byte[] out, int offset, int length) { + if (!initialized) + throw new IllegalStateException(" Fortuna generator not initialized/seeded"); + + if (length == 0) + return; + + if (offset < 0 || length < 0 || offset + length > out.length) + throw new ArrayIndexOutOfBoundsException("offset=" + offset + " length=" + + length + " limit=" + + out.length); + + if (ndx >= buffer.length) { + fillBlock(); + ndx = 0; + } + int count = 0; + while (count < length) { + int amount = Math.min(buffer.length - ndx, length - count); + System.arraycopy(buffer, ndx, out, offset + count, amount); + count += amount; + ndx += amount; + if (ndx >= buffer.length) { + fillBlock(); + ndx = 0; + } + } + } + + /** + * Adds new random data (entropy) to an entropy pool. + *

+ * This functions adds entropy data to the current pool. Fortuna uses + * 32 pools to gather entropy. After the function added the entropy to + * the pool it increments the current pool number modulo 32. + *

+ * Only if pool 0 (zero) got enough entropy (min. 64 bytes) then Fortuna + * uses the pools to perform a real re-seed. If an application uses this + * function to add entropy it shall take this behaviour into consideration. + * + * @param b a long with new entropy data. If the current pool is 0 then + * the function adds the length of a long to the overall + * entropy count that controls re-seed. + */ + public void addSeedMaterial(long b) { + pools[pool].update((byte)(b & 0xff)); + pools[pool].update((byte)((b >> 8) & 0xff)); + pools[pool].update((byte)((b >> 16) & 0xff)); + pools[pool].update((byte)((b >> 24) & 0xff)); + pools[pool].update((byte)((b >> 32) & 0xff)); + pools[pool].update((byte)((b >> 40) & 0xff)); + pools[pool].update((byte)((b >> 48) & 0xff)); + pools[pool].update((byte)((b >> 56) & 0xff)); + if (pool == 0) + pool0Count += 8; + pool = (pool + 1) % NUM_POOLS; + } + + /** + * Adds new random data (entropy) to an entropy pool. + *

+ * This functions adds entropy data to the current pool. Fortuna uses + * 32 pools to gather entropy. After the function added the entropy to + * the pool it increments the current pool number modulo 32. + *

+ * Only if pool 0 (zero) got enough entropy (min. 64 bytes) then Fortuna + * uses the pools to perform a real re-seed. If an application uses this + * function to add entropy it shall take this behaviour into consideration. + * + * @param buf buffer with new entropy data. If the current pool is 0 then + * the function adds the length of the buffer to the overall + * entropy count that controls re-seed. + */ + public void addSeedMaterial(byte[] buf) { + addSeedMaterial(buf, 0, buf.length); + } + + /** + * Adds new random data (entropy) to an entropy pool. + *

+ * This functions adds entropy data to the current pool. Fortuna uses + * 32 pools to gather entropy. After the function added the entropy to + * the pool it increments the current pool number modulo 32. + *

+ * Only if pool 0 (zero) got enough entropy (min. 64 bytes) then Fortuna + * uses the pools to perform a real re-seed. If an application uses this + * function to add entropy it shall take this behaviour into consideration. + * + * @param buf buffer with new entropy data. + * @param offset offset into the buffer + * @param length number of bytes to add to the current pool's entropy. + * If the current pool is 0 then the function adds the length + * of the buffer to the overall entropy count that controls + * re-seed. + */ + public void addSeedMaterial(byte[] buf, int offset, int length) { + pools[pool].update(buf, offset, length); + if (pool == 0) + pool0Count += buf.length; + pool = (pool + 1) % NUM_POOLS; + } + + /** + * Adds new random data (entropy) to the specified entropy pool. + *

+ * This functions adds entropy data to the the specified pool. Fortuna + * uses32 pools to gather entropy. + *

+ * Only if pool 0 (zero) got enough entropy (min. 64 bytes) then Fortuna + * uses the pools to perform a real re-seed. If an application uses this + * function to add entropy it shall take this behaviour into consideration. + * + * @param poolNumber specifies which pool receives the entropy data + * @param data buffer with new entropy data. + * @param offset offset into the buffer + * @param length number of bytes to add to the specified pool's entropy. + * If the specified pool is 0 then the function adds the length + * of the data to the overall entropy count that controls + * re-seed. + */ + public void addSeedMaterial(int poolNumber, byte[] data, int offset, int length) { + if (poolNumber < 0 || poolNumber >= pools.length) + throw new IllegalArgumentException("pool number out of range: " + + poolNumber); + pools[poolNumber].update((byte)length); + pools[poolNumber].update(data, offset, length); + if (poolNumber == 0) + pool0Count += length; + } + + + /** + * Return the generator's seed status. + *

+ * An application may get the seed status, store it in a safe place + * and retrieve it to seed a new Fortuna PRNG instance. + * + * @return The seed status. + */ + public byte[] getSeedStatus() { + byte[] seed = new byte[SEED_FILE_SIZE]; + generator.nextBytes(seed, 0, seed.length); + return seed; + } + + /** + * Seed the generator with a previously saved seed. + * + * @param seedStatus the generator's seed. + */ + public void setSeedStatus(byte[] seedStatus) { + generator.init(seedStatus); + fillBlock(); + initialized = true; + } + + /** + * The Fortuna generator function. The generator is a PRNG in its own right; + * Fortuna itself is basically a wrapper around this generator that manages + * re-seeding in a secure way. + */ + private static class Generator { + private static final int LIMIT = 1 << 20; + private final BlockCipher cipher; + private final Digest hash; + private final byte[] counter; + private final byte[] key; + + /** A temporary buffer to serve random bytes. */ + private byte[] buffer; + + /** The index into buffer of where the next byte will come from. */ + protected int ndx = 0; + + private Generator(final BlockCipher cipher, final Digest hash) + { + this.cipher = cipher; + this.hash = hash; + counter = new byte[cipher.getBlockSize()]; + buffer = new byte[cipher.getBlockSize()]; + key = new byte[32]; + } + + private void nextBytes(byte[] out, int offset, int length) { + + int count = 0; + do { + int amount = Math.min(LIMIT, length - count); + nextBytesInternal(out, offset + count, amount); + count += amount; + for (int i = 0; i < key.length; i += counter.length) { + fillBlock(); + int l = Math.min(key.length - i, cipher.getBlockSize()); + System.arraycopy(buffer, 0, key, i, l); + } + resetKey(); + } while (count < length); + + fillBlock(); + ndx = 0; + } + + private void addRandomBytes(byte[] seed, int offset, int length) { + hash.update(key, 0, key.length); + hash.update(seed, offset, length); + byte[] newkey = new byte[hash.getDigestSize()]; + hash.doFinal(newkey, 0); + System.arraycopy(newkey, 0, key, 0, Math.min(key.length, newkey.length)); + resetKey(); + incrementCounter(); + } + + private void fillBlock() { + cipher.processBlock(counter, 0, buffer, 0); + incrementCounter(); + } + + private void init(byte[] seed) { + Arrays.fill(key, (byte) 0); + Arrays.fill(counter, (byte) 0); + if (seed != null) + addRandomBytes(seed, 0, seed.length); + fillBlock(); + } + + private void nextBytesInternal(byte[] out, int offset, int length) { + + if (length == 0) + return; + + if (offset < 0 || length < 0 || offset + length > out.length) + throw new ArrayIndexOutOfBoundsException("offset=" + offset + " length=" + + length + " limit=" + + out.length); + if (ndx >= buffer.length) { + fillBlock(); + ndx = 0; + } + int count = 0; + while (count < length) { + int amount = Math.min(buffer.length - ndx, length - count); + System.arraycopy(buffer, ndx, out, offset + count, amount); + count += amount; + ndx += amount; + if (ndx >= buffer.length) { + fillBlock(); + ndx = 0; + } + } + } + + /** + * Resets the cipher's key. This is done after every reseed, which combines + * the old key and the seed, and processes that through the hash function. + */ + private void resetKey() { + cipher.reset(); + cipher.init(true, new KeyParameter(key)); + } + + /** + * Increment `counter' as a sixteen-byte little-endian unsigned integer by + * one. + */ + private void incrementCounter() { + for (int i = 0; i < counter.length; i++) { + counter[i]++; + if (counter[i] != 0) + break; + } + } + } +} + diff --git a/src/gnu/java/zrtp/utils/FortunaSecureRandom.java b/src/gnu/java/zrtp/utils/FortunaSecureRandom.java new file mode 100644 index 0000000..283b4d6 --- /dev/null +++ b/src/gnu/java/zrtp/utils/FortunaSecureRandom.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2017 Ingo Bauersachs + * + * 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 3 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, see . + */ +package gnu.java.zrtp.utils; + +import java.security.SecureRandom; +import java.security.SecureRandomSpi; + +/** + * A SecureRandom that generates the data based on the Fortuna PRNG. + */ +public class FortunaSecureRandom extends SecureRandom { + public FortunaSecureRandom() { + super(new FortunaSpi(), null); + } + + private static class FortunaSpi extends SecureRandomSpi { + private FortunaGenerator fortuna = new FortunaGenerator(engineGenerateSeed(256)); + + @Override + protected byte[] engineGenerateSeed(int numBytes) { + byte[] someData = new byte[numBytes]; + new SecureRandom().nextBytes(someData); + return someData; + } + + @Override + protected void engineNextBytes(byte[] bytes) { + fortuna.nextBytes(bytes, 0, bytes.length); + } + + @Override + protected void engineSetSeed(byte[] seed) { + fortuna.addSeedMaterial(seed); + } + } +} diff --git a/src/gnu/java/zrtp/utils/ZrtpFortuna.java b/src/gnu/java/zrtp/utils/ZrtpFortuna.java deleted file mode 100755 index 4e2de23..0000000 --- a/src/gnu/java/zrtp/utils/ZrtpFortuna.java +++ /dev/null @@ -1,190 +0,0 @@ -package gnu.java.zrtp.utils; - -import org.bouncycastle.crypto.prng.RandomGenerator; -import org.jitsi.bccontrib.prng.FortunaGenerator; - -import java.security.SecureRandom; - -/** - * A Fortuna PRNG utility class to maintain a Fortuna generator singleton. - * - * If several threads of an application require random data then this class - * helps to increase the quality of the random data. This class implements the - * BouncyCastle RandomNumber interface and the FortunaGenerator specific - * methods. - *

- * This class manages a Fortuna PRNG generator instance and maintains access. - * Thus all threads of an application can contribute entropy data to the same - * Fortuna PRNG instance. The quality of random data enhances if an application - * is able to add more entropy data. - *

- * If a thread requires random data it should use the methods of this class to - * get high quality random data. - *

- * ZrtpFortuna always creates a Fortuna generator instance and initializes the - * seed with some random data. An application may set another initialized - * Fortuna instance using the setFortuna() method after calling - * getInstance(). An application may use this feature to use a - * Fortuna instance that was initialized with a saved seed ( - * org.bouncycastle.crypto.prng. FortunaGenerator) - * - */ -public class ZrtpFortuna implements RandomGenerator { - - static private ZrtpFortuna singleInstance = null; - private FortunaGenerator fortuna = null; - - protected ZrtpFortuna() { - } - - synchronized static public ZrtpFortuna getInstance() { - if (singleInstance == null) { - singleInstance = new ZrtpFortuna(); - singleInstance.initialize(); - } - return singleInstance; - } - - private void initialize() { - byte[] someData = new byte[256]; - new SecureRandom().nextBytes(someData); - fortuna = new FortunaGenerator(someData); - } - - /** - * Get the Fortuna instance. - * - * @return The Fortuna instance. - */ - public FortunaGenerator getFortuna() { - return fortuna; - } - - /** - * Set the Fortuna instance. - * - * @param fortuna - * The Fortuna instance to use. - */ - synchronized public void setFortuna(FortunaGenerator fortuna) { - this.fortuna = fortuna; - } - - /** - * Adds new random data (entropy) to a entropy pool. - * - * This functions adds entropy data to the current pool. Fortuna uses 32 - * pools to gather entropy. After the function added the entropy to the pool - * it increments the current pool number modulo 32. - *

- * Only if pool 0 (zero) got enough entropy (min. 64 bytes) then Fortuna - * uses the pools to perform a real re-seed. If an application uses this - * function to add entropy it shall take this behaviour into consideration. - * - * @param entropy - * with new entropy data. If the current pool is 0 then the - * function adds the length of the buffer to the overall entropy - * count that controls re-seed. - */ - synchronized public void addSeedMaterial(byte[] entropy) { - fortuna.addSeedMaterial(entropy); - } - - /** - * Adds new random data (entropy) to a entropy pool. - * - * This functions adds entropy data to the current pool. Fortuna uses 32 - * pools to gather entropy. After the function added the entropy to the pool - * it increments the current pool number modulo 32. - *

- * Only if pool 0 (zero) got enough entropy (min. 64 bytes) then Fortuna - * uses the pools to perform a real re-seed. If an application uses this - * function to add entropy it shall take this behaviour into consideration. - * - * @param entropy - * a long with new entropy data. If the current pool is 0 then - * the function adds the length of a long to the overall entropy - * count that controls re-seed. - */ - synchronized public void addSeedMaterial(long entropy) { - fortuna.addSeedMaterial(entropy); - } - - /** - * Adds new random data (entropy) to a entropy pool. - * - * This functions adds entropy data to the current pool. Fortuna uses 32 - * pools to gather entropy. After the function added the entropy to the pool - * it increments the current pool number modulo 32. - *

- * Only if pool 0 (zero) got enough entropy (min. 64 bytes) then Fortuna - * uses the pools to perform a real re-seed. If an application uses this - * function to add entropy it shall take this behaviour into consideration. - * - * @param entropy - * buffer with new entropy data. - * @param offset - * offset into the buffer - * @param length - * number of bytes to add to the current pool's entropy. If the - * current pool is 0 then the function adds the length of the - * entropy to the overall entropy count that controls re-seed. - */ - synchronized public void addSeedMaterial(byte[] entropy, int offset, int length) { - fortuna.addSeedMaterial(entropy, offset, length); - } - - /** - * Adds new random data (entropy) to the specified entropy pool. - * - * This functions adds entropy data to the the specified pool. Fortuna - * uses32 pools to gather entropy. - *

- * Only if pool 0 (zero) got enough entropy (min. 64 bytes) then Fortuna - * uses the pools to perform a real re-seed. If an application uses this - * function to add entropy it shall take this behaviour into consideration. - * - * @param poolNumber - * specifies which pool receives the entropy data - * @param entropy - * buffer with new entropy data. - * @param offset - * offset into the buffer - * @param length - * number of bytes to add to the specified pool's entropy. If the - * specified pool is 0 then the function adds the length of the - * entropy to the overall entropy count that controls re-seed. - */ - synchronized public void addSeedMaterial(int poolNumber, byte[] entropy, - int offset, int length) { - fortuna.addSeedMaterial(poolNumber, entropy, offset, length); - } - - /** - * Get new random data. - * - * This functions fills a byte buffer with new random data. - * - * @param randomData - * the buffer that receives the random data - */ - synchronized public void nextBytes(byte[] randomData) { - fortuna.nextBytes(randomData); - } - - /** - * Get new random data. - * - * This functions returns new random data. - * - * @param randomData - * the buffer that receives the random data - * @param offset - * offset into the buffer - * @param length - * number of random bytes - */ - synchronized public void nextBytes(byte[] randomData, int offset, int length) { - fortuna.nextBytes(randomData, offset, length); - } -} diff --git a/src/gnu/java/zrtp/utils/ZrtpSecureRandom.java b/src/gnu/java/zrtp/utils/ZrtpSecureRandom.java new file mode 100644 index 0000000..0bd20cf --- /dev/null +++ b/src/gnu/java/zrtp/utils/ZrtpSecureRandom.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2017 Ingo Bauersachs + * + * 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 3 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, see . + */ +package gnu.java.zrtp.utils; + +import java.security.InvalidParameterException; +import java.security.SecureRandom; + +/** + * Utility class that provides a singleton for secure random numbers + * inside the entire ZRTP library. + */ +public class ZrtpSecureRandom extends SecureRandom { + private static SecureRandom instance; + + public static synchronized SecureRandom getInstance() { + if (instance == null) { + instance = new FortunaSecureRandom(); + } + + return instance; + } + + public static synchronized void setInstance(SecureRandom secureRandom) { + if (instance == null) { + instance = secureRandom; + } else { + throw new InvalidParameterException("The singleton has already been initialized"); + } + } +} diff --git a/src/org/bouncycastle/cryptozrtp/AsymmetricCipherKeyPair.java b/src/org/bouncycastle/cryptozrtp/AsymmetricCipherKeyPair.java deleted file mode 100755 index 23f122c..0000000 --- a/src/org/bouncycastle/cryptozrtp/AsymmetricCipherKeyPair.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.bouncycastle.cryptozrtp; - -/** - * a holding class for public/private parameter pairs. - */ -public class AsymmetricCipherKeyPair -{ - private CipherParameters publicParam; - private CipherParameters privateParam; - - /** - * basic constructor. - * - * @param publicParam a public key parameters object. - * @param privateParam the corresponding private key parameters. - */ - public AsymmetricCipherKeyPair( - CipherParameters publicParam, - CipherParameters privateParam) - { - this.publicParam = publicParam; - this.privateParam = privateParam; - } - - /** - * return the public key parameters. - * - * @return the public key parameters. - */ - public CipherParameters getPublic() - { - return publicParam; - } - - /** - * return the private key parameters. - * - * @return the private key parameters. - */ - public CipherParameters getPrivate() - { - return privateParam; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/AsymmetricCipherKeyPairGenerator.java b/src/org/bouncycastle/cryptozrtp/AsymmetricCipherKeyPairGenerator.java deleted file mode 100755 index a73b91e..0000000 --- a/src/org/bouncycastle/cryptozrtp/AsymmetricCipherKeyPairGenerator.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.bouncycastle.cryptozrtp; - -/** - * interface that a public/private key pair generator should conform to. - */ -public interface AsymmetricCipherKeyPairGenerator -{ - /** - * intialise the key pair generator. - * - * @param param the parameters the key pair is to be initialised with. - */ - public void init(KeyGenerationParameters param); - - /** - * return an AsymmetricCipherKeyPair containing the generated keys. - * - * @return an AsymmetricCipherKeyPair containing the generated keys. - */ - public AsymmetricCipherKeyPair generateKeyPair(); -} - diff --git a/src/org/bouncycastle/cryptozrtp/BasicAgreement.java b/src/org/bouncycastle/cryptozrtp/BasicAgreement.java deleted file mode 100755 index fdbcab8..0000000 --- a/src/org/bouncycastle/cryptozrtp/BasicAgreement.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.bouncycastle.cryptozrtp; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -/** - * The basic interface that basic Diffie-Hellman implementations - * conforms to. - */ -public interface BasicAgreement { - /** - * initialise the agreement engine. - */ - void init(CipherParameters param); - - /** - * given a public key from a given party calculate the next - * message in the agreement sequence. - */ - BigIntegerCrypto calculateAgreement(CipherParameters pubKey); - - /** - * Clear agreement data including private key data. - *

- * Clears all known agreement data and resets the agreement. To use the - * agreement againt the application must initialize it again. - */ - - void clear(); -} \ No newline at end of file diff --git a/src/org/bouncycastle/cryptozrtp/CipherParameters.java b/src/org/bouncycastle/cryptozrtp/CipherParameters.java deleted file mode 100755 index d5ff291..0000000 --- a/src/org/bouncycastle/cryptozrtp/CipherParameters.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.bouncycastle.cryptozrtp; - -/** - * all parameter classes implement this. - */ -public interface CipherParameters -{ -} diff --git a/src/org/bouncycastle/cryptozrtp/KeyGenerationParameters.java b/src/org/bouncycastle/cryptozrtp/KeyGenerationParameters.java deleted file mode 100755 index cb0689c..0000000 --- a/src/org/bouncycastle/cryptozrtp/KeyGenerationParameters.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.bouncycastle.cryptozrtp; - -import org.bouncycastle.crypto.prng.RandomGenerator; -/** - * The base class for parameters to key generators. - */ -public class KeyGenerationParameters -{ - private RandomGenerator random; - private int strength; - - /** - * initialise the generator with a source of randomness - * and a strength (in bits). - * - * @param random the random byte source. - * @param strength the size, in bits, of the keys we want to produce. - */ - public KeyGenerationParameters( - RandomGenerator random, - int strength) - { - this.random = random; - this.strength = strength; - } - - /** - * return the random source associated with this - * generator. - * - * @return the generators random source. - */ - public RandomGenerator getRandom() - { - return random; - } - - /** - * return the bit strength for keys produced by this generator, - * - * @return the strength of the keys this generator produces (in bits). - */ - public int getStrength() - { - return strength; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/agreement/DHAgreement.java b/src/org/bouncycastle/cryptozrtp/agreement/DHAgreement.java deleted file mode 100755 index c96fbb1..0000000 --- a/src/org/bouncycastle/cryptozrtp/agreement/DHAgreement.java +++ /dev/null @@ -1,88 +0,0 @@ -package org.bouncycastle.cryptozrtp.agreement; - -import gnu.java.bigintcrypto.BigIntegerCrypto; -import java.security.SecureRandom; - -import org.bouncycastle.cryptozrtp.CipherParameters; -import org.bouncycastle.cryptozrtp.params.DHParameters; -import org.bouncycastle.cryptozrtp.params.DHPublicKeyParameters; -import org.bouncycastle.cryptozrtp.params.DHPrivateKeyParameters; -import org.bouncycastle.cryptozrtp.params.AsymmetricKeyParameter; -import org.bouncycastle.cryptozrtp.params.ParametersWithRandom; - -/** - * a Diffie-Hellman key exchange engine. - *

- * note: This uses MTI/A0 key agreement in order to make the key agreement - * secure against passive attacks. If you're doing Diffie-Hellman and both - * parties have long term public keys you should look at using this. For - * further information have a look at RFC 2631. - *

- * It's possible to extend this to more than two parties as well, for the moment - * that is left as an exercise for the reader. - */ -public class DHAgreement -{ - private DHPrivateKeyParameters key; - private DHParameters dhParams; - private BigIntegerCrypto privateValue; - private SecureRandom random; - - public void init( - CipherParameters param) - { - AsymmetricKeyParameter kParam; - - if (param instanceof ParametersWithRandom) - { - ParametersWithRandom rParam = (ParametersWithRandom)param; - - this.random = rParam.getRandom(); - kParam = (AsymmetricKeyParameter)rParam.getParameters(); - } - else - { - this.random = new SecureRandom(); - kParam = (AsymmetricKeyParameter)param; - } - - - if (!(kParam instanceof DHPrivateKeyParameters)) - { - throw new IllegalArgumentException("DHEngine expects DHPrivateKeyParameters"); - } - - this.key = (DHPrivateKeyParameters)kParam; - this.dhParams = key.getParameters(); - } - - /** - * calculate our initial message. - */ - public BigIntegerCrypto calculateMessage() - { - int bits = dhParams.getP().bitLength() - 1; - - // TODO Should the generated numbers always have length 'p.bitLength() - 1'? - this.privateValue = new BigIntegerCrypto(bits, random).setBit(bits - 1); - - return dhParams.getG().modPow(privateValue, dhParams.getP()); - } - - /** - * given a message from a given party and the corresponding public key, - * calculate the next message in the agreement sequence. In this case - * this will represent the shared secret. - */ - public BigIntegerCrypto calculateAgreement( - DHPublicKeyParameters pub, - BigIntegerCrypto message) - { - if (!pub.getParameters().equals(dhParams)) - { - throw new IllegalArgumentException("Diffie-Hellman public key has wrong parameters."); - } - - return message.modPow(key.getX(), dhParams.getP()).multiply(pub.getY().modPow(privateValue, dhParams.getP())).mod(dhParams.getP()); - } -} diff --git a/src/org/bouncycastle/cryptozrtp/agreement/DHBasicAgreement.java b/src/org/bouncycastle/cryptozrtp/agreement/DHBasicAgreement.java deleted file mode 100755 index 273a23b..0000000 --- a/src/org/bouncycastle/cryptozrtp/agreement/DHBasicAgreement.java +++ /dev/null @@ -1,79 +0,0 @@ -package org.bouncycastle.cryptozrtp.agreement; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -import org.bouncycastle.cryptozrtp.BasicAgreement; -import org.bouncycastle.cryptozrtp.CipherParameters; -import org.bouncycastle.cryptozrtp.params.DHParameters; -import org.bouncycastle.cryptozrtp.params.DHPublicKeyParameters; -import org.bouncycastle.cryptozrtp.params.DHPrivateKeyParameters; -import org.bouncycastle.cryptozrtp.params.AsymmetricKeyParameter; -import org.bouncycastle.cryptozrtp.params.ParametersWithRandom; - -/** - * a Diffie-Hellman key agreement class. - *

- * note: This is only the basic algorithm, it doesn't take advantage of - * long term public keys if they are available. See the DHAgreement class - * for a "better" implementation. - */ -public class DHBasicAgreement - implements BasicAgreement -{ - private DHPrivateKeyParameters key; - private DHParameters dhParams; - - public void init( - CipherParameters param) - { - AsymmetricKeyParameter kParam; - - if (param instanceof ParametersWithRandom) - { - ParametersWithRandom rParam = (ParametersWithRandom)param; - kParam = (AsymmetricKeyParameter)rParam.getParameters(); - } - else - { - kParam = (AsymmetricKeyParameter)param; - } - - if (!(kParam instanceof DHPrivateKeyParameters)) - { - throw new IllegalArgumentException("DHEngine expects DHPrivateKeyParameters"); - } - - this.key = (DHPrivateKeyParameters)kParam; - this.dhParams = key.getParameters(); - } - - /** - * given a short term public key from a given party calculate the next - * message in the agreement sequence. - */ - public BigIntegerCrypto calculateAgreement( - CipherParameters pubKey) - { - DHPublicKeyParameters pub = (DHPublicKeyParameters)pubKey; - - if (!pub.getParameters().equals(dhParams)) - { - throw new IllegalArgumentException("Diffie-Hellman public key has wrong parameters."); - } - - return pub.getY().modPow(key.getX(), dhParams.getP()); - } - - /** - * Clear agreement data including private key data. - * - * Clears all known agreement data and resets the agreement. To use the - * agreement againt the application must initialize it again. - */ - - public void clear() { - key.getX().zeroize(); // clear private key data - key = null; - dhParams = null; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/agreement/Djb25519DHBasicAgreement.java b/src/org/bouncycastle/cryptozrtp/agreement/Djb25519DHBasicAgreement.java deleted file mode 100755 index 1cbd24a..0000000 --- a/src/org/bouncycastle/cryptozrtp/agreement/Djb25519DHBasicAgreement.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.bouncycastle.cryptozrtp.agreement; - -import djb.Curve25519; -import gnu.java.bigintcrypto.BigIntegerCrypto; -import org.bouncycastle.cryptozrtp.BasicAgreement; -import org.bouncycastle.cryptozrtp.CipherParameters; -import org.bouncycastle.cryptozrtp.params.Djb25519PrivateKeyParameters; -import org.bouncycastle.cryptozrtp.params.Djb25519PublicKeyParameters; -import org.bouncycastle.cryptozrtp.params.ECPrivateKeyParameters; -import org.bouncycastle.cryptozrtp.params.ECPublicKeyParameters; -import org.bouncycastle.mathzrtp.ec.ECPoint; - -import java.util.Arrays; - - -/** - * P1363 7.2.1 ECSVDP-DH - * - * ECSVDP-DH is Elliptic Curve Secret Value Derivation Primitive, - * Diffie-Hellman version. It is based on the work of [DH76], [Mil86], - * and [Kob87]. This primitive derives a shared secret value from one - * party's private key and another party's public key, where both have - * the same set of EC domain parameters. If two parties correctly - * execute this primitive, they will produce the same output. This - * primitive can be invoked by a scheme to derive a shared secret key; - * specifically, it may be used with the schemes ECKAS-DH1 and - * DL/ECKAS-DH2. It assumes that the input keys are valid (see also - * Section 7.2.2). - */ -public class Djb25519DHBasicAgreement implements BasicAgreement -{ - private Djb25519PrivateKeyParameters key; - - public void init(CipherParameters key) { - this.key = (Djb25519PrivateKeyParameters)key; - } - - public BigIntegerCrypto calculateAgreement(CipherParameters pubKey) { - Djb25519PublicKeyParameters pub = (Djb25519PublicKeyParameters)pubKey; - byte[] P = pub.getP(); - - /* Key agreement - * Z [out] shared secret (needs hashing before use) - * k [in] your private key for key agreement - * P [in] peer's public key - */ - byte[] Z = new byte[Curve25519.KEY_SIZE]; - Curve25519.curve(Z, key.getK(), P); - - // Return a BigInteger, use only as a byte array transport and to keep the API - return new BigIntegerCrypto(1, Z); - } - /** - * Clear agreement data including private key data. - * - * Clears all known agreement data and resets the agreement. To use the - * agreement againt the application must initialize it again. - */ - - public void clear() { - Arrays.fill(key.getK(), (byte)0); - key = null; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/agreement/ECDHBasicAgreement.java b/src/org/bouncycastle/cryptozrtp/agreement/ECDHBasicAgreement.java deleted file mode 100755 index 66baee1..0000000 --- a/src/org/bouncycastle/cryptozrtp/agreement/ECDHBasicAgreement.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.bouncycastle.cryptozrtp.agreement; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -import org.bouncycastle.mathzrtp.ec.ECPoint; - -import org.bouncycastle.cryptozrtp.BasicAgreement; -import org.bouncycastle.cryptozrtp.CipherParameters; -import org.bouncycastle.cryptozrtp.params.ECPublicKeyParameters; -import org.bouncycastle.cryptozrtp.params.ECPrivateKeyParameters; - - -/** - * P1363 7.2.1 ECSVDP-DH - * - * ECSVDP-DH is Elliptic Curve Secret Value Derivation Primitive, - * Diffie-Hellman version. It is based on the work of [DH76], [Mil86], - * and [Kob87]. This primitive derives a shared secret value from one - * party's private key and another party's public key, where both have - * the same set of EC domain parameters. If two parties correctly - * execute this primitive, they will produce the same output. This - * primitive can be invoked by a scheme to derive a shared secret key; - * specifically, it may be used with the schemes ECKAS-DH1 and - * DL/ECKAS-DH2. It assumes that the input keys are valid (see also - * Section 7.2.2). - */ -public class ECDHBasicAgreement - implements BasicAgreement -{ - private ECPrivateKeyParameters key; - - public void init( - CipherParameters key) - { - this.key = (ECPrivateKeyParameters)key; - } - - public BigIntegerCrypto calculateAgreement( - CipherParameters pubKey) - { - ECPublicKeyParameters pub = (ECPublicKeyParameters)pubKey; - ECPoint P = pub.getQ().multiply(key.getD()); - - // if (p.isInfinity()) throw new RuntimeException("d*Q == infinity"); - - return P.getX().toBigInteger(); - } - /** - * Clear agreement data including private key data. - * - * Clears all known agreement data and resets the agreement. To use the - * agreement againt the application must initialize it again. - */ - - public void clear() { - key.getD().zeroize(); // clear private key data - key = null; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/generators/DHBasicKeyPairGenerator.java b/src/org/bouncycastle/cryptozrtp/generators/DHBasicKeyPairGenerator.java deleted file mode 100755 index f63cc99..0000000 --- a/src/org/bouncycastle/cryptozrtp/generators/DHBasicKeyPairGenerator.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.bouncycastle.cryptozrtp.generators; - -import org.bouncycastle.cryptozrtp.AsymmetricCipherKeyPair; -import org.bouncycastle.cryptozrtp.AsymmetricCipherKeyPairGenerator; -import org.bouncycastle.cryptozrtp.KeyGenerationParameters; -import org.bouncycastle.cryptozrtp.params.DHKeyGenerationParameters; -import org.bouncycastle.cryptozrtp.params.DHParameters; -import org.bouncycastle.cryptozrtp.params.DHPrivateKeyParameters; -import org.bouncycastle.cryptozrtp.params.DHPublicKeyParameters; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -/** - * a basic Diffie-Helman key pair generator. - * - * This generates keys consistent for use with the basic algorithm for - * Diffie-Helman. - */ -public class DHBasicKeyPairGenerator - implements AsymmetricCipherKeyPairGenerator -{ - private DHKeyGeneratorHelper helper = DHKeyGeneratorHelper.INSTANCE; - private DHKeyGenerationParameters param; - - public void init( - KeyGenerationParameters param) - { - this.param = (DHKeyGenerationParameters)param; - } - - public AsymmetricCipherKeyPair generateKeyPair() - { - BigIntegerCrypto p, x, y; - DHParameters dhParams = param.getParameters(); - - p = dhParams.getP(); - x = helper.calculatePrivate(p, param.getRandom(), dhParams.getL()); - y = helper.calculatePublic(p, dhParams.getG(), x); - - return new AsymmetricCipherKeyPair( - new DHPublicKeyParameters(y, dhParams), - new DHPrivateKeyParameters(x, dhParams)); - } -} diff --git a/src/org/bouncycastle/cryptozrtp/generators/DHKeyGeneratorHelper.java b/src/org/bouncycastle/cryptozrtp/generators/DHKeyGeneratorHelper.java deleted file mode 100755 index 68cb2c3..0000000 --- a/src/org/bouncycastle/cryptozrtp/generators/DHKeyGeneratorHelper.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.bouncycastle.cryptozrtp.generators; - -import gnu.java.bigintcrypto.BigIntegerCrypto; -import org.bouncycastle.crypto.prng.RandomGenerator; - -class DHKeyGeneratorHelper -{ - private static final int MAX_ITERATIONS = 1000; - - static final DHKeyGeneratorHelper INSTANCE = new DHKeyGeneratorHelper(); - - private static final BigIntegerCrypto ZERO = BigIntegerCrypto.valueOf(0); - private static final BigIntegerCrypto TWO = BigIntegerCrypto.valueOf(2); - - private DHKeyGeneratorHelper() - { - } - - BigIntegerCrypto calculatePrivate(BigIntegerCrypto p, RandomGenerator random, int limit) - { - // - // calculate the private key - // - BigIntegerCrypto pSub2 = p.subtract(TWO); - BigIntegerCrypto x; - - if (limit == 0) - { - x = createInRange(pSub2, random); - } - else - { - do - { - x = new BigIntegerCrypto(limit, 0, random); - } - while (x.equals(ZERO)); - } - - return x; - } - - private BigIntegerCrypto createInRange(BigIntegerCrypto max, RandomGenerator random) - { - BigIntegerCrypto x; - int maxLength = max.bitLength(); - int count = 0; - - do - { - x = new BigIntegerCrypto(maxLength, random); - count++; - } - while ((x.equals(ZERO) || x.compareTo(max) > 0) && count != MAX_ITERATIONS); - - if (count == MAX_ITERATIONS) // fall back to a faster (restricted) method - { - return new BigIntegerCrypto(maxLength - 1, random).setBit(0); - } - - return x; - } - - BigIntegerCrypto calculatePublic(BigIntegerCrypto p, BigIntegerCrypto g, BigIntegerCrypto x) - { - return g.modPow(x, p); - } -} diff --git a/src/org/bouncycastle/cryptozrtp/generators/DHKeyPairGenerator.java b/src/org/bouncycastle/cryptozrtp/generators/DHKeyPairGenerator.java deleted file mode 100755 index 1b8dd28..0000000 --- a/src/org/bouncycastle/cryptozrtp/generators/DHKeyPairGenerator.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.bouncycastle.cryptozrtp.generators; - -import org.bouncycastle.cryptozrtp.AsymmetricCipherKeyPair; -import org.bouncycastle.cryptozrtp.AsymmetricCipherKeyPairGenerator; -import org.bouncycastle.cryptozrtp.KeyGenerationParameters; -import org.bouncycastle.cryptozrtp.params.DHKeyGenerationParameters; -import org.bouncycastle.cryptozrtp.params.DHParameters; -import org.bouncycastle.cryptozrtp.params.DHPrivateKeyParameters; -import org.bouncycastle.cryptozrtp.params.DHPublicKeyParameters; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -/** - * a Diffie-Helman key pair generator. - * - * This generates keys consistent for use in the MTI/A0 key agreement protocol - * as described in "Handbook of Applied Cryptography", Pages 516-519. - */ -public class DHKeyPairGenerator - implements AsymmetricCipherKeyPairGenerator -{ - private DHKeyGeneratorHelper helper = DHKeyGeneratorHelper.INSTANCE; - - private DHKeyGenerationParameters param; - - public void init( - KeyGenerationParameters param) - { - this.param = (DHKeyGenerationParameters)param; - } - - public AsymmetricCipherKeyPair generateKeyPair() - { - BigIntegerCrypto p, x, y; - DHParameters dhParams = param.getParameters(); - - p = dhParams.getP(); - x = helper.calculatePrivate(p, param.getRandom(), dhParams.getL()); - y = helper.calculatePublic(p, dhParams.getG(), x); - - return new AsymmetricCipherKeyPair( - new DHPublicKeyParameters(y, dhParams), - new DHPrivateKeyParameters(x, dhParams)); - } -} diff --git a/src/org/bouncycastle/cryptozrtp/generators/DHParametersGenerator.java b/src/org/bouncycastle/cryptozrtp/generators/DHParametersGenerator.java deleted file mode 100755 index b0e2ef9..0000000 --- a/src/org/bouncycastle/cryptozrtp/generators/DHParametersGenerator.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.bouncycastle.cryptozrtp.generators; - -import org.bouncycastle.cryptozrtp.params.DHParameters; - -import gnu.java.bigintcrypto.BigIntegerCrypto; -import org.bouncycastle.crypto.prng.RandomGenerator; - -public class DHParametersGenerator -{ - private int size; - private int certainty; - private RandomGenerator random; - - private static final BigIntegerCrypto TWO = BigIntegerCrypto.valueOf(2); - - /** - * Initialise the parameters generator. - * - * @param size bit length for the prime p - * @param certainty level of certainty for the prime number tests - * @param random a source of randomness - */ - public void init( - int size, - int certainty, - RandomGenerator random) - { - this.size = size; - this.certainty = certainty; - this.random = random; - } - - /** - * which generates the p and g values from the given parameters, - * returning the DHParameters object. - *

- * Note: can take a while... - */ - public DHParameters generateParameters() - { - // - // find a safe prime p where p = 2*q + 1, where p and q are prime. - // - BigIntegerCrypto[] safePrimes = DHParametersHelper.generateSafePrimes(size, certainty, random); - - BigIntegerCrypto p = safePrimes[0]; - BigIntegerCrypto q = safePrimes[1]; - BigIntegerCrypto g = DHParametersHelper.selectGenerator(p, q, random); - - return new DHParameters(p, g, q, TWO, null); - } -} diff --git a/src/org/bouncycastle/cryptozrtp/generators/DHParametersHelper.java b/src/org/bouncycastle/cryptozrtp/generators/DHParametersHelper.java deleted file mode 100755 index c7c2eed..0000000 --- a/src/org/bouncycastle/cryptozrtp/generators/DHParametersHelper.java +++ /dev/null @@ -1,70 +0,0 @@ -package org.bouncycastle.cryptozrtp.generators; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -import org.bouncycastle.crypto.prng.RandomGenerator; -import org.bouncycastle.cryptozrtp.util.BigIntegers; - -class DHParametersHelper -{ - private static final BigIntegerCrypto ONE = BigIntegerCrypto.valueOf(1); - private static final BigIntegerCrypto TWO = BigIntegerCrypto.valueOf(2); - - // Finds a pair of prime BigIntegerCrypto's {p, q: p = 2q + 1} - static BigIntegerCrypto[] generateSafePrimes( - int size, - int certainty, - RandomGenerator random) - { - BigIntegerCrypto p, q; - int qLength = size - 1; - - for (;;) - { - q = new BigIntegerCrypto(qLength, 2, random); - - // p <- 2q + 1 - p = q.shiftLeft(1).add(ONE); - - if (p.isProbablePrime(certainty) - && (certainty <= 2 || q.isProbablePrime(certainty))) - { - break; - } - } - - return new BigIntegerCrypto[] { p, q }; - } - - // Select a high order element of the multiplicative group Zp* - // p and q must be s.t. p = 2*q + 1, where p and q are prime - static BigIntegerCrypto selectGenerator( - BigIntegerCrypto p, - BigIntegerCrypto q, - RandomGenerator random) - { - BigIntegerCrypto pMinusTwo = p.subtract(TWO); - BigIntegerCrypto g; - - // Handbook of Applied Cryptography 4.86 - do - { - g = BigIntegers.createRandomInRange(TWO, pMinusTwo, random); - } - while (g.modPow(TWO, p).equals(ONE) - || g.modPow(q, p).equals(ONE)); - -/* - // RFC 2631 2.1.1 (and see Handbook of Applied Cryptography 4.81) - do - { - BigInteger h = createInRange(TWO, pMinusTwo, random); - - g = h.modPow(TWO, p); - } - while (g.equals(ONE)); -*/ - - return g; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/generators/Djb25519KeyPairGenerator.java b/src/org/bouncycastle/cryptozrtp/generators/Djb25519KeyPairGenerator.java deleted file mode 100755 index 7dccea8..0000000 --- a/src/org/bouncycastle/cryptozrtp/generators/Djb25519KeyPairGenerator.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.bouncycastle.cryptozrtp.generators; - -import djb.Curve25519; -import gnu.java.bigintcrypto.BigIntegerCrypto; -import org.bouncycastle.crypto.prng.RandomGenerator; -import org.bouncycastle.cryptozrtp.AsymmetricCipherKeyPair; -import org.bouncycastle.cryptozrtp.AsymmetricCipherKeyPairGenerator; -import org.bouncycastle.cryptozrtp.KeyGenerationParameters; -import org.bouncycastle.cryptozrtp.params.*; -import org.bouncycastle.mathzrtp.ec.ECConstants; -import org.bouncycastle.mathzrtp.ec.ECPoint; - -public class Djb25519KeyPairGenerator implements AsymmetricCipherKeyPairGenerator, ECConstants -{ - RandomGenerator random; - - public void init(KeyGenerationParameters param) { - Djb25519KeyGenerationParameters ecP = (Djb25519KeyGenerationParameters)param; - - this.random = ecP.getRandom(); - } - - /** - * Given the domain parameters this routine generates an EC key - * pair in accordance with X9.62 section 5.2.1 pages 26, 27. - */ - public AsymmetricCipherKeyPair generateKeyPair() - { - int nBitLength = Curve25519.KEY_SIZE * 8; - BigIntegerCrypto d; - - // Generate 32 bytes random data - byte[] k = new byte[Curve25519.KEY_SIZE]; - random.nextBytes(k); - - byte[] P = new byte[Curve25519.KEY_SIZE]; - Curve25519.keygen(P, null, k); - return new AsymmetricCipherKeyPair( - new Djb25519PublicKeyParameters(P), - new Djb25519PrivateKeyParameters(k)); - } -} diff --git a/src/org/bouncycastle/cryptozrtp/generators/ECKeyPairGenerator.java b/src/org/bouncycastle/cryptozrtp/generators/ECKeyPairGenerator.java deleted file mode 100755 index c7dc12c..0000000 --- a/src/org/bouncycastle/cryptozrtp/generators/ECKeyPairGenerator.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.bouncycastle.cryptozrtp.generators; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -import org.bouncycastle.crypto.prng.RandomGenerator; -import org.bouncycastle.cryptozrtp.AsymmetricCipherKeyPair; -import org.bouncycastle.cryptozrtp.AsymmetricCipherKeyPairGenerator; -import org.bouncycastle.cryptozrtp.KeyGenerationParameters; -import org.bouncycastle.cryptozrtp.params.ECDomainParameters; -import org.bouncycastle.cryptozrtp.params.ECKeyGenerationParameters; -import org.bouncycastle.cryptozrtp.params.ECPrivateKeyParameters; -import org.bouncycastle.cryptozrtp.params.ECPublicKeyParameters; -import org.bouncycastle.mathzrtp.ec.ECConstants; -import org.bouncycastle.mathzrtp.ec.ECPoint; - -public class ECKeyPairGenerator - implements AsymmetricCipherKeyPairGenerator, ECConstants -{ - ECDomainParameters params; - RandomGenerator random; - - public void init(KeyGenerationParameters param) { - ECKeyGenerationParameters ecP = (ECKeyGenerationParameters)param; - - this.random = ecP.getRandom(); - this.params = ecP.getDomainParameters(); - } - - /** - * Given the domain parameters this routine generates an EC key - * pair in accordance with X9.62 section 5.2.1 pages 26, 27. - */ - public AsymmetricCipherKeyPair generateKeyPair() - { - BigIntegerCrypto n = params.getN(); - int nBitLength = n.bitLength(); - BigIntegerCrypto d; - - do - { - d = new BigIntegerCrypto(nBitLength, random); - } - while (d.equals(ZERO) || (d.compareTo(n) >= 0)); - - ECPoint Q = params.getG().multiply(d); - - return new AsymmetricCipherKeyPair( - new ECPublicKeyParameters(Q, params), - new ECPrivateKeyParameters(d, params)); - } -} diff --git a/src/org/bouncycastle/cryptozrtp/params/AsymmetricKeyParameter.java b/src/org/bouncycastle/cryptozrtp/params/AsymmetricKeyParameter.java deleted file mode 100755 index 1154ba9..0000000 --- a/src/org/bouncycastle/cryptozrtp/params/AsymmetricKeyParameter.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.bouncycastle.cryptozrtp.params; - -import org.bouncycastle.cryptozrtp.CipherParameters; - -public class AsymmetricKeyParameter - implements CipherParameters -{ - boolean privateKey; - - public AsymmetricKeyParameter( - boolean privateKey) - { - this.privateKey = privateKey; - } - - public boolean isPrivate() - { - return privateKey; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/params/DHKeyGenerationParameters.java b/src/org/bouncycastle/cryptozrtp/params/DHKeyGenerationParameters.java deleted file mode 100755 index e0aeb32..0000000 --- a/src/org/bouncycastle/cryptozrtp/params/DHKeyGenerationParameters.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.bouncycastle.cryptozrtp.params; - -import org.bouncycastle.crypto.prng.RandomGenerator; - -import org.bouncycastle.cryptozrtp.KeyGenerationParameters; - -public class DHKeyGenerationParameters - extends KeyGenerationParameters -{ - private DHParameters params; - - public DHKeyGenerationParameters( - RandomGenerator random, - DHParameters params) - { - super(random, params.getP().bitLength()); - - this.params = params; - } - - public DHParameters getParameters() - { - return params; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/params/DHKeyParameters.java b/src/org/bouncycastle/cryptozrtp/params/DHKeyParameters.java deleted file mode 100755 index a522880..0000000 --- a/src/org/bouncycastle/cryptozrtp/params/DHKeyParameters.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.bouncycastle.cryptozrtp.params; - - -public class DHKeyParameters - extends AsymmetricKeyParameter -{ - private DHParameters params; - - protected DHKeyParameters( - boolean isPrivate, - DHParameters params) - { - super(isPrivate); - - this.params = params; - } - - public DHParameters getParameters() - { - return params; - } - - public boolean equals( - Object obj) - { - if (!(obj instanceof DHKeyParameters)) - { - return false; - } - - DHKeyParameters dhKey = (DHKeyParameters)obj; - - if (params == null) - { - return dhKey.getParameters() == null; - } - else - { - return params.equals(dhKey.getParameters()); - } - } - - public int hashCode() - { - int code = isPrivate() ? 0 : 1; - - if (params != null) - { - code ^= params.hashCode(); - } - - return code; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/params/DHParameters.java b/src/org/bouncycastle/cryptozrtp/params/DHParameters.java deleted file mode 100755 index dafdff8..0000000 --- a/src/org/bouncycastle/cryptozrtp/params/DHParameters.java +++ /dev/null @@ -1,169 +0,0 @@ -package org.bouncycastle.cryptozrtp.params; - -import org.bouncycastle.cryptozrtp.CipherParameters; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -public class DHParameters - implements CipherParameters -{ - private static final int DEFAULT_MINIMUM_LENGTH = 160; - - private BigIntegerCrypto g; - private BigIntegerCrypto p; - private BigIntegerCrypto q; - private BigIntegerCrypto j; - private int m = DEFAULT_MINIMUM_LENGTH; - private int l; - private DHValidationParameters validation; - - public DHParameters( - BigIntegerCrypto p, - BigIntegerCrypto g) - { - this(p, g, null, DEFAULT_MINIMUM_LENGTH, 0, null, null); - } - - public DHParameters( - BigIntegerCrypto p, - BigIntegerCrypto g, - BigIntegerCrypto q) - { - this(p, g, q, DEFAULT_MINIMUM_LENGTH, 0, null, null); - } - - public DHParameters( - BigIntegerCrypto p, - BigIntegerCrypto g, - BigIntegerCrypto q, - int l) - { - this(p, g, q, l, l, null, null); - } - - public DHParameters( - BigIntegerCrypto p, - BigIntegerCrypto g, - BigIntegerCrypto q, - int m, - int l) - { - this(p, g, q, m, l, null, null); - } - - public DHParameters( - BigIntegerCrypto p, - BigIntegerCrypto g, - BigIntegerCrypto q, - BigIntegerCrypto j, - DHValidationParameters validation) - { - this(p, g, q, DEFAULT_MINIMUM_LENGTH, 0, j, validation); - } - - public DHParameters( - BigIntegerCrypto p, - BigIntegerCrypto g, - BigIntegerCrypto q, - int m, - int l, - BigIntegerCrypto j, - DHValidationParameters validation) - { - if (l != 0 && m > l) - { - throw new IllegalArgumentException("l value must be greater than m value if provided"); - } - - this.g = g; - this.p = p; - this.q = q; - this.m = m; - this.l = l; - this.j = j; - this.validation = validation; - } - - public BigIntegerCrypto getP() - { - return p; - } - - public BigIntegerCrypto getG() - { - return g; - } - - public BigIntegerCrypto getQ() - { - return q; - } - - /** - * Return the subgroup factor J. - * - * @return subgroup factor - */ - public BigIntegerCrypto getJ() - { - return j; - } - - /** - * Return the minimum length of the private value. - * - * @return the minimum length of the private value in bits. - */ - public int getM() - { - return m; - } - - /** - * Return the private value length in bits - if set, zero otherwise (use bitLength(P) - 1). - * - * @return the private value length in bits, zero otherwise. - */ - public int getL() - { - return l; - } - - public DHValidationParameters getValidationParameters() - { - return validation; - } - - public boolean equals( - Object obj) - { - if (!(obj instanceof DHParameters)) - { - return false; - } - - DHParameters pm = (DHParameters)obj; - - if (this.getQ() != null) - { - if (!this.getQ().equals(pm.getQ())) - { - return false; - } - } - else - { - if (pm.getQ() != null) - { - return false; - } - } - - return pm.getP().equals(p) && pm.getG().equals(g); - } - - public int hashCode() - { - return getP().hashCode() ^ getG().hashCode() ^ (getQ() != null ? getQ().hashCode() : 0); - } -} diff --git a/src/org/bouncycastle/cryptozrtp/params/DHPrivateKeyParameters.java b/src/org/bouncycastle/cryptozrtp/params/DHPrivateKeyParameters.java deleted file mode 100755 index fc62f6b..0000000 --- a/src/org/bouncycastle/cryptozrtp/params/DHPrivateKeyParameters.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.bouncycastle.cryptozrtp.params; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -public class DHPrivateKeyParameters - extends DHKeyParameters -{ - private BigIntegerCrypto x; - - public DHPrivateKeyParameters( - BigIntegerCrypto x, - DHParameters params) - { - super(true, params); - - this.x = x; - } - - public BigIntegerCrypto getX() - { - return x; - } - - public int hashCode() - { - return x.hashCode() ^ super.hashCode(); - } - - public boolean equals( - Object obj) - { - if (!(obj instanceof DHPrivateKeyParameters)) - { - return false; - } - - DHPrivateKeyParameters other = (DHPrivateKeyParameters)obj; - - return other.getX().equals(this.x) && super.equals(obj); - } - - /** - * Clear private key data. - * - * Clears the private key data and overwrites it. To use the - * agreement again the application must initialize it again. - */ - - public void clear() { - if (x != null) - x.zeroize(); // overwrites BigIntere data with zero - x = null; - } - -} diff --git a/src/org/bouncycastle/cryptozrtp/params/DHPublicKeyParameters.java b/src/org/bouncycastle/cryptozrtp/params/DHPublicKeyParameters.java deleted file mode 100755 index 5fd9e44..0000000 --- a/src/org/bouncycastle/cryptozrtp/params/DHPublicKeyParameters.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.bouncycastle.cryptozrtp.params; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -public class DHPublicKeyParameters - extends DHKeyParameters -{ - private BigIntegerCrypto y; - - public DHPublicKeyParameters( - BigIntegerCrypto y, - DHParameters params) - { - super(false, params); - - this.y = y; - } - - public BigIntegerCrypto getY() - { - return y; - } - - public int hashCode() - { - return y.hashCode() ^ super.hashCode(); - } - - public boolean equals( - Object obj) - { - if (!(obj instanceof DHPublicKeyParameters)) - { - return false; - } - - DHPublicKeyParameters other = (DHPublicKeyParameters)obj; - - return other.getY().equals(y) && super.equals(obj); - } -} diff --git a/src/org/bouncycastle/cryptozrtp/params/DHValidationParameters.java b/src/org/bouncycastle/cryptozrtp/params/DHValidationParameters.java deleted file mode 100755 index 44a2d89..0000000 --- a/src/org/bouncycastle/cryptozrtp/params/DHValidationParameters.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.bouncycastle.cryptozrtp.params; - -import java.util.Arrays; - -public class DHValidationParameters -{ - private byte[] seed; - private int counter; - - public DHValidationParameters( - byte[] seed, - int counter) - { - this.seed = seed; - this.counter = counter; - } - - public int getCounter() - { - return counter; - } - - public byte[] getSeed() - { - return seed; - } - - public boolean equals( - Object o) - { - if (!(o instanceof DHValidationParameters)) - { - return false; - } - - DHValidationParameters other = (DHValidationParameters)o; - - if (other.counter != this.counter) - { - return false; - } - - return Arrays.equals(this.seed, other.seed); - } - - public int hashCode() - { - return counter ^ Arrays.hashCode(seed); - } -} diff --git a/src/org/bouncycastle/cryptozrtp/params/Djb25519KeyGenerationParameters.java b/src/org/bouncycastle/cryptozrtp/params/Djb25519KeyGenerationParameters.java deleted file mode 100755 index f2f4f14..0000000 --- a/src/org/bouncycastle/cryptozrtp/params/Djb25519KeyGenerationParameters.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.bouncycastle.cryptozrtp.params; - -import djb.Curve25519; -import org.bouncycastle.crypto.prng.RandomGenerator; -import org.bouncycastle.cryptozrtp.KeyGenerationParameters; - -public class Djb25519KeyGenerationParameters extends KeyGenerationParameters { - - public Djb25519KeyGenerationParameters(RandomGenerator random) { - super(random, Curve25519.KEY_SIZE * 8); - } -} diff --git a/src/org/bouncycastle/cryptozrtp/params/Djb25519PrivateKeyParameters.java b/src/org/bouncycastle/cryptozrtp/params/Djb25519PrivateKeyParameters.java deleted file mode 100755 index a8d360b..0000000 --- a/src/org/bouncycastle/cryptozrtp/params/Djb25519PrivateKeyParameters.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.bouncycastle.cryptozrtp.params; - -// Curve25519 uses 32 byte random data as a private key, not a BigInteger -public class Djb25519PrivateKeyParameters extends ECKeyParameters { - byte[] k; - - public Djb25519PrivateKeyParameters(byte[] k) { - super(true, null); - this.k = k; - } - - public byte[] getK() - { - return k; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/params/Djb25519PublicKeyParameters.java b/src/org/bouncycastle/cryptozrtp/params/Djb25519PublicKeyParameters.java deleted file mode 100755 index 4b589c6..0000000 --- a/src/org/bouncycastle/cryptozrtp/params/Djb25519PublicKeyParameters.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.bouncycastle.cryptozrtp.params; - -// Curve25519 derives 32 byte data as a public key from the private key data. -public class Djb25519PublicKeyParameters extends ECKeyParameters { - byte[] P; - - public Djb25519PublicKeyParameters(byte[] P) { - super(false, null); - this.P = P; - } - - public byte[] getP() - { - return P; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/params/ECDomainParameters.java b/src/org/bouncycastle/cryptozrtp/params/ECDomainParameters.java deleted file mode 100755 index 4017223..0000000 --- a/src/org/bouncycastle/cryptozrtp/params/ECDomainParameters.java +++ /dev/null @@ -1,102 +0,0 @@ -package org.bouncycastle.cryptozrtp.params; - -import gnu.java.bigintcrypto.BigIntegerCrypto; -import org.bouncycastle.mathzrtp.ec.ECConstants; -import org.bouncycastle.mathzrtp.ec.ECCurve; -import org.bouncycastle.mathzrtp.ec.ECPoint; - -public class ECDomainParameters - implements ECConstants -{ - ECCurve curve; - byte[] seed; - ECPoint G; - BigIntegerCrypto n; - BigIntegerCrypto h; - - public ECDomainParameters( - ECCurve curve, - ECPoint G, - BigIntegerCrypto n) - { - this.curve = curve; - this.G = G; - this.n = n; - this.h = ONE; - this.seed = null; - } - - public ECDomainParameters( - ECCurve curve, - ECPoint G, - BigIntegerCrypto n, - BigIntegerCrypto h) - { - this.curve = curve; - this.G = G; - this.n = n; - this.h = h; - this.seed = null; - } - - public ECDomainParameters( - ECCurve curve, - ECPoint G, - BigIntegerCrypto n, - BigIntegerCrypto h, - byte[] seed) - { - this.curve = curve; - this.G = G; - this.n = n; - this.h = h; - this.seed = seed; - } - - // Convert from "classic" parameters to cryptozrtp/mathzrtp parameters - public ECDomainParameters( - org.bouncycastle.math.ec.ECCurve curveIn, - org.bouncycastle.math.ec.ECPoint GIn, - java.math.BigInteger nIn, - java.math.BigInteger hIn, - byte[] seed) - { - org.bouncycastle.math.ec.ECCurve.Fp fpCurve = - (org.bouncycastle.math.ec.ECCurve.Fp)curveIn; - BigIntegerCrypto q = new BigIntegerCrypto(fpCurve.getQ().toByteArray()); - BigIntegerCrypto a = new BigIntegerCrypto(curveIn.getA().toBigInteger().toByteArray()); - BigIntegerCrypto b = new BigIntegerCrypto(curveIn.getB().toBigInteger().toByteArray()); - this.curve = new ECCurve.Fp(q, a, b); - - byte[] encoded = GIn.getEncoded(); - this.G = this.curve.decodePoint(encoded); - this.n = new BigIntegerCrypto(nIn.toByteArray()); - this.h = new BigIntegerCrypto(hIn.toByteArray()); - this.seed = seed; - } - - public ECCurve getCurve() - { - return curve; - } - - public ECPoint getG() - { - return G; - } - - public BigIntegerCrypto getN() - { - return n; - } - - public BigIntegerCrypto getH() - { - return h; - } - - public byte[] getSeed() - { - return seed; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/params/ECKeyGenerationParameters.java b/src/org/bouncycastle/cryptozrtp/params/ECKeyGenerationParameters.java deleted file mode 100755 index 8c32baf..0000000 --- a/src/org/bouncycastle/cryptozrtp/params/ECKeyGenerationParameters.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.bouncycastle.cryptozrtp.params; - -import org.bouncycastle.crypto.prng.RandomGenerator; - -import org.bouncycastle.cryptozrtp.KeyGenerationParameters; - -public class ECKeyGenerationParameters - extends KeyGenerationParameters -{ - private ECDomainParameters domainParams; - - public ECKeyGenerationParameters( - ECDomainParameters domainParams, - RandomGenerator random) - { - super(random, domainParams.getN().bitLength()); - - this.domainParams = domainParams; - } - - public ECDomainParameters getDomainParameters() - { - return domainParams; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/params/ECKeyParameters.java b/src/org/bouncycastle/cryptozrtp/params/ECKeyParameters.java deleted file mode 100755 index e36a04c..0000000 --- a/src/org/bouncycastle/cryptozrtp/params/ECKeyParameters.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.bouncycastle.cryptozrtp.params; - -public class ECKeyParameters - extends AsymmetricKeyParameter -{ - ECDomainParameters params; - - protected ECKeyParameters( - boolean isPrivate, - ECDomainParameters params) - { - super(isPrivate); - - this.params = params; - } - - public ECDomainParameters getParameters() - { - return params; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/params/ECPrivateKeyParameters.java b/src/org/bouncycastle/cryptozrtp/params/ECPrivateKeyParameters.java deleted file mode 100755 index fcac37e..0000000 --- a/src/org/bouncycastle/cryptozrtp/params/ECPrivateKeyParameters.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.bouncycastle.cryptozrtp.params; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -public class ECPrivateKeyParameters - extends ECKeyParameters -{ - BigIntegerCrypto d; - - public ECPrivateKeyParameters( - BigIntegerCrypto d, - ECDomainParameters params) - { - super(true, params); - this.d = d; - } - - public BigIntegerCrypto getD() - { - return d; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/params/ECPublicKeyParameters.java b/src/org/bouncycastle/cryptozrtp/params/ECPublicKeyParameters.java deleted file mode 100755 index 866f9a4..0000000 --- a/src/org/bouncycastle/cryptozrtp/params/ECPublicKeyParameters.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.bouncycastle.cryptozrtp.params; - -import org.bouncycastle.mathzrtp.ec.ECPoint; - -public class ECPublicKeyParameters - extends ECKeyParameters -{ - ECPoint Q; - - public ECPublicKeyParameters( - ECPoint Q, - ECDomainParameters params) - { - super(false, params); - this.Q = Q; - } - - public ECPoint getQ() - { - return Q; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/params/ParametersWithRandom.java b/src/org/bouncycastle/cryptozrtp/params/ParametersWithRandom.java deleted file mode 100755 index cbf6d9d..0000000 --- a/src/org/bouncycastle/cryptozrtp/params/ParametersWithRandom.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.bouncycastle.cryptozrtp.params; - -import org.bouncycastle.crypto.CipherParameters; - -import java.security.SecureRandom; - -public class ParametersWithRandom - implements CipherParameters -{ - private SecureRandom random; - private CipherParameters parameters; - - public ParametersWithRandom( - CipherParameters parameters, - SecureRandom random) - { - this.random = random; - this.parameters = parameters; - } - - public ParametersWithRandom( - CipherParameters parameters) - { - this(parameters, new SecureRandom()); - } - - public SecureRandom getRandom() - { - return random; - } - - public CipherParameters getParameters() - { - return parameters; - } -} diff --git a/src/org/bouncycastle/cryptozrtp/util/BigIntegers.java b/src/org/bouncycastle/cryptozrtp/util/BigIntegers.java deleted file mode 100755 index 5f99bd8..0000000 --- a/src/org/bouncycastle/cryptozrtp/util/BigIntegers.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.bouncycastle.cryptozrtp.util; - -import gnu.java.bigintcrypto.BigIntegerCrypto; -import org.bouncycastle.crypto.prng.RandomGenerator; - -/** - * BigInteger utilities. - */ -public final class BigIntegers -{ - /** - * Return the passed in value as an unsigned byte array. - * - * @param value value to be converted. - * @return a byte array without a leading zero byte if present in the signed encoding. - */ - public static byte[] asUnsignedByteArray( - BigIntegerCrypto value) - { - byte[] bytes = value.toByteArray(); - - if (bytes[0] == 0) - { - byte[] tmp = new byte[bytes.length - 1]; - - System.arraycopy(bytes, 1, tmp, 0, tmp.length); - - return tmp; - } - - return bytes; - } - - /** - * Return a random BigInteger not less than 'min' and not greater than 'max' - * - * @param min the least value that may be generated - * @param max the greatest value that may be generated - * @param random the source of randomness - * @return a random BigInteger value in the range [min,max] - */ - public static BigIntegerCrypto createRandomInRange( - BigIntegerCrypto min, - BigIntegerCrypto max, - RandomGenerator random) - { - BigIntegerCrypto x; - do - { - x = new BigIntegerCrypto(max.bitLength(), random); - } - while (x.compareTo(min) < 0 || x.compareTo(max) > 0); - return x; - } -} diff --git a/src/org/bouncycastle/mathzrtp/ec/ECAlgorithms.java b/src/org/bouncycastle/mathzrtp/ec/ECAlgorithms.java deleted file mode 100755 index 0a5379f..0000000 --- a/src/org/bouncycastle/mathzrtp/ec/ECAlgorithms.java +++ /dev/null @@ -1,93 +0,0 @@ -package org.bouncycastle.mathzrtp.ec; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -public class ECAlgorithms -{ - public static ECPoint sumOfTwoMultiplies(ECPoint P, BigIntegerCrypto a, - ECPoint Q, BigIntegerCrypto b) - { - ECCurve c = P.getCurve(); - if (!c.equals(Q.getCurve())) - { - throw new IllegalArgumentException("P and Q must be on same curve"); - } - - // TODO Add special case back in when WTNAF is enabled -// // Point multiplication for Koblitz curves (using WTNAF) beats Shamir's trick -// if (c instanceof ECCurve.F2m) -// { -// ECCurve.F2m f2mCurve = (ECCurve.F2m) c; -// if (f2mCurve.isKoblitz()) -// { -// return P.multiply(a).add(Q.multiply(b)); -// } -// } - - return implShamirsTrick(P, a, Q, b); - } - - /* - * "Shamir's Trick", originally due to E. G. Straus - * (Addition chains of vectors. American Mathematical Monthly, - * 71(7):806-808, Aug./Sept. 1964) - *

-     * Input: The points P, Q, scalar k = (km?, ... , k1, k0)
-     * and scalar l = (lm?, ... , l1, l0).
-     * Output: R = k * P + l * Q.
-     * 1: Z <- P + Q
-     * 2: R <- O
-     * 3: for i from m-1 down to 0 do
-     * 4:        R <- R + R        {point doubling}
-     * 5:        if (ki = 1) and (li = 0) then R <- R + P end if
-     * 6:        if (ki = 0) and (li = 1) then R <- R + Q end if
-     * 7:        if (ki = 1) and (li = 1) then R <- R + Z end if
-     * 8: end for
-     * 9: return R
-     * 
- */ - public static ECPoint shamirsTrick(ECPoint P, BigIntegerCrypto k, - ECPoint Q, BigIntegerCrypto l) - { - if (!P.getCurve().equals(Q.getCurve())) - { - throw new IllegalArgumentException("P and Q must be on same curve"); - } - - return implShamirsTrick(P, k, Q, l); - } - - private static ECPoint implShamirsTrick(ECPoint P, BigIntegerCrypto k, - ECPoint Q, BigIntegerCrypto l) - { - int m = Math.max(k.bitLength(), l.bitLength()); - ECPoint Z = P.add(Q); - ECPoint R = P.getCurve().getInfinity(); - - for (int i = m - 1; i >= 0; --i) - { - R = R.twice(); - - if (k.testBit(i)) - { - if (l.testBit(i)) - { - R = R.add(Z); - } - else - { - R = R.add(P); - } - } - else - { - if (l.testBit(i)) - { - R = R.add(Q); - } - } - } - - return R; - } -} diff --git a/src/org/bouncycastle/mathzrtp/ec/ECConstants.java b/src/org/bouncycastle/mathzrtp/ec/ECConstants.java deleted file mode 100755 index c430d3b..0000000 --- a/src/org/bouncycastle/mathzrtp/ec/ECConstants.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.bouncycastle.mathzrtp.ec; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -public interface ECConstants -{ - public static final BigIntegerCrypto ZERO = BigIntegerCrypto.valueOf(0); - public static final BigIntegerCrypto ONE = BigIntegerCrypto.valueOf(1); - public static final BigIntegerCrypto TWO = BigIntegerCrypto.valueOf(2); - public static final BigIntegerCrypto THREE = BigIntegerCrypto.valueOf(3); - public static final BigIntegerCrypto FOUR = BigIntegerCrypto.valueOf(4); -} diff --git a/src/org/bouncycastle/mathzrtp/ec/ECCurve.java b/src/org/bouncycastle/mathzrtp/ec/ECCurve.java deleted file mode 100755 index f3da51c..0000000 --- a/src/org/bouncycastle/mathzrtp/ec/ECCurve.java +++ /dev/null @@ -1,660 +0,0 @@ -package org.bouncycastle.mathzrtp.ec; - -import gnu.java.bigintcrypto.BigIntegerCrypto; -import java.util.Random; - -/** - * base class for an elliptic curve - */ -public abstract class ECCurve -{ - ECFieldElement a, b; - - public abstract int getFieldSize(); - - public abstract ECFieldElement fromBigInteger(BigIntegerCrypto x); - - public abstract ECPoint createPoint(BigIntegerCrypto x, BigIntegerCrypto y, boolean withCompression); - - public abstract ECPoint decodePoint(byte[] encoded); - - public abstract ECPoint getInfinity(); - - public ECFieldElement getA() - { - return a; - } - - public ECFieldElement getB() - { - return b; - } - - /** - * Elliptic curve over Fp - */ - public static class Fp extends ECCurve - { - BigIntegerCrypto q; - ECPoint.Fp infinity; - - public Fp(BigIntegerCrypto q, BigIntegerCrypto a, BigIntegerCrypto b) - { - this.q = q; - this.a = fromBigInteger(a); - this.b = fromBigInteger(b); - this.infinity = new ECPoint.Fp(this, null, null); - } - - public BigIntegerCrypto getQ() - { - return q; - } - - public int getFieldSize() - { - return q.bitLength(); - } - - public ECFieldElement fromBigInteger(BigIntegerCrypto x) - { - return new ECFieldElement.Fp(this.q, x); - } - - public ECPoint createPoint(BigIntegerCrypto x, BigIntegerCrypto y, boolean withCompression) - { - return new ECPoint.Fp(this, fromBigInteger(x), fromBigInteger(y), withCompression); - } - - /** - * Decode a point on this curve from its ASN.1 encoding. The different - * encodings are taken account of, including point compression for - * Fp (X9.62 s 4.2.1 pg 17). - * @return The decoded point. - */ - public ECPoint decodePoint(byte[] encoded) - { - ECPoint p = null; - - switch (encoded[0]) - { - // infinity - case 0x00: - p = getInfinity(); - break; - // compressed - case 0x02: - case 0x03: - int ytilde = encoded[0] & 1; - byte[] i = new byte[encoded.length - 1]; - - System.arraycopy(encoded, 1, i, 0, i.length); - - ECFieldElement x = new ECFieldElement.Fp(this.q, new BigIntegerCrypto(1, i)); - ECFieldElement alpha = x.multiply(x.square().add(a)).add(b); - ECFieldElement beta = alpha.sqrt(); - - // - // if we can't find a sqrt we haven't got a point on the - // curve - run! - // - if (beta == null) - { - throw new RuntimeException("Invalid point compression"); - } - - int bit0 = (beta.toBigInteger().testBit(0) ? 1 : 0); - - if (bit0 == ytilde) - { - p = new ECPoint.Fp(this, x, beta, true); - } - else - { - p = new ECPoint.Fp(this, x, - new ECFieldElement.Fp(this.q, q.subtract(beta.toBigInteger())), true); - } - break; - // uncompressed - case 0x04: - // hybrid - case 0x06: - case 0x07: - byte[] xEnc = new byte[(encoded.length - 1) / 2]; - byte[] yEnc = new byte[(encoded.length - 1) / 2]; - - System.arraycopy(encoded, 1, xEnc, 0, xEnc.length); - System.arraycopy(encoded, xEnc.length + 1, yEnc, 0, yEnc.length); - - p = new ECPoint.Fp(this, - new ECFieldElement.Fp(this.q, new BigIntegerCrypto(1, xEnc)), - new ECFieldElement.Fp(this.q, new BigIntegerCrypto(1, yEnc))); - break; - default: - throw new RuntimeException("Invalid point encoding 0x" + Integer.toString(encoded[0], 16)); - } - - return p; - } - - public ECPoint getInfinity() - { - return infinity; - } - - public boolean equals( - Object anObject) - { - if (anObject == this) - { - return true; - } - - if (!(anObject instanceof ECCurve.Fp)) - { - return false; - } - - ECCurve.Fp other = (ECCurve.Fp) anObject; - - return this.q.equals(other.q) - && a.equals(other.a) && b.equals(other.b); - } - - public int hashCode() - { - return a.hashCode() ^ b.hashCode() ^ q.hashCode(); - } - } - - /** - * Elliptic curves over F2m. The Weierstrass equation is given by - * y2 + xy = x3 + ax2 + b. - */ - public static class F2m extends ECCurve - { - /** - * The exponent m of F2m. - */ - private int m; // can't be final - JDK 1.1 - - /** - * TPB: The integer k where xm + - * xk + 1 represents the reduction polynomial - * f(z).
- * PPB: The integer k1 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z).
- */ - private int k1; // can't be final - JDK 1.1 - - /** - * TPB: Always set to 0
- * PPB: The integer k2 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z).
- */ - private int k2; // can't be final - JDK 1.1 - - /** - * TPB: Always set to 0
- * PPB: The integer k3 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z).
- */ - private int k3; // can't be final - JDK 1.1 - - /** - * The order of the base point of the curve. - */ - private BigIntegerCrypto n; // can't be final - JDK 1.1 - - /** - * The cofactor of the curve. - */ - private BigIntegerCrypto h; // can't be final - JDK 1.1 - - /** - * The point at infinity on this curve. - */ - private ECPoint.F2m infinity; // can't be final - JDK 1.1 - - /** - * The parameter μ of the elliptic curve if this is - * a Koblitz curve. - */ - private byte mu = 0; - - /** - * The auxiliary values s0 and - * s1 used for partial modular reduction for - * Koblitz curves. - */ - private BigIntegerCrypto[] si = null; - - /** - * Constructor for Trinomial Polynomial Basis (TPB). - * @param m The exponent m of - * F2m. - * @param k The integer k where xm + - * xk + 1 represents the reduction - * polynomial f(z). - * @param a The coefficient a in the Weierstrass equation - * for non-supersingular elliptic curves over - * F2m. - * @param b The coefficient b in the Weierstrass equation - * for non-supersingular elliptic curves over - * F2m. - */ - public F2m( - int m, - int k, - BigIntegerCrypto a, - BigIntegerCrypto b) - { - this(m, k, 0, 0, a, b, null, null); - } - - /** - * Constructor for Trinomial Polynomial Basis (TPB). - * @param m The exponent m of - * F2m. - * @param k The integer k where xm + - * xk + 1 represents the reduction - * polynomial f(z). - * @param a The coefficient a in the Weierstrass equation - * for non-supersingular elliptic curves over - * F2m. - * @param b The coefficient b in the Weierstrass equation - * for non-supersingular elliptic curves over - * F2m. - * @param n The order of the main subgroup of the elliptic curve. - * @param h The cofactor of the elliptic curve, i.e. - * #Ea(F2m) = h * n. - */ - public F2m( - int m, - int k, - BigIntegerCrypto a, - BigIntegerCrypto b, - BigIntegerCrypto n, - BigIntegerCrypto h) - { - this(m, k, 0, 0, a, b, n, h); - } - - /** - * Constructor for Pentanomial Polynomial Basis (PPB). - * @param m The exponent m of - * F2m. - * @param k1 The integer k1 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z). - * @param k2 The integer k2 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z). - * @param k3 The integer k3 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z). - * @param a The coefficient a in the Weierstrass equation - * for non-supersingular elliptic curves over - * F2m. - * @param b The coefficient b in the Weierstrass equation - * for non-supersingular elliptic curves over - * F2m. - */ - public F2m( - int m, - int k1, - int k2, - int k3, - BigIntegerCrypto a, - BigIntegerCrypto b) - { - this(m, k1, k2, k3, a, b, null, null); - } - - /** - * Constructor for Pentanomial Polynomial Basis (PPB). - * @param m The exponent m of - * F2m. - * @param k1 The integer k1 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z). - * @param k2 The integer k2 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z). - * @param k3 The integer k3 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z). - * @param a The coefficient a in the Weierstrass equation - * for non-supersingular elliptic curves over - * F2m. - * @param b The coefficient b in the Weierstrass equation - * for non-supersingular elliptic curves over - * F2m. - * @param n The order of the main subgroup of the elliptic curve. - * @param h The cofactor of the elliptic curve, i.e. - * #Ea(F2m) = h * n. - */ - public F2m( - int m, - int k1, - int k2, - int k3, - BigIntegerCrypto a, - BigIntegerCrypto b, - BigIntegerCrypto n, - BigIntegerCrypto h) - { - this.m = m; - this.k1 = k1; - this.k2 = k2; - this.k3 = k3; - this.n = n; - this.h = h; - - if (k1 == 0) - { - throw new IllegalArgumentException("k1 must be > 0"); - } - - if (k2 == 0) - { - if (k3 != 0) - { - throw new IllegalArgumentException("k3 must be 0 if k2 == 0"); - } - } - else - { - if (k2 <= k1) - { - throw new IllegalArgumentException("k2 must be > k1"); - } - - if (k3 <= k2) - { - throw new IllegalArgumentException("k3 must be > k2"); - } - } - - this.a = fromBigInteger(a); - this.b = fromBigInteger(b); - this.infinity = new ECPoint.F2m(this, null, null); - } - - public int getFieldSize() - { - return m; - } - - public ECFieldElement fromBigInteger(BigIntegerCrypto x) - { - return new ECFieldElement.F2m(this.m, this.k1, this.k2, this.k3, x); - } - - public ECPoint createPoint(BigIntegerCrypto x, BigIntegerCrypto y, boolean withCompression) - { - return new ECPoint.F2m(this, fromBigInteger(x), fromBigInteger(y), withCompression); - } - - /* (non-Javadoc) - * @see org.bouncycastle.math.ec.ECCurve#decodePoint(byte[]) - */ - public ECPoint decodePoint(byte[] encoded) - { - ECPoint p = null; - - switch (encoded[0]) - { - // infinity - case 0x00: - p = getInfinity(); - break; - // compressed - case 0x02: - case 0x03: - byte[] enc = new byte[encoded.length - 1]; - System.arraycopy(encoded, 1, enc, 0, enc.length); - if (encoded[0] == 0x02) - { - p = decompressPoint(enc, 0); - } - else - { - p = decompressPoint(enc, 1); - } - break; - // uncompressed - case 0x04: - // hybrid - case 0x06: - case 0x07: - byte[] xEnc = new byte[(encoded.length - 1) / 2]; - byte[] yEnc = new byte[(encoded.length - 1) / 2]; - - System.arraycopy(encoded, 1, xEnc, 0, xEnc.length); - System.arraycopy(encoded, xEnc.length + 1, yEnc, 0, yEnc.length); - - p = new ECPoint.F2m(this, - new ECFieldElement.F2m(this.m, this.k1, this.k2, this.k3, - new BigIntegerCrypto(1, xEnc)), - new ECFieldElement.F2m(this.m, this.k1, this.k2, this.k3, - new BigIntegerCrypto(1, yEnc)), false); - break; - - default: - throw new RuntimeException("Invalid point encoding 0x" + Integer.toString(encoded[0], 16)); - } - - return p; - } - - public ECPoint getInfinity() - { - return infinity; - } - - /** - * Returns true if this is a Koblitz curve (ABC curve). - * @return true if this is a Koblitz curve (ABC curve), false otherwise - */ - public boolean isKoblitz() - { - return ((n != null) && (h != null) && - ((a.toBigInteger().equals(ECConstants.ZERO)) || - (a.toBigInteger().equals(ECConstants.ONE))) && - (b.toBigInteger().equals(ECConstants.ONE))); - } - - /** - * Returns the parameter μ of the elliptic curve. - * @return μ of the elliptic curve. - * @throws IllegalArgumentException if the given ECCurve is not a - * Koblitz curve. - */ - synchronized byte getMu() - { - if (mu == 0) - { - mu = Tnaf.getMu(this); - } - return mu; - } - - /** - * @return the auxiliary values s0 and - * s1 used for partial modular reduction for - * Koblitz curves. - */ - synchronized BigIntegerCrypto[] getSi() - { - if (si == null) - { - si = Tnaf.getSi(this); - } - return si; - } - - /** - * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2). - * - * @param xEnc - * The encoding of field element xp. - * @param ypBit - * ~yp, an indication bit for the decompression of yp. - * @return the decompressed point. - */ - private ECPoint decompressPoint( - byte[] xEnc, - int ypBit) - { - ECFieldElement xp = new ECFieldElement.F2m( - this.m, this.k1, this.k2, this.k3, new BigIntegerCrypto(1, xEnc)); - ECFieldElement yp = null; - if (xp.toBigInteger().equals(ECConstants.ZERO)) - { - yp = b; - for (int i = 0; i < m - 1; i++) - { - yp = yp.square(); - } - } - else - { - ECFieldElement beta = xp.add(a).add( - b.multiply(xp.square().invert())); - ECFieldElement z = solveQuadradicEquation(beta); - if (z == null) - { - throw new RuntimeException("Invalid point compression"); - } - int zBit = 0; - if (z.toBigInteger().testBit(0)) - { - zBit = 1; - } - if (zBit != ypBit) - { - z = z.add(new ECFieldElement.F2m(this.m, this.k1, this.k2, - this.k3, ECConstants.ONE)); - } - yp = xp.multiply(z); - } - - return new ECPoint.F2m(this, xp, yp); - } - - /** - * Solves a quadratic equation z2 + z = beta(X9.62 - * D.1.6) The other solution is z + 1. - * - * @param beta - * The value to solve the qradratic equation for. - * @return the solution for z2 + z = beta or - * null if no solution exists. - */ - private ECFieldElement solveQuadradicEquation(ECFieldElement beta) - { - ECFieldElement zeroElement = new ECFieldElement.F2m( - this.m, this.k1, this.k2, this.k3, ECConstants.ZERO); - - if (beta.toBigInteger().equals(ECConstants.ZERO)) - { - return zeroElement; - } - - ECFieldElement z = null; - ECFieldElement gamma = zeroElement; - - Random rand = new Random(); - do - { - ECFieldElement t = new ECFieldElement.F2m(this.m, this.k1, - this.k2, this.k3, new BigIntegerCrypto(m, rand)); - z = zeroElement; - ECFieldElement w = beta; - for (int i = 1; i <= m - 1; i++) - { - ECFieldElement w2 = w.square(); - z = z.square().add(w2.multiply(t)); - w = w2.add(beta); - } - if (!w.toBigInteger().equals(ECConstants.ZERO)) - { - return null; - } - gamma = z.square().add(z); - } - while (gamma.toBigInteger().equals(ECConstants.ZERO)); - - return z; - } - - public boolean equals( - Object anObject) - { - if (anObject == this) - { - return true; - } - - if (!(anObject instanceof ECCurve.F2m)) - { - return false; - } - - ECCurve.F2m other = (ECCurve.F2m)anObject; - - return (this.m == other.m) && (this.k1 == other.k1) - && (this.k2 == other.k2) && (this.k3 == other.k3) - && a.equals(other.a) && b.equals(other.b); - } - - public int hashCode() - { - return this.a.hashCode() ^ this.b.hashCode() ^ m ^ k1 ^ k2 ^ k3; - } - - public int getM() - { - return m; - } - - /** - * Return true if curve uses a Trinomial basis. - * - * @return true if curve Trinomial, false otherwise. - */ - public boolean isTrinomial() - { - return k2 == 0 && k3 == 0; - } - - public int getK1() - { - return k1; - } - - public int getK2() - { - return k2; - } - - public int getK3() - { - return k3; - } - - public BigIntegerCrypto getN() - { - return n; - } - - public BigIntegerCrypto getH() - { - return h; - } - } -} diff --git a/src/org/bouncycastle/mathzrtp/ec/ECFieldElement.java b/src/org/bouncycastle/mathzrtp/ec/ECFieldElement.java deleted file mode 100755 index 9bfd175..0000000 --- a/src/org/bouncycastle/mathzrtp/ec/ECFieldElement.java +++ /dev/null @@ -1,1196 +0,0 @@ -package org.bouncycastle.mathzrtp.ec; - -import java.util.Random; -import gnu.java.bigintcrypto.BigIntegerCrypto; - -public abstract class ECFieldElement - implements ECConstants -{ - - public abstract BigIntegerCrypto toBigInteger(); - public abstract String getFieldName(); - public abstract int getFieldSize(); - public abstract ECFieldElement add(ECFieldElement b); - public abstract ECFieldElement subtract(ECFieldElement b); - public abstract ECFieldElement multiply(ECFieldElement b); - public abstract ECFieldElement divide(ECFieldElement b); - public abstract ECFieldElement negate(); - public abstract ECFieldElement square(); - public abstract ECFieldElement invert(); - public abstract ECFieldElement sqrt(); - - public String toString() - { - return this.toBigInteger().toString(2); - } - - public static class Fp extends ECFieldElement - { - BigIntegerCrypto x; - - BigIntegerCrypto q; - - public Fp(BigIntegerCrypto q, BigIntegerCrypto x) - { - this.x = x; - - if (x.compareTo(q) >= 0) - { - throw new IllegalArgumentException("x value too large in field element"); - } - - this.q = q; - } - - public BigIntegerCrypto toBigInteger() - { - return x; - } - - /** - * return the field name for this field. - * - * @return the string "Fp". - */ - public String getFieldName() - { - return "Fp"; - } - - public int getFieldSize() - { - return q.bitLength(); - } - - public BigIntegerCrypto getQ() - { - return q; - } - - public ECFieldElement add(ECFieldElement b) - { - return new Fp(q, x.add(b.toBigInteger()).mod(q)); - } - - public ECFieldElement subtract(ECFieldElement b) - { - return new Fp(q, x.subtract(b.toBigInteger()).mod(q)); - } - - public ECFieldElement multiply(ECFieldElement b) - { - return new Fp(q, x.multiply(b.toBigInteger()).mod(q)); - } - - public ECFieldElement divide(ECFieldElement b) - { - return new Fp(q, x.multiply(b.toBigInteger().modInverse(q)).mod(q)); - } - - public ECFieldElement negate() - { - return new Fp(q, x.negate().mod(q)); - } - - public ECFieldElement square() - { - return new Fp(q, x.multiply(x).mod(q)); - } - - public ECFieldElement invert() - { - return new Fp(q, x.modInverse(q)); - } - - // D.1.4 91 - /** - * return a sqrt root - the routine verifies that the calculation - * returns the right value - if none exists it returns null. - */ - public ECFieldElement sqrt() - { - if (!q.testBit(0)) - { - throw new RuntimeException("not done yet"); - } - - // note: even though this class implements ECConstants don't be tempted to - // remove the explicit declaration, some J2ME environments don't cope. - // p mod 4 == 3 - if (q.testBit(1)) - { - // z = g^(u+1) + p, p = 4u + 3 - ECFieldElement z = new Fp(q, x.modPow(q.shiftRight(2).add(ECConstants.ONE), q)); - - return z.square().equals(this) ? z : null; - } - - // p mod 4 == 1 - BigIntegerCrypto qMinusOne = q.subtract(ECConstants.ONE); - - BigIntegerCrypto legendreExponent = qMinusOne.shiftRight(1); - if (!(x.modPow(legendreExponent, q).equals(ECConstants.ONE))) - { - return null; - } - - BigIntegerCrypto u = qMinusOne.shiftRight(2); - BigIntegerCrypto k = u.shiftLeft(1).add(ECConstants.ONE); - - BigIntegerCrypto Q = this.x; - BigIntegerCrypto fourQ = Q.shiftLeft(2).mod(q); - - BigIntegerCrypto U, V; - Random rand = new Random(); - do - { - BigIntegerCrypto P; - do - { - P = new BigIntegerCrypto(q.bitLength(), rand); - } - while (P.compareTo(q) >= 0 - || !(P.multiply(P).subtract(fourQ).modPow(legendreExponent, q).equals(qMinusOne))); - - BigIntegerCrypto[] result = lucasSequence(q, P, Q, k); - U = result[0]; - V = result[1]; - - if (V.multiply(V).mod(q).equals(fourQ)) - { - // Integer division by 2, mod q - if (V.testBit(0)) - { - V = V.add(q); - } - - V = V.shiftRight(1); - - //assert V.multiply(V).mod(q).equals(x); - - return new ECFieldElement.Fp(q, V); - } - } - while (U.equals(ECConstants.ONE) || U.equals(qMinusOne)); - - return null; - -// BigIntegerCrypto qMinusOne = q.subtract(ECConstants.ONE); -// BigIntegerCrypto legendreExponent = qMinusOne.shiftRight(1); //divide(ECConstants.TWO); -// if (!(x.modPow(legendreExponent, q).equals(ECConstants.ONE))) -// { -// return null; -// } -// -// Random rand = new Random(); -// BigIntegerCrypto fourX = x.shiftLeft(2); -// -// BigIntegerCrypto r; -// do -// { -// r = new BigIntegerCrypto(q.bitLength(), rand); -// } -// while (r.compareTo(q) >= 0 -// || !(r.multiply(r).subtract(fourX).modPow(legendreExponent, q).equals(qMinusOne))); -// -// BigIntegerCrypto n1 = qMinusOne.shiftRight(2); //.divide(ECConstants.FOUR); -// BigIntegerCrypto n2 = n1.add(ECConstants.ONE); //q.add(ECConstants.THREE).divide(ECConstants.FOUR); -// -// BigIntegerCrypto wOne = WOne(r, x, q); -// BigIntegerCrypto wSum = W(n1, wOne, q).add(W(n2, wOne, q)).mod(q); -// BigIntegerCrypto twoR = r.shiftLeft(1); //ECConstants.TWO.multiply(r); -// -// BigIntegerCrypto root = twoR.modPow(q.subtract(ECConstants.TWO), q) -// .multiply(x).mod(q) -// .multiply(wSum).mod(q); -// -// return new Fp(q, root); - } - -// private static BigIntegerCrypto W(BigIntegerCrypto n, BigIntegerCrypto wOne, BigIntegerCrypto p) -// { -// if (n.equals(ECConstants.ONE)) -// { -// return wOne; -// } -// boolean isEven = !n.testBit(0); -// n = n.shiftRight(1);//divide(ECConstants.TWO); -// if (isEven) -// { -// BigIntegerCrypto w = W(n, wOne, p); -// return w.multiply(w).subtract(ECConstants.TWO).mod(p); -// } -// BigIntegerCrypto w1 = W(n.add(ECConstants.ONE), wOne, p); -// BigIntegerCrypto w2 = W(n, wOne, p); -// return w1.multiply(w2).subtract(wOne).mod(p); -// } -// -// private BigIntegerCrypto WOne(BigIntegerCrypto r, BigIntegerCrypto x, BigIntegerCrypto p) -// { -// return r.multiply(r).multiply(x.modPow(q.subtract(ECConstants.TWO), q)).subtract(ECConstants.TWO).mod(p); -// } - - private static BigIntegerCrypto[] lucasSequence( - BigIntegerCrypto p, - BigIntegerCrypto P, - BigIntegerCrypto Q, - BigIntegerCrypto k) - { - int n = k.bitLength(); - int s = k.getLowestSetBit(); - - BigIntegerCrypto Uh = ECConstants.ONE; - BigIntegerCrypto Vl = ECConstants.TWO; - BigIntegerCrypto Vh = P; - BigIntegerCrypto Ql = ECConstants.ONE; - BigIntegerCrypto Qh = ECConstants.ONE; - - for (int j = n - 1; j >= s + 1; --j) - { - Ql = Ql.multiply(Qh).mod(p); - - if (k.testBit(j)) - { - Qh = Ql.multiply(Q).mod(p); - Uh = Uh.multiply(Vh).mod(p); - Vl = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p); - Vh = Vh.multiply(Vh).subtract(Qh.shiftLeft(1)).mod(p); - } - else - { - Qh = Ql; - Uh = Uh.multiply(Vl).subtract(Ql).mod(p); - Vh = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p); - Vl = Vl.multiply(Vl).subtract(Ql.shiftLeft(1)).mod(p); - } - } - - Ql = Ql.multiply(Qh).mod(p); - Qh = Ql.multiply(Q).mod(p); - Uh = Uh.multiply(Vl).subtract(Ql).mod(p); - Vl = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p); - Ql = Ql.multiply(Qh).mod(p); - - for (int j = 1; j <= s; ++j) - { - Uh = Uh.multiply(Vl).mod(p); - Vl = Vl.multiply(Vl).subtract(Ql.shiftLeft(1)).mod(p); - Ql = Ql.multiply(Ql).mod(p); - } - - return new BigIntegerCrypto[]{ Uh, Vl }; - } - - public boolean equals(Object other) - { - if (other == this) - { - return true; - } - - if (!(other instanceof ECFieldElement.Fp)) - { - return false; - } - - ECFieldElement.Fp o = (ECFieldElement.Fp)other; - return q.equals(o.q) && x.equals(o.x); - } - - public int hashCode() - { - return q.hashCode() ^ x.hashCode(); - } - } - -// /** -// * Class representing the Elements of the finite field -// * F2m in polynomial basis (PB) -// * representation. Both trinomial (TPB) and pentanomial (PPB) polynomial -// * basis representations are supported. Gaussian normal basis (GNB) -// * representation is not supported. -// */ -// public static class F2m extends ECFieldElement -// { -// BigIntegerCrypto x; -// -// /** -// * Indicates gaussian normal basis representation (GNB). Number chosen -// * according to X9.62. GNB is not implemented at present. -// */ -// public static final int GNB = 1; -// -// /** -// * Indicates trinomial basis representation (TPB). Number chosen -// * according to X9.62. -// */ -// public static final int TPB = 2; -// -// /** -// * Indicates pentanomial basis representation (PPB). Number chosen -// * according to X9.62. -// */ -// public static final int PPB = 3; -// -// /** -// * TPB or PPB. -// */ -// private int representation; -// -// /** -// * The exponent m of F2m. -// */ -// private int m; -// -// /** -// * TPB: The integer k where xm + -// * xk + 1 represents the reduction polynomial -// * f(z).
-// * PPB: The integer k1 where xm + -// * xk3 + xk2 + xk1 + 1 -// * represents the reduction polynomial f(z).
-// */ -// private int k1; -// -// /** -// * TPB: Always set to 0
-// * PPB: The integer k2 where xm + -// * xk3 + xk2 + xk1 + 1 -// * represents the reduction polynomial f(z).
-// */ -// private int k2; -// -// /** -// * TPB: Always set to 0
-// * PPB: The integer k3 where xm + -// * xk3 + xk2 + xk1 + 1 -// * represents the reduction polynomial f(z).
-// */ -// private int k3; -// -// /** -// * Constructor for PPB. -// * @param m The exponent m of -// * F2m. -// * @param k1 The integer k1 where xm + -// * xk3 + xk2 + xk1 + 1 -// * represents the reduction polynomial f(z). -// * @param k2 The integer k2 where xm + -// * xk3 + xk2 + xk1 + 1 -// * represents the reduction polynomial f(z). -// * @param k3 The integer k3 where xm + -// * xk3 + xk2 + xk1 + 1 -// * represents the reduction polynomial f(z). -// * @param x The BigIntegerCrypto representing the value of the field element. -// */ -// public F2m( -// int m, -// int k1, -// int k2, -// int k3, -// BigIntegerCrypto x) -// { -//// super(x); -// this.x = x; -// -// if ((k2 == 0) && (k3 == 0)) -// { -// this.representation = TPB; -// } -// else -// { -// if (k2 >= k3) -// { -// throw new IllegalArgumentException( -// "k2 must be smaller than k3"); -// } -// if (k2 <= 0) -// { -// throw new IllegalArgumentException( -// "k2 must be larger than 0"); -// } -// this.representation = PPB; -// } -// -// if (x.signum() < 0) -// { -// throw new IllegalArgumentException("x value cannot be negative"); -// } -// -// this.m = m; -// this.k1 = k1; -// this.k2 = k2; -// this.k3 = k3; -// } -// -// /** -// * Constructor for TPB. -// * @param m The exponent m of -// * F2m. -// * @param k The integer k where xm + -// * xk + 1 represents the reduction -// * polynomial f(z). -// * @param x The BigIntegerCrypto representing the value of the field element. -// */ -// public F2m(int m, int k, BigIntegerCrypto x) -// { -// // Set k1 to k, and set k2 and k3 to 0 -// this(m, k, 0, 0, x); -// } -// -// public BigIntegerCrypto toBigInteger() -// { -// return x; -// } -// -// public String getFieldName() -// { -// return "F2m"; -// } -// -// public int getFieldSize() -// { -// return m; -// } -// -// /** -// * Checks, if the ECFieldElements a and b -// * are elements of the same field F2m -// * (having the same representation). -// * @param a field element. -// * @param b field element to be compared. -// * @throws IllegalArgumentException if a and b -// * are not elements of the same field -// * F2m (having the same -// * representation). -// */ -// public static void checkFieldElements( -// ECFieldElement a, -// ECFieldElement b) -// { -// if ((!(a instanceof F2m)) || (!(b instanceof F2m))) -// { -// throw new IllegalArgumentException("Field elements are not " -// + "both instances of ECFieldElement.F2m"); -// } -// -// if ((a.toBigInteger().signum() < 0) || (b.toBigInteger().signum() < 0)) -// { -// throw new IllegalArgumentException( -// "x value may not be negative"); -// } -// -// ECFieldElement.F2m aF2m = (ECFieldElement.F2m)a; -// ECFieldElement.F2m bF2m = (ECFieldElement.F2m)b; -// -// if ((aF2m.m != bF2m.m) || (aF2m.k1 != bF2m.k1) -// || (aF2m.k2 != bF2m.k2) || (aF2m.k3 != bF2m.k3)) -// { -// throw new IllegalArgumentException("Field elements are not " -// + "elements of the same field F2m"); -// } -// -// if (aF2m.representation != bF2m.representation) -// { -// // Should never occur -// throw new IllegalArgumentException( -// "One of the field " -// + "elements are not elements has incorrect representation"); -// } -// } -// -// /** -// * Computes z * a(z) mod f(z), where f(z) is -// * the reduction polynomial of this. -// * @param a The polynomial a(z) to be multiplied by -// * z mod f(z). -// * @return z * a(z) mod f(z) -// */ -// private BigIntegerCrypto multZModF(final BigIntegerCrypto a) -// { -// // Left-shift of a(z) -// BigIntegerCrypto az = a.shiftLeft(1); -// if (az.testBit(this.m)) -// { -// // If the coefficient of z^m in a(z) equals 1, reduction -// // modulo f(z) is performed: Add f(z) to to a(z): -// // Step 1: Unset mth coeffient of a(z) -// az = az.clearBit(this.m); -// -// // Step 2: Add r(z) to a(z), where r(z) is defined as -// // f(z) = z^m + r(z), and k1, k2, k3 are the positions of -// // the non-zero coefficients in r(z) -// az = az.flipBit(0); -// az = az.flipBit(this.k1); -// if (this.representation == PPB) -// { -// az = az.flipBit(this.k2); -// az = az.flipBit(this.k3); -// } -// } -// return az; -// } -// -// public ECFieldElement add(final ECFieldElement b) -// { -// // No check performed here for performance reasons. Instead the -// // elements involved are checked in ECPoint.F2m -// // checkFieldElements(this, b); -// if (b.toBigInteger().signum() == 0) -// { -// return this; -// } -// -// return new F2m(this.m, this.k1, this.k2, this.k3, this.x.xor(b.toBigInteger())); -// } -// -// public ECFieldElement subtract(final ECFieldElement b) -// { -// // Addition and subtraction are the same in F2m -// return add(b); -// } -// -// -// public ECFieldElement multiply(final ECFieldElement b) -// { -// // Left-to-right shift-and-add field multiplication in F2m -// // Input: Binary polynomials a(z) and b(z) of degree at most m-1 -// // Output: c(z) = a(z) * b(z) mod f(z) -// -// // No check performed here for performance reasons. Instead the -// // elements involved are checked in ECPoint.F2m -// // checkFieldElements(this, b); -// final BigIntegerCrypto az = this.x; -// BigIntegerCrypto bz = b.toBigInteger(); -// BigIntegerCrypto cz; -// -// // Compute c(z) = a(z) * b(z) mod f(z) -// if (az.testBit(0)) -// { -// cz = bz; -// } -// else -// { -// cz = ECConstants.ZERO; -// } -// -// for (int i = 1; i < this.m; i++) -// { -// // b(z) := z * b(z) mod f(z) -// bz = multZModF(bz); -// -// if (az.testBit(i)) -// { -// // If the coefficient of x^i in a(z) equals 1, b(z) is added -// // to c(z) -// cz = cz.xor(bz); -// } -// } -// return new ECFieldElement.F2m(m, this.k1, this.k2, this.k3, cz); -// } -// -// -// public ECFieldElement divide(final ECFieldElement b) -// { -// // There may be more efficient implementations -// ECFieldElement bInv = b.invert(); -// return multiply(bInv); -// } -// -// public ECFieldElement negate() -// { -// // -x == x holds for all x in F2m -// return this; -// } -// -// public ECFieldElement square() -// { -// // Naive implementation, can probably be speeded up using modular -// // reduction -// return multiply(this); -// } -// -// public ECFieldElement invert() -// { -// // Inversion in F2m using the extended Euclidean algorithm -// // Input: A nonzero polynomial a(z) of degree at most m-1 -// // Output: a(z)^(-1) mod f(z) -// -// // u(z) := a(z) -// BigIntegerCrypto uz = this.x; -// if (uz.signum() <= 0) -// { -// throw new ArithmeticException("x is zero or negative, " + -// "inversion is impossible"); -// } -// -// // v(z) := f(z) -// BigIntegerCrypto vz = ECConstants.ZERO.setBit(m); -// vz = vz.setBit(0); -// vz = vz.setBit(this.k1); -// if (this.representation == PPB) -// { -// vz = vz.setBit(this.k2); -// vz = vz.setBit(this.k3); -// } -// -// // g1(z) := 1, g2(z) := 0 -// BigIntegerCrypto g1z = ECConstants.ONE; -// BigIntegerCrypto g2z = ECConstants.ZERO; -// -// // while u != 1 -// while (!(uz.equals(ECConstants.ZERO))) -// { -// // j := deg(u(z)) - deg(v(z)) -// int j = uz.bitLength() - vz.bitLength(); -// -// // If j < 0 then: u(z) <-> v(z), g1(z) <-> g2(z), j := -j -// if (j < 0) -// { -// final BigIntegerCrypto uzCopy = uz; -// uz = vz; -// vz = uzCopy; -// -// final BigIntegerCrypto g1zCopy = g1z; -// g1z = g2z; -// g2z = g1zCopy; -// -// j = -j; -// } -// -// // u(z) := u(z) + z^j * v(z) -// // Note, that no reduction modulo f(z) is required, because -// // deg(u(z) + z^j * v(z)) <= max(deg(u(z)), j + deg(v(z))) -// // = max(deg(u(z)), deg(u(z)) - deg(v(z)) + deg(v(z)) -// // = deg(u(z)) -// uz = uz.xor(vz.shiftLeft(j)); -// -// // g1(z) := g1(z) + z^j * g2(z) -// g1z = g1z.xor(g2z.shiftLeft(j)); -//// if (g1z.bitLength() > this.m) { -//// throw new ArithmeticException( -//// "deg(g1z) >= m, g1z = " + g1z.toString(2)); -//// } -// } -// return new ECFieldElement.F2m( -// this.m, this.k1, this.k2, this.k3, g2z); -// } -// -// public ECFieldElement sqrt() -// { -// throw new RuntimeException("Not implemented"); -// } -// -// /** -// * @return the representation of the field -// * F2m, either of -// * TPB (trinomial -// * basis representation) or -// * PPB (pentanomial -// * basis representation). -// */ -// public int getRepresentation() -// { -// return this.representation; -// } -// -// /** -// * @return the degree m of the reduction polynomial -// * f(z). -// */ -// public int getM() -// { -// return this.m; -// } -// -// /** -// * @return TPB: The integer k where xm + -// * xk + 1 represents the reduction polynomial -// * f(z).
-// * PPB: The integer k1 where xm + -// * xk3 + xk2 + xk1 + 1 -// * represents the reduction polynomial f(z).
-// */ -// public int getK1() -// { -// return this.k1; -// } -// -// /** -// * @return TPB: Always returns 0
-// * PPB: The integer k2 where xm + -// * xk3 + xk2 + xk1 + 1 -// * represents the reduction polynomial f(z).
-// */ -// public int getK2() -// { -// return this.k2; -// } -// -// /** -// * @return TPB: Always set to 0
-// * PPB: The integer k3 where xm + -// * xk3 + xk2 + xk1 + 1 -// * represents the reduction polynomial f(z).
-// */ -// public int getK3() -// { -// return this.k3; -// } -// -// public boolean equals(Object anObject) -// { -// if (anObject == this) -// { -// return true; -// } -// -// if (!(anObject instanceof ECFieldElement.F2m)) -// { -// return false; -// } -// -// ECFieldElement.F2m b = (ECFieldElement.F2m)anObject; -// -// return ((this.m == b.m) && (this.k1 == b.k1) && (this.k2 == b.k2) -// && (this.k3 == b.k3) -// && (this.representation == b.representation) -// && (this.x.equals(b.x))); -// } -// -// public int hashCode() -// { -// return x.hashCode() ^ m ^ k1 ^ k2 ^ k3; -// } -// } - - /** - * Class representing the Elements of the finite field - * F2m in polynomial basis (PB) - * representation. Both trinomial (TPB) and pentanomial (PPB) polynomial - * basis representations are supported. Gaussian normal basis (GNB) - * representation is not supported. - */ - public static class F2m extends ECFieldElement - { - /** - * Indicates gaussian normal basis representation (GNB). Number chosen - * according to X9.62. GNB is not implemented at present. - */ - public static final int GNB = 1; - - /** - * Indicates trinomial basis representation (TPB). Number chosen - * according to X9.62. - */ - public static final int TPB = 2; - - /** - * Indicates pentanomial basis representation (PPB). Number chosen - * according to X9.62. - */ - public static final int PPB = 3; - - /** - * TPB or PPB. - */ - private int representation; - - /** - * The exponent m of F2m. - */ - private int m; - - /** - * TPB: The integer k where xm + - * xk + 1 represents the reduction polynomial - * f(z).
- * PPB: The integer k1 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z).
- */ - private int k1; - - /** - * TPB: Always set to 0
- * PPB: The integer k2 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z).
- */ - private int k2; - - /** - * TPB: Always set to 0
- * PPB: The integer k3 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z).
- */ - private int k3; - - /** - * The IntArray holding the bits. - */ - private IntArray x; - - /** - * The number of ints required to hold m bits. - */ - private int t; - - /** - * Constructor for PPB. - * @param m The exponent m of - * F2m. - * @param k1 The integer k1 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z). - * @param k2 The integer k2 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z). - * @param k3 The integer k3 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z). - * @param x The BigInteger representing the value of the field element. - */ - public F2m( - int m, - int k1, - int k2, - int k3, - BigIntegerCrypto x) - { - // t = m / 32 rounded up to the next integer - t = (m + 31) >> 5; - this.x = new IntArray(x, t); - - if ((k2 == 0) && (k3 == 0)) - { - this.representation = TPB; - } - else - { - if (k2 >= k3) - { - throw new IllegalArgumentException( - "k2 must be smaller than k3"); - } - if (k2 <= 0) - { - throw new IllegalArgumentException( - "k2 must be larger than 0"); - } - this.representation = PPB; - } - - if (x.signum() < 0) - { - throw new IllegalArgumentException("x value cannot be negative"); - } - - this.m = m; - this.k1 = k1; - this.k2 = k2; - this.k3 = k3; - } - - /** - * Constructor for TPB. - * @param m The exponent m of - * F2m. - * @param k The integer k where xm + - * xk + 1 represents the reduction - * polynomial f(z). - * @param x The BigInteger representing the value of the field element. - */ - public F2m(int m, int k, BigIntegerCrypto x) - { - // Set k1 to k, and set k2 and k3 to 0 - this(m, k, 0, 0, x); - } - - private F2m(int m, int k1, int k2, int k3, IntArray x) - { - t = (m + 31) >> 5; - this.x = x; - this.m = m; - this.k1 = k1; - this.k2 = k2; - this.k3 = k3; - - if ((k2 == 0) && (k3 == 0)) - { - this.representation = TPB; - } - else - { - this.representation = PPB; - } - - } - - public BigIntegerCrypto toBigInteger() - { - return x.toBigInteger(); - } - - public String getFieldName() - { - return "F2m"; - } - - public int getFieldSize() - { - return m; - } - - /** - * Checks, if the ECFieldElements a and b - * are elements of the same field F2m - * (having the same representation). - * @param a field element. - * @param b field element to be compared. - * @throws IllegalArgumentException if a and b - * are not elements of the same field - * F2m (having the same - * representation). - */ - public static void checkFieldElements( - ECFieldElement a, - ECFieldElement b) - { - if ((!(a instanceof F2m)) || (!(b instanceof F2m))) - { - throw new IllegalArgumentException("Field elements are not " - + "both instances of ECFieldElement.F2m"); - } - - ECFieldElement.F2m aF2m = (ECFieldElement.F2m)a; - ECFieldElement.F2m bF2m = (ECFieldElement.F2m)b; - - if ((aF2m.m != bF2m.m) || (aF2m.k1 != bF2m.k1) - || (aF2m.k2 != bF2m.k2) || (aF2m.k3 != bF2m.k3)) - { - throw new IllegalArgumentException("Field elements are not " - + "elements of the same field F2m"); - } - - if (aF2m.representation != bF2m.representation) - { - // Should never occur - throw new IllegalArgumentException( - "One of the field " - + "elements are not elements has incorrect representation"); - } - } - - public ECFieldElement add(final ECFieldElement b) - { - // No check performed here for performance reasons. Instead the - // elements involved are checked in ECPoint.F2m - // checkFieldElements(this, b); - IntArray iarrClone = (IntArray)this.x.clone(); - F2m bF2m = (F2m)b; - iarrClone.addShifted(bF2m.x, 0); - return new F2m(m, k1, k2, k3, iarrClone); - } - - public ECFieldElement subtract(final ECFieldElement b) - { - // Addition and subtraction are the same in F2m - return add(b); - } - - public ECFieldElement multiply(final ECFieldElement b) - { - // Right-to-left comb multiplication in the IntArray - // Input: Binary polynomials a(z) and b(z) of degree at most m-1 - // Output: c(z) = a(z) * b(z) mod f(z) - - // No check performed here for performance reasons. Instead the - // elements involved are checked in ECPoint.F2m - // checkFieldElements(this, b); - F2m bF2m = (F2m)b; - IntArray mult = x.multiply(bF2m.x, m); - mult.reduce(m, new int[]{k1, k2, k3}); - return new F2m(m, k1, k2, k3, mult); - } - - public ECFieldElement divide(final ECFieldElement b) - { - // There may be more efficient implementations - ECFieldElement bInv = b.invert(); - return multiply(bInv); - } - - public ECFieldElement negate() - { - // -x == x holds for all x in F2m - return this; - } - - public ECFieldElement square() - { - IntArray squared = x.square(m); - squared.reduce(m, new int[]{k1, k2, k3}); - return new F2m(m, k1, k2, k3, squared); - } - - - public ECFieldElement invert() - { - // Inversion in F2m using the extended Euclidean algorithm - // Input: A nonzero polynomial a(z) of degree at most m-1 - // Output: a(z)^(-1) mod f(z) - - // u(z) := a(z) - IntArray uz = (IntArray)this.x.clone(); - - // v(z) := f(z) - IntArray vz = new IntArray(t); - vz.setBit(m); - vz.setBit(0); - vz.setBit(this.k1); - if (this.representation == PPB) - { - vz.setBit(this.k2); - vz.setBit(this.k3); - } - - // g1(z) := 1, g2(z) := 0 - IntArray g1z = new IntArray(t); - g1z.setBit(0); - IntArray g2z = new IntArray(t); - - // while u != 0 - while (!uz.isZero()) -// while (uz.getUsedLength() > 0) -// while (uz.bitLength() > 1) - { - // j := deg(u(z)) - deg(v(z)) - int j = uz.bitLength() - vz.bitLength(); - - // If j < 0 then: u(z) <-> v(z), g1(z) <-> g2(z), j := -j - if (j < 0) - { - final IntArray uzCopy = uz; - uz = vz; - vz = uzCopy; - - final IntArray g1zCopy = g1z; - g1z = g2z; - g2z = g1zCopy; - - j = -j; - } - - // u(z) := u(z) + z^j * v(z) - // Note, that no reduction modulo f(z) is required, because - // deg(u(z) + z^j * v(z)) <= max(deg(u(z)), j + deg(v(z))) - // = max(deg(u(z)), deg(u(z)) - deg(v(z)) + deg(v(z)) - // = deg(u(z)) - // uz = uz.xor(vz.shiftLeft(j)); - // jInt = n / 32 - int jInt = j >> 5; - // jInt = n % 32 - int jBit = j & 0x1F; - IntArray vzShift = vz.shiftLeft(jBit); - uz.addShifted(vzShift, jInt); - - // g1(z) := g1(z) + z^j * g2(z) -// g1z = g1z.xor(g2z.shiftLeft(j)); - IntArray g2zShift = g2z.shiftLeft(jBit); - g1z.addShifted(g2zShift, jInt); - - } - return new ECFieldElement.F2m( - this.m, this.k1, this.k2, this.k3, g2z); - } - - public ECFieldElement sqrt() - { - throw new RuntimeException("Not implemented"); - } - - /** - * @return the representation of the field - * F2m, either of - * TPB (trinomial - * basis representation) or - * PPB (pentanomial - * basis representation). - */ - public int getRepresentation() - { - return this.representation; - } - - /** - * @return the degree m of the reduction polynomial - * f(z). - */ - public int getM() - { - return this.m; - } - - /** - * @return TPB: The integer k where xm + - * xk + 1 represents the reduction polynomial - * f(z).
- * PPB: The integer k1 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z).
- */ - public int getK1() - { - return this.k1; - } - - /** - * @return TPB: Always returns 0
- * PPB: The integer k2 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z).
- */ - public int getK2() - { - return this.k2; - } - - /** - * @return TPB: Always set to 0
- * PPB: The integer k3 where xm + - * xk3 + xk2 + xk1 + 1 - * represents the reduction polynomial f(z).
- */ - public int getK3() - { - return this.k3; - } - - public boolean equals(Object anObject) - { - if (anObject == this) - { - return true; - } - - if (!(anObject instanceof ECFieldElement.F2m)) - { - return false; - } - - ECFieldElement.F2m b = (ECFieldElement.F2m)anObject; - - return ((this.m == b.m) && (this.k1 == b.k1) && (this.k2 == b.k2) - && (this.k3 == b.k3) - && (this.representation == b.representation) - && (this.x.equals(b.x))); - } - - public int hashCode() - { - return x.hashCode() ^ m ^ k1 ^ k2 ^ k3; - } - } -} diff --git a/src/org/bouncycastle/mathzrtp/ec/ECMultiplier.java b/src/org/bouncycastle/mathzrtp/ec/ECMultiplier.java deleted file mode 100755 index 9a0c9a0..0000000 --- a/src/org/bouncycastle/mathzrtp/ec/ECMultiplier.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.bouncycastle.mathzrtp.ec; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -/** - * Interface for classes encapsulating a point multiplication algorithm - * for ECPoints. - */ -interface ECMultiplier -{ - /** - * Multiplies the ECPoint p by k, i.e. - * p is added k times to itself. - * @param p The ECPoint to be multiplied. - * @param k The factor by which p i multiplied. - * @return p multiplied by k. - */ - ECPoint multiply(ECPoint p, BigIntegerCrypto k, PreCompInfo preCompInfo); -} diff --git a/src/org/bouncycastle/mathzrtp/ec/ECPoint.java b/src/org/bouncycastle/mathzrtp/ec/ECPoint.java deleted file mode 100755 index c9c9682..0000000 --- a/src/org/bouncycastle/mathzrtp/ec/ECPoint.java +++ /dev/null @@ -1,592 +0,0 @@ -package org.bouncycastle.mathzrtp.ec; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -/** - * base class for points on elliptic curves. - */ -public abstract class ECPoint -{ - ECCurve curve; - ECFieldElement x; - ECFieldElement y; - - protected boolean withCompression; - - protected ECMultiplier multiplier = null; - - protected PreCompInfo preCompInfo = null; - - private static X9IntegerConverter converter = new X9IntegerConverter(); - - protected ECPoint(ECCurve curve, ECFieldElement x, ECFieldElement y) - { - this.curve = curve; - this.x = x; - this.y = y; - } - - public ECCurve getCurve() - { - return curve; - } - - public ECFieldElement getX() - { - return x; - } - - public ECFieldElement getY() - { - return y; - } - - public boolean isInfinity() - { - return x == null && y == null; - } - - public boolean isCompressed() - { - return withCompression; - } - - public boolean equals( - Object other) - { - if (other == this) - { - return true; - } - - if (!(other instanceof ECPoint)) - { - return false; - } - - ECPoint o = (ECPoint)other; - - if (this.isInfinity()) - { - return o.isInfinity(); - } - - return x.equals(o.x) && y.equals(o.y); - } - - public int hashCode() - { - if (this.isInfinity()) - { - return 0; - } - - return x.hashCode() ^ y.hashCode(); - } - -// /** -// * Mainly for testing. Explicitly set the ECMultiplier. -// * @param multiplier The ECMultiplier to be used to multiply -// * this ECPoint. -// */ -// public void setECMultiplier(ECMultiplier multiplier) -// { -// this.multiplier = multiplier; -// } - - /** - * Sets the PreCompInfo. Used by ECMultipliers - * to save the precomputation for this ECPoint to store the - * precomputation result for use by subsequent multiplication. - * @param preCompInfo The values precomputed by the - * ECMultiplier. - */ - void setPreCompInfo(PreCompInfo preCompInfo) - { - this.preCompInfo = preCompInfo; - } - - public abstract byte[] getEncoded(); - - public abstract ECPoint add(ECPoint b); - public abstract ECPoint subtract(ECPoint b); - public abstract ECPoint negate(); - public abstract ECPoint twice(); - - /** - * Sets the default ECMultiplier, unless already set. - */ - synchronized void assertECMultiplier() - { - if (this.multiplier == null) - { - this.multiplier = new FpNafMultiplier(); - } - } - - /** - * Multiplies this ECPoint by the given number. - * @param k The multiplicator. - * @return k * this. - */ - public ECPoint multiply(BigIntegerCrypto k) - { - if (this.isInfinity()) - { - return this; - } - - if (k.signum() == 0) - { - return this.curve.getInfinity(); - } - - assertECMultiplier(); - return this.multiplier.multiply(this, k, preCompInfo); - } - - /** - * Elliptic curve points over Fp - */ - public static class Fp extends ECPoint - { - - /** - * Create a point which encodes with point compression. - * - * @param curve the curve to use - * @param x affine x co-ordinate - * @param y affine y co-ordinate - */ - public Fp(ECCurve curve, ECFieldElement x, ECFieldElement y) - { - this(curve, x, y, false); - } - - /** - * Create a point that encodes with or without point compresion. - * - * @param curve the curve to use - * @param x affine x co-ordinate - * @param y affine y co-ordinate - * @param withCompression if true encode with point compression - */ - public Fp(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression) - { - super(curve, x, y); - - if ((x != null && y == null) || (x == null && y != null)) - { - throw new IllegalArgumentException("Exactly one of the field elements is null"); - } - - this.withCompression = withCompression; - } - - /** - * return the field element encoded with point compression. (S 4.3.6) - */ - public byte[] getEncoded() - { - if (this.isInfinity()) - { - return new byte[1]; - } - - int qLength = converter.getByteLength(x); - - if (withCompression) - { - byte PC; - - if (this.getY().toBigInteger().testBit(0)) - { - PC = 0x03; - } - else - { - PC = 0x02; - } - - byte[] X = converter.integerToBytes(this.getX().toBigInteger(), qLength); - byte[] PO = new byte[X.length + 1]; - - PO[0] = PC; - System.arraycopy(X, 0, PO, 1, X.length); - - return PO; - } - else - { - byte[] X = converter.integerToBytes(this.getX().toBigInteger(), qLength); - byte[] Y = converter.integerToBytes(this.getY().toBigInteger(), qLength); - byte[] PO = new byte[X.length + Y.length + 1]; - - PO[0] = 0x04; - System.arraycopy(X, 0, PO, 1, X.length); - System.arraycopy(Y, 0, PO, X.length + 1, Y.length); - - return PO; - } - } - - // B.3 pg 62 - public ECPoint add(ECPoint b) - { - if (this.isInfinity()) - { - return b; - } - - if (b.isInfinity()) - { - return this; - } - - // Check if b = this or b = -this - if (this.x.equals(b.x)) - { - if (this.y.equals(b.y)) - { - // this = b, i.e. this must be doubled - return this.twice(); - } - - // this = -b, i.e. the result is the point at infinity - return this.curve.getInfinity(); - } - - ECFieldElement gamma = b.y.subtract(this.y).divide(b.x.subtract(this.x)); - - ECFieldElement x3 = gamma.square().subtract(this.x).subtract(b.x); - ECFieldElement y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y); - - return new ECPoint.Fp(curve, x3, y3); - } - - // B.3 pg 62 - public ECPoint twice() - { - if (this.isInfinity()) - { - // Twice identity element (point at infinity) is identity - return this; - } - - if (this.y.toBigInteger().signum() == 0) - { - // if y1 == 0, then (x1, y1) == (x1, -y1) - // and hence this = -this and thus 2(x1, y1) == infinity - return this.curve.getInfinity(); - } - - ECFieldElement TWO = this.curve.fromBigInteger(BigIntegerCrypto.valueOf(2)); - ECFieldElement THREE = this.curve.fromBigInteger(BigIntegerCrypto.valueOf(3)); - ECFieldElement gamma = this.x.square().multiply(THREE).add(curve.a).divide(y.multiply(TWO)); - - ECFieldElement x3 = gamma.square().subtract(this.x.multiply(TWO)); - ECFieldElement y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y); - - return new ECPoint.Fp(curve, x3, y3, this.withCompression); - } - - // D.3.2 pg 102 (see Note:) - public ECPoint subtract(ECPoint b) - { - if (b.isInfinity()) - { - return this; - } - - // Add -b - return add(b.negate()); - } - - public ECPoint negate() - { - return new ECPoint.Fp(curve, this.x, this.y.negate(), this.withCompression); - } - - // TODO Uncomment this to enable WNAF algorithm for Fp point multiplication -// /** -// * Sets the default ECMultiplier, unless already set. -// */ -// synchronized void assertECMultiplier() -// { -// if (this.multiplier == null) -// { -// this.multiplier = new WNafMultiplier(); -// } -// } - } - - /** - * Elliptic curve points over F2m - */ - public static class F2m extends ECPoint - { - /** - * @param curve base curve - * @param x x point - * @param y y point - */ - public F2m(ECCurve curve, ECFieldElement x, ECFieldElement y) - { - this(curve, x, y, false); - } - - /** - * @param curve base curve - * @param x x point - * @param y y point - * @param withCompression true if encode with point compression. - */ - public F2m(ECCurve curve, ECFieldElement x, ECFieldElement y, boolean withCompression) - { - super(curve, x, y); - - if ((x != null && y == null) || (x == null && y != null)) - { - throw new IllegalArgumentException("Exactly one of the field elements is null"); - } - - if (x != null) - { - // Check if x and y are elements of the same field - ECFieldElement.F2m.checkFieldElements(this.x, this.y); - - // Check if x and a are elements of the same field - if (curve != null) - { - ECFieldElement.F2m.checkFieldElements(this.x, this.curve.getA()); - } - } - - this.withCompression = withCompression; - } - - /** - * @deprecated use ECCurve.getInfinity() - * Constructor for point at infinity - */ - public F2m(ECCurve curve) - { - super(curve, null, null); - } - - /* (non-Javadoc) - * @see org.bouncycastle.math.ec.ECPoint#getEncoded() - */ - public byte[] getEncoded() - { - if (this.isInfinity()) - { - return new byte[1]; - } - - int byteCount = converter.getByteLength(this.x); - byte[] X = converter.integerToBytes(this.getX().toBigInteger(), byteCount); - byte[] PO; - - if (withCompression) - { - // See X9.62 4.3.6 and 4.2.2 - PO = new byte[byteCount + 1]; - - PO[0] = 0x02; - // X9.62 4.2.2 and 4.3.6: - // if x = 0 then ypTilde := 0, else ypTilde is the rightmost - // bit of y * x^(-1) - // if ypTilde = 0, then PC := 02, else PC := 03 - // Note: PC === PO[0] - if (!(this.getX().toBigInteger().equals(ECConstants.ZERO))) - { - if (this.getY().multiply(this.getX().invert()) - .toBigInteger().testBit(0)) - { - // ypTilde = 1, hence PC = 03 - PO[0] = 0x03; - } - } - - System.arraycopy(X, 0, PO, 1, byteCount); - } - else - { - byte[] Y = converter.integerToBytes(this.getY().toBigInteger(), byteCount); - - PO = new byte[byteCount + byteCount + 1]; - - PO[0] = 0x04; - System.arraycopy(X, 0, PO, 1, byteCount); - System.arraycopy(Y, 0, PO, byteCount + 1, byteCount); - } - - return PO; - } - - /** - * Check, if two ECPoints can be added or subtracted. - * @param a The first ECPoint to check. - * @param b The second ECPoint to check. - * @throws IllegalArgumentException if a and b - * cannot be added. - */ - private static void checkPoints(ECPoint a, ECPoint b) - { - // Check, if points are on the same curve - if (!(a.curve.equals(b.curve))) - { - throw new IllegalArgumentException("Only points on the same " - + "curve can be added or subtracted"); - } - -// ECFieldElement.F2m.checkFieldElements(a.x, b.x); - } - - /* (non-Javadoc) - * @see org.bouncycastle.math.ec.ECPoint#add(org.bouncycastle.math.ec.ECPoint) - */ - public ECPoint add(ECPoint b) - { - checkPoints(this, b); - return addSimple((ECPoint.F2m)b); - } - - /** - * Adds another ECPoints.F2m to this without - * checking if both points are on the same curve. Used by multiplication - * algorithms, because there all points are a multiple of the same point - * and hence the checks can be omitted. - * @param b The other ECPoints.F2m to add to - * this. - * @return this + b - */ - public ECPoint.F2m addSimple(ECPoint.F2m b) - { - ECPoint.F2m other = b; - if (this.isInfinity()) - { - return other; - } - - if (other.isInfinity()) - { - return this; - } - - ECFieldElement.F2m x2 = (ECFieldElement.F2m)other.getX(); - ECFieldElement.F2m y2 = (ECFieldElement.F2m)other.getY(); - - // Check if other = this or other = -this - if (this.x.equals(x2)) - { - if (this.y.equals(y2)) - { - // this = other, i.e. this must be doubled - return (ECPoint.F2m)this.twice(); - } - - // this = -other, i.e. the result is the point at infinity - return (ECPoint.F2m)this.curve.getInfinity(); - } - - ECFieldElement.F2m lambda - = (ECFieldElement.F2m)(this.y.add(y2)).divide(this.x.add(x2)); - - ECFieldElement.F2m x3 - = (ECFieldElement.F2m)lambda.square().add(lambda).add(this.x).add(x2).add(this.curve.getA()); - - ECFieldElement.F2m y3 - = (ECFieldElement.F2m)lambda.multiply(this.x.add(x3)).add(x3).add(this.y); - - return new ECPoint.F2m(curve, x3, y3, withCompression); - } - - /* (non-Javadoc) - * @see org.bouncycastle.math.ec.ECPoint#subtract(org.bouncycastle.math.ec.ECPoint) - */ - public ECPoint subtract(ECPoint b) - { - checkPoints(this, b); - return subtractSimple((ECPoint.F2m)b); - } - - /** - * Subtracts another ECPoints.F2m from this - * without checking if both points are on the same curve. Used by - * multiplication algorithms, because there all points are a multiple - * of the same point and hence the checks can be omitted. - * @param b The other ECPoints.F2m to subtract from - * this. - * @return this - b - */ - public ECPoint.F2m subtractSimple(ECPoint.F2m b) - { - if (b.isInfinity()) - { - return this; - } - - // Add -b - return addSimple((ECPoint.F2m)b.negate()); - } - - /* (non-Javadoc) - * @see org.bouncycastle.math.ec.ECPoint#twice() - */ - public ECPoint twice() - { - if (this.isInfinity()) - { - // Twice identity element (point at infinity) is identity - return this; - } - - if (this.x.toBigInteger().signum() == 0) - { - // if x1 == 0, then (x1, y1) == (x1, x1 + y1) - // and hence this = -this and thus 2(x1, y1) == infinity - return this.curve.getInfinity(); - } - - ECFieldElement.F2m lambda - = (ECFieldElement.F2m)this.x.add(this.y.divide(this.x)); - - ECFieldElement.F2m x3 - = (ECFieldElement.F2m)lambda.square().add(lambda). - add(this.curve.getA()); - - ECFieldElement ONE = this.curve.fromBigInteger(ECConstants.ONE); - ECFieldElement.F2m y3 - = (ECFieldElement.F2m)this.x.square().add( - x3.multiply(lambda.add(ONE))); - - return new ECPoint.F2m(this.curve, x3, y3, withCompression); - } - - public ECPoint negate() - { - return new ECPoint.F2m(curve, this.getX(), this.getY().add(this.getX()), withCompression); - } - - // TODO Uncomment this to enable WNAF/WTNAF F2m point multiplication -// /** -// * Sets the appropriate ECMultiplier, unless already set. -// */ -// synchronized void assertECMultiplier() -// { -// if (this.multiplier == null) -// { -// if (((ECCurve.F2m)(this.curve)).isKoblitz()) -// { -// this.multiplier = new WTauNafMultiplier(); -// } -// else -// { -// this.multiplier = new WNafMultiplier(); -// } -// } -// } - } -} diff --git a/src/org/bouncycastle/mathzrtp/ec/FpNafMultiplier.java b/src/org/bouncycastle/mathzrtp/ec/FpNafMultiplier.java deleted file mode 100755 index 21ba32a..0000000 --- a/src/org/bouncycastle/mathzrtp/ec/FpNafMultiplier.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.bouncycastle.mathzrtp.ec; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -/** - * Class implementing the NAF (Non-Adjacent Form) multiplication algorithm. - */ -class FpNafMultiplier implements ECMultiplier -{ - /** - * D.3.2 pg 101 - * @see org.bouncycastle.math.ec.ECMultiplier#multiply(org.bouncycastle.math.ec.ECPoint, java.math.BigInteger) - */ - public ECPoint multiply(ECPoint p, BigIntegerCrypto k, PreCompInfo preCompInfo) - { - // TODO Probably should try to add this - // BigInteger e = k.mod(n); // n == order of p - BigIntegerCrypto e = k; - BigIntegerCrypto h = e.multiply(BigIntegerCrypto.valueOf(3)); - - ECPoint neg = p.negate(); - ECPoint R = p; - - for (int i = h.bitLength() - 2; i > 0; --i) - { - R = R.twice(); - - boolean hBit = h.testBit(i); - boolean eBit = e.testBit(i); - - if (hBit != eBit) - { - R = R.add(hBit ? p : neg); - } - } - - return R; - } -} diff --git a/src/org/bouncycastle/mathzrtp/ec/IntArray.java b/src/org/bouncycastle/mathzrtp/ec/IntArray.java deleted file mode 100755 index e6a8356..0000000 --- a/src/org/bouncycastle/mathzrtp/ec/IntArray.java +++ /dev/null @@ -1,518 +0,0 @@ -package org.bouncycastle.mathzrtp.ec; - -import org.bouncycastle.util.Arrays; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -class IntArray -{ - // TODO make m fixed for the IntArray, and hence compute T once and for all - - private int[] m_ints; - - public IntArray(int intLen) - { - m_ints = new int[intLen]; - } - - public IntArray(int[] ints) - { - m_ints = ints; - } - - public IntArray(BigIntegerCrypto bigInt) - { - this(bigInt, 0); - } - - public IntArray(BigIntegerCrypto bigInt, int minIntLen) - { - if (bigInt.signum() == -1) - { - throw new IllegalArgumentException("Only positive Integers allowed"); - } - if (bigInt.equals(ECConstants.ZERO)) - { - m_ints = new int[] { 0 }; - return; - } - - byte[] barr = bigInt.toByteArray(); - int barrLen = barr.length; - int barrStart = 0; - if (barr[0] == 0) - { - // First byte is 0 to enforce highest (=sign) bit is zero. - // In this case ignore barr[0]. - barrLen--; - barrStart = 1; - } - int intLen = (barrLen + 3) / 4; - if (intLen < minIntLen) - { - m_ints = new int[minIntLen]; - } - else - { - m_ints = new int[intLen]; - } - - int iarrJ = intLen - 1; - int rem = barrLen % 4 + barrStart; - int temp = 0; - int barrI = barrStart; - if (barrStart < rem) - { - for (; barrI < rem; barrI++) - { - temp <<= 8; - int barrBarrI = barr[barrI]; - if (barrBarrI < 0) - { - barrBarrI += 256; - } - temp |= barrBarrI; - } - m_ints[iarrJ--] = temp; - } - - for (; iarrJ >= 0; iarrJ--) - { - temp = 0; - for (int i = 0; i < 4; i++) - { - temp <<= 8; - int barrBarrI = barr[barrI++]; - if (barrBarrI < 0) - { - barrBarrI += 256; - } - temp |= barrBarrI; - } - m_ints[iarrJ] = temp; - } - } - - public boolean isZero() - { - return m_ints.length == 0 - || (m_ints[0] == 0 && getUsedLength() == 0); - } - - public int getUsedLength() - { - int highestIntPos = m_ints.length; - - if (highestIntPos < 1) - { - return 0; - } - - // Check if first element will act as sentinel - if (m_ints[0] != 0) - { - while (m_ints[--highestIntPos] == 0) - { - } - return highestIntPos + 1; - } - - do - { - if (m_ints[--highestIntPos] != 0) - { - return highestIntPos + 1; - } - } - while (highestIntPos > 0); - - return 0; - } - - public int bitLength() - { - // JDK 1.5: see Integer.numberOfLeadingZeros() - int intLen = getUsedLength(); - if (intLen == 0) - { - return 0; - } - - int last = intLen - 1; - int highest = m_ints[last]; - int bits = (last << 5) + 1; - - // A couple of binary search steps - if ((highest & 0xffff0000) != 0) - { - if ((highest & 0xff000000) != 0) - { - bits += 24; - highest >>>= 24; - } - else - { - bits += 16; - highest >>>= 16; - } - } - else if (highest > 0x000000ff) - { - bits += 8; - highest >>>= 8; - } - - while (highest != 1) - { - ++bits; - highest >>>= 1; - } - - return bits; - } - - private int[] resizedInts(int newLen) - { - int[] newInts = new int[newLen]; - int oldLen = m_ints.length; - int copyLen = oldLen < newLen ? oldLen : newLen; - System.arraycopy(m_ints, 0, newInts, 0, copyLen); - return newInts; - } - - public BigIntegerCrypto toBigInteger() - { - int usedLen = getUsedLength(); - if (usedLen == 0) - { - return ECConstants.ZERO; - } - - int highestInt = m_ints[usedLen - 1]; - byte[] temp = new byte[4]; - int barrI = 0; - boolean trailingZeroBytesDone = false; - for (int j = 3; j >= 0; j--) - { - byte thisByte = (byte) (highestInt >>> (8 * j)); - if (trailingZeroBytesDone || (thisByte != 0)) - { - trailingZeroBytesDone = true; - temp[barrI++] = thisByte; - } - } - - int barrLen = 4 * (usedLen - 1) + barrI; - byte[] barr = new byte[barrLen]; - for (int j = 0; j < barrI; j++) - { - barr[j] = temp[j]; - } - // Highest value int is done now - - for (int iarrJ = usedLen - 2; iarrJ >= 0; iarrJ--) - { - for (int j = 3; j >= 0; j--) - { - barr[barrI++] = (byte) (m_ints[iarrJ] >>> (8 * j)); - } - } - return new BigIntegerCrypto(1, barr); - } - - public void shiftLeft() - { - int usedLen = getUsedLength(); - if (usedLen == 0) - { - return; - } - if (m_ints[usedLen - 1] < 0) - { - // highest bit of highest used byte is set, so shifting left will - // make the IntArray one byte longer - usedLen++; - if (usedLen > m_ints.length) - { - // make the m_ints one byte longer, because we need one more - // byte which is not available in m_ints - m_ints = resizedInts(m_ints.length + 1); - } - } - - boolean carry = false; - for (int i = 0; i < usedLen; i++) - { - // nextCarry is true if highest bit is set - boolean nextCarry = m_ints[i] < 0; - m_ints[i] <<= 1; - if (carry) - { - // set lowest bit - m_ints[i] |= 1; - } - carry = nextCarry; - } - } - - public IntArray shiftLeft(int n) - { - int usedLen = getUsedLength(); - if (usedLen == 0) - { - return this; - } - - if (n == 0) - { - return this; - } - - if (n > 31) - { - throw new IllegalArgumentException("shiftLeft() for max 31 bits " - + ", " + n + "bit shift is not possible"); - } - - int[] newInts = new int[usedLen + 1]; - - int nm32 = 32 - n; - newInts[0] = m_ints[0] << n; - for (int i = 1; i < usedLen; i++) - { - newInts[i] = (m_ints[i] << n) | (m_ints[i - 1] >>> nm32); - } - newInts[usedLen] = m_ints[usedLen - 1] >>> nm32; - - return new IntArray(newInts); - } - - public void addShifted(IntArray other, int shift) - { - int usedLenOther = other.getUsedLength(); - int newMinUsedLen = usedLenOther + shift; - if (newMinUsedLen > m_ints.length) - { - m_ints = resizedInts(newMinUsedLen); - //System.out.println("Resize required"); - } - - for (int i = 0; i < usedLenOther; i++) - { - m_ints[i + shift] ^= other.m_ints[i]; - } - } - - public int getLength() - { - return m_ints.length; - } - - public boolean testBit(int n) - { - // theInt = n / 32 - int theInt = n >> 5; - // theBit = n % 32 - int theBit = n & 0x1F; - int tester = 1 << theBit; - return ((m_ints[theInt] & tester) != 0); - } - - public void flipBit(int n) - { - // theInt = n / 32 - int theInt = n >> 5; - // theBit = n % 32 - int theBit = n & 0x1F; - int flipper = 1 << theBit; - m_ints[theInt] ^= flipper; - } - - public void setBit(int n) - { - // theInt = n / 32 - int theInt = n >> 5; - // theBit = n % 32 - int theBit = n & 0x1F; - int setter = 1 << theBit; - m_ints[theInt] |= setter; - } - - public IntArray multiply(IntArray other, int m) - { - // Lenght of c is 2m bits rounded up to the next int (32 bit) - int t = (m + 31) >> 5; - if (m_ints.length < t) - { - m_ints = resizedInts(t); - } - - IntArray b = new IntArray(other.resizedInts(other.getLength() + 1)); - IntArray c = new IntArray((m + m + 31) >> 5); - // IntArray c = new IntArray(t + t); - int testBit = 1; - for (int k = 0; k < 32; k++) - { - for (int j = 0; j < t; j++) - { - if ((m_ints[j] & testBit) != 0) - { - // The kth bit of m_ints[j] is set - c.addShifted(b, j); - } - } - testBit <<= 1; - b.shiftLeft(); - } - return c; - } - - // public IntArray multiplyLeftToRight(IntArray other, int m) { - // // Lenght of c is 2m bits rounded up to the next int (32 bit) - // int t = (m + 31) / 32; - // if (m_ints.length < t) { - // m_ints = resizedInts(t); - // } - // - // IntArray b = new IntArray(other.resizedInts(other.getLength() + 1)); - // IntArray c = new IntArray((m + m + 31) / 32); - // // IntArray c = new IntArray(t + t); - // int testBit = 1 << 31; - // for (int k = 31; k >= 0; k--) { - // for (int j = 0; j < t; j++) { - // if ((m_ints[j] & testBit) != 0) { - // // The kth bit of m_ints[j] is set - // c.addShifted(b, j); - // } - // } - // testBit >>>= 1; - // if (k > 0) { - // c.shiftLeft(); - // } - // } - // return c; - // } - - // TODO note, redPol.length must be 3 for TPB and 5 for PPB - public void reduce(int m, int[] redPol) - { - for (int i = m + m - 2; i >= m; i--) - { - if (testBit(i)) - { - int bit = i - m; - flipBit(bit); - flipBit(i); - int l = redPol.length; - while (--l >= 0) - { - flipBit(redPol[l] + bit); - } - } - } - m_ints = resizedInts((m + 31) >> 5); - } - - public IntArray square(int m) - { - // TODO make the table static final - final int[] table = { 0x0, 0x1, 0x4, 0x5, 0x10, 0x11, 0x14, 0x15, 0x40, - 0x41, 0x44, 0x45, 0x50, 0x51, 0x54, 0x55 }; - - int t = (m + 31) >> 5; - if (m_ints.length < t) - { - m_ints = resizedInts(t); - } - - IntArray c = new IntArray(t + t); - - // TODO twice the same code, put in separate private method - for (int i = 0; i < t; i++) - { - int v0 = 0; - for (int j = 0; j < 4; j++) - { - v0 = v0 >>> 8; - int u = (m_ints[i] >>> (j * 4)) & 0xF; - int w = table[u] << 24; - v0 |= w; - } - c.m_ints[i + i] = v0; - - v0 = 0; - int upper = m_ints[i] >>> 16; - for (int j = 0; j < 4; j++) - { - v0 = v0 >>> 8; - int u = (upper >>> (j * 4)) & 0xF; - int w = table[u] << 24; - v0 |= w; - } - c.m_ints[i + i + 1] = v0; - } - return c; - } - - public boolean equals(Object o) - { - if (!(o instanceof IntArray)) - { - return false; - } - IntArray other = (IntArray) o; - int usedLen = getUsedLength(); - if (other.getUsedLength() != usedLen) - { - return false; - } - for (int i = 0; i < usedLen; i++) - { - if (m_ints[i] != other.m_ints[i]) - { - return false; - } - } - return true; - } - - public int hashCode() - { - int usedLen = getUsedLength(); - int hash = 1; - for (int i = 0; i < usedLen; i++) - { - hash = hash * 31 + m_ints[i]; - } - return hash; - } - - public Object clone() - { - return new IntArray(Arrays.clone(m_ints)); - } - - public String toString() - { - int usedLen = getUsedLength(); - if (usedLen == 0) - { - return "0"; - } - - StringBuffer sb = new StringBuffer(Integer - .toBinaryString(m_ints[usedLen - 1])); - for (int iarrJ = usedLen - 2; iarrJ >= 0; iarrJ--) - { - String hexString = Integer.toBinaryString(m_ints[iarrJ]); - - // Add leading zeroes, except for highest significant int - for (int i = hexString.length(); i < 8; i++) - { - hexString = "0" + hexString; - } - sb.append(hexString); - } - return sb.toString(); - } -} diff --git a/src/org/bouncycastle/mathzrtp/ec/PreCompInfo.java b/src/org/bouncycastle/mathzrtp/ec/PreCompInfo.java deleted file mode 100755 index ee67294..0000000 --- a/src/org/bouncycastle/mathzrtp/ec/PreCompInfo.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.bouncycastle.mathzrtp.ec; - -/** - * Interface for classes storing precomputation data for multiplication - * algorithms. Used as a Memento (see GOF patterns) for - * WNafMultiplier. - */ -interface PreCompInfo -{ -} diff --git a/src/org/bouncycastle/mathzrtp/ec/ReferenceMultiplier.java b/src/org/bouncycastle/mathzrtp/ec/ReferenceMultiplier.java deleted file mode 100755 index 6107537..0000000 --- a/src/org/bouncycastle/mathzrtp/ec/ReferenceMultiplier.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.bouncycastle.mathzrtp.ec; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -class ReferenceMultiplier implements ECMultiplier -{ - /** - * Simple shift-and-add multiplication. Serves as reference implementation - * to verify (possibly faster) implementations in - * {@link org.bouncycastle.math.ec.ECPoint ECPoint}. - * - * @param p The point to multiply. - * @param k The factor by which to multiply. - * @return The result of the point multiplication k * p. - */ - public ECPoint multiply(ECPoint p, BigIntegerCrypto k, PreCompInfo preCompInfo) - { - ECPoint q = p.getCurve().getInfinity(); - int t = k.bitLength(); - for (int i = 0; i < t; i++) - { - if (k.testBit(i)) - { - q = q.add(p); - } - p = p.twice(); - } - return q; - } -} diff --git a/src/org/bouncycastle/mathzrtp/ec/SimpleBigDecimal.java b/src/org/bouncycastle/mathzrtp/ec/SimpleBigDecimal.java deleted file mode 100755 index 7678818..0000000 --- a/src/org/bouncycastle/mathzrtp/ec/SimpleBigDecimal.java +++ /dev/null @@ -1,253 +0,0 @@ -package org.bouncycastle.mathzrtp.ec; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -/** - * Class representing a simple version of a big decimal. A - * SimpleBigDecimal is basically a - * {@link java.math.BigInteger BigInteger} with a few digits on the right of - * the decimal point. The number of (binary) digits on the right of the decimal - * point is called the scale of the SimpleBigDecimal. - * Unlike in {@link java.math.BigDecimal BigDecimal}, the scale is not adjusted - * automatically, but must be set manually. All SimpleBigDecimals - * taking part in the same arithmetic operation must have equal scale. The - * result of a multiplication of two SimpleBigDecimals returns a - * SimpleBigDecimal with double scale. - */ -class SimpleBigDecimal - //extends Number // not in J2ME - add compatibility class? -{ - private static final long serialVersionUID = 1L; - - private final BigIntegerCrypto bigInt; - private final int scale; - - /** - * Returns a SimpleBigDecimal representing the same numerical - * value as value. - * @param value The value of the SimpleBigDecimal to be - * created. - * @param scale The scale of the SimpleBigDecimal to be - * created. - * @return The such created SimpleBigDecimal. - */ - public static SimpleBigDecimal getInstance(BigIntegerCrypto value, int scale) - { - return new SimpleBigDecimal(value.shiftLeft(scale), scale); - } - - /** - * Constructor for SimpleBigDecimal. The value of the - * constructed SimpleBigDecimal equals bigInt / - * 2scale. - * @param bigInt The bigInt value parameter. - * @param scale The scale of the constructed SimpleBigDecimal. - */ - public SimpleBigDecimal(BigIntegerCrypto bigInt, int scale) - { - if (scale < 0) - { - throw new IllegalArgumentException("scale may not be negative"); - } - - this.bigInt = bigInt; - this.scale = scale; - } - - private SimpleBigDecimal(SimpleBigDecimal limBigDec) - { - bigInt = limBigDec.bigInt; - scale = limBigDec.scale; - } - - private void checkScale(SimpleBigDecimal b) - { - if (scale != b.scale) - { - throw new IllegalArgumentException("Only SimpleBigDecimal of " + - "same scale allowed in arithmetic operations"); - } - } - - public SimpleBigDecimal adjustScale(int newScale) - { - if (newScale < 0) - { - throw new IllegalArgumentException("scale may not be negative"); - } - - if (newScale == scale) - { - return new SimpleBigDecimal(this); - } - - return new SimpleBigDecimal(bigInt.shiftLeft(newScale - scale), - newScale); - } - - public SimpleBigDecimal add(SimpleBigDecimal b) - { - checkScale(b); - return new SimpleBigDecimal(bigInt.add(b.bigInt), scale); - } - - public SimpleBigDecimal add(BigIntegerCrypto b) - { - return new SimpleBigDecimal(bigInt.add(b.shiftLeft(scale)), scale); - } - - public SimpleBigDecimal negate() - { - return new SimpleBigDecimal(bigInt.negate(), scale); - } - - public SimpleBigDecimal subtract(SimpleBigDecimal b) - { - return add(b.negate()); - } - - public SimpleBigDecimal subtract(BigIntegerCrypto b) - { - return new SimpleBigDecimal(bigInt.subtract(b.shiftLeft(scale)), - scale); - } - - public SimpleBigDecimal multiply(SimpleBigDecimal b) - { - checkScale(b); - return new SimpleBigDecimal(bigInt.multiply(b.bigInt), scale + scale); - } - - public SimpleBigDecimal multiply(BigIntegerCrypto b) - { - return new SimpleBigDecimal(bigInt.multiply(b), scale); - } - - public SimpleBigDecimal divide(SimpleBigDecimal b) - { - checkScale(b); - BigIntegerCrypto dividend = bigInt.shiftLeft(scale); - return new SimpleBigDecimal(dividend.divide(b.bigInt), scale); - } - - public SimpleBigDecimal divide(BigIntegerCrypto b) - { - return new SimpleBigDecimal(bigInt.divide(b), scale); - } - - public SimpleBigDecimal shiftLeft(int n) - { - return new SimpleBigDecimal(bigInt.shiftLeft(n), scale); - } - - public int compareTo(SimpleBigDecimal val) - { - checkScale(val); - return bigInt.compareTo(val.bigInt); - } - - public int compareTo(BigIntegerCrypto val) - { - return bigInt.compareTo(val.shiftLeft(scale)); - } - - public BigIntegerCrypto floor() - { - return bigInt.shiftRight(scale); - } - - public BigIntegerCrypto round() - { - SimpleBigDecimal oneHalf = new SimpleBigDecimal(ECConstants.ONE, 1); - return add(oneHalf.adjustScale(scale)).floor(); - } - - public int intValue() - { - return floor().intValue(); - } - - public long longValue() - { - return floor().longValue(); - } - /* NON-J2ME compliant. - public double doubleValue() - { - return Double.valueOf(toString()).doubleValue(); - } - - public float floatValue() - { - return Float.valueOf(toString()).floatValue(); - } - */ - public int getScale() - { - return scale; - } - - public String toString() - { - if (scale == 0) - { - return bigInt.toString(); - } - - BigIntegerCrypto floorBigInt = floor(); - - BigIntegerCrypto fract = bigInt.subtract(floorBigInt.shiftLeft(scale)); - if (bigInt.signum() == -1) - { - fract = ECConstants.ONE.shiftLeft(scale).subtract(fract); - } - - if ((floorBigInt.signum() == -1) && (!(fract.equals(ECConstants.ZERO)))) - { - floorBigInt = floorBigInt.add(ECConstants.ONE); - } - String leftOfPoint = floorBigInt.toString(); - - char[] fractCharArr = new char[scale]; - String fractStr = fract.toString(2); - int fractLen = fractStr.length(); - int zeroes = scale - fractLen; - for (int i = 0; i < zeroes; i++) - { - fractCharArr[i] = '0'; - } - for (int j = 0; j < fractLen; j++) - { - fractCharArr[zeroes + j] = fractStr.charAt(j); - } - String rightOfPoint = new String(fractCharArr); - - StringBuffer sb = new StringBuffer(leftOfPoint); - sb.append("."); - sb.append(rightOfPoint); - - return sb.toString(); - } - - public boolean equals(Object o) - { - if (this == o) - { - return true; - } - - if (!(o instanceof SimpleBigDecimal)) - { - return false; - } - - SimpleBigDecimal other = (SimpleBigDecimal)o; - return ((bigInt.equals(other.bigInt)) && (scale == other.scale)); - } - - public int hashCode() - { - return bigInt.hashCode() ^ scale; - } - -} diff --git a/src/org/bouncycastle/mathzrtp/ec/Tnaf.java b/src/org/bouncycastle/mathzrtp/ec/Tnaf.java deleted file mode 100755 index f7479c3..0000000 --- a/src/org/bouncycastle/mathzrtp/ec/Tnaf.java +++ /dev/null @@ -1,844 +0,0 @@ -package org.bouncycastle.mathzrtp.ec; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -/** - * Class holding methods for point multiplication based on the window - * τ-adic nonadjacent form (WTNAF). The algorithms are based on the - * paper "Improved Algorithms for Arithmetic on Anomalous Binary Curves" - * by Jerome A. Solinas. The paper first appeared in the Proceedings of - * Crypto 1997. - */ -class Tnaf -{ - private static final BigIntegerCrypto MINUS_ONE = ECConstants.ONE.negate(); - private static final BigIntegerCrypto MINUS_TWO = ECConstants.TWO.negate(); - private static final BigIntegerCrypto MINUS_THREE = ECConstants.THREE.negate(); - - /** - * The window width of WTNAF. The standard value of 4 is slightly less - * than optimal for running time, but keeps space requirements for - * precomputation low. For typical curves, a value of 5 or 6 results in - * a better running time. When changing this value, the - * αu's must be computed differently, see - * e.g. "Guide to Elliptic Curve Cryptography", Darrel Hankerson, - * Alfred Menezes, Scott Vanstone, Springer-Verlag New York Inc., 2004, - * p. 121-122 - */ - public static final byte WIDTH = 4; - - /** - * 24 - */ - public static final byte POW_2_WIDTH = 16; - - /** - * The αu's for a=0 as an array - * of ZTauElements. - */ - public static final ZTauElement[] alpha0 = { - null, - new ZTauElement(ECConstants.ONE, ECConstants.ZERO), null, - new ZTauElement(MINUS_THREE, MINUS_ONE), null, - new ZTauElement(MINUS_ONE, MINUS_ONE), null, - new ZTauElement(ECConstants.ONE, MINUS_ONE), null - }; - - /** - * The αu's for a=0 as an array - * of TNAFs. - */ - public static final byte[][] alpha0Tnaf = { - null, {1}, null, {-1, 0, 1}, null, {1, 0, 1}, null, {-1, 0, 0, 1} - }; - - /** - * The αu's for a=1 as an array - * of ZTauElements. - */ - public static final ZTauElement[] alpha1 = {null, - new ZTauElement(ECConstants.ONE, ECConstants.ZERO), null, - new ZTauElement(MINUS_THREE, ECConstants.ONE), null, - new ZTauElement(MINUS_ONE, ECConstants.ONE), null, - new ZTauElement(ECConstants.ONE, ECConstants.ONE), null - }; - - /** - * The αu's for a=1 as an array - * of TNAFs. - */ - public static final byte[][] alpha1Tnaf = { - null, {1}, null, {-1, 0, 1}, null, {1, 0, 1}, null, {-1, 0, 0, -1} - }; - - /** - * Computes the norm of an element λ of - * Z[τ]. - * @param mu The parameter μ of the elliptic curve. - * @param lambda The element λ of - * Z[τ]. - * @return The norm of λ. - */ - public static BigIntegerCrypto norm(final byte mu, ZTauElement lambda) - { - BigIntegerCrypto norm; - - // s1 = u^2 - BigIntegerCrypto s1 = lambda.u.multiply(lambda.u); - - // s2 = u * v - BigIntegerCrypto s2 = lambda.u.multiply(lambda.v); - - // s3 = 2 * v^2 - BigIntegerCrypto s3 = lambda.v.multiply(lambda.v).shiftLeft(1); - - if (mu == 1) - { - norm = s1.add(s2).add(s3); - } - else if (mu == -1) - { - norm = s1.subtract(s2).add(s3); - } - else - { - throw new IllegalArgumentException("mu must be 1 or -1"); - } - - return norm; - } - - /** - * Computes the norm of an element λ of - * R[τ], where λ = u + vτ - * and u and u are real numbers (elements of - * R). - * @param mu The parameter μ of the elliptic curve. - * @param u The real part of the element λ of - * R[τ]. - * @param v The τ-adic part of the element - * λ of R[τ]. - * @return The norm of λ. - */ - public static SimpleBigDecimal norm(final byte mu, SimpleBigDecimal u, - SimpleBigDecimal v) - { - SimpleBigDecimal norm; - - // s1 = u^2 - SimpleBigDecimal s1 = u.multiply(u); - - // s2 = u * v - SimpleBigDecimal s2 = u.multiply(v); - - // s3 = 2 * v^2 - SimpleBigDecimal s3 = v.multiply(v).shiftLeft(1); - - if (mu == 1) - { - norm = s1.add(s2).add(s3); - } - else if (mu == -1) - { - norm = s1.subtract(s2).add(s3); - } - else - { - throw new IllegalArgumentException("mu must be 1 or -1"); - } - - return norm; - } - - /** - * Rounds an element λ of R[τ] - * to an element of Z[τ], such that their difference - * has minimal norm. λ is given as - * λ = λ0 + λ1τ. - * @param lambda0 The component λ0. - * @param lambda1 The component λ1. - * @param mu The parameter μ of the elliptic curve. Must - * equal 1 or -1. - * @return The rounded element of Z[τ]. - * @throws IllegalArgumentException if lambda0 and - * lambda1 do not have same scale. - */ - public static ZTauElement round(SimpleBigDecimal lambda0, - SimpleBigDecimal lambda1, byte mu) - { - int scale = lambda0.getScale(); - if (lambda1.getScale() != scale) - { - throw new IllegalArgumentException("lambda0 and lambda1 do not " + - "have same scale"); - } - - if (!((mu == 1) || (mu == -1))) - { - throw new IllegalArgumentException("mu must be 1 or -1"); - } - - BigIntegerCrypto f0 = lambda0.round(); - BigIntegerCrypto f1 = lambda1.round(); - - SimpleBigDecimal eta0 = lambda0.subtract(f0); - SimpleBigDecimal eta1 = lambda1.subtract(f1); - - // eta = 2*eta0 + mu*eta1 - SimpleBigDecimal eta = eta0.add(eta0); - if (mu == 1) - { - eta = eta.add(eta1); - } - else - { - // mu == -1 - eta = eta.subtract(eta1); - } - - // check1 = eta0 - 3*mu*eta1 - // check2 = eta0 + 4*mu*eta1 - SimpleBigDecimal threeEta1 = eta1.add(eta1).add(eta1); - SimpleBigDecimal fourEta1 = threeEta1.add(eta1); - SimpleBigDecimal check1; - SimpleBigDecimal check2; - if (mu == 1) - { - check1 = eta0.subtract(threeEta1); - check2 = eta0.add(fourEta1); - } - else - { - // mu == -1 - check1 = eta0.add(threeEta1); - check2 = eta0.subtract(fourEta1); - } - - byte h0 = 0; - byte h1 = 0; - - // if eta >= 1 - if (eta.compareTo(ECConstants.ONE) >= 0) - { - if (check1.compareTo(MINUS_ONE) < 0) - { - h1 = mu; - } - else - { - h0 = 1; - } - } - else - { - // eta < 1 - if (check2.compareTo(ECConstants.TWO) >= 0) - { - h1 = mu; - } - } - - // if eta < -1 - if (eta.compareTo(MINUS_ONE) < 0) - { - if (check1.compareTo(ECConstants.ONE) >= 0) - { - h1 = (byte)-mu; - } - else - { - h0 = -1; - } - } - else - { - // eta >= -1 - if (check2.compareTo(MINUS_TWO) < 0) - { - h1 = (byte)-mu; - } - } - - BigIntegerCrypto q0 = f0.add(BigIntegerCrypto.valueOf(h0)); - BigIntegerCrypto q1 = f1.add(BigIntegerCrypto.valueOf(h1)); - return new ZTauElement(q0, q1); - } - - /** - * Approximate division by n. For an integer - * k, the value λ = s k / n is - * computed to c bits of accuracy. - * @param k The parameter k. - * @param s The curve parameter s0 or - * s1. - * @param vm The Lucas Sequence element Vm. - * @param a The parameter a of the elliptic curve. - * @param m The bit length of the finite field - * Fm. - * @param c The number of bits of accuracy, i.e. the scale of the returned - * SimpleBigDecimal. - * @return The value λ = s k / n computed to - * c bits of accuracy. - */ - public static SimpleBigDecimal approximateDivisionByN(BigIntegerCrypto k, - BigIntegerCrypto s, BigIntegerCrypto vm, byte a, int m, int c) - { - int _k = (m + 5)/2 + c; - BigIntegerCrypto ns = k.shiftRight(m - _k - 2 + a); - - BigIntegerCrypto gs = s.multiply(ns); - - BigIntegerCrypto hs = gs.shiftRight(m); - - BigIntegerCrypto js = vm.multiply(hs); - - BigIntegerCrypto gsPlusJs = gs.add(js); - BigIntegerCrypto ls = gsPlusJs.shiftRight(_k-c); - if (gsPlusJs.testBit(_k-c-1)) - { - // round up - ls = ls.add(ECConstants.ONE); - } - - return new SimpleBigDecimal(ls, c); - } - - /** - * Computes the τ-adic NAF (non-adjacent form) of an - * element λ of Z[τ]. - * @param mu The parameter μ of the elliptic curve. - * @param lambda The element λ of - * Z[τ]. - * @return The τ-adic NAF of λ. - */ - public static byte[] tauAdicNaf(byte mu, ZTauElement lambda) - { - if (!((mu == 1) || (mu == -1))) - { - throw new IllegalArgumentException("mu must be 1 or -1"); - } - - BigIntegerCrypto norm = norm(mu, lambda); - - // Ceiling of log2 of the norm - int log2Norm = norm.bitLength(); - - // If length(TNAF) > 30, then length(TNAF) < log2Norm + 3.52 - int maxLength = log2Norm > 30 ? log2Norm + 4 : 34; - - // The array holding the TNAF - byte[] u = new byte[maxLength]; - int i = 0; - - // The actual length of the TNAF - int length = 0; - - BigIntegerCrypto r0 = lambda.u; - BigIntegerCrypto r1 = lambda.v; - - while(!((r0.equals(ECConstants.ZERO)) && (r1.equals(ECConstants.ZERO)))) - { - // If r0 is odd - if (r0.testBit(0)) - { - u[i] = (byte) ECConstants.TWO.subtract((r0.subtract(r1.shiftLeft(1))).mod(ECConstants.FOUR)).intValue(); - - // r0 = r0 - u[i] - if (u[i] == 1) - { - r0 = r0.clearBit(0); - } - else - { - // u[i] == -1 - r0 = r0.add(ECConstants.ONE); - } - length = i; - } - else - { - u[i] = 0; - } - - BigIntegerCrypto t = r0; - BigIntegerCrypto s = r0.shiftRight(1); - if (mu == 1) - { - r0 = r1.add(s); - } - else - { - // mu == -1 - r0 = r1.subtract(s); - } - - r1 = t.shiftRight(1).negate(); - i++; - } - - length++; - - // Reduce the TNAF array to its actual length - byte[] tnaf = new byte[length]; - System.arraycopy(u, 0, tnaf, 0, length); - return tnaf; - } - - /** - * Applies the operation τ() to an - * ECPoint.F2m. - * @param p The ECPoint.F2m to which τ() is applied. - * @return τ(p) - */ - public static ECPoint.F2m tau(ECPoint.F2m p) - { - if (p.isInfinity()) - { - return p; - } - - ECFieldElement x = p.getX(); - ECFieldElement y = p.getY(); - - return new ECPoint.F2m(p.getCurve(), x.square(), y.square(), p.isCompressed()); - } - - /** - * Returns the parameter μ of the elliptic curve. - * @param curve The elliptic curve from which to obtain μ. - * The curve must be a Koblitz curve, i.e. a equals - * 0 or 1 and b equals - * 1. - * @return μ of the elliptic curve. - * @throws IllegalArgumentException if the given ECCurve is not a Koblitz - * curve. - */ - public static byte getMu(ECCurve.F2m curve) - { - BigIntegerCrypto a = curve.getA().toBigInteger(); - byte mu; - - if (a.equals(ECConstants.ZERO)) - { - mu = -1; - } - else if (a.equals(ECConstants.ONE)) - { - mu = 1; - } - else - { - throw new IllegalArgumentException("No Koblitz curve (ABC), " + - "TNAF multiplication not possible"); - } - return mu; - } - - /** - * Calculates the Lucas Sequence elements Uk-1 and - * Uk or Vk-1 and - * Vk. - * @param mu The parameter μ of the elliptic curve. - * @param k The index of the second element of the Lucas Sequence to be - * returned. - * @param doV If set to true, computes Vk-1 and - * Vk, otherwise Uk-1 and - * Uk. - * @return An array with 2 elements, containing Uk-1 - * and Uk or Vk-1 - * and Vk. - */ - public static BigIntegerCrypto[] getLucas(byte mu, int k, boolean doV) - { - if (!((mu == 1) || (mu == -1))) - { - throw new IllegalArgumentException("mu must be 1 or -1"); - } - - BigIntegerCrypto u0; - BigIntegerCrypto u1; - BigIntegerCrypto u2; - - if (doV) - { - u0 = ECConstants.TWO; - u1 = BigIntegerCrypto.valueOf(mu); - } - else - { - u0 = ECConstants.ZERO; - u1 = ECConstants.ONE; - } - - for (int i = 1; i < k; i++) - { - // u2 = mu*u1 - 2*u0; - BigIntegerCrypto s = null; - if (mu == 1) - { - s = u1; - } - else - { - // mu == -1 - s = u1.negate(); - } - - u2 = s.subtract(u0.shiftLeft(1)); - u0 = u1; - u1 = u2; -// System.out.println(i + ": " + u2); -// System.out.println(); - } - - BigIntegerCrypto[] retVal = {u0, u1}; - return retVal; - } - - /** - * Computes the auxiliary value tw. If the width is - * 4, then for mu = 1, tw = 6 and for - * mu = -1, tw = 10 - * @param mu The parameter μ of the elliptic curve. - * @param w The window width of the WTNAF. - * @return the auxiliary value tw - */ - public static BigIntegerCrypto getTw(byte mu, int w) - { - if (w == 4) - { - if (mu == 1) - { - return BigIntegerCrypto.valueOf(6); - } - else - { - // mu == -1 - return BigIntegerCrypto.valueOf(10); - } - } - else - { - // For w <> 4, the values must be computed - BigIntegerCrypto[] us = getLucas(mu, w, false); - BigIntegerCrypto twoToW = ECConstants.ZERO.setBit(w); - BigIntegerCrypto u1invert = us[1].modInverse(twoToW); - BigIntegerCrypto tw; - tw = ECConstants.TWO.multiply(us[0]).multiply(u1invert).mod(twoToW); -// System.out.println("mu = " + mu); -// System.out.println("tw = " + tw); - return tw; - } - } - - /** - * Computes the auxiliary values s0 and - * s1 used for partial modular reduction. - * @param curve The elliptic curve for which to compute - * s0 and s1. - * @throws IllegalArgumentException if curve is not a - * Koblitz curve (Anomalous Binary Curve, ABC). - */ - public static BigIntegerCrypto[] getSi(ECCurve.F2m curve) - { - if (!curve.isKoblitz()) - { - throw new IllegalArgumentException("si is defined for Koblitz curves only"); - } - - int m = curve.getM(); - int a = curve.getA().toBigInteger().intValue(); - byte mu = curve.getMu(); - int h = curve.getH().intValue(); - int index = m + 3 - a; - BigIntegerCrypto[] ui = getLucas(mu, index, false); - - BigIntegerCrypto dividend0; - BigIntegerCrypto dividend1; - if (mu == 1) - { - dividend0 = ECConstants.ONE.subtract(ui[1]); - dividend1 = ECConstants.ONE.subtract(ui[0]); - } - else if (mu == -1) - { - dividend0 = ECConstants.ONE.add(ui[1]); - dividend1 = ECConstants.ONE.add(ui[0]); - } - else - { - throw new IllegalArgumentException("mu must be 1 or -1"); - } - - BigIntegerCrypto[] si = new BigIntegerCrypto[2]; - - if (h == 2) - { - si[0] = dividend0.shiftRight(1); - si[1] = dividend1.shiftRight(1).negate(); - } - else if (h == 4) - { - si[0] = dividend0.shiftRight(2); - si[1] = dividend1.shiftRight(2).negate(); - } - else - { - throw new IllegalArgumentException("h (Cofactor) must be 2 or 4"); - } - - return si; - } - - /** - * Partial modular reduction modulo - * m - 1)/(τ - 1). - * @param k The integer to be reduced. - * @param m The bitlength of the underlying finite field. - * @param a The parameter a of the elliptic curve. - * @param s The auxiliary values s0 and - * s1. - * @param mu The parameter μ of the elliptic curve. - * @param c The precision (number of bits of accuracy) of the partial - * modular reduction. - * @return ρ := k partmod (τm - 1)/(τ - 1) - */ - public static ZTauElement partModReduction(BigIntegerCrypto k, int m, byte a, - BigIntegerCrypto[] s, byte mu, byte c) - { - // d0 = s[0] + mu*s[1]; mu is either 1 or -1 - BigIntegerCrypto d0; - if (mu == 1) - { - d0 = s[0].add(s[1]); - } - else - { - d0 = s[0].subtract(s[1]); - } - - BigIntegerCrypto[] v = getLucas(mu, m, true); - BigIntegerCrypto vm = v[1]; - - SimpleBigDecimal lambda0 = approximateDivisionByN( - k, s[0], vm, a, m, c); - - SimpleBigDecimal lambda1 = approximateDivisionByN( - k, s[1], vm, a, m, c); - - ZTauElement q = round(lambda0, lambda1, mu); - - // r0 = n - d0*q0 - 2*s1*q1 - BigIntegerCrypto r0 = k.subtract(d0.multiply(q.u)).subtract( - BigIntegerCrypto.valueOf(2).multiply(s[1]).multiply(q.v)); - - // r1 = s1*q0 - s0*q1 - BigIntegerCrypto r1 = s[1].multiply(q.u).subtract(s[0].multiply(q.v)); - - return new ZTauElement(r0, r1); - } - - /** - * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m} - * by a BigInteger using the reduced τ-adic - * NAF (RTNAF) method. - * @param p The ECPoint.F2m to multiply. - * @param k The BigInteger by which to multiply p. - * @return k * p - */ - public static ECPoint.F2m multiplyRTnaf(ECPoint.F2m p, BigIntegerCrypto k) - { - ECCurve.F2m curve = (ECCurve.F2m) p.getCurve(); - int m = curve.getM(); - byte a = (byte) curve.getA().toBigInteger().intValue(); - byte mu = curve.getMu(); - BigIntegerCrypto[] s = curve.getSi(); - ZTauElement rho = partModReduction(k, m, a, s, mu, (byte)10); - - return multiplyTnaf(p, rho); - } - - /** - * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m} - * by an element λ of Z[τ] - * using the τ-adic NAF (TNAF) method. - * @param p The ECPoint.F2m to multiply. - * @param lambda The element λ of - * Z[τ]. - * @return λ * p - */ - public static ECPoint.F2m multiplyTnaf(ECPoint.F2m p, ZTauElement lambda) - { - ECCurve.F2m curve = (ECCurve.F2m)p.getCurve(); - byte mu = curve.getMu(); - byte[] u = tauAdicNaf(mu, lambda); - - ECPoint.F2m q = multiplyFromTnaf(p, u); - - return q; - } - - /** - * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m} - * by an element λ of Z[τ] - * using the τ-adic NAF (TNAF) method, given the TNAF - * of λ. - * @param p The ECPoint.F2m to multiply. - * @param u The the TNAF of λ.. - * @return λ * p - */ - public static ECPoint.F2m multiplyFromTnaf(ECPoint.F2m p, byte[] u) - { - ECCurve.F2m curve = (ECCurve.F2m)p.getCurve(); - ECPoint.F2m q = (ECPoint.F2m) curve.getInfinity(); - for (int i = u.length - 1; i >= 0; i--) - { - q = tau(q); - if (u[i] == 1) - { - q = q.addSimple(p); - } - else if (u[i] == -1) - { - q = q.subtractSimple(p); - } - } - return q; - } - - /** - * Computes the [τ]-adic window NAF of an element - * λ of Z[τ]. - * @param mu The parameter μ of the elliptic curve. - * @param lambda The element λ of - * Z[τ] of which to compute the - * [τ]-adic NAF. - * @param width The window width of the resulting WNAF. - * @param pow2w 2width. - * @param tw The auxiliary value tw. - * @param alpha The αu's for the window width. - * @return The [τ]-adic window NAF of - * λ. - */ - public static byte[] tauAdicWNaf(byte mu, ZTauElement lambda, - byte width, BigIntegerCrypto pow2w, BigIntegerCrypto tw, ZTauElement[] alpha) - { - if (!((mu == 1) || (mu == -1))) - { - throw new IllegalArgumentException("mu must be 1 or -1"); - } - - BigIntegerCrypto norm = norm(mu, lambda); - - // Ceiling of log2 of the norm - int log2Norm = norm.bitLength(); - - // If length(TNAF) > 30, then length(TNAF) < log2Norm + 3.52 - int maxLength = log2Norm > 30 ? log2Norm + 4 + width : 34 + width; - - // The array holding the TNAF - byte[] u = new byte[maxLength]; - - // 2^(width - 1) - BigIntegerCrypto pow2wMin1 = pow2w.shiftRight(1); - - // Split lambda into two BigIntegers to simplify calculations - BigIntegerCrypto r0 = lambda.u; - BigIntegerCrypto r1 = lambda.v; - int i = 0; - - // while lambda <> (0, 0) - while (!((r0.equals(ECConstants.ZERO))&&(r1.equals(ECConstants.ZERO)))) - { - // if r0 is odd - if (r0.testBit(0)) - { - // uUnMod = r0 + r1*tw mod 2^width - BigIntegerCrypto uUnMod - = r0.add(r1.multiply(tw)).mod(pow2w); - - byte uLocal; - // if uUnMod >= 2^(width - 1) - if (uUnMod.compareTo(pow2wMin1) >= 0) - { - uLocal = (byte) uUnMod.subtract(pow2w).intValue(); - } - else - { - uLocal = (byte) uUnMod.intValue(); - } - // uLocal is now in [-2^(width-1), 2^(width-1)-1] - - u[i] = uLocal; - boolean s = true; - if (uLocal < 0) - { - s = false; - uLocal = (byte)-uLocal; - } - // uLocal is now >= 0 - - if (s) - { - r0 = r0.subtract(alpha[uLocal].u); - r1 = r1.subtract(alpha[uLocal].v); - } - else - { - r0 = r0.add(alpha[uLocal].u); - r1 = r1.add(alpha[uLocal].v); - } - } - else - { - u[i] = 0; - } - - BigIntegerCrypto t = r0; - - if (mu == 1) - { - r0 = r1.add(r0.shiftRight(1)); - } - else - { - // mu == -1 - r0 = r1.subtract(r0.shiftRight(1)); - } - r1 = t.shiftRight(1).negate(); - i++; - } - return u; - } - - /** - * Does the precomputation for WTNAF multiplication. - * @param p The ECPoint for which to do the precomputation. - * @param a The parameter a of the elliptic curve. - * @return The precomputation array for p. - */ - public static ECPoint.F2m[] getPreComp(ECPoint.F2m p, byte a) - { - ECPoint.F2m[] pu; - pu = new ECPoint.F2m[16]; - pu[1] = p; - byte[][] alphaTnaf; - if (a == 0) - { - alphaTnaf = Tnaf.alpha0Tnaf; - } - else - { - // a == 1 - alphaTnaf = Tnaf.alpha1Tnaf; - } - - int precompLen = alphaTnaf.length; - for (int i = 3; i < precompLen; i = i + 2) - { - pu[i] = Tnaf.multiplyFromTnaf(p, alphaTnaf[i]); - } - - return pu; - } -} diff --git a/src/org/bouncycastle/mathzrtp/ec/WNafMultiplier.java b/src/org/bouncycastle/mathzrtp/ec/WNafMultiplier.java deleted file mode 100755 index a019bf6..0000000 --- a/src/org/bouncycastle/mathzrtp/ec/WNafMultiplier.java +++ /dev/null @@ -1,240 +0,0 @@ -package org.bouncycastle.mathzrtp.ec; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -/** - * Class implementing the WNAF (Window Non-Adjacent Form) multiplication - * algorithm. - */ -class WNafMultiplier implements ECMultiplier -{ - /** - * Computes the Window NAF (non-adjacent Form) of an integer. - * @param width The width w of the Window NAF. The width is - * defined as the minimal number w, such that for any - * w consecutive digits in the resulting representation, at - * most one is non-zero. - * @param k The integer of which the Window NAF is computed. - * @return The Window NAF of the given width, such that the following holds: - * k = ∑i=0l-1 ki2i - * , where the ki denote the elements of the - * returned byte[]. - */ - public byte[] windowNaf(byte width, BigIntegerCrypto k) - { - // The window NAF is at most 1 element longer than the binary - // representation of the integer k. byte can be used instead of short or - // int unless the window width is larger than 8. For larger width use - // short or int. However, a width of more than 8 is not efficient for - // m = log2(q) smaller than 2305 Bits. Note: Values for m larger than - // 1000 Bits are currently not used in practice. - byte[] wnaf = new byte[k.bitLength() + 1]; - - // 2^width as short and BigInteger - short pow2wB = (short)(1 << width); - BigIntegerCrypto pow2wBI = BigIntegerCrypto.valueOf(pow2wB); - - int i = 0; - - // The actual length of the WNAF - int length = 0; - - // while k >= 1 - while (k.signum() > 0) - { - // if k is odd - if (k.testBit(0)) - { - // k mod 2^width - BigIntegerCrypto remainder = k.mod(pow2wBI); - - // if remainder > 2^(width - 1) - 1 - if (remainder.testBit(width - 1)) - { - wnaf[i] = (byte)(remainder.intValue() - pow2wB); - } - else - { - wnaf[i] = (byte)remainder.intValue(); - } - // wnaf[i] is now in [-2^(width-1), 2^(width-1)-1] - - k = k.subtract(BigIntegerCrypto.valueOf(wnaf[i])); - length = i; - } - else - { - wnaf[i] = 0; - } - - // k = k/2 - k = k.shiftRight(1); - i++; - } - - length++; - - // Reduce the WNAF array to its actual length - byte[] wnafShort = new byte[length]; - System.arraycopy(wnaf, 0, wnafShort, 0, length); - return wnafShort; - } - - /** - * Multiplies this by an integer k using the - * Window NAF method. - * @param k The integer by which this is multiplied. - * @return A new ECPoint which equals this - * multiplied by k. - */ - public ECPoint multiply(ECPoint p, BigIntegerCrypto k, PreCompInfo preCompInfo) - { - WNafPreCompInfo wnafPreCompInfo; - - if ((preCompInfo != null) && (preCompInfo instanceof WNafPreCompInfo)) - { - wnafPreCompInfo = (WNafPreCompInfo)preCompInfo; - } - else - { - // Ignore empty PreCompInfo or PreCompInfo of incorrect type - wnafPreCompInfo = new WNafPreCompInfo(); - } - - // floor(log2(k)) - int m = k.bitLength(); - - // width of the Window NAF - byte width; - - // Required length of precomputation array - int reqPreCompLen; - - // Determine optimal width and corresponding length of precomputation - // array based on literature values - if (m < 13) - { - width = 2; - reqPreCompLen = 1; - } - else - { - if (m < 41) - { - width = 3; - reqPreCompLen = 2; - } - else - { - if (m < 121) - { - width = 4; - reqPreCompLen = 4; - } - else - { - if (m < 337) - { - width = 5; - reqPreCompLen = 8; - } - else - { - if (m < 897) - { - width = 6; - reqPreCompLen = 16; - } - else - { - if (m < 2305) - { - width = 7; - reqPreCompLen = 32; - } - else - { - width = 8; - reqPreCompLen = 127; - } - } - } - } - } - } - - // The length of the precomputation array - int preCompLen = 1; - - ECPoint[] preComp = wnafPreCompInfo.getPreComp(); - ECPoint twiceP = wnafPreCompInfo.getTwiceP(); - - // Check if the precomputed ECPoints already exist - if (preComp == null) - { - // Precomputation must be performed from scratch, create an empty - // precomputation array of desired length - preComp = new ECPoint[]{ p }; - } - else - { - // Take the already precomputed ECPoints to start with - preCompLen = preComp.length; - } - - if (twiceP == null) - { - // Compute twice(p) - twiceP = p.twice(); - } - - if (preCompLen < reqPreCompLen) - { - // Precomputation array must be made bigger, copy existing preComp - // array into the larger new preComp array - ECPoint[] oldPreComp = preComp; - preComp = new ECPoint[reqPreCompLen]; - System.arraycopy(oldPreComp, 0, preComp, 0, preCompLen); - - for (int i = preCompLen; i < reqPreCompLen; i++) - { - // Compute the new ECPoints for the precomputation array. - // The values 1, 3, 5, ..., 2^(width-1)-1 times p are - // computed - preComp[i] = twiceP.add(preComp[i - 1]); - } - } - - // Compute the Window NAF of the desired width - byte[] wnaf = windowNaf(width, k); - int l = wnaf.length; - - // Apply the Window NAF to p using the precomputed ECPoint values. - ECPoint q = p.getCurve().getInfinity(); - for (int i = l - 1; i >= 0; i--) - { - q = q.twice(); - - if (wnaf[i] != 0) - { - if (wnaf[i] > 0) - { - q = q.add(preComp[(wnaf[i] - 1)/2]); - } - else - { - // wnaf[i] < 0 - q = q.subtract(preComp[(-wnaf[i] - 1)/2]); - } - } - } - - // Set PreCompInfo in ECPoint, such that it is available for next - // multiplication. - wnafPreCompInfo.setPreComp(preComp); - wnafPreCompInfo.setTwiceP(twiceP); - p.setPreCompInfo(wnafPreCompInfo); - return q; - } - -} diff --git a/src/org/bouncycastle/mathzrtp/ec/WNafPreCompInfo.java b/src/org/bouncycastle/mathzrtp/ec/WNafPreCompInfo.java deleted file mode 100755 index 1c303cc..0000000 --- a/src/org/bouncycastle/mathzrtp/ec/WNafPreCompInfo.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.bouncycastle.mathzrtp.ec; - -/** - * Class holding precomputation data for the WNAF (Window Non-Adjacent Form) - * algorithm. - */ -class WNafPreCompInfo implements PreCompInfo -{ - /** - * Array holding the precomputed ECPoints used for the Window - * NAF multiplication in - * {@link org.bouncycastle.math.ec.multiplier.WNafMultiplier.multiply() - * WNafMultiplier.multiply()}. - */ - private ECPoint[] preComp = null; - - /** - * Holds an ECPoint representing twice(this). Used for the - * Window NAF multiplication in - * {@link org.bouncycastle.math.ec.multiplier.WNafMultiplier.multiply() - * WNafMultiplier.multiply()}. - */ - private ECPoint twiceP = null; - - protected ECPoint[] getPreComp() - { - return preComp; - } - - protected void setPreComp(ECPoint[] preComp) - { - this.preComp = preComp; - } - - protected ECPoint getTwiceP() - { - return twiceP; - } - - protected void setTwiceP(ECPoint twiceThis) - { - this.twiceP = twiceThis; - } -} diff --git a/src/org/bouncycastle/mathzrtp/ec/WTauNafMultiplier.java b/src/org/bouncycastle/mathzrtp/ec/WTauNafMultiplier.java deleted file mode 100755 index e2d42e7..0000000 --- a/src/org/bouncycastle/mathzrtp/ec/WTauNafMultiplier.java +++ /dev/null @@ -1,119 +0,0 @@ -package org.bouncycastle.mathzrtp.ec; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -/** - * Class implementing the WTNAF (Window - * τ-adic Non-Adjacent Form) algorithm. - */ -class WTauNafMultiplier implements ECMultiplier -{ - /** - * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m} - * by k using the reduced τ-adic NAF (RTNAF) - * method. - * @param p The ECPoint.F2m to multiply. - * @param k The integer by which to multiply k. - * @return p multiplied by k. - */ - public ECPoint multiply(ECPoint point, BigIntegerCrypto k, PreCompInfo preCompInfo) - { - if (!(point instanceof ECPoint.F2m)) - { - throw new IllegalArgumentException("Only ECPoint.F2m can be " + - "used in WTauNafMultiplier"); - } - - ECPoint.F2m p = (ECPoint.F2m)point; - - ECCurve.F2m curve = (ECCurve.F2m) p.getCurve(); - int m = curve.getM(); - byte a = curve.getA().toBigInteger().byteValue(); - byte mu = curve.getMu(); - BigIntegerCrypto[] s = curve.getSi(); - - ZTauElement rho = Tnaf.partModReduction(k, m, a, s, mu, (byte)10); - - return multiplyWTnaf(p, rho, preCompInfo, a, mu); - } - - /** - * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m} - * by an element λ of Z[τ] using - * the τ-adic NAF (TNAF) method. - * @param p The ECPoint.F2m to multiply. - * @param lambda The element λ of - * Z[τ] of which to compute the - * [τ]-adic NAF. - * @return p multiplied by λ. - */ - private ECPoint.F2m multiplyWTnaf(ECPoint.F2m p, ZTauElement lambda, - PreCompInfo preCompInfo, byte a, byte mu) - { - ZTauElement[] alpha; - if (a == 0) - { - alpha = Tnaf.alpha0; - } - else - { - // a == 1 - alpha = Tnaf.alpha1; - } - - BigIntegerCrypto tw = Tnaf.getTw(mu, Tnaf.WIDTH); - - byte[]u = Tnaf.tauAdicWNaf(mu, lambda, Tnaf.WIDTH, - BigIntegerCrypto.valueOf(Tnaf.POW_2_WIDTH), tw, alpha); - - return multiplyFromWTnaf(p, u, preCompInfo); - } - - /** - * Multiplies a {@link org.bouncycastle.math.ec.ECPoint.F2m ECPoint.F2m} - * by an element λ of Z[τ] - * using the window τ-adic NAF (TNAF) method, given the - * WTNAF of λ. - * @param p The ECPoint.F2m to multiply. - * @param u The the WTNAF of λ.. - * @return λ * p - */ - private static ECPoint.F2m multiplyFromWTnaf(ECPoint.F2m p, byte[] u, - PreCompInfo preCompInfo) - { - ECCurve.F2m curve = (ECCurve.F2m)p.getCurve(); - byte a = curve.getA().toBigInteger().byteValue(); - - ECPoint.F2m[] pu; - if ((preCompInfo == null) || !(preCompInfo instanceof WTauNafPreCompInfo)) - { - pu = Tnaf.getPreComp(p, a); - p.setPreCompInfo(new WTauNafPreCompInfo(pu)); - } - else - { - pu = ((WTauNafPreCompInfo)preCompInfo).getPreComp(); - } - - // q = infinity - ECPoint.F2m q = (ECPoint.F2m) p.getCurve().getInfinity(); - for (int i = u.length - 1; i >= 0; i--) - { - q = Tnaf.tau(q); - if (u[i] != 0) - { - if (u[i] > 0) - { - q = q.addSimple(pu[u[i]]); - } - else - { - // u[i] < 0 - q = q.subtractSimple(pu[-u[i]]); - } - } - } - - return q; - } -} diff --git a/src/org/bouncycastle/mathzrtp/ec/WTauNafPreCompInfo.java b/src/org/bouncycastle/mathzrtp/ec/WTauNafPreCompInfo.java deleted file mode 100755 index 17d3b63..0000000 --- a/src/org/bouncycastle/mathzrtp/ec/WTauNafPreCompInfo.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.bouncycastle.mathzrtp.ec; - -/** - * Class holding precomputation data for the WTNAF (Window - * τ-adic Non-Adjacent Form) algorithm. - */ -class WTauNafPreCompInfo implements PreCompInfo -{ - /** - * Array holding the precomputed ECPoint.F2ms used for the - * WTNAF multiplication in - * {@link org.bouncycastle.math.ec.multiplier.WTauNafMultiplier.multiply() - * WTauNafMultiplier.multiply()}. - */ - private ECPoint.F2m[] preComp = null; - - /** - * Constructor for WTauNafPreCompInfo - * @param preComp Array holding the precomputed ECPoint.F2ms - * used for the WTNAF multiplication in - * {@link org.bouncycastle.math.ec.multiplier.WTauNafMultiplier.multiply() - * WTauNafMultiplier.multiply()}. - */ - WTauNafPreCompInfo(ECPoint.F2m[] preComp) - { - this.preComp = preComp; - } - - /** - * @return the array holding the precomputed ECPoint.F2ms - * used for the WTNAF multiplication in - * {@link org.bouncycastle.math.ec.multiplier.WTauNafMultiplier.multiply() - * WTauNafMultiplier.multiply()}. - */ - protected ECPoint.F2m[] getPreComp() - { - return preComp; - } -} diff --git a/src/org/bouncycastle/mathzrtp/ec/X9IntegerConverter.java b/src/org/bouncycastle/mathzrtp/ec/X9IntegerConverter.java deleted file mode 100755 index 0f26d8a..0000000 --- a/src/org/bouncycastle/mathzrtp/ec/X9IntegerConverter.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.bouncycastle.mathzrtp.ec; - -import org.bouncycastle.mathzrtp.ec.ECCurve; -import org.bouncycastle.mathzrtp.ec.ECFieldElement; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -public class X9IntegerConverter -{ - public int getByteLength( - ECCurve c) - { - return (c.getFieldSize() + 7) / 8; - } - - public int getByteLength( - ECFieldElement fe) - { - return (fe.getFieldSize() + 7) / 8; - } - - public byte[] integerToBytes( - BigIntegerCrypto s, - int qLength) - { - byte[] bytes = s.toByteArray(); - - if (qLength < bytes.length) - { - byte[] tmp = new byte[qLength]; - - System.arraycopy(bytes, bytes.length - tmp.length, tmp, 0, tmp.length); - - return tmp; - } - else if (qLength > bytes.length) - { - byte[] tmp = new byte[qLength]; - - System.arraycopy(bytes, 0, tmp, tmp.length - bytes.length, bytes.length); - - return tmp; - } - - return bytes; - } -} diff --git a/src/org/bouncycastle/mathzrtp/ec/ZTauElement.java b/src/org/bouncycastle/mathzrtp/ec/ZTauElement.java deleted file mode 100755 index 40ac910..0000000 --- a/src/org/bouncycastle/mathzrtp/ec/ZTauElement.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.bouncycastle.mathzrtp.ec; - -import gnu.java.bigintcrypto.BigIntegerCrypto; - -/** - * Class representing an element of Z[τ]. Let - * λ be an element of Z[τ]. Then - * λ is given as λ = u + vτ. The - * components u and v may be used directly, there - * are no accessor methods. - * Immutable class. - */ -class ZTauElement -{ - /** - * The "real" part of λ. - */ - public final BigIntegerCrypto u; - - /** - * The "τ-adic" part of λ. - */ - public final BigIntegerCrypto v; - - /** - * Constructor for an element λ of - * Z[τ]. - * @param u The "real" part of λ. - * @param v The "τ-adic" part of - * λ. - */ - public ZTauElement(BigIntegerCrypto u, BigIntegerCrypto v) - { - this.u = u; - this.v = v; - } -}