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:
@@ -33,6 +33,7 @@
|
||||
<b>Platform:</b> <%=System.getProperty("os.name")%> <%=System.getProperty("os.arch")%> <%=System.getProperty("os.version")%><br>
|
||||
<b>Processor:</b> <%=net.i2p.util.NativeBigInteger.cpuModel()%> (<%=net.i2p.util.NativeBigInteger.cpuType()%>)<br>
|
||||
<b>Jbigi:</b> <%=net.i2p.util.NativeBigInteger.loadStatus()%><br>
|
||||
<b>Jbigi version:</b> <%=net.i2p.util.NativeBigInteger.getJbigiVersion()%> GMP <%=net.i2p.util.NativeBigInteger.getLibGMPVersion()%><br>
|
||||
<b>Encoding:</b> <%=System.getProperty("file.encoding")%><br>
|
||||
<b>Charset:</b> <%=java.nio.charset.Charset.defaultCharset().name()%><br>
|
||||
</p>
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# NOTE:
|
||||
# This script is not supported - see mbuild-all.sh
|
||||
#
|
||||
|
||||
case `uname -sr` in
|
||||
MINGW*)
|
||||
@@ -14,21 +18,27 @@ FreeBSD*)
|
||||
exit;;
|
||||
esac
|
||||
|
||||
VER=4.2.4
|
||||
echo "Extracting GMP Version $VER ..."
|
||||
tar -xjf gmp-$VER.tar.bz2
|
||||
echo "Building..."
|
||||
mkdir bin
|
||||
mkdir lib
|
||||
mkdir lib/net
|
||||
mkdir lib/net/i2p
|
||||
mkdir lib/net/i2p/util
|
||||
VER=6.0.0
|
||||
TARVER=${VER}a
|
||||
TAR=gmp-${TARVER}.tar.bz2
|
||||
|
||||
for x in none pentium pentiummmx pentium2 pentium3 pentium4 k6 k62 k63 athlon geode pentiumm core2
|
||||
echo "Extracting GMP Version $VER ..."
|
||||
tar -xjf $TAR
|
||||
echo "Building..."
|
||||
mkdir -p lib/net/i2p/util
|
||||
|
||||
#
|
||||
# look in configure file in gmp source for supported host CPUs, at about line 5000
|
||||
#
|
||||
#
|
||||
for x in \
|
||||
none pentium pentiummmx pentium2 pentium3 pentium4 k6 k62 k63 athlon geode pentiumm core2 \
|
||||
athlon64 k10 bobcat jaguar bulldozer piledriver steamroller excavator corei atom nano
|
||||
do
|
||||
mkdir bin/$x
|
||||
mkdir -p bin/$x
|
||||
cd bin/$x
|
||||
../../gmp-$VER/configure --build=$x
|
||||
../../gmp-$VER/configure --with-pic --build=$x
|
||||
make clean
|
||||
make
|
||||
sh ../../build_jbigi.sh static
|
||||
case `uname -sr` in
|
||||
|
||||
@@ -22,7 +22,9 @@ mkdir -p lib bin/local
|
||||
|
||||
# Use 4.3.2 32bit CPUs.
|
||||
# Use 5.0.2 64bit CPUs.
|
||||
VER=4.3.2
|
||||
VER=6.0.0
|
||||
TARVER=${VER}a
|
||||
TAR=gmp-${TARVER}.tar.bz2
|
||||
|
||||
# If JAVA_HOME isn't set, try to figure it out on our own
|
||||
[ -z $JAVA_HOME ] && . ../find-java-home
|
||||
@@ -37,13 +39,14 @@ set -e
|
||||
|
||||
download_gmp ()
|
||||
{
|
||||
URL="https://gmplib.org/download/gmp/${TAR}"
|
||||
if [ $(which wget) ]; then
|
||||
echo "Downloading ftp://ftp.gmplib.org/pub/gmp-${VER}/${TAR}"
|
||||
wget -N --progress=dot ftp://ftp.gmplib.org/pub/gmp-${VER}/${TAR}
|
||||
echo "Downloading $URL"
|
||||
wget -N --progress=dot $URL
|
||||
else
|
||||
echo "ERROR: Cannot find wget." >&2
|
||||
echo >&2
|
||||
echo "Please download ftp://ftp.gmplib.org/pub/gmp-${VER}/${TAR}" >&2
|
||||
echo "Please download $URL" >&2
|
||||
echo "manually and rerun this script." >&2
|
||||
exit 1
|
||||
fi
|
||||
@@ -54,8 +57,6 @@ extract_gmp ()
|
||||
tar -xjf ${TAR} > /dev/null 2>&1|| (rm -f ${TAR} && download_gmp && extract_gmp || exit 1)
|
||||
}
|
||||
|
||||
TAR=gmp-${VER}.tar.bz2
|
||||
|
||||
if [ "$1" != "dynamic" -a ! -d gmp-${VER} ]; then
|
||||
if [ ! -f $TAR ]; then
|
||||
download_gmp
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
[ -z "$CC" ] && CC="gcc"
|
||||
|
||||
# If JAVA_HOME isn't set we'll try to figure it out
|
||||
[ -z $JAVA_HOME ] && . ../find-java-home
|
||||
[ -z $JAVA_HOME ] && . `dirname $0`/../find-java-home
|
||||
if [ ! -f "$JAVA_HOME/include/jni.h" ]; then
|
||||
echo "Cannot find jni.h! Looked in '$JAVA_HOME/include/jni.h'"
|
||||
echo "Please set JAVA_HOME to a java home that has the JNI"
|
||||
|
||||
@@ -7,11 +7,56 @@
|
||||
void convert_j2mp(JNIEnv* env, jbyteArray jvalue, mpz_t* mvalue);
|
||||
void convert_mp2j(JNIEnv* env, mpz_t mvalue, jbyteArray* jvalue);
|
||||
|
||||
/*
|
||||
* Versions:
|
||||
*
|
||||
* 1: Original version, with nativeModPow() and nativeDoubleValue()
|
||||
*
|
||||
* 2: (I2P 0.8.7)
|
||||
* Removed nativeDoubleValue()
|
||||
*
|
||||
* 3: (I2P 0.9.18)
|
||||
* Added:
|
||||
* nativeJbigiVersion()
|
||||
* nativeGMPMajorVersion()
|
||||
* nativeGMPMinorVersion()
|
||||
* nativeGMPPatchVersion()
|
||||
* nativeModInverse()
|
||||
* nativeModPowCT()
|
||||
* Support negative base value in modPow()
|
||||
* Throw ArithmeticException for bad arguments in modPow()
|
||||
*
|
||||
*/
|
||||
#define JBIGI_VERSION 3
|
||||
|
||||
/*****************************************
|
||||
*****Native method implementations*******
|
||||
*****************************************/
|
||||
|
||||
/* since version 3 */
|
||||
JNIEXPORT jint JNICALL Java_net_i2p_util_NativeBigInteger_nativeJbigiVersion
|
||||
(JNIEnv* env, jclass cls) {
|
||||
return (jint) JBIGI_VERSION;
|
||||
}
|
||||
|
||||
/* since version 3 */
|
||||
JNIEXPORT jint JNICALL Java_net_i2p_util_NativeBigInteger_nativeGMPMajorVersion
|
||||
(JNIEnv* env, jclass cls) {
|
||||
return (jint) __GNU_MP_VERSION;
|
||||
}
|
||||
|
||||
/* since version 3 */
|
||||
JNIEXPORT jint JNICALL Java_net_i2p_util_NativeBigInteger_nativeGMPMinorVersion
|
||||
(JNIEnv* env, jclass cls) {
|
||||
return (jint) __GNU_MP_VERSION_MINOR;
|
||||
}
|
||||
|
||||
/* since version 3 */
|
||||
JNIEXPORT jint JNICALL Java_net_i2p_util_NativeBigInteger_nativeGMPPatchVersion
|
||||
(JNIEnv* env, jclass cls) {
|
||||
return (jint) __GNU_MP_VERSION_PATCHLEVEL;
|
||||
}
|
||||
|
||||
/******** nativeModPow() */
|
||||
/*
|
||||
* Class: net_i2p_util_NativeBigInteger
|
||||
@@ -21,10 +66,17 @@ void convert_mp2j(JNIEnv* env, mpz_t mvalue, jbyteArray* jvalue);
|
||||
* From the javadoc:
|
||||
*
|
||||
* calculate (base ^ exponent) % modulus.
|
||||
* @param curVal 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
|
||||
* @param jbase big endian twos complement representation of the base
|
||||
* Negative values allowed as of version 3
|
||||
* @param jexp big endian twos complement representation of the exponent
|
||||
* Must be greater than or equal to zero.
|
||||
* As of version 3, throws java.lang.ArithmeticException if < 0.
|
||||
* @param jmod big endian twos complement representation of the modulus
|
||||
* Must be greater than zero.
|
||||
* As of version 3, throws java.lang.ArithmeticException if <= 0.
|
||||
* Prior to version 3, crashed the JVM if <= 0.
|
||||
* @return big endian twos complement representation of (base ^ exponent) % modulus
|
||||
* @throws java.lang.ArithmeticException if jmod is <= 0
|
||||
*/
|
||||
|
||||
JNIEXPORT jbyteArray JNICALL Java_net_i2p_util_NativeBigInteger_nativeModPow
|
||||
@@ -39,24 +91,203 @@ JNIEXPORT jbyteArray JNICALL Java_net_i2p_util_NativeBigInteger_nativeModPow
|
||||
mpz_t mmod;
|
||||
jbyteArray jresult;
|
||||
|
||||
convert_j2mp(env, jbase, &mbase);
|
||||
convert_j2mp(env, jexp, &mexp);
|
||||
convert_j2mp(env, jmod, &mmod);
|
||||
if (mpz_sgn(mmod) <= 0) {
|
||||
mpz_clear(mmod);
|
||||
jclass exc = (*env)->FindClass(env, "java/lang/ArithmeticException");
|
||||
(*env)->ThrowNew(env, exc, "Modulus must be positive");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// disallow negative exponents to avoid divide by zero exception if no inverse exists
|
||||
convert_j2mp(env, jexp, &mexp);
|
||||
if (mpz_sgn(mexp) < 0) {
|
||||
mpz_clears(mmod, mexp, 0);
|
||||
jclass exc = (*env)->FindClass(env, "java/lang/ArithmeticException");
|
||||
(*env)->ThrowNew(env, exc, "Exponent cannot be negative");
|
||||
return 0;
|
||||
}
|
||||
|
||||
convert_j2mp(env, jbase, &mbase);
|
||||
|
||||
/* Perform the actual powmod. We use mmod for the result because it is
|
||||
/* Perform the actual powmod. We use mmod for the result because it is
|
||||
* always at least as big as the result.
|
||||
*/
|
||||
mpz_powm(mmod, mbase, mexp, mmod);
|
||||
|
||||
convert_mp2j(env, mmod, &jresult);
|
||||
convert_mp2j(env, mmod, &jresult);
|
||||
|
||||
mpz_clear(mbase);
|
||||
mpz_clear(mexp);
|
||||
mpz_clear(mmod);
|
||||
mpz_clears(mbase, mexp, mmod, 0);
|
||||
|
||||
return jresult;
|
||||
}
|
||||
|
||||
/******** nativeModPowCT() */
|
||||
/*
|
||||
* Class: net_i2p_util_NativeBigInteger
|
||||
* Method: nativeModPowCT
|
||||
* Signature: ([B[B[B)[B
|
||||
*
|
||||
* Constant time version of nativeModPow()
|
||||
*
|
||||
* From the javadoc:
|
||||
*
|
||||
* calculate (base ^ exponent) % modulus.
|
||||
* @param jbase big endian twos complement representation of the base
|
||||
* Negative values allowed.
|
||||
* @param jexp big endian twos complement representation of the exponent
|
||||
* Must be positive.
|
||||
* @param jmod big endian twos complement representation of the modulus
|
||||
* Must be positive and odd.
|
||||
* @return big endian twos complement representation of (base ^ exponent) % modulus
|
||||
* @throws java.lang.ArithmeticException if jmod or jexp is <= 0, or jmod is even.
|
||||
* @since version 3
|
||||
*/
|
||||
|
||||
JNIEXPORT jbyteArray JNICALL Java_net_i2p_util_NativeBigInteger_nativeModPowCT
|
||||
(JNIEnv* env, jclass cls, jbyteArray jbase, jbyteArray jexp, jbyteArray jmod) {
|
||||
|
||||
mpz_t mbase;
|
||||
mpz_t mexp;
|
||||
mpz_t mmod;
|
||||
jbyteArray jresult;
|
||||
|
||||
convert_j2mp(env, jmod, &mmod);
|
||||
if (mpz_sgn(mmod) <= 0) {
|
||||
mpz_clear(mmod);
|
||||
jclass exc = (*env)->FindClass(env, "java/lang/ArithmeticException");
|
||||
(*env)->ThrowNew(env, exc, "Modulus must be positive");
|
||||
return 0;
|
||||
}
|
||||
// disallow even modulus as specified in the GMP docs
|
||||
if (mpz_odd_p(mmod) == 0) {
|
||||
mpz_clear(mmod);
|
||||
jclass exc = (*env)->FindClass(env, "java/lang/ArithmeticException");
|
||||
(*env)->ThrowNew(env, exc, "Modulus must be odd");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// disallow negative or zero exponents as specified in the GMP docs
|
||||
convert_j2mp(env, jexp, &mexp);
|
||||
if (mpz_sgn(mexp) <= 0) {
|
||||
mpz_clears(mmod, mexp, 0);
|
||||
jclass exc = (*env)->FindClass(env, "java/lang/ArithmeticException");
|
||||
(*env)->ThrowNew(env, exc, "Exponent must be positive");
|
||||
return 0;
|
||||
}
|
||||
|
||||
convert_j2mp(env, jbase, &mbase);
|
||||
|
||||
mpz_powm_sec(mmod, mbase, mexp, mmod);
|
||||
|
||||
convert_mp2j(env, mmod, &jresult);
|
||||
|
||||
mpz_clears(mbase, mexp, mmod, 0);
|
||||
|
||||
return jresult;
|
||||
}
|
||||
|
||||
/******** nativeModInverse() */
|
||||
/*
|
||||
* Class: net_i2p_util_NativeBigInteger
|
||||
* Method: nativeModInverse
|
||||
* Signature: ([B[B)[B
|
||||
*
|
||||
* From the javadoc:
|
||||
*
|
||||
* calculate (base ^ -1) % modulus.
|
||||
* @param jbase big endian twos complement representation of the base
|
||||
* Negative values allowed
|
||||
* @param jmod big endian twos complement representation of the modulus
|
||||
* Zero or Negative values will throw a java.lang.ArithmeticException
|
||||
* @return big endian twos complement representation of (base ^ exponent) % modulus
|
||||
* @throws java.lang.ArithmeticException if jbase and jmod are not coprime or jmod is <= 0
|
||||
* @since version 3
|
||||
*/
|
||||
|
||||
JNIEXPORT jbyteArray JNICALL Java_net_i2p_util_NativeBigInteger_nativeModInverse
|
||||
(JNIEnv* env, jclass cls, jbyteArray jbase, jbyteArray jmod) {
|
||||
|
||||
mpz_t mbase;
|
||||
mpz_t mexp;
|
||||
mpz_t mmod;
|
||||
mpz_t mgcd;
|
||||
jbyteArray jresult;
|
||||
|
||||
convert_j2mp(env, jmod, &mmod);
|
||||
|
||||
if (mpz_sgn(mmod) <= 0) {
|
||||
mpz_clear(mmod);
|
||||
jclass exc = (*env)->FindClass(env, "java/lang/ArithmeticException");
|
||||
(*env)->ThrowNew(env, exc, "Modulus must be positive");
|
||||
return 0;
|
||||
}
|
||||
|
||||
convert_j2mp(env, jbase, &mbase);
|
||||
mpz_init_set_si(mexp, -1);
|
||||
|
||||
/* We must protect the jvm by doing a gcd test first.
|
||||
* If the arguments are not coprime, GMP will throw a divide by zero
|
||||
* and crash the JVM.
|
||||
* We could test in Java using BigInteger.gcd() but it is almost as slow
|
||||
* as the Java modInverse() itself, thus defeating the point.
|
||||
* Unfortunately, this almost doubles our time here too.
|
||||
*/
|
||||
mpz_init(mgcd);
|
||||
mpz_gcd(mgcd, mbase, mmod);
|
||||
if (mpz_cmp_si(mgcd, 1) != 0) {
|
||||
mpz_clears(mbase, mexp, mmod, mgcd, 0);
|
||||
jclass exc = (*env)->FindClass(env, "java/lang/ArithmeticException");
|
||||
(*env)->ThrowNew(env, exc, "Not coprime in nativeModInverse()");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Perform the actual powmod. We use mmod for the result because it is
|
||||
* always at least as big as the result.
|
||||
*/
|
||||
mpz_powm(mmod, mbase, mexp, mmod);
|
||||
|
||||
convert_mp2j(env, mmod, &jresult);
|
||||
|
||||
mpz_clears(mbase, mexp, mmod, mgcd, 0);
|
||||
|
||||
return jresult;
|
||||
}
|
||||
|
||||
/******** nativeNeg() */
|
||||
/* since version 3 */
|
||||
/*
|
||||
* Class: net_i2p_util_NativeBigInteger
|
||||
* Method: nativeNeg
|
||||
* Signature: ([B)[B
|
||||
*
|
||||
* For testing of the conversion functions only!
|
||||
*
|
||||
* calculate n mod d
|
||||
* @param n big endian twos complement representation
|
||||
* @return big endian twos complement representation of -n
|
||||
*/
|
||||
|
||||
/****
|
||||
JNIEXPORT jbyteArray JNICALL Java_net_i2p_util_NativeBigInteger_nativeNeg
|
||||
(JNIEnv* env, jclass cls, jbyteArray jn) {
|
||||
|
||||
mpz_t mn;
|
||||
jbyteArray jresult;
|
||||
|
||||
convert_j2mp(env, jn, &mn);
|
||||
|
||||
// result to mn
|
||||
mpz_neg(mn, mn);
|
||||
|
||||
convert_mp2j(env, mn, &jresult);
|
||||
|
||||
mpz_clear(mn);
|
||||
|
||||
return jresult;
|
||||
}
|
||||
****/
|
||||
|
||||
/******************************
|
||||
*****Conversion methods*******
|
||||
******************************/
|
||||
@@ -70,13 +301,15 @@ JNIEXPORT jbyteArray JNICALL Java_net_i2p_util_NativeBigInteger_nativeModPow
|
||||
* Initializes the GMP value with enough preallocated size, and converts the
|
||||
* Java value into the GMP value. The value that mvalue points to should be
|
||||
* uninitialized
|
||||
*
|
||||
* As of version 3, negative values are correctly converted.
|
||||
*/
|
||||
|
||||
void convert_j2mp(JNIEnv* env, jbyteArray jvalue, mpz_t* mvalue)
|
||||
{
|
||||
jsize size;
|
||||
jbyte* jbuffer;
|
||||
//int sign;
|
||||
mpz_t mask;
|
||||
|
||||
size = (*env)->GetArrayLength(env, jvalue);
|
||||
jbuffer = (*env)->GetByteArrayElements(env, jvalue, NULL);
|
||||
@@ -98,12 +331,22 @@ void convert_j2mp(JNIEnv* env, jbyteArray jvalue, mpz_t* mvalue)
|
||||
* be 0 to use the full words.
|
||||
*/
|
||||
mpz_import(*mvalue, size, 1, sizeof(jbyte), 1, 0, (void*)jbuffer);
|
||||
/*Uncomment this to support negative integer values,
|
||||
not tested though..
|
||||
sign = jbuffer[0] < 0?-1:1;
|
||||
if(sign == -1)
|
||||
mpz_neg(*mvalue,*mvalue);
|
||||
*/
|
||||
if (jbuffer[0] < 0) {
|
||||
// ones complement, making a negative number
|
||||
mpz_com(*mvalue, *mvalue);
|
||||
// construct the mask needed to get rid of the new high bit
|
||||
mpz_init_set_ui(mask, 1);
|
||||
mpz_mul_2exp(mask, mask, size * 8);
|
||||
mpz_sub_ui(mask, mask, 1);
|
||||
// mask off the high bits, making a postive number (the magnitude, off by one)
|
||||
mpz_and(*mvalue, *mvalue, mask);
|
||||
// release the mask
|
||||
mpz_clear(mask);
|
||||
// add one to get the correct magnitude
|
||||
mpz_add_ui(*mvalue, *mvalue, 1);
|
||||
// invert to a negative number
|
||||
mpz_neg(*mvalue, *mvalue);
|
||||
}
|
||||
(*env)->ReleaseByteArrayElements(env, jvalue, jbuffer, JNI_ABORT);
|
||||
}
|
||||
|
||||
@@ -112,6 +355,8 @@ void convert_j2mp(JNIEnv* env, jbyteArray jvalue, mpz_t* mvalue)
|
||||
* Converts the GMP value into the Java value; Doesn't do anything else.
|
||||
* Pads the resulting jbyte array with 0, so the twos complement value is always
|
||||
* positive.
|
||||
*
|
||||
* As of version 3, negative values are correctly converted.
|
||||
*/
|
||||
|
||||
void convert_mp2j(JNIEnv* env, mpz_t mvalue, jbyteArray* jvalue)
|
||||
@@ -121,33 +366,39 @@ void convert_mp2j(JNIEnv* env, mpz_t mvalue, jbyteArray* jvalue)
|
||||
size_t size;
|
||||
jbyte* buffer;
|
||||
jboolean copy;
|
||||
//int i;
|
||||
int i;
|
||||
int neg;
|
||||
|
||||
copy = JNI_FALSE;
|
||||
|
||||
neg = mpz_sgn(mvalue) < 0;
|
||||
if (neg) {
|
||||
// add 1...
|
||||
// have to do this before we calculate the size!
|
||||
mpz_add_ui(mvalue, mvalue, 1);
|
||||
}
|
||||
|
||||
/* sizeinbase() + 7 => Ceil division */
|
||||
size = (mpz_sizeinbase(mvalue, 2) + 7) / 8 + sizeof(jbyte);
|
||||
*jvalue = (*env)->NewByteArray(env, size);
|
||||
|
||||
buffer = (*env)->GetByteArrayElements(env, *jvalue, ©);
|
||||
buffer[0] = 0x00;
|
||||
//Uncomment the comments below to support negative integer values,
|
||||
//not very well-tested though..
|
||||
//if(mpz_sgn(mvalue) >=0){
|
||||
mpz_export((void*)&buffer[1], &size, 1, sizeof(jbyte), 1, 0, mvalue);
|
||||
//}else{
|
||||
// mpz_add_ui(mvalue,mvalue,1);
|
||||
// mpz_export((void*)&buffer[1], &size, 1, sizeof(jbyte), 1, 0, mvalue);
|
||||
// for(i =0;i<=size;i++){ //This could be done more effectively
|
||||
// buffer[i]=~buffer[i];
|
||||
// }
|
||||
//}
|
||||
|
||||
/* mode has (supposedly) no effect if elems is not a copy of the
|
||||
if (!neg) {
|
||||
mpz_export((void*)&buffer[1], NULL, 1, sizeof(jbyte), 1, 0, mvalue);
|
||||
} else {
|
||||
mpz_export((void*)&buffer[1], NULL, 1, sizeof(jbyte), 1, 0, mvalue);
|
||||
// ... and invert the bits
|
||||
// This could be done all in mpz, the reverse of the above
|
||||
for (i = 0; i <= size; i++) {
|
||||
buffer[i] = ~buffer[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* mode has (supposedly) no effect if elems is not a copy of the
|
||||
* elements in array
|
||||
*/
|
||||
(*env)->ReleaseByteArrayElements(env, *jvalue, buffer, 0);
|
||||
//mode has (supposedly) no effect if elems is not a copy of the elements in array
|
||||
}
|
||||
|
||||
/******** eof */
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Run with BITS=32 to generate 32-bit libs on a 64-bit platform
|
||||
# On Ubuntu you will need sudo apt-get install gcc-multilib libc6-i386 libc6-dev-i386
|
||||
#
|
||||
|
||||
# ON Solaris 11 (at least) this variable must be set.
|
||||
# Linux and *BSD will do the right thing.
|
||||
#
|
||||
#BITS=32
|
||||
|
||||
#
|
||||
# look in configure file in gmp source for supported host CPUs, at about line 5000
|
||||
#
|
||||
|
||||
# FIXME Is this all?
|
||||
DARWIN_PLATFORMS="core2 corei"
|
||||
MISC_DARWIN_PLATFORMS="powerpc powerpc64 powerpc64le powerpcle"
|
||||
@@ -36,9 +44,19 @@ MISC_MINGW_PLATFORMS=""
|
||||
#
|
||||
# Are there any other X86 platforms that work on i2p? Add them here.
|
||||
#
|
||||
|
||||
# Note! these build on 32bit as 32bit when operating as 32bit...
|
||||
X86_64_PLATFORMS="atom athlon64 core2 corei nano pentium4"
|
||||
# starting with k10 added for 6.0.0
|
||||
# As of GMP 6.0.0, libgmp 3,
|
||||
# the following architectures appear to build to identical code:
|
||||
# core2 corei
|
||||
# bulldozer piledriver streamroller excavator
|
||||
# bobcat jaguar
|
||||
# k62 k63
|
||||
# viac32 pentium3
|
||||
#
|
||||
# Even more duplicates are in 32-bit mode, so it doesn't pay to have everything for 32 bit.
|
||||
#
|
||||
X86_64_PLATFORMS="atom athlon64 core2 corei nano pentium4 k10 bobcat jaguar bulldozer piledriver steamroller excavator"
|
||||
|
||||
# Note! these are 32bit _ONLY_
|
||||
X86_PLATFORMS="pentium pentiummmx pentium2 pentium3 pentiumm k6 k62 k63 athlon geode viac3 viac32 ${X86_64_PLATFORMS}"
|
||||
|
||||
@@ -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