aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJ08nY2017-11-30 23:57:09 +0100
committerJ08nY2017-11-30 23:57:09 +0100
commitc33faeed138b3cbb0324878fa24481916791ec50 (patch)
tree4e1ec7d79ba0bfa4b8af41b235af00c1c3aa6a0a
parentd571f404e51356239cdb7d23de95074b271016e1 (diff)
downloadECTester-c33faeed138b3cbb0324878fa24481916791ec50.tar.gz
ECTester-c33faeed138b3cbb0324878fa24481916791ec50.tar.zst
ECTester-c33faeed138b3cbb0324878fa24481916791ec50.zip
-rw-r--r--build-standalone.xml1
-rw-r--r--src/cz/crcs/ectester/standalone/ECTesterStandalone.java6
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java4
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java57
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/native.h27
-rw-r--r--src/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c135
6 files changed, 188 insertions, 42 deletions
diff --git a/build-standalone.xml b/build-standalone.xml
index 8098ce2..ef6ab2a 100644
--- a/build-standalone.xml
+++ b/build-standalone.xml
@@ -101,6 +101,7 @@
<class name="cz.crcs.ectester.standalone.libs.jni.NativeECPublicKey$TomCrypt"/>
<class name="cz.crcs.ectester.standalone.libs.jni.NativeECPrivateKey$TomCrypt"/>
<class name="cz.crcs.ectester.standalone.libs.jni.NativeKeyAgreementSpi$TomCrypt"/>
+ <class name="cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$TomCryptRaw"/>
</javah>
</target>
</project>
diff --git a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
index 3ad7141..5ecff9b 100644
--- a/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
+++ b/src/cz/crcs/ectester/standalone/ECTesterStandalone.java
@@ -116,6 +116,8 @@ public class ECTesterStandalone {
Options ecdsaOpts = new Options();
ecdsaOpts.addOption(Option.builder("t").longOpt("type").desc("Set Signature object [type].").hasArg().argName("type").optionalArg(false).build());
ecdsaOpts.addOption(Option.builder("n").longOpt("amount").hasArg().argName("amount").optionalArg(false).desc("Do ECDSA [amount] times.").build());
+ ecdsaOpts.addOption(Option.builder("b").longOpt("bits").hasArg().argName("n").optionalArg(false).desc("What size of curve to use.").build());
+ ecdsaOpts.addOption(Option.builder("nc").longOpt("named-curve").desc("Use a named curve, from CurveDB: <cat/id>").hasArg().argName("cat/id").build());
ecdsaOpts.addOption(Option.builder("f").longOpt("file").hasArg().argName("file").optionalArg(false).desc("Input [file] to sign.").build());
ParserOptions ecdsa = new ParserOptions(new DefaultParser(), ecdsaOpts);
actions.put("ecdsa", ecdsa);
@@ -271,7 +273,7 @@ public class ECTesterStandalone {
dataString = "";
} else {
SecureRandom random = new SecureRandom();
- data = new byte[128];
+ data = new byte[32];
random.nextBytes(data);
dataString = ByteUtil.bytesToHex(data, false);
}
@@ -449,7 +451,7 @@ public class ECTesterStandalone {
}
boolean readOptions(TreeCommandLine cli) {
- if (cli.isNext("generate") || cli.isNext("export") || cli.isNext("ecdh")) {
+ if (cli.isNext("generate") || cli.isNext("export") || cli.isNext("ecdh") || cli.isNext("ecdsa")) {
if (!cli.hasArg(-1)) {
System.err.println("Missing library name argument.");
return false;
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java
index 47eeabd..913f73e 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeKeyAgreementSpi.java
@@ -23,7 +23,7 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi {
protected void engineInit(Key key, SecureRandom random) throws InvalidKeyException {
if (!(key instanceof ECPrivateKey)) {
throw new InvalidKeyException
- ("Key must be instance of PrivateKey");
+ ("Key must be instance of ECPrivateKey");
}
privateKey = (ECPrivateKey) key;
this.params = privateKey.getParams();
@@ -52,7 +52,7 @@ public abstract class NativeKeyAgreementSpi extends KeyAgreementSpi {
}
if (!(key instanceof ECPublicKey)) {
throw new InvalidKeyException
- ("Key must be a PublicKey with algorithm EC");
+ ("Key must be an instance of ECPublicKey");
}
ECParameterSpec publicParams = ((ECPublicKey) key).getParams();
if (!(params.getCurve().equals(publicParams.getCurve()) &&
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java b/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java
index 0c6332e..a9ec8a6 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java
+++ b/src/cz/crcs/ectester/standalone/libs/jni/NativeSignatureSpi.java
@@ -1,49 +1,86 @@
package cz.crcs.ectester.standalone.libs.jni;
+import cz.crcs.ectester.common.util.ECUtil;
+
+import java.io.ByteArrayOutputStream;
import java.security.*;
+import java.security.interfaces.ECPrivateKey;
+import java.security.interfaces.ECPublicKey;
+import java.security.spec.ECParameterSpec;
+/**
+ * @author Jan Jancar johny@neuromancer.sk
+ */
public abstract class NativeSignatureSpi extends SignatureSpi {
+ private ECPublicKey verifyKey;
+ private ECPrivateKey signKey;
+ private ECParameterSpec params;
+
+ private ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+
@Override
protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException {
-
+ if (!(publicKey instanceof ECPublicKey)) {
+ throw new InvalidKeyException
+ ("Key must be an instance of ECPublicKey");
+ }
+ verifyKey = (ECPublicKey) publicKey;
+ params = verifyKey.getParams();
+ buffer.reset();
}
@Override
protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException {
-
+ if (!(privateKey instanceof ECPrivateKey)) {
+ throw new InvalidKeyException
+ ("Key must be an instance of ECPrivateKey");
+ }
+ signKey = (ECPrivateKey) privateKey;
+ params = signKey.getParams();
+ buffer.reset();
}
@Override
protected void engineUpdate(byte b) throws SignatureException {
-
+ buffer.write(b);
}
@Override
protected void engineUpdate(byte[] b, int off, int len) throws SignatureException {
-
+ buffer.write(b, off, len);
}
@Override
protected byte[] engineSign() throws SignatureException {
- return new byte[0];
+ return sign(buffer.toByteArray(), ECUtil.toByteArray(signKey.getS(), params.getCurve().getField().getFieldSize()), params);
}
@Override
protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
- return false;
+ return verify(sigBytes, buffer.toByteArray(), ECUtil.toX962Uncompressed(verifyKey.getW(), params), params);
}
@Override
protected void engineSetParameter(String param, Object value) throws InvalidParameterException {
-
+ throw new UnsupportedOperationException("setParameter() not supported");
}
@Override
protected Object engineGetParameter(String param) throws InvalidParameterException {
- return null;
+ throw new UnsupportedOperationException("getParameter() not supported");
}
- public static class TomCrypt extends NativeSignatureSpi {
-
+ abstract byte[] sign(byte[] data, byte[] privkey, ECParameterSpec params);
+
+ abstract boolean verify(byte[] signature, byte[] data, byte[] pubkey, ECParameterSpec params);
+
+ public static class TomCryptRaw extends NativeSignatureSpi {
+
+ @Override
+ native byte[] sign(byte[] data, byte[] privkey, ECParameterSpec params);
+
+ @Override
+ native boolean verify(byte[] signature, byte[] data, byte[] pubkey, ECParameterSpec params);
+
}
}
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/native.h b/src/cz/crcs/ectester/standalone/libs/jni/native.h
index 7f63f61..852dd53 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/native.h
+++ b/src/cz/crcs/ectester/standalone/libs/jni/native.h
@@ -144,3 +144,30 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey
}
#endif
#endif
+/* Header for class cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw */
+
+#ifndef _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw
+#define _Included_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw
+ * Method: sign
+ * Signature: ([B[BLjava/security/spec/ECParameterSpec;)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024TomCryptRaw_sign
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jobject);
+
+/*
+ * Class: cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_TomCryptRaw
+ * Method: verify
+ * Signature: ([B[B[BLjava/security/spec/ECParameterSpec;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024TomCryptRaw_verify
+ (JNIEnv *, jobject, jbyteArray, jbyteArray, jbyteArray, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c b/src/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c
index d32c6a6..629ffc1 100644
--- a/src/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c
+++ b/src/cz/crcs/ectester/standalone/libs/jni/tomcrypt.c
@@ -45,8 +45,8 @@ JNIEXPORT void JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeProvider_
jstring ecdh_value = (*env)->NewStringUTF(env, "cz.crcs.ectester.standalone.libs.jni.NativeKeyAgreementSpi$TomCrypt");
(*env)->CallObjectMethod(env, this, provider_put, ecdh, ecdh_value);
- jstring ecdsa = (*env)->NewStringUTF(env, "Signature.ECDSA");
- jstring ecdsa_value = (*env)->NewStringUTF(env, "cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$TomCrypt");
+ jstring ecdsa = (*env)->NewStringUTF(env, "Signature.NONEwithECDSA");
+ jstring ecdsa_value = (*env)->NewStringUTF(env, "cz.crcs.ectester.standalone.libs.jni.NativeSignatureSpi$TomCryptRaw");
(*env)->CallObjectMethod(env, this, provider_put, ecdsa, ecdsa_value);
int err;
@@ -112,9 +112,10 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_TomcryptLib_getC
}
JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_keysizeSupported(JNIEnv *env, jobject this, jint keysize){
+ int key_bytes = (keysize + 7) / 8;
const ltc_ecc_set_type * curve = ltc_ecc_sets;
while (curve->size != 0) {
- if (curve->size * 8 == keysize) {
+ if (curve->size == key_bytes) {
return JNI_TRUE;
}
curve++;
@@ -309,7 +310,7 @@ static jobject generate_from_curve(JNIEnv *env, const ltc_ecc_set_type *curve) {
}
JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPairGeneratorSpi_00024TomCrypt_generate__ILjava_security_SecureRandom_2(JNIEnv *env, jobject this, jint keysize, jobject random){
- int key_bytes = keysize / 8;
+ int key_bytes = (keysize + 7) / 8;
const ltc_ecc_set_type *curve = ltc_ecc_sets;
while (curve->size != 0) {
@@ -351,49 +352,63 @@ JNIEXPORT jobject JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyPai
}
}
-JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024TomCrypt_generateSecret(JNIEnv *env, jobject this, jbyteArray pubkey, jbyteArray privkey, jobject params){
- ltc_ecc_set_type *curve = create_curve(env, params);
+static jboolean privkey_from_bytes(JNIEnv *env, jbyteArray privkey, const ltc_ecc_set_type *curve, ecc_key *out) {
+ 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);
+ return JNI_FALSE;
+ }
+
+ out->type = PK_PRIVATE;
+ out->idx = -1;
+ out->dp = curve;
+ ltc_mp.init(&out->k);
+ ltc_mp.unsigned_read(out->k, priv_data, (unsigned long) curve->size);
+
+ (*env)->ReleaseByteArrayElements(env, privkey, priv_data, JNI_ABORT);
+ return JNI_TRUE;
+}
+
+static jboolean pubkey_from_bytes(JNIEnv *env, jbyteArray pubkey, const ltc_ecc_set_type *curve, ecc_key *out) {
jsize pub_size = (*env)->GetArrayLength(env, pubkey);
jbyte *pub_data = (*env)->GetByteArrayElements(env, pubkey, NULL);
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;
+ return JNI_FALSE;
}
- ecc_key pub;
- pub.type = PK_PUBLIC;
- pub.idx = -1;
- 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) curve->size);
- ltc_mp.unsigned_read(pub.pubkey.y, pub_data + 1 + curve->size, (unsigned long) curve->size);
+ out->type = PK_PUBLIC;
+ out->idx = -1;
+ out->dp = curve;
+ ltc_init_multi(&out->pubkey.x, &out->pubkey.y, &out->pubkey.z, NULL);
+ ltc_mp.set_int(out->pubkey.z, 1);
+ ltc_mp.unsigned_read(out->pubkey.x, pub_data + 1, (unsigned long) curve->size);
+ ltc_mp.unsigned_read(out->pubkey.y, pub_data + 1 + curve->size, (unsigned long) curve->size);
(*env)->ReleaseByteArrayElements(env, pubkey, pub_data, JNI_ABORT);
+ return JNI_TRUE;
+}
- jsize priv_size = (*env)->GetArrayLength(env, privkey);
- jbyte *priv_data = (*env)->GetByteArrayElements(env, privkey, NULL);
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKeyAgreementSpi_00024TomCrypt_generateSecret(JNIEnv *env, jobject this, jbyteArray pubkey, jbyteArray privkey, jobject params){
+ ltc_ecc_set_type *curve = create_curve(env, params);
- 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);
+ ecc_key pub;
+ if (!pubkey_from_bytes(env, pubkey, curve, &pub)) {
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) curve->size);
-
- (*env)->ReleaseByteArrayElements(env, privkey, priv_data, JNI_ABORT);
+ if (!privkey_from_bytes(env, privkey, curve, &priv)) {
+ free(curve);
+ return NULL;
+ }
unsigned char result[curve->size];
unsigned long output_len = curve->size;
@@ -412,4 +427,68 @@ JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeKey
ltc_cleanup_multi(&pub.pubkey.x, &pub.pubkey.y, &pub.pubkey.z, &priv.k, NULL);
free(curve);
return output;
+}
+
+JNIEXPORT jbyteArray JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024TomCryptRaw_sign(JNIEnv *env, jobject this, jbyteArray data, jbyteArray privkey, jobject params) {
+ ltc_ecc_set_type *curve = create_curve(env, params);
+
+ ecc_key priv;
+ if (!privkey_from_bytes(env, privkey, curve, &priv)) {
+ free(curve);
+ return NULL;
+ }
+
+ jsize data_size = (*env)->GetArrayLength(env, data);
+ jbyte *data_data = (*env)->GetByteArrayElements(env, data, NULL);
+
+ unsigned char result[curve->size*4];
+ unsigned long output_len = curve->size*4;
+ int err;
+ if ((err = ecc_sign_hash(data_data, data_size, result, &output_len, &ltc_prng, find_prng("yarrow"), &priv)) != CRYPT_OK) {
+ throw_new(env, "java/security/GeneralSecurityException", error_to_string(err));
+ free(curve);
+ (*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT);
+ return NULL;
+ }
+
+ (*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT);
+
+ jbyteArray output = (*env)->NewByteArray(env, output_len);
+ jbyte *output_data = (*env)->GetByteArrayElements(env, output, NULL);
+ memcpy(output_data, result, output_len);
+ (*env)->ReleaseByteArrayElements(env, output, output_data, JNI_COMMIT);
+
+ free(curve);
+ return output;
+}
+
+JNIEXPORT jboolean JNICALL Java_cz_crcs_ectester_standalone_libs_jni_NativeSignatureSpi_00024TomCryptRaw_verify(JNIEnv *env, jobject this, jbyteArray signature, jbyteArray data, jbyteArray pubkey, jobject params) {
+ ltc_ecc_set_type *curve = create_curve(env, params);
+
+ ecc_key pub;
+ if (!pubkey_from_bytes(env, pubkey, curve, &pub)) {
+ free(curve);
+ return JNI_FALSE;
+ }
+
+ jsize data_size = (*env)->GetArrayLength(env, data);
+ jbyte *data_data = (*env)->GetByteArrayElements(env, data, NULL);
+
+ jsize sig_size = (*env)->GetArrayLength(env, signature);
+ jbyte *sig_data = (*env)->GetByteArrayElements(env, signature, NULL);
+
+ int err;
+ int result;
+ if ((err = ecc_verify_hash(sig_data, sig_size, data_data, data_size, &result, &pub)) != CRYPT_OK) {
+ throw_new(env, "java/security/GeneralSecurityException", error_to_string(err));
+ free(curve);
+ (*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT);
+ (*env)->ReleaseByteArrayElements(env, signature, sig_data, JNI_ABORT);
+ return JNI_FALSE;
+ }
+
+ (*env)->ReleaseByteArrayElements(env, data, data_data, JNI_ABORT);
+ (*env)->ReleaseByteArrayElements(env, signature, sig_data, JNI_ABORT);
+ free(curve);
+ return result;
} \ No newline at end of file