@@ -1,10 +1,178 @@ | |||||
package com.jd.blockchain.crypto.utils.classic; | package com.jd.blockchain.crypto.utils.classic; | ||||
import org.bouncycastle.asn1.sec.SECNamedCurves; | |||||
import org.bouncycastle.asn1.x9.X9ECParameters; | |||||
import org.bouncycastle.crypto.AsymmetricCipherKeyPair; | |||||
import org.bouncycastle.crypto.CipherParameters; | |||||
import org.bouncycastle.crypto.generators.ECKeyPairGenerator; | |||||
import org.bouncycastle.crypto.params.*; | |||||
import org.bouncycastle.crypto.signers.ECDSASigner; | |||||
import org.bouncycastle.math.ec.ECCurve; | |||||
import org.bouncycastle.math.ec.ECMultiplier; | |||||
import org.bouncycastle.math.ec.ECPoint; | |||||
import org.bouncycastle.math.ec.FixedPointCombMultiplier; | |||||
import java.math.BigInteger; | |||||
import java.security.SecureRandom; | |||||
/** | /** | ||||
* @author zhanglin33 | * @author zhanglin33 | ||||
* @title: ECDSAUtils | * @title: ECDSAUtils | ||||
* @description: ECDSA signature algorithm | |||||
* @description: ECDSA signature algorithm based on Curve secp256k1 with SHA256 | |||||
* @date 2019-03-25, 17:21 | * @date 2019-03-25, 17:21 | ||||
*/ | */ | ||||
public class ECDSAUtils { | public class ECDSAUtils { | ||||
private static final int R_SIZE =32; | |||||
private static final int S_SIZE =32; | |||||
// p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1 | |||||
// the curve equation is y^2 = x^3 + 7. | |||||
private static final X9ECParameters X9_PARAMS = SECNamedCurves.getByName("secp256k1"); | |||||
private static final ECCurve CURVE = X9_PARAMS.getCurve(); | |||||
private static final ECPoint ECDSA_G = X9_PARAMS.getG(); | |||||
private static final BigInteger ECDSA_H = X9_PARAMS.getH(); | |||||
private static final BigInteger ECDSA_N = X9_PARAMS.getN(); | |||||
private static final ECDomainParameters DOMAIN_PARAMS = new ECDomainParameters(CURVE, ECDSA_G,ECDSA_N,ECDSA_H); | |||||
//-----------------Key Generation Algorithm----------------- | |||||
/** | |||||
* key generation | |||||
* | |||||
* @return key pair | |||||
*/ | |||||
public static AsymmetricCipherKeyPair generateKeyPair(){ | |||||
SecureRandom random = new SecureRandom(); | |||||
return generateKeyPair(random); | |||||
} | |||||
public static AsymmetricCipherKeyPair generateKeyPair(SecureRandom random){ | |||||
ECKeyGenerationParameters keyGenerationParams = new ECKeyGenerationParameters(DOMAIN_PARAMS,random); | |||||
ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator(); | |||||
// To generate the key pair | |||||
keyPairGenerator.init(keyGenerationParams); | |||||
return keyPairGenerator.generateKeyPair(); | |||||
} | |||||
/** | |||||
* public key 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); | |||||
} | |||||
//-----------------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){ | |||||
SecureRandom random = new SecureRandom(); | |||||
ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(new BigInteger(1,privateKey), DOMAIN_PARAMS); | |||||
CipherParameters params = new ParametersWithRandom(privKey,random); | |||||
return sign(data,params); | |||||
} | |||||
public static byte[] sign(byte[] data, byte[] privateKey, SecureRandom random, String ID){ | |||||
ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(new BigInteger(1,privateKey), DOMAIN_PARAMS); | |||||
CipherParameters params = new ParametersWithID(new ParametersWithRandom(privKey,random),ID.getBytes()); | |||||
return sign(data,params); | |||||
} | |||||
public static byte[] sign(byte[] data, CipherParameters params){ | |||||
byte[] hashedMsg = SHA256Utils.hash(data); | |||||
ECDSASigner signer = new ECDSASigner(); | |||||
signer.init(true, params); | |||||
BigInteger[] signature = signer.generateSignature(hashedMsg); | |||||
// // To decode the signature | |||||
// ASN1Sequence sig = ASN1Sequence.getInstance(encodedSignature); | |||||
// byte[] rBytes = BigIntegerTo32Bytes(ASN1Integer.getInstance(sig.getObjectAt(0)).getValue()); | |||||
// byte[] sBytes = BigIntegerTo32Bytes(ASN1Integer.getInstance(sig.getObjectAt(1)).getValue()); | |||||
byte[] rBytes = BigIntegerTo32Bytes(signature[0]); | |||||
byte[] sBytes = BigIntegerTo32Bytes(signature[1]); | |||||
byte[] result = new byte[R_SIZE + S_SIZE]; | |||||
System.arraycopy(rBytes,0,result,0,R_SIZE); | |||||
System.arraycopy(sBytes,0,result,R_SIZE,S_SIZE); | |||||
return result; | |||||
} | |||||
/** | |||||
* 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){ | |||||
ECPoint pubKeyPoint = resolvePubKeyBytes(publicKey); | |||||
ECPublicKeyParameters pubKey = new ECPublicKeyParameters(pubKeyPoint, DOMAIN_PARAMS); | |||||
return verify(data,pubKey,signature); | |||||
} | |||||
public static boolean verify(byte[] data, CipherParameters params, byte[] signature){ | |||||
byte[] hashedMsg = SHA256Utils.hash(data); | |||||
byte[] rBytes = new byte[R_SIZE]; | |||||
byte[] sBytes = new byte[S_SIZE]; | |||||
System.arraycopy(signature,0,rBytes,0,R_SIZE); | |||||
System.arraycopy(signature,R_SIZE,sBytes,0,S_SIZE); | |||||
BigInteger r = new BigInteger(1,rBytes); | |||||
BigInteger s = new BigInteger(1,sBytes); | |||||
ECDSASigner verifier = new ECDSASigner(); | |||||
verifier.init(false,params); | |||||
return verifier.verifySignature(hashedMsg,r,s); | |||||
} | |||||
// To convert BigInteger to byte[] whose length is 32 | |||||
private static byte[] BigIntegerTo32Bytes(BigInteger b){ | |||||
byte[] tmp = b.toByteArray(); | |||||
byte[] result = new byte[32]; | |||||
if (tmp.length > result.length) { | |||||
System.arraycopy(tmp, tmp.length - result.length, result, 0, result.length); | |||||
} | |||||
else { | |||||
System.arraycopy(tmp,0,result,result.length-tmp.length,tmp.length); | |||||
} | |||||
return result; | |||||
} | |||||
// To retrieve the public key point from publicKey in byte array mode | |||||
private static ECPoint resolvePubKeyBytes(byte[] publicKey){ | |||||
return CURVE.decodePoint(publicKey); | |||||
} | |||||
public static ECCurve getCurve(){return CURVE;} | |||||
public static ECDomainParameters getDomainParams(){return DOMAIN_PARAMS;} | |||||
} | } |
@@ -18,10 +18,10 @@ import java.security.SecureRandom; | |||||
*/ | */ | ||||
public class ED25519Utils { | public class ED25519Utils { | ||||
//-----------------Key Pair Generation Algorithm----------------- | |||||
//-----------------Key Generation Algorithm----------------- | |||||
/** | /** | ||||
* key generation | |||||
* key pair generation | |||||
* | * | ||||
* @return key pair | * @return key pair | ||||
*/ | */ | ||||
@@ -37,7 +37,7 @@ public class ED25519Utils { | |||||
} | } | ||||
/** | /** | ||||
* public retrieval | |||||
* public key retrieval | |||||
* | * | ||||
* @param privateKey private key | * @param privateKey private key | ||||
* @return publicKey | * @return publicKey | ||||
@@ -0,0 +1,25 @@ | |||||
package com.jd.blockchain.crypto.utils.classic; | |||||
import org.bouncycastle.crypto.digests.SHA256Digest; | |||||
/** | |||||
* @author zhanglin33 | |||||
* @title: SHA256Utils | |||||
* @description: SHA256 hash algorithm | |||||
* @date 2019-04-09, 14:28 | |||||
*/ | |||||
public class SHA256Utils { | |||||
// The length of SHA256 output is 32 bytes | |||||
private static final int SHA256DIGEST_LENGTH = 256 / 8; | |||||
public static byte[] hash(byte[] data){ | |||||
byte[] result = new byte[SHA256DIGEST_LENGTH]; | |||||
SHA256Digest sha256Digest = new SHA256Digest(); | |||||
sha256Digest.update(data,0,data.length); | |||||
sha256Digest.doFinal(result,0); | |||||
return result; | |||||
} | |||||
} |
@@ -0,0 +1,127 @@ | |||||
package test.com.jd.blockchain.crypto.utils.classic; | |||||
import com.jd.blockchain.crypto.utils.classic.ECDSAUtils; | |||||
import org.bouncycastle.crypto.AsymmetricCipherKeyPair; | |||||
import org.bouncycastle.crypto.params.ECDomainParameters; | |||||
import org.bouncycastle.crypto.params.ECPrivateKeyParameters; | |||||
import org.bouncycastle.crypto.params.ECPublicKeyParameters; | |||||
import org.bouncycastle.math.ec.ECMultiplier; | |||||
import org.bouncycastle.math.ec.ECPoint; | |||||
import org.bouncycastle.math.ec.FixedPointCombMultiplier; | |||||
import org.bouncycastle.util.encoders.Hex; | |||||
import org.junit.Test; | |||||
import java.math.BigInteger; | |||||
import java.util.Random; | |||||
import static org.junit.Assert.*; | |||||
/** | |||||
* @author zhanglin33 | |||||
* @title: ECDSAUtilsTest | |||||
* @description: Tests for methods in ECDSAUtils | |||||
* @date 2019-04-09, 14:58 | |||||
*/ | |||||
public class ECDSAUtilsTest { | |||||
@Test | |||||
public void generateKeyPairTest(){ | |||||
AsymmetricCipherKeyPair keyPair = ECDSAUtils.generateKeyPair(); | |||||
ECPrivateKeyParameters privKeyParams = (ECPrivateKeyParameters) keyPair.getPrivate(); | |||||
ECPublicKeyParameters pubKeyParams = (ECPublicKeyParameters) keyPair.getPublic(); | |||||
byte[] privKeyBytes = BigIntegerTo32Bytes(privKeyParams.getD()); | |||||
byte[] pubKeyBytes = pubKeyParams.getQ().getEncoded(false); | |||||
assertEquals(32,privKeyBytes.length); | |||||
assertEquals(65,pubKeyBytes.length); | |||||
} | |||||
@Test | |||||
public void retrievePublicKeyTest(){ | |||||
AsymmetricCipherKeyPair keyPair = ECDSAUtils.generateKeyPair(); | |||||
ECPrivateKeyParameters privKeyParams = (ECPrivateKeyParameters) keyPair.getPrivate(); | |||||
ECPublicKeyParameters pubKeyParams = (ECPublicKeyParameters) keyPair.getPublic(); | |||||
byte[] privKeyBytes = BigIntegerTo32Bytes(privKeyParams.getD()); | |||||
byte[] pubKeyBytes = pubKeyParams.getQ().getEncoded(false); | |||||
byte[] retrievedPubKeyBytes = ECDSAUtils.retrievePublicKey(privKeyBytes); | |||||
assertArrayEquals(pubKeyBytes,retrievedPubKeyBytes); | |||||
} | |||||
@Test | |||||
public void signTest(){ | |||||
AsymmetricCipherKeyPair keyPair = ECDSAUtils.generateKeyPair(); | |||||
ECPrivateKeyParameters privKeyParams = (ECPrivateKeyParameters) keyPair.getPrivate(); | |||||
byte[] privKeyBytes = BigIntegerTo32Bytes(privKeyParams.getD()); | |||||
Random random = new Random(); | |||||
byte[] data = new byte[1024]; | |||||
random.nextBytes(data); | |||||
byte[] signatureDigestFromBytes = ECDSAUtils.sign(data,privKeyBytes); | |||||
byte[] signatureDigestFromParams = ECDSAUtils.sign(data,privKeyBytes); | |||||
assertEquals(64,signatureDigestFromParams.length); | |||||
assertEquals(64,signatureDigestFromBytes.length); | |||||
} | |||||
@Test | |||||
public void verifyTest(){ | |||||
AsymmetricCipherKeyPair keyPair = ECDSAUtils.generateKeyPair(); | |||||
ECPrivateKeyParameters privKeyParams = (ECPrivateKeyParameters) keyPair.getPrivate(); | |||||
ECPublicKeyParameters pubKeyParams = (ECPublicKeyParameters) keyPair.getPublic(); | |||||
byte[] pubKeyBytes = pubKeyParams.getQ().getEncoded(false); | |||||
Random random = new Random(); | |||||
byte[] data = new byte[1024]; | |||||
random.nextBytes(data); | |||||
byte[] signatureDigest = ECDSAUtils.sign(data,privKeyParams); | |||||
assertTrue(ECDSAUtils.verify(data,pubKeyParams,signatureDigest)); | |||||
assertTrue(ECDSAUtils.verify(data,pubKeyBytes,signatureDigest)); | |||||
} | |||||
@Test | |||||
public void checkParams(){ | |||||
// https://crypto.stackexchange.com/questions/784/are-there-any-secp256k1-ecdsa-test-examples-available | |||||
ECDomainParameters params = ECDSAUtils.getDomainParams(); | |||||
ECPoint ECDSA_G = params.getG(); | |||||
BigInteger scalar = new BigInteger("AA5E28D6A97A2479A65527F7290311A3624D4CC0FA1578598EE3C2613BF99522",16); | |||||
String xCoord = "34F9460F0E4F08393D192B3C5133A6BA099AA0AD9FD54EBCCFACDFA239FF49C6"; | |||||
String yCoord = "0B71EA9BD730FD8923F6D25A7A91E7DD7728A960686CB5A901BB419E0F2CA232"; | |||||
ECMultiplier createBasePointMultiplier = new FixedPointCombMultiplier(); | |||||
ECPoint point = createBasePointMultiplier.multiply(ECDSA_G,scalar).normalize(); | |||||
byte[] result = point.getEncoded(false); | |||||
assertEquals("04" + xCoord + yCoord,Hex.toHexString(result).toUpperCase()); | |||||
} | |||||
// To convert BigInteger to byte[] whose length is 32 | |||||
private static byte[] BigIntegerTo32Bytes(BigInteger b){ | |||||
byte[] tmp = b.toByteArray(); | |||||
byte[] result = new byte[32]; | |||||
if (tmp.length > result.length) { | |||||
System.arraycopy(tmp, tmp.length - result.length, result, 0, result.length); | |||||
} | |||||
else { | |||||
System.arraycopy(tmp,0,result,result.length-tmp.length,tmp.length); | |||||
} | |||||
return result; | |||||
} | |||||
} |
@@ -0,0 +1,36 @@ | |||||
package test.com.jd.blockchain.crypto.utils.classic; | |||||
import com.jd.blockchain.crypto.utils.classic.SHA256Utils; | |||||
import org.bouncycastle.util.encoders.Hex; | |||||
import org.junit.Test; | |||||
import static org.junit.Assert.assertEquals; | |||||
/** | |||||
* @author zhanglin33 | |||||
* @title: SHA256UtilsTest | |||||
* @description: Tests for the hash method in ECDSAUtils | |||||
* @date 2019-04-09, 16:18 | |||||
*/ | |||||
public class SHA256UtilsTest { | |||||
@Test | |||||
public void hashTest() { | |||||
byte[] data1 = "abc".getBytes(); | |||||
byte[] data2 = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".getBytes(); | |||||
byte[] data3 = "aaaaaaaaaa".getBytes(); | |||||
byte[] result1 = SHA256Utils.hash(data1); | |||||
byte[] result2 = SHA256Utils.hash(data2); | |||||
byte[] result3 = SHA256Utils.hash(data3); | |||||
String respectedResult1 = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"; | |||||
String respectedResult2 = "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"; | |||||
String respectedResult3 = "bf2cb58a68f684d95a3b78ef8f661c9a4e5b09e82cc8f9cc88cce90528caeb27"; | |||||
assertEquals(respectedResult1,Hex.toHexString(result1)); | |||||
assertEquals(respectedResult2,Hex.toHexString(result2)); | |||||
assertEquals(respectedResult3,Hex.toHexString(result3)); | |||||
} | |||||
} |
@@ -43,15 +43,14 @@ public class SM2Utils { | |||||
private static final ECDomainParameters DOMAIN_PARAMS = new ECDomainParameters(CURVE, G, SM2_N); | private static final ECDomainParameters DOMAIN_PARAMS = new ECDomainParameters(CURVE, G, SM2_N); | ||||
//-----------------Key Pair Generation Algorithm----------------- | |||||
//-----------------Key Generation Algorithm----------------- | |||||
/** | /** | ||||
* key generation | |||||
* key pair generation | |||||
* | * | ||||
* @return key pair | * @return key pair | ||||
*/ | */ | ||||
public static AsymmetricCipherKeyPair generateKeyPair(){ | public static AsymmetricCipherKeyPair generateKeyPair(){ | ||||
SecureRandom random = new SecureRandom(); | SecureRandom random = new SecureRandom(); | ||||
return generateKeyPair(random); | return generateKeyPair(random); | ||||
} | } | ||||
@@ -67,7 +66,7 @@ public class SM2Utils { | |||||
} | } | ||||
/** | /** | ||||
* public retrieval | |||||
* public key retrieval | |||||
* | * | ||||
* @param privateKey private key | * @param privateKey private key | ||||
* @return publicKey | * @return publicKey | ||||
@@ -81,7 +80,6 @@ public class SM2Utils { | |||||
//-----------------Digital Signature Algorithm----------------- | //-----------------Digital Signature Algorithm----------------- | ||||
/** | /** | ||||
* signature generation | * signature generation | ||||
* | * | ||||
@@ -93,17 +91,17 @@ public class SM2Utils { | |||||
SecureRandom random = new SecureRandom(); | SecureRandom random = new SecureRandom(); | ||||
ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(new BigInteger(1,privateKey), DOMAIN_PARAMS); | ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(new BigInteger(1,privateKey), DOMAIN_PARAMS); | ||||
CipherParameters param = new ParametersWithRandom(privKey,random); | |||||
CipherParameters params = new ParametersWithRandom(privKey,random); | |||||
return sign(data,param); | |||||
return sign(data,params); | |||||
} | } | ||||
public static byte[] sign(byte[] data, byte[] privateKey, SecureRandom random, String ID){ | public static byte[] sign(byte[] data, byte[] privateKey, SecureRandom random, String ID){ | ||||
ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(new BigInteger(1,privateKey), DOMAIN_PARAMS); | ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(new BigInteger(1,privateKey), DOMAIN_PARAMS); | ||||
CipherParameters param = new ParametersWithID(new ParametersWithRandom(privKey,random),ID.getBytes()); | |||||
CipherParameters params = new ParametersWithID(new ParametersWithRandom(privKey,random),ID.getBytes()); | |||||
return sign(data,param); | |||||
return sign(data,params); | |||||
} | } | ||||
public static byte[] sign(byte[] data, CipherParameters params){ | public static byte[] sign(byte[] data, CipherParameters params){ | ||||
@@ -155,18 +153,18 @@ public class SM2Utils { | |||||
ECPoint pubKeyPoint = resolvePubKeyBytes(publicKey); | ECPoint pubKeyPoint = resolvePubKeyBytes(publicKey); | ||||
ECPublicKeyParameters pubKey = new ECPublicKeyParameters(pubKeyPoint, DOMAIN_PARAMS); | ECPublicKeyParameters pubKey = new ECPublicKeyParameters(pubKeyPoint, DOMAIN_PARAMS); | ||||
ParametersWithID param = new ParametersWithID(pubKey,ID.getBytes()); | |||||
ParametersWithID params = new ParametersWithID(pubKey,ID.getBytes()); | |||||
return verify(data,param,signature); | |||||
return verify(data,params,signature); | |||||
} | } | ||||
public static boolean verify(byte[] data, CipherParameters param, byte[] signature){ | |||||
public static boolean verify(byte[] data, CipherParameters params, byte[] signature){ | |||||
SM2Signer verifier = new SM2Signer(); | SM2Signer verifier = new SM2Signer(); | ||||
// To get Z_A and prepare parameters | // To get Z_A and prepare parameters | ||||
verifier.init(false,param); | |||||
verifier.init(false,params); | |||||
// To fill the whole message | // To fill the whole message | ||||
verifier.update(data,0,data.length); | verifier.update(data,0,data.length); | ||||
// To verify the signature | // To verify the signature | ||||
@@ -211,25 +209,25 @@ public class SM2Utils { | |||||
ECPoint pubKeyPoint = resolvePubKeyBytes(publicKey); | ECPoint pubKeyPoint = resolvePubKeyBytes(publicKey); | ||||
ECPublicKeyParameters pubKey = new ECPublicKeyParameters(pubKeyPoint, DOMAIN_PARAMS); | ECPublicKeyParameters pubKey = new ECPublicKeyParameters(pubKeyPoint, DOMAIN_PARAMS); | ||||
ParametersWithRandom param = new ParametersWithRandom(pubKey,random); | |||||
ParametersWithRandom params = new ParametersWithRandom(pubKey,random); | |||||
return encrypt(plainBytes,param); | |||||
return encrypt(plainBytes,params); | |||||
} | } | ||||
public static byte[] encrypt(byte[] plainBytes, ECPublicKeyParameters pubKey){ | public static byte[] encrypt(byte[] plainBytes, ECPublicKeyParameters pubKey){ | ||||
SecureRandom random = new SecureRandom(); | SecureRandom random = new SecureRandom(); | ||||
ParametersWithRandom param = new ParametersWithRandom(pubKey,random); | |||||
ParametersWithRandom params = new ParametersWithRandom(pubKey,random); | |||||
return encrypt(plainBytes,param); | |||||
return encrypt(plainBytes,params); | |||||
} | } | ||||
public static byte[] encrypt(byte[] plainBytes, CipherParameters param){ | |||||
public static byte[] encrypt(byte[] plainBytes, CipherParameters params){ | |||||
SM2Engine encryptor = new SM2Engine(); | SM2Engine encryptor = new SM2Engine(); | ||||
// To prepare parameters | // To prepare parameters | ||||
encryptor.init(true,param); | |||||
encryptor.init(true,params); | |||||
// To generate the twisted ciphertext c1c2c3. | // To generate the twisted ciphertext c1c2c3. | ||||
// The latest standard specification indicates that the correct ordering is c1c3c2 | // The latest standard specification indicates that the correct ordering is c1c3c2 | ||||
@@ -263,12 +261,12 @@ public class SM2Utils { | |||||
return decrypt(cipherBytes,privKey); | return decrypt(cipherBytes,privKey); | ||||
} | } | ||||
public static byte[] decrypt(byte[] cipherBytes, CipherParameters param){ | |||||
public static byte[] decrypt(byte[] cipherBytes, CipherParameters params){ | |||||
SM2Engine decryptor = new SM2Engine(); | SM2Engine decryptor = new SM2Engine(); | ||||
// To prepare parameters | // To prepare parameters | ||||
decryptor.init(false,param); | |||||
decryptor.init(false,params); | |||||
// To get c1c2c3 from ciphertext whose ordering is c1c3c2 | // To get c1c2c3 from ciphertext whose ordering is c1c3c2 | ||||
byte[] c1c2c3 = new byte[cipherBytes.length]; | byte[] c1c2c3 = new byte[cipherBytes.length]; | ||||