From a5f2706f43a13bd2195bf7d39117632362d90112 Mon Sep 17 00:00:00 2001 From: zhanglin33 Date: Mon, 8 Apr 2019 18:06:14 +0800 Subject: [PATCH] replace Ed25519Utils with ED25519Utils from BouncyCastle.jar --- .../classic/ED25519SignatureFunction.java | 44 ++++--- .../crypto/utils/classic/ED25519Utils.java | 81 +++++++++++++ .../utils/classic/ED25519UtilsTest.java | 111 ++++++++++++++++++ .../blockchain/crypto/utils/sm/SM2Utils.java | 14 ++- 4 files changed, 227 insertions(+), 23 deletions(-) create mode 100644 source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/ED25519UtilsTest.java diff --git a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/ED25519SignatureFunction.java b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/ED25519SignatureFunction.java index 3925e857..72039c2f 100644 --- a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/ED25519SignatureFunction.java +++ b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/service/classic/ED25519SignatureFunction.java @@ -5,8 +5,6 @@ import static com.jd.blockchain.crypto.CryptoBytes.ALGORYTHM_CODE_SIZE; import static com.jd.blockchain.crypto.CryptoKeyType.PRIVATE; import static com.jd.blockchain.crypto.CryptoKeyType.PUBLIC; -import java.security.KeyPair; - import com.jd.blockchain.crypto.CryptoAlgorithm; import com.jd.blockchain.crypto.CryptoException; import com.jd.blockchain.crypto.PrivKey; @@ -14,14 +12,11 @@ import com.jd.blockchain.crypto.PubKey; import com.jd.blockchain.crypto.asymmetric.CryptoKeyPair; import com.jd.blockchain.crypto.asymmetric.SignatureDigest; import com.jd.blockchain.crypto.asymmetric.SignatureFunction; -import com.jd.blockchain.utils.security.Ed25519Utils; +import com.jd.blockchain.crypto.utils.classic.ED25519Utils; -import net.i2p.crypto.eddsa.EdDSAPrivateKey; -import net.i2p.crypto.eddsa.EdDSAPublicKey; -import net.i2p.crypto.eddsa.KeyPairGenerator; -import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable; -import net.i2p.crypto.eddsa.spec.EdDSAParameterSpec; -import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec; +import org.bouncycastle.crypto.AsymmetricCipherKeyPair; +import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters; +import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters; public class ED25519SignatureFunction implements SignatureFunction { @@ -54,7 +49,9 @@ public class ED25519SignatureFunction implements SignatureFunction { } // 调用ED25519签名算法计算签名结果 - return new SignatureDigest(ED25519, Ed25519Utils.sign_512(data, rawPrivKeyBytes)); +// return new SignatureDigest(ED25519, Ed25519Utils.sign_512(data, rawPrivKeyBytes)); + return new SignatureDigest(ED25519, ED25519Utils.sign(data, rawPrivKeyBytes)); + } @Override @@ -79,15 +76,17 @@ public class ED25519SignatureFunction implements SignatureFunction { } // 调用ED25519验签算法验证签名结果 - return Ed25519Utils.verify(data, rawPubKeyBytes, rawDigestBytes); +// return Ed25519Utils.verify(data, rawPubKeyBytes, rawDigestBytes); + return ED25519Utils.verify(data, rawPubKeyBytes, rawDigestBytes); } @Override public PubKey retrievePubKey(PrivKey privKey) { byte[] rawPrivKeyBytes = privKey.getRawKeyBytes(); - EdDSAParameterSpec spec = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.CURVE_ED25519_SHA512); - EdDSAPrivateKeySpec privateKeySpec = new EdDSAPrivateKeySpec(rawPrivKeyBytes, spec); - byte[] rawPubKeyBytes = privateKeySpec.getA().toByteArray(); + byte[] rawPubKeyBytes = ED25519Utils.retrievePublicKey(rawPrivKeyBytes); +// EdDSAParameterSpec spec = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.CURVE_ED25519_SHA512); +// EdDSAPrivateKeySpec privateKeySpec = new EdDSAPrivateKeySpec(rawPrivKeyBytes, spec); +// byte[] rawPubKeyBytes = privateKeySpec.getA().toByteArray(); return new PubKey(ED25519, rawPubKeyBytes); } // @@ -157,11 +156,18 @@ public class ED25519SignatureFunction implements SignatureFunction { @Override public CryptoKeyPair generateKeyPair() { // 调用ED25519算法的密钥生成算法生成公私钥对priKey和pubKey,返回密钥对 - KeyPairGenerator keyPairGenerator = new KeyPairGenerator(); - KeyPair keyPair = keyPairGenerator.generateKeyPair(); - EdDSAPrivateKey privKey = (EdDSAPrivateKey) keyPair.getPrivate(); - EdDSAPublicKey pubKey = (EdDSAPublicKey) keyPair.getPublic(); - return new CryptoKeyPair(new PubKey(ED25519, pubKey.getAbyte()), new PrivKey(ED25519, privKey.getSeed())); + AsymmetricCipherKeyPair keyPair = ED25519Utils.generateKeyPair(); + Ed25519PrivateKeyParameters privKeyParams = (Ed25519PrivateKeyParameters) keyPair.getPrivate(); + Ed25519PublicKeyParameters pubKeyParams = (Ed25519PublicKeyParameters) keyPair.getPublic(); + + byte[] privKeyBytes = privKeyParams.getEncoded(); + byte[] pubKeyBytes = pubKeyParams.getEncoded(); +// KeyPairGenerator keyPairGenerator = new KeyPairGenerator(); +// KeyPair keyPair = keyPairGenerator.generateKeyPair(); +// EdDSAPrivateKey privKey = (EdDSAPrivateKey) keyPair.getPrivate(); +// EdDSAPublicKey pubKey = (EdDSAPublicKey) keyPair.getPublic(); +// return new CryptoKeyPair(new PubKey(ED25519, pubKey.getAbyte()), new PrivKey(ED25519, privKey.getSeed())); + return new CryptoKeyPair(new PubKey(ED25519, pubKeyBytes), new PrivKey(ED25519, privKeyBytes)); } } diff --git a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/ED25519Utils.java b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/ED25519Utils.java index 563ccd28..0545ecb7 100644 --- a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/ED25519Utils.java +++ b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/ED25519Utils.java @@ -1,5 +1,15 @@ package com.jd.blockchain.crypto.utils.classic; +import org.bouncycastle.crypto.AsymmetricCipherKeyPair; +import org.bouncycastle.crypto.CipherParameters; +import org.bouncycastle.crypto.generators.Ed25519KeyPairGenerator; +import org.bouncycastle.crypto.params.Ed25519KeyGenerationParameters; +import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters; +import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters; +import org.bouncycastle.crypto.signers.Ed25519Signer; + +import java.security.SecureRandom; + /** * @author zhanglin33 * @title: ED25519Utils @@ -7,4 +17,75 @@ package com.jd.blockchain.crypto.utils.classic; * @date 2019-04-04, 20:01 */ public class ED25519Utils { + + //-----------------Key Pair Generation Algorithm----------------- + + /** + * key generation + * + * @return key pair + */ + public static AsymmetricCipherKeyPair generateKeyPair(){ + SecureRandom random = new SecureRandom(); + return generateKeyPair(random); + } + + public static AsymmetricCipherKeyPair generateKeyPair(SecureRandom random){ + Ed25519KeyPairGenerator keyPairGenerator = new Ed25519KeyPairGenerator(); + keyPairGenerator.init(new Ed25519KeyGenerationParameters(random)); + return keyPairGenerator.generateKeyPair(); + } + + /** + * public retrieval + * + * @param privateKey private key + * @return publicKey + */ + public static byte[] retrievePublicKey(byte[] privateKey){ + Ed25519PrivateKeyParameters privKeyParams = new Ed25519PrivateKeyParameters(privateKey,0); + return privKeyParams.generatePublicKey().getEncoded(); + } + + + //-----------------Digital Signature Algorithm----------------- + + /** + * signature generation + * + * @param data data to be signed + * @param privateKey private key + * @return signature + */ + public static byte[] sign(byte[] data, byte[] privateKey){ + Ed25519PrivateKeyParameters privKeyParams = new Ed25519PrivateKeyParameters(privateKey,0); + return sign(data,privKeyParams); + } + + public static byte[] sign(byte[] data, CipherParameters params){ + Ed25519Signer signer = new Ed25519Signer(); + signer.init(true, params); + signer.update(data,0,data.length); + return signer.generateSignature(); + } + + /** + * verification + * + * @param data data to be signed + * @param publicKey public key + * @param signature signature to be verified + * @return true or false + */ + public static boolean verify(byte[] data, byte[] publicKey, byte[] signature){ + Ed25519PublicKeyParameters pubKeyParams = new Ed25519PublicKeyParameters(publicKey,0); + return verify(data,pubKeyParams,signature); + } + + public static boolean verify(byte[] data, CipherParameters params, byte[] signature){ + Ed25519Signer verifier = new Ed25519Signer(); + verifier.init(false, params); + verifier.update(data,0,data.length); + return verifier.verifySignature(signature); + } } diff --git a/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/ED25519UtilsTest.java b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/ED25519UtilsTest.java new file mode 100644 index 00000000..afbea883 --- /dev/null +++ b/source/crypto/crypto-classic/src/test/java/test/com/jd/blockchain/crypto/utils/classic/ED25519UtilsTest.java @@ -0,0 +1,111 @@ +package test.com.jd.blockchain.crypto.utils.classic; + +import com.jd.blockchain.crypto.utils.classic.ED25519Utils; +import com.jd.blockchain.utils.security.Ed25519Utils; +import org.bouncycastle.crypto.AsymmetricCipherKeyPair; +import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters; +import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters; +import org.junit.Test; + +import java.util.Random; + +import static org.junit.Assert.*; + +/** + * @author zhanglin33 + * @title: ED25519UtilsTest + * @description: Tests for methods in ED25519Utils + * @date 2019-04-08, 16:32 + */ +public class ED25519UtilsTest { + + @Test + public void generateKeyPairTest(){ + + AsymmetricCipherKeyPair keyPair = ED25519Utils.generateKeyPair(); + Ed25519PrivateKeyParameters privKeyParams = (Ed25519PrivateKeyParameters) keyPair.getPrivate(); + Ed25519PublicKeyParameters pubKeyParams = (Ed25519PublicKeyParameters) keyPair.getPublic(); + + byte[] privKeyBytes = privKeyParams.getEncoded(); + byte[] pubKeyBytes = pubKeyParams.getEncoded(); + + assertEquals(32,privKeyBytes.length); + assertEquals(32,pubKeyBytes.length); + } + + @Test + public void retrievePublicKeyTest(){ + + AsymmetricCipherKeyPair keyPair = ED25519Utils.generateKeyPair(); + Ed25519PrivateKeyParameters privKeyParams = (Ed25519PrivateKeyParameters) keyPair.getPrivate(); + Ed25519PublicKeyParameters pubKeyParams = (Ed25519PublicKeyParameters) keyPair.getPublic(); + + byte[] privKeyBytes = privKeyParams.getEncoded(); + byte[] pubKeyBytes = pubKeyParams.getEncoded(); + + byte[] retrievedPubKeyBytes = ED25519Utils.retrievePublicKey(privKeyBytes); + + assertArrayEquals(pubKeyBytes,retrievedPubKeyBytes); + } + + @Test + public void signTest(){ + + AsymmetricCipherKeyPair keyPair = ED25519Utils.generateKeyPair(); + Ed25519PrivateKeyParameters privKeyParams = (Ed25519PrivateKeyParameters) keyPair.getPrivate(); + + byte[] privKeyBytes = privKeyParams.getEncoded(); + + Random random = new Random(); + byte[] data = new byte[1024]; + random.nextBytes(data); + + byte[] signatureDigestFromBytes = ED25519Utils.sign(data,privKeyBytes); + byte[] signatureDigestFromParams = ED25519Utils.sign(data,privKeyBytes); + + assertArrayEquals(signatureDigestFromBytes,signatureDigestFromParams); + assertEquals(64,signatureDigestFromBytes.length); + } + + @Test + public void verifyTest(){ + + AsymmetricCipherKeyPair keyPair = ED25519Utils.generateKeyPair(); + Ed25519PrivateKeyParameters privKeyParams = (Ed25519PrivateKeyParameters) keyPair.getPrivate(); + Ed25519PublicKeyParameters pubKeyParams = (Ed25519PublicKeyParameters) keyPair.getPublic(); + + byte[] pubKeyBytes = pubKeyParams.getEncoded(); + + Random random = new Random(); + byte[] data = new byte[1024]; + random.nextBytes(data); + + byte[] signatureDigest = ED25519Utils.sign(data,privKeyParams); + + assertTrue(ED25519Utils.verify(data,pubKeyParams,signatureDigest)); + assertTrue(ED25519Utils.verify(data,pubKeyBytes,signatureDigest)); + } + + @Test + public void consistencyTest(){ + + AsymmetricCipherKeyPair keyPair = ED25519Utils.generateKeyPair(); + Ed25519PrivateKeyParameters privKeyParams = (Ed25519PrivateKeyParameters) keyPair.getPrivate(); + Ed25519PublicKeyParameters pubKeyParams = (Ed25519PublicKeyParameters) keyPair.getPublic(); + + byte[] pubKeyBytes = pubKeyParams.getEncoded(); + byte[] privKeyBytes = privKeyParams.getEncoded(); + + Random random = new Random(); + byte[] data = new byte[1024]; + random.nextBytes(data); + + byte[] signatureDigest = ED25519Utils.sign(data,privKeyParams); + + byte[] signatureDigestFromOlderVersion = Ed25519Utils.sign_512(data,privKeyBytes); + + assertArrayEquals(signatureDigest,signatureDigestFromOlderVersion); + assertTrue(Ed25519Utils.verify(data,pubKeyBytes,signatureDigest)); + + } +} diff --git a/source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/utils/sm/SM2Utils.java b/source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/utils/sm/SM2Utils.java index 2e16d553..bbf38772 100644 --- a/source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/utils/sm/SM2Utils.java +++ b/source/crypto/crypto-sm/src/main/java/com/jd/blockchain/crypto/utils/sm/SM2Utils.java @@ -68,8 +68,13 @@ public class SM2Utils { return keyPairGenerator.generateKeyPair(); } - public static byte[] retrievePublicKey(byte[] privateKey) - { + /** + * public retrieval + * + * @param privateKey private key + * @return publicKey + */ + public static byte[] retrievePublicKey(byte[] privateKey) { ECMultiplier createBasePointMultiplier = new FixedPointCombMultiplier(); ECPoint publicKeyPoint = createBasePointMultiplier.multiply(DOMAIN_PARAMS.getG(), new BigInteger(1,privateKey)).normalize(); return publicKeyPoint.getEncoded(false); @@ -103,12 +108,12 @@ public class SM2Utils { return sign(data,param); } - public static byte[] sign(byte[] data, CipherParameters param){ + public static byte[] sign(byte[] data, CipherParameters params){ SM2Signer signer = new SM2Signer(); // To get Z_A and prepare parameters - signer.init(true,param); + signer.init(true,params); // To fill the whole message to be signed signer.update(data,0,data.length); // To get and return the signature result; @@ -137,6 +142,7 @@ public class SM2Utils { * * @param data data to be signed * @param publicKey public key + * @param signature signature to be verified * @return true or false */ public static boolean verify(byte[] data, byte[] publicKey, byte[] signature){