diff options
| author | J08nY | 2017-11-30 19:42:20 +0100 |
|---|---|---|
| committer | J08nY | 2017-11-30 19:42:20 +0100 |
| commit | d571f404e51356239cdb7d23de95074b271016e1 (patch) | |
| tree | a2ebd05f05cb3dd10376aa22534850be0324fe4d /src | |
| parent | 715dd7f068dfc9e5b90ce0c1e2d3aad0a9fe982a (diff) | |
| download | ECTester-d571f404e51356239cdb7d23de95074b271016e1.tar.gz ECTester-d571f404e51356239cdb7d23de95074b271016e1.tar.zst ECTester-d571f404e51356239cdb7d23de95074b271016e1.zip | |
Diffstat (limited to 'src')
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(<c_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 |
