summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJ08nY2017-11-30 19:42:20 +0100
committerJ08nY2017-11-30 19:42:20 +0100
commitd571f404e51356239cdb7d23de95074b271016e1 (patch)
treea2ebd05f05cb3dd10376aa22534850be0324fe4d /src
parent715dd7f068dfc9e5b90ce0c1e2d3aad0a9fe982a (diff)
downloadECTester-d571f404e51356239cdb7d23de95074b271016e1.tar.gz
ECTester-d571f404e51356239cdb7d23de95074b271016e1.tar.zst
ECTester-d571f404e51356239cdb7d23de95074b271016e1.zip
Diffstat (limited to 'src')
-rw-r--r--src/cz/crcs/ectester/common/util/ECUtil.java62
-rw-r--r--src/cz/crcs/ectester/standalone/ECTesterStandalone.java7
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java4
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c51
4 files changed, 94 insertions, 30 deletions
diff --git a/src/cz/crcs/ectester/common/util/ECUtil.java b/src/cz/crcs/ectester/common/util/ECUtil.java
index 80ba34e..662720a 100644
--- a/src/cz/crcs/ectester/common/util/ECUtil.java
+++ b/src/cz/crcs/ectester/common/util/ECUtil.java
@@ -7,34 +7,75 @@ import java.security.spec.*;
* @author Jan Jancar johny@neuromancer.sk
*/
public class ECUtil {
- public static byte[] toX962Compressed(ECPoint point) {
+
+ public static byte[] toByteArray(BigInteger what, int bits) {
+ byte[] raw = what.toByteArray();
+ int bytes = (bits + 7) / 8;
+ if (raw.length < bytes) {
+ byte[] result = new byte[bytes];
+ System.arraycopy(raw,0, result, bytes - raw.length, raw.length);
+ return result;
+ }
+ if (bytes < raw.length) {
+ byte[] result = new byte[bytes];
+ System.arraycopy(raw, raw.length - bytes, result, 0, bytes);
+ return result;
+ }
+ return raw;
+ }
+
+ public static byte[] toX962Compressed(ECPoint point, int bits) {
if (point.equals(ECPoint.POINT_INFINITY)) {
return new byte[]{0};
}
- byte[] x = point.getAffineX().toByteArray();
+ byte[] x = toByteArray(point.getAffineX(), bits);
byte marker = (byte) (0x02 | point.getAffineY().mod(BigInteger.valueOf(2)).byteValue());
return ByteUtil.concatenate(new byte[]{marker}, x);
}
- public static byte[] toX962Uncompressed(ECPoint point) {
+ public static byte[] toX962Compressed(ECPoint point, EllipticCurve curve) {
+ return toX962Compressed(point, curve.getField().getFieldSize());
+ }
+
+ public static byte[] toX962Compressed(ECPoint point, ECParameterSpec spec) {
+ return toX962Compressed(point, spec.getCurve());
+ }
+
+ public static byte[] toX962Uncompressed(ECPoint point, int bits) {
if (point.equals(ECPoint.POINT_INFINITY)) {
return new byte[]{0};
}
- byte[] x = point.getAffineX().toByteArray();
- byte[] y = point.getAffineY().toByteArray();
+ byte[] x = toByteArray(point.getAffineX(), bits);
+ byte[] y = toByteArray(point.getAffineY(), bits);
return ByteUtil.concatenate(new byte[]{0x04}, x, y);
}
- public static byte[] toX962Hybrid(ECPoint point) {
+ public static byte[] toX962Uncompressed(ECPoint point, EllipticCurve curve) {
+ return toX962Uncompressed(point, curve.getField().getFieldSize());
+ }
+
+ public static byte[] toX962Uncompressed(ECPoint point, ECParameterSpec spec) {
+ return toX962Uncompressed(point, spec.getCurve());
+ }
+
+ public static byte[] toX962Hybrid(ECPoint point, int bits) {
if (point.equals(ECPoint.POINT_INFINITY)) {
return new byte[]{0};
}
- byte[] x = point.getAffineX().toByteArray();
- byte[] y = point.getAffineY().toByteArray();
+ byte[] x = toByteArray(point.getAffineX(), bits);
+ byte[] y = toByteArray(point.getAffineY(), bits);
byte marker = (byte) (0x06 | point.getAffineY().mod(BigInteger.valueOf(2)).byteValue());
return ByteUtil.concatenate(new byte[]{marker}, x, y);
}
+ public static byte[] toX962Hybrid(ECPoint point, EllipticCurve curve) {
+ return toX962Hybrid(point, curve.getField().getFieldSize());
+ }
+
+ public static byte[] toX962Hybrid(ECPoint point, ECParameterSpec spec) {
+ return toX962Hybrid(point, spec.getCurve());
+ }
+
private static boolean isResidue(BigInteger a, BigInteger p) {
BigInteger exponent = p.subtract(BigInteger.ONE).divide(BigInteger.valueOf(2));
BigInteger result = a.modPow(exponent, p);
@@ -64,7 +105,7 @@ public class ECUtil {
int i = 0;
BigInteger exponent;
do {
- exponent = BigInteger.valueOf(2).pow(++i);
+ exponent = BigInteger.valueOf(2).pow(++i);
} while (!t.modPow(exponent, p).equals(BigInteger.ONE));
BigInteger twoExponent = m.subtract(BigInteger.valueOf(i + 1));
@@ -120,7 +161,8 @@ public class ECUtil {
return new ECPoint(x, beta);
} else if (field instanceof ECFieldF2m) {
-
+ //TODO
+ throw new UnsupportedOperationException();
}
return null;
} else {
diff --git a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
index 8605158..3ad7141 100644
--- a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
+++ b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
@@ -23,7 +23,6 @@ import java.security.*;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.AlgorithmParameterSpec;
-import java.security.spec.ECGenParameterSpec;
import java.security.spec.ECParameterSpec;
import java.util.*;
import java.util.stream.Collectors;
@@ -246,7 +245,7 @@ public class ECTesterStandalone {
byte[] result = ka.generateSecret();
ka = kaIdent.getInstance(lib.getProvider());
- String pub = ByteUtil.bytesToHex(ECUtil.toX962Uncompressed(pubkey.getW()), false);
+ String pub = ByteUtil.bytesToHex(ECUtil.toX962Uncompressed(pubkey.getW(), pubkey.getParams()), false);
String priv = ByteUtil.bytesToHex(privkey.getS().toByteArray(), false);
String dh = ByteUtil.bytesToHex(result, false);
System.out.println(String.format("%d;%d;%s;%s;%s", i, elapsed, pub, priv, dh));
@@ -336,7 +335,7 @@ public class ECTesterStandalone {
verifyTime += System.nanoTime();
- String pub = ByteUtil.bytesToHex(ECUtil.toX962Uncompressed(pubkey.getW()), false);
+ String pub = ByteUtil.bytesToHex(ECUtil.toX962Uncompressed(pubkey.getW(), pubkey.getParams()), false);
String priv = ByteUtil.bytesToHex(privkey.getS().toByteArray(), false);
String sign = ByteUtil.bytesToHex(signature, false);
System.out.println(String.format("%d;%s;%d;%d;%s;%s;%s;%d", i, dataString, signTime, verifyTime, pub, priv, sign, verified ? 1 : 0));
@@ -385,7 +384,7 @@ public class ECTesterStandalone {
ECPublicKey publicKey = (ECPublicKey) kp.getPublic();
ECPrivateKey privateKey = (ECPrivateKey) kp.getPrivate();
- String pub = ByteUtil.bytesToHex(ECUtil.toX962Uncompressed(publicKey.getW()), false);
+ String pub = ByteUtil.bytesToHex(ECUtil.toX962Uncompressed(publicKey.getW(), publicKey.getParams()), false);
String priv = ByteUtil.bytesToHex(privateKey.getS().toByteArray(), false);
System.out.println(String.format("%d;%d;%s;%s", i, elapsed, pub, priv));
}
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java
index fee0ea8..47eeabd 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java
@@ -67,8 +67,8 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi {
@Override
protected byte[] engineGenerateSecret() throws IllegalStateException {
- byte[] pubkey = ECUtil.toX962Uncompressed(publicKey.getW());
- byte[] privkey = privateKey.getS().toByteArray();
+ byte[] pubkey = ECUtil.toX962Uncompressed(publicKey.getW(), params.getCurve());
+ byte[] privkey = ECUtil.toByteArray(privateKey.getS(), params.getCurve().getField().getFieldSize());
return generateSecret(pubkey, privkey, params);
}
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c b/src/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c
index b43b05a..d32c6a6 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c
+++ b/src/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c
@@ -15,6 +15,7 @@ static jclass fp_field_class;
static jclass f2m_field_class;
static jclass point_class;
static jclass biginteger_class;
+static jclass illegal_state_exception_class;
JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_createProvider(JNIEnv *env, jobject this) {
/* Create the custom provider. */
@@ -88,6 +89,9 @@ JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_
jclass local_point_class = (*env)->FindClass(env, "java/security/spec/ECPoint");
point_class = (*env)->NewGlobalRef(env, local_point_class);
+
+ jclass local_illegal_state_exception_class = (*env)->FindClass(env, "java/lang/IllegalStateException");
+ illegal_state_exception_class = (*env)->NewGlobalRef(env, local_illegal_state_exception_class);
}
JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_getCurves(JNIEnv *env, jobject this) {
@@ -233,7 +237,7 @@ static ltc_ecc_set_type* create_curve(JNIEnv *env, jobject params) {
jmethodID get_bits = (*env)->GetMethodID(env, fp_field_class, "getFieldSize", "()I");
jint bits = (*env)->CallIntMethod(env, field, get_bits);
- jint bytes = (bits + (8 - bits % 8)) / 8;
+ jint bytes = (bits + 7) / 8;
jmethodID get_b = (*env)->GetMethodID(env, elliptic_curve_class, "getB", "()Ljava/math/BigInteger;");
jobject b = (*env)->CallObjectMethod(env, elliptic_curve, get_b);
@@ -265,18 +269,23 @@ static ltc_ecc_set_type* create_curve(JNIEnv *env, jobject params) {
return curve;
}
+static void throw_new(JNIEnv *env, const char *class, const char *message) {
+ jclass clazz = (*env)->FindClass(env, class);
+ (*env)->ThrowNew(env, clazz, message);
+}
+
static jobject generate_from_curve(JNIEnv *env, const ltc_ecc_set_type *curve) {
ecc_key key;
int err;
if ((err = ecc_make_key_ex(&ltc_prng, find_prng("yarrow"), &key, curve)) != CRYPT_OK) {
- printf("Error making key: %s\n", error_to_string(err));
+ throw_new(env, "java/security/GeneralSecurityException", error_to_string(err));
return NULL;
}
unsigned long key_len = 2*curve->size + 1;
jbyteArray pub_bytes = (*env)->NewByteArray(env, key_len);
jbyte *key_pub = (*env)->GetByteArrayElements(env, pub_bytes, NULL);
ecc_ansi_x963_export(&key, key_pub, &key_len);
- (*env)->ReleaseByteArrayElements(env, pub_bytes, key_pub, 0);
+ (*env)->ReleaseByteArrayElements(env, pub_bytes, key_pub, JNI_COMMIT);
jobject ec_param_spec = create_ec_param_spec(env, curve);
@@ -287,7 +296,7 @@ static jobject generate_from_curve(JNIEnv *env, const ltc_ecc_set_type *curve) {
jbyteArray priv_bytes = (*env)->NewByteArray(env, curve->size);
jbyte *key_priv = (*env)->GetByteArrayElements(env, priv_bytes, NULL);
ltc_mp.unsigned_write(key.k, key_priv);
- (*env)->ReleaseByteArrayElements(env, priv_bytes, key_priv, 0);
+ (*env)->ReleaseByteArrayElements(env, priv_bytes, key_priv, JNI_COMMIT);
jobject ec_priv_param_spec = (*env)->NewLocalRef(env, ec_param_spec);
jmethodID ec_priv_init = (*env)->GetMethodID(env, privkey_class, "<init>", "([BLjava/security/spec/ECParameterSpec;)V");
@@ -347,7 +356,13 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey
jsize pub_size = (*env)->GetArrayLength(env, pubkey);
jbyte *pub_data = (*env)->GetByteArrayElements(env, pubkey, NULL);
- jsize pub_half = (pub_size - 1) / 2;
+
+ if (curve->size != (pub_size - 1) / 2) {
+ throw_new(env, "java/lang/IllegalStateException", "Curve size does not match the public key size.");
+ (*env)->ReleaseByteArrayElements(env, pubkey, pub_data, JNI_ABORT);
+ free(curve);
+ return NULL;
+ }
ecc_key pub;
pub.type = PK_PUBLIC;
@@ -355,38 +370,46 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey
pub.dp = curve;
ltc_init_multi(&pub.pubkey.x, &pub.pubkey.y, &pub.pubkey.z, NULL);
ltc_mp.set_int(pub.pubkey.z, 1);
- ltc_mp.unsigned_read(pub.pubkey.x, pub_data + 1, (unsigned long) pub_half);
- ltc_mp.unsigned_read(pub.pubkey.y, pub_data + 1 + pub_half, (unsigned long) pub_half);
+ ltc_mp.unsigned_read(pub.pubkey.x, pub_data + 1, (unsigned long) curve->size);
+ ltc_mp.unsigned_read(pub.pubkey.y, pub_data + 1 + curve->size, (unsigned long) curve->size);
(*env)->ReleaseByteArrayElements(env, pubkey, pub_data, JNI_ABORT);
+
jsize priv_size = (*env)->GetArrayLength(env, privkey);
jbyte *priv_data = (*env)->GetByteArrayElements(env, privkey, NULL);
+ if (curve->size != priv_size) {
+ throw_new(env, "java/lang/IllegalStateException", "Curve size does not match the private key size.");
+ (*env)->ReleaseByteArrayElements(env, privkey, priv_data, JNI_ABORT);
+ free(curve);
+ return NULL;
+ }
+
ecc_key priv;
priv.type = PK_PRIVATE;
priv.idx = -1;
priv.dp = curve;
ltc_mp.init(&priv.k);
- ltc_mp.unsigned_read(priv.k, priv_data, (unsigned long) priv_size);
+ ltc_mp.unsigned_read(priv.k, priv_data, (unsigned long) curve->size);
(*env)->ReleaseByteArrayElements(env, privkey, priv_data, JNI_ABORT);
- unsigned char result[pub_half];
-
- unsigned long output_len = pub_half;
+ unsigned char result[curve->size];
+ unsigned long output_len = curve->size;
int err;
if ((err = ecc_shared_secret(&priv, &pub, result, &output_len)) != CRYPT_OK) {
- printf("Error during shared secret computation: %s\n", error_to_string(err));
+ throw_new(env, "java/security/GeneralSecurityException", error_to_string(err));
free(curve);
return NULL;
}
- jbyteArray output = (*env)->NewByteArray(env, pub_half);
+ jbyteArray output = (*env)->NewByteArray(env, curve->size);
jbyte *output_data = (*env)->GetByteArrayElements(env, output, NULL);
- memcpy(output_data, result, pub_half);
+ memcpy(output_data, result, curve->size);
(*env)->ReleaseByteArrayElements(env, output, output_data, JNI_COMMIT);
+ ltc_cleanup_multi(&pub.pubkey.x, &pub.pubkey.y, &pub.pubkey.z, &priv.k, NULL);
free(curve);
return output;
} \ No newline at end of file