forked from I2P_Developers/i2p.i2p
libjbigi updates:
Added:
nativeJbigiVersion()
nativeGMPMajorVersion()
nativeGMPMinorVersion()
nativeGMPPatchVersion()
nativeModInverse()
nativeModPowCT()
Support negative vaules in conversion functions
Support negative base value in modPow()
Throw ArithmeticException for bad arguments rather than crashing
Switch to GMP 6.0.0
New build targets
NativeBigInteger changes:
Test improvements
Version reporting
Crypto changes:
Use constant time modPow() for signing and decryption
Use native modInverse()
This commit is contained in:
@@ -39,20 +39,20 @@ import net.i2p.util.NativeBigInteger;
|
||||
* Primes for DSA: Generated by TheCrypto http://article.gmane.org/gmane.comp.security.invisiblenet.iip.devel/343
|
||||
*/
|
||||
public class CryptoConstants {
|
||||
public static final BigInteger dsap = new NativeBigInteger(
|
||||
public static final NativeBigInteger dsap = new NativeBigInteger(
|
||||
"9c05b2aa960d9b97b8931963c9cc9e8c3026e9b8ed92fad0a69cc886d5bf8015fcadae31"
|
||||
+ "a0ad18fab3f01b00a358de237655c4964afaa2b337e96ad316b9fb1cc564b5aec5b69a9f"
|
||||
+ "f6c3e4548707fef8503d91dd8602e867e6d35d2235c1869ce2479c3b9d5401de04e0727f"
|
||||
+ "b33d6511285d4cf29538d9e3b6051f5b22cc1c93",
|
||||
16);
|
||||
public static final BigInteger dsaq = new NativeBigInteger("a5dfc28fef4ca1e286744cd8eed9d29d684046b7", 16);
|
||||
public static final BigInteger dsag = new NativeBigInteger(
|
||||
public static final NativeBigInteger dsaq = new NativeBigInteger("a5dfc28fef4ca1e286744cd8eed9d29d684046b7", 16);
|
||||
public static final NativeBigInteger dsag = new NativeBigInteger(
|
||||
"c1f4d27d40093b429e962d7223824e0bbc47e7c832a39236fc683af84889581075ff9082"
|
||||
+ "ed32353d4374d7301cda1d23c431f4698599dda02451824ff369752593647cc3ddc197de"
|
||||
+ "985e43d136cdcfc6bd5409cd2f450821142a5e6f8eb1c3ab5d0484b8129fcf17bce4f7f3"
|
||||
+ "3321c3cb3dbb14a905e7b2b3e93be4708cbcc82",
|
||||
16);
|
||||
public static final BigInteger elgp = new NativeBigInteger("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
|
||||
public static final NativeBigInteger elgp = new NativeBigInteger("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
|
||||
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
|
||||
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
|
||||
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
|
||||
@@ -63,7 +63,7 @@ public class CryptoConstants {
|
||||
+ "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
|
||||
+ "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
|
||||
+ "15728E5A8AACAA68FFFFFFFFFFFFFFFF", 16);
|
||||
public static final BigInteger elgg = new NativeBigInteger("2");
|
||||
public static final NativeBigInteger elgg = new NativeBigInteger("2");
|
||||
|
||||
/**
|
||||
* @since 0.9.9
|
||||
|
||||
@@ -234,7 +234,7 @@ public class DSAEngine {
|
||||
BigInteger s = new NativeBigInteger(1, sbytes);
|
||||
BigInteger r = new NativeBigInteger(1, rbytes);
|
||||
BigInteger y = new NativeBigInteger(1, verifyingKey.getData());
|
||||
BigInteger w = null;
|
||||
BigInteger w;
|
||||
try {
|
||||
w = s.modInverse(CryptoConstants.dsaq);
|
||||
} catch (ArithmeticException ae) {
|
||||
@@ -405,13 +405,13 @@ public class DSAEngine {
|
||||
|
||||
boolean ok = false;
|
||||
do {
|
||||
k = new BigInteger(160, _context.random());
|
||||
k = new NativeBigInteger(160, _context.random());
|
||||
ok = k.compareTo(CryptoConstants.dsaq) != 1;
|
||||
ok = ok && !k.equals(BigInteger.ZERO);
|
||||
//System.out.println("K picked (ok? " + ok + "): " + k.bitLength() + ": " + k.toString());
|
||||
} while (!ok);
|
||||
|
||||
BigInteger r = CryptoConstants.dsag.modPow(k, CryptoConstants.dsap).mod(CryptoConstants.dsaq);
|
||||
BigInteger r = CryptoConstants.dsag.modPowCT(k, CryptoConstants.dsap).mod(CryptoConstants.dsaq);
|
||||
BigInteger kinv = k.modInverse(CryptoConstants.dsaq);
|
||||
|
||||
BigInteger M = new NativeBigInteger(1, hash.getData());
|
||||
|
||||
@@ -52,7 +52,10 @@ class ECUtil {
|
||||
else if (s.equals(ECPoint.POINT_INFINITY))
|
||||
return r;
|
||||
BigInteger prime = ((ECFieldFp) curve.getField()).getP();
|
||||
BigInteger slope = (r.getAffineY().subtract(s.getAffineY())).multiply(r.getAffineX().subtract(s.getAffineX()).modInverse(prime)).mod(prime);
|
||||
// use NBI modInverse();
|
||||
BigInteger tmp = r.getAffineX().subtract(s.getAffineX());
|
||||
tmp = new NativeBigInteger(tmp);
|
||||
BigInteger slope = (r.getAffineY().subtract(s.getAffineY())).multiply(tmp.modInverse(prime)).mod(prime);
|
||||
slope = new NativeBigInteger(slope);
|
||||
BigInteger xOut = (slope.modPow(TWO, prime).subtract(r.getAffineX())).subtract(s.getAffineX()).mod(prime);
|
||||
BigInteger yOut = s.getAffineY().negate().mod(prime);
|
||||
@@ -67,7 +70,10 @@ class ECUtil {
|
||||
BigInteger slope = (r.getAffineX().pow(2)).multiply(THREE);
|
||||
slope = slope.add(curve.getA());
|
||||
BigInteger prime = ((ECFieldFp) curve.getField()).getP();
|
||||
slope = slope.multiply((r.getAffineY().multiply(TWO)).modInverse(prime));
|
||||
// use NBI modInverse();
|
||||
BigInteger tmp = r.getAffineY().multiply(TWO);
|
||||
tmp = new NativeBigInteger(tmp);
|
||||
slope = slope.multiply(tmp.modInverse(prime));
|
||||
BigInteger xOut = slope.pow(2).subtract(r.getAffineX().multiply(TWO)).mod(prime);
|
||||
BigInteger yOut = (r.getAffineY().negate()).add(slope.multiply(r.getAffineX().subtract(xOut))).mod(prime);
|
||||
ECPoint out = new ECPoint(xOut, yOut);
|
||||
|
||||
@@ -197,8 +197,8 @@ public class ElGamalEngine {
|
||||
// we use this buf first for Y, then for D, then for the hash
|
||||
byte[] buf = SimpleByteCache.acquire(257);
|
||||
System.arraycopy(encrypted, 0, buf, 0, 257);
|
||||
BigInteger y = new NativeBigInteger(1, buf);
|
||||
BigInteger ya = y.modPow(y1p, CryptoConstants.elgp);
|
||||
NativeBigInteger y = new NativeBigInteger(1, buf);
|
||||
BigInteger ya = y.modPowCT(y1p, CryptoConstants.elgp);
|
||||
System.arraycopy(encrypted, 257, buf, 0, 257);
|
||||
BigInteger d = new NativeBigInteger(1, buf);
|
||||
BigInteger m = ya.multiply(d);
|
||||
|
||||
@@ -97,6 +97,10 @@ import net.i2p.crypto.CryptoConstants;
|
||||
public class NativeBigInteger extends BigInteger {
|
||||
/** did we load the native lib correctly? */
|
||||
private static boolean _nativeOk;
|
||||
/** is native lib loaded and at least version 3? */
|
||||
private static boolean _nativeOk3;
|
||||
private static int _jbigiVersion;
|
||||
private static String _libGMPVersion = "unknown";
|
||||
private static String _loadStatus = "uninitialized";
|
||||
private static String _cpuModel = "uninitialized";
|
||||
private static String _extractedResource;
|
||||
@@ -277,10 +281,118 @@ public class NativeBigInteger extends BigInteger {
|
||||
* big endian twos complement representation of the exponent
|
||||
* @param modulus
|
||||
* big endian twos complement representation of the modulus
|
||||
* @throws ArithmeticException if modulus <= 0 (since libjbigi version3)
|
||||
* @return big endian twos complement representation of (base ^ exponent) % modulus
|
||||
*/
|
||||
public native static byte[] nativeModPow(byte base[], byte exponent[], byte modulus[]);
|
||||
private native static byte[] nativeModPow(byte base[], byte exponent[], byte modulus[]);
|
||||
|
||||
/**
|
||||
* calculate (base ^ exponent) % modulus.
|
||||
* Constant Time.
|
||||
*
|
||||
* @param base
|
||||
* big endian twos complement representation of the base (but it must be positive)
|
||||
* @param exponent
|
||||
* big endian twos complement representation of the exponent
|
||||
* @param modulus
|
||||
* big endian twos complement representation of the modulus
|
||||
* @return big endian twos complement representation of (base ^ exponent) % modulus
|
||||
* @throws ArithmeticException if modulus <= 0
|
||||
* @since 0.9.18 and libjbigi version 3
|
||||
*/
|
||||
private native static byte[] nativeModPowCT(byte base[], byte exponent[], byte modulus[]);
|
||||
|
||||
/**
|
||||
* @since 0.9.18 and libjbigi version 3
|
||||
* @throws ArithmeticException
|
||||
*/
|
||||
private native static byte[] nativeModInverse(byte base[], byte d[]);
|
||||
|
||||
/**
|
||||
* Only for testing jbigi's negative conversion functions!
|
||||
* @since 0.9.18
|
||||
*/
|
||||
//private native static byte[] nativeNeg(byte d[]);
|
||||
|
||||
/**
|
||||
* Get the jbigi version, only available since jbigi version 3
|
||||
* Caller must catch Throwable
|
||||
* @since 0.9.18
|
||||
*/
|
||||
private native static int nativeJbigiVersion();
|
||||
|
||||
/**
|
||||
* Get the libmp version, only available since jbigi version 3
|
||||
* @since 0.9.18
|
||||
*/
|
||||
private native static int nativeGMPMajorVersion();
|
||||
|
||||
/**
|
||||
* Get the libmp version, only available since jbigi version 3
|
||||
* @since 0.9.18
|
||||
*/
|
||||
private native static int nativeGMPMinorVersion();
|
||||
|
||||
/**
|
||||
* Get the libmp version, only available since jbigi version 3
|
||||
* @since 0.9.18
|
||||
*/
|
||||
private native static int nativeGMPPatchVersion();
|
||||
|
||||
/**
|
||||
* Get the jbigi version
|
||||
* @return 0 if no jbigi available, 2 if version not supported
|
||||
* @since 0.9.18
|
||||
*/
|
||||
private static int fetchJbigiVersion() {
|
||||
if (!_nativeOk)
|
||||
return 0;
|
||||
try {
|
||||
return nativeJbigiVersion();
|
||||
} catch (Throwable t) {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the jbigi and libgmp versions. Call after loading.
|
||||
* Sets _jbigiVersion, _nativeOK3, and _libGMPVersion.
|
||||
* @since 0.9.18
|
||||
*/
|
||||
private static void setVersions() {
|
||||
_jbigiVersion = fetchJbigiVersion();
|
||||
_nativeOk3 = _jbigiVersion > 2;
|
||||
if (_nativeOk3) {
|
||||
try {
|
||||
int maj = nativeGMPMajorVersion();
|
||||
int min = nativeGMPMinorVersion();
|
||||
int pat = nativeGMPPatchVersion();
|
||||
_libGMPVersion = maj + "." + min + "." + pat;
|
||||
} catch (Throwable t) {
|
||||
warn("jbigi version " + _jbigiVersion + " but GMP version not available???", t);
|
||||
}
|
||||
}
|
||||
warn("jbigi version: " + _jbigiVersion + "; GMP version: " + _libGMPVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the jbigi version
|
||||
* @return 0 if no jbigi available, 2 if version info not supported
|
||||
* @since 0.9.18
|
||||
*/
|
||||
public static int getJbigiVersion() {
|
||||
return _jbigiVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the libgmp version
|
||||
* @return "unknown" if no jbigi available or if version not supported
|
||||
* @since 0.9.18
|
||||
*/
|
||||
public static String getLibGMPVersion() {
|
||||
return _libGMPVersion;
|
||||
}
|
||||
|
||||
private byte[] cachedBa;
|
||||
|
||||
public NativeBigInteger(byte[] val) {
|
||||
@@ -316,17 +428,50 @@ public class NativeBigInteger extends BigInteger {
|
||||
this(integer.toByteArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ArithmeticException if m <= 0
|
||||
*/
|
||||
@Override
|
||||
public BigInteger modPow(BigInteger exponent, BigInteger m) {
|
||||
// jbigi.c convert_j2mp() and convert_mp2j() do NOT currently support negative numbers
|
||||
// Where negative or zero values aren't legal in modPow() anyway, avoid native,
|
||||
// as the Java code will throw an exception rather than silently fail
|
||||
if (_nativeOk && signum() >= 0 && exponent.signum() >= 0 && m.signum() > 0)
|
||||
// as the Java code will throw an exception rather than silently fail or crash the JVM
|
||||
// Negative values supported as of version 3
|
||||
if (_nativeOk3 || (_nativeOk && signum() >= 0 && exponent.signum() >= 0 && m.signum() > 0))
|
||||
return new NativeBigInteger(nativeModPow(toByteArray(), exponent.toByteArray(), m.toByteArray()));
|
||||
else
|
||||
return super.modPow(exponent, m);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ArithmeticException if m <= 0
|
||||
* @since 0.9.18 and libjbigi version 3
|
||||
*/
|
||||
public BigInteger modPowCT(BigInteger exponent, BigInteger m) {
|
||||
if (_nativeOk3)
|
||||
return new NativeBigInteger(nativeModPowCT(toByteArray(), exponent.toByteArray(), m.toByteArray()));
|
||||
else
|
||||
return modPow(exponent, m);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ArithmeticException if not coprime with m, or m <= 0
|
||||
* @since 0.9.18 and libjbigi version 3
|
||||
*/
|
||||
@Override
|
||||
public BigInteger modInverse(BigInteger m) {
|
||||
// Where negative or zero values aren't legal in modInverse() anyway, avoid native,
|
||||
// as the Java code will throw an exception rather than silently fail or crash the JVM
|
||||
// Note that 'this' can be negative
|
||||
// If this and m are not coprime, gmp will do a divide by zero exception and crash the JVM.
|
||||
// super will throw an ArithmeticException
|
||||
// if (_nativeOk3 && m.signum() > 0)
|
||||
if (_nativeOk3)
|
||||
return new NativeBigInteger(nativeModInverse(toByteArray(), m.toByteArray()));
|
||||
else
|
||||
return super.modInverse(m);
|
||||
}
|
||||
|
||||
/** caches */
|
||||
@Override
|
||||
public byte[] toByteArray(){
|
||||
if(cachedBa == null) //Since we are immutable it is safe to never update the cached ba after it has initially been generated
|
||||
@@ -378,12 +523,63 @@ public class NativeBigInteger extends BigInteger {
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
_doLog = true;
|
||||
runModPowTest(100);
|
||||
//if (_nativeOk3)
|
||||
// testnegs();
|
||||
runModPowTest(100, 1);
|
||||
if (_nativeOk3) {
|
||||
System.out.println("ModPowCT test:");
|
||||
runModPowTest(100, 2);
|
||||
System.out.println("ModInverse test:");
|
||||
runModPowTest(10000, 3);
|
||||
}
|
||||
}
|
||||
|
||||
private static void runModPowTest(int numRuns) {
|
||||
/** version >= 3 only */
|
||||
/****
|
||||
private static void testnegs() {
|
||||
for (int i = -66000; i <= 66000; i++) {
|
||||
testneg(i);
|
||||
}
|
||||
test(3, 11);
|
||||
test(25, 4);
|
||||
}
|
||||
|
||||
private static void testneg(long a) {
|
||||
NativeBigInteger ba = new NativeBigInteger(Long.toString(a));
|
||||
long r = ba.testNegate().longValue();
|
||||
if (r != 0 - a)
|
||||
warn("FAIL Neg test " + a + " = " + r);
|
||||
}
|
||||
|
||||
private static void test(long a, long b) {
|
||||
BigInteger ba = new NativeBigInteger(Long.toString(a));
|
||||
BigInteger bb = new NativeBigInteger(Long.toString(b));
|
||||
long r1 = a * b;
|
||||
long r2 = ba.multiply(bb).longValue();
|
||||
if (r1 != r2)
|
||||
warn("FAIL Mul test " + a + ' ' + b + " = " + r2);
|
||||
r1 = a / b;
|
||||
r2 = ba.divide(bb).longValue();
|
||||
if (r1 != r2)
|
||||
warn("FAIL Div test " + a + ' ' + b + " = " + r2);
|
||||
r1 = a % b;
|
||||
r2 = ba.mod(bb).longValue();
|
||||
if (r1 != r2)
|
||||
warn("FAIL Mod test " + a + ' ' + b + " = " + r2);
|
||||
}
|
||||
|
||||
private BigInteger testNegate() {
|
||||
return new NativeBigInteger(nativeNeg(toByteArray()));
|
||||
}
|
||||
|
||||
****/
|
||||
|
||||
/**
|
||||
* @parm mode 1: modPow; 2: modPowCT 3: modInverse
|
||||
*/
|
||||
private static void runModPowTest(int numRuns, int mode) {
|
||||
System.out.println("DEBUG: Warming up the random number generator...");
|
||||
SecureRandom rand = new SecureRandom();
|
||||
SecureRandom rand = RandomSource.getInstance();
|
||||
rand.nextBoolean();
|
||||
System.out.println("DEBUG: Random number generator warmed up");
|
||||
|
||||
@@ -392,22 +588,42 @@ public class NativeBigInteger extends BigInteger {
|
||||
byte[] _samplePrime = CryptoConstants.elgp.toByteArray();
|
||||
|
||||
BigInteger jg = new BigInteger(_sampleGenerator);
|
||||
NativeBigInteger ng = new NativeBigInteger(_sampleGenerator);
|
||||
BigInteger jp = new BigInteger(_samplePrime);
|
||||
|
||||
long totalTime = 0;
|
||||
long javaTime = 0;
|
||||
|
||||
int runsProcessed = 0;
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
// JIT warmup
|
||||
BigInteger bi = new NativeBigInteger(16, rand);
|
||||
if (mode == 1)
|
||||
jg.modPow(bi, jp);
|
||||
else if (mode == 2)
|
||||
ng.modPowCT(bi, jp);
|
||||
else
|
||||
bi.modInverse(jp);
|
||||
}
|
||||
for (runsProcessed = 0; runsProcessed < numRuns; runsProcessed++) {
|
||||
BigInteger bi = new BigInteger(226, rand); // 2048, rand); //
|
||||
BigInteger bi = new BigInteger(2048, rand); // 2048, rand); //
|
||||
NativeBigInteger g = new NativeBigInteger(_sampleGenerator);
|
||||
NativeBigInteger p = new NativeBigInteger(_samplePrime);
|
||||
NativeBigInteger k = new NativeBigInteger(1, bi.toByteArray());
|
||||
long beforeModPow = System.currentTimeMillis();
|
||||
BigInteger myValue = g.modPow(k, p);
|
||||
long afterModPow = System.currentTimeMillis();
|
||||
BigInteger jval = jg.modPow(bi, jp);
|
||||
long afterJavaModPow = System.currentTimeMillis();
|
||||
BigInteger myValue, jval;
|
||||
long beforeModPow = System.nanoTime();
|
||||
if (mode == 1)
|
||||
myValue = g.modPow(k, p);
|
||||
else if (mode == 2)
|
||||
myValue = g.modPowCT(bi, jp);
|
||||
else
|
||||
myValue = k.modInverse(p);
|
||||
long afterModPow = System.nanoTime();
|
||||
if (mode != 3)
|
||||
jval = jg.modPow(bi, jp);
|
||||
else
|
||||
jval = bi.modInverse(jp);
|
||||
long afterJavaModPow = System.nanoTime();
|
||||
|
||||
totalTime += (afterModPow - beforeModPow);
|
||||
javaTime += (afterJavaModPow - afterModPow);
|
||||
@@ -415,26 +631,37 @@ public class NativeBigInteger extends BigInteger {
|
||||
System.err.println("ERROR: [" + runsProcessed + "]\tnative modPow != java modPow");
|
||||
System.err.println("ERROR: native modPow value: " + myValue.toString());
|
||||
System.err.println("ERROR: java modPow value: " + jval.toString());
|
||||
System.err.println("ERROR: run time: " + totalTime + "ms (" + (totalTime / (runsProcessed + 1)) + "ms each)");
|
||||
break;
|
||||
} else {
|
||||
System.out.println("DEBUG: current run time: " + (afterModPow - beforeModPow) + "ms (total: "
|
||||
+ totalTime + "ms, " + (totalTime / (runsProcessed + 1)) + "ms each)");
|
||||
//} else if (mode == 1) {
|
||||
// System.out.println(String.format("DEBUG: current run time: %7.3f ms (total: %9.3f ms, %7.3f ms each)",
|
||||
// (afterModPow - beforeModPow) / 1000000d,
|
||||
// totalTime / 1000000d,
|
||||
// totalTime / (1000000d * (runsProcessed + 1))));
|
||||
}
|
||||
}
|
||||
System.out.println("INFO: run time: " + totalTime + "ms (" + (totalTime / (runsProcessed + 1)) + "ms each)");
|
||||
double dtotal = totalTime / 1000000f;
|
||||
double djava = javaTime / 1000000f;
|
||||
System.out.println(String.format("INFO: run time: %.3f ms (%.3f ms each)",
|
||||
dtotal, dtotal / (runsProcessed + 1)));
|
||||
if (numRuns == runsProcessed)
|
||||
System.out.println("INFO: " + runsProcessed + " runs complete without any errors");
|
||||
else
|
||||
System.out.println("ERROR: " + runsProcessed + " runs until we got an error");
|
||||
|
||||
if (_nativeOk) {
|
||||
System.out.println("native run time: \t" + totalTime + "ms (" + (totalTime / (runsProcessed + 1))
|
||||
+ "ms each)");
|
||||
System.out.println("java run time: \t" + javaTime + "ms (" + (javaTime / (runsProcessed + 1)) + "ms each)");
|
||||
System.out.println("native = " + ((totalTime * 100.0d) / javaTime) + "% of pure java time");
|
||||
System.out.println(String.format("Native run time: \t%9.3f ms (%7.3f ms each)",
|
||||
dtotal, dtotal / (runsProcessed + 1)));
|
||||
System.out.println(String.format("Java run time: \t%9.3f ms (%7.3f ms each)",
|
||||
djava, djava / (runsProcessed + 1)));
|
||||
System.out.println(String.format("Native = %.3f%% of pure Java time",
|
||||
dtotal * 100.0d / djava));
|
||||
if (dtotal < djava)
|
||||
System.out.println(String.format("Native is BETTER by a factor of %.3f -- YAY!", djava / dtotal));
|
||||
else
|
||||
System.out.println(String.format("Native is WORSE by a factor of %.3f -- BOO!", dtotal / djava));
|
||||
} else {
|
||||
System.out.println("java run time: \t" + javaTime + "ms (" + (javaTime / (runsProcessed + 1)) + "ms each)");
|
||||
System.out.println(String.format("java run time: \t%.3f ms (%.3f ms each)",
|
||||
djava, djava / (runsProcessed + 1)));
|
||||
System.out.println("However, we couldn't load the native library, so this doesn't test much");
|
||||
}
|
||||
}
|
||||
@@ -497,6 +724,8 @@ public class NativeBigInteger extends BigInteger {
|
||||
if (!_nativeOk) {
|
||||
warn("Native BigInteger library jbigi not loaded - using pure Java - " +
|
||||
"poor performance may result - see http://i2p-projekt.i2p/jbigi for help");
|
||||
} else {
|
||||
setVersions();
|
||||
}
|
||||
} catch(Exception e) {
|
||||
warn("Native BigInteger library jbigi not loaded, using pure java", e);
|
||||
|
||||
Reference in New Issue
Block a user