package minsecurity.crypto.sm2; import org.bouncycastle.crypto.AsymmetricCipherKeyPair; import org.bouncycastle.crypto.generators.ECKeyPairGenerator; import org.bouncycastle.crypto.params.ECDomainParameters; import org.bouncycastle.crypto.params.ECKeyGenerationParameters; import org.bouncycastle.crypto.params.ECPrivateKeyParameters; import org.bouncycastle.crypto.params.ECPublicKeyParameters; import org.bouncycastle.crypto.util.PrivateKeyInfoFactory; import org.bouncycastle.crypto.util.SubjectPublicKeyInfoFactory; import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey; import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.jce.spec.ECParameterSpec; import org.bouncycastle.math.ec.ECPoint; import org.bouncycastle.math.ec.custom.gm.SM2P256V1Curve; import org.slf4j.LoggerFactory; import java.math.BigInteger; import java.security.*; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import static minsecurity.Common.ALGO_NAME_EC; /* * @Author: hongyu guo * @Description: SM2推荐曲线参数 * @Version: 1.0.0 * @Date: 18:48 2021/03/03 * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 */ public class SM2Base { static { Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); } private static final org.slf4j.Logger logger = LoggerFactory.getLogger(SM2Base.class); /* * 以下为SM2推荐曲线参数 */ public static final SM2P256V1Curve CURVE = new SM2P256V1Curve(); public final static BigInteger SM2_ECC_P = CURVE.getQ(); public final static BigInteger SM2_ECC_A = CURVE.getA().toBigInteger(); public final static BigInteger SM2_ECC_B = CURVE.getB().toBigInteger(); public final static BigInteger SM2_ECC_N = CURVE.getOrder(); public final static BigInteger SM2_ECC_H = CURVE.getCofactor(); public final static BigInteger SM2_ECC_GX = new BigInteger( "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", 16); public final static BigInteger SM2_ECC_GY = new BigInteger( "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", 16); public static final ECPoint G_POINT = CURVE.createPoint(SM2_ECC_GX, SM2_ECC_GY); public static final ECDomainParameters DOMAIN_PARAMS = new ECDomainParameters(CURVE, G_POINT, SM2_ECC_N, SM2_ECC_H); private static final String PEM_STRING_PUBLIC = "PUBLIC KEY"; private static final String PEM_STRING_ECPRIVATEKEY = "EC PRIVATE KEY"; /** * 生成BC自定义的SM2公私钥 * @param * @return org.bouncycastle.crypto.AsymmetricCipherKeyPair * @author hongyu guo * @date 2021/3/7 **/ public static AsymmetricCipherKeyPair generateKeyPairParameter(){ SecureRandom random = new SecureRandom(); ECKeyGenerationParameters keyGenerationParams = new ECKeyGenerationParameters(DOMAIN_PARAMS, random); ECKeyPairGenerator keyGen = new ECKeyPairGenerator(); keyGen.init(keyGenerationParams); AsymmetricCipherKeyPair keyPair = keyGen.generateKeyPair(); return keyPair; } /** * 生成java.security.KeyPair类型的SM2公私钥 * @param * @return java.security.KeyPair * @author hongyu guo * @date 2021/3/7 **/ public static KeyPair generateKeyPair() throws NoSuchProviderException, NoSuchAlgorithmException, InvalidAlgorithmParameterException { SecureRandom random = new SecureRandom(); return generateKeyPair(DOMAIN_PARAMS, random); } /** * 生成java.security.KeyPair类型的SM2公私钥, 需自定义曲线参数 * @param domainParameters * @param random * @return * @author hongyu guo * @date 2021/3/7 **/ public static KeyPair generateKeyPair(ECDomainParameters domainParameters, SecureRandom random) throws NoSuchProviderException, NoSuchAlgorithmException, InvalidAlgorithmParameterException { KeyPairGenerator kpg = KeyPairGenerator.getInstance(ALGO_NAME_EC, BouncyCastleProvider.PROVIDER_NAME); ECParameterSpec parameterSpec = new ECParameterSpec(domainParameters.getCurve(), domainParameters.getG(), domainParameters.getN(), domainParameters.getH()); kpg.initialize(parameterSpec, random); return kpg.generateKeyPair(); } /** * BC公私钥转换为java.security.KeyPair公私钥 * @param bcKeyPair * @return * @author hongyu guo * @date 2021/3/7 **/ public static KeyPair convertBcToJceKeyPair(AsymmetricCipherKeyPair bcKeyPair) throws Exception { byte[] pkcs8Encoded = PrivateKeyInfoFactory.createPrivateKeyInfo(bcKeyPair.getPrivate()).getEncoded(); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(pkcs8Encoded); byte[] spkiEncoded = SubjectPublicKeyInfoFactory.createSubjectPublicKeyInfo(bcKeyPair.getPublic()).getEncoded(); X509EncodedKeySpec spkiKeySpec = new X509EncodedKeySpec(spkiEncoded); KeyFactory keyFac = KeyFactory.getInstance(ALGO_NAME_EC, BouncyCastleProvider.PROVIDER_NAME); return new KeyPair(keyFac.generatePublic(spkiKeySpec), keyFac.generatePrivate(pkcs8KeySpec)); } /** * java.security.KeyPair转换为BC类型的公私钥对 * @param keyPair * @return * @author hongyu guo * @date 2021/3/7 **/ public static AsymmetricCipherKeyPair convertKeyPair2Bc(KeyPair keyPair) { ECPrivateKeyParameters priKey = convertPrivateKeyToParameters((BCECPrivateKey) keyPair.getPrivate()); ECPublicKeyParameters pubKey = convertPublicKeyToParameters((BCECPublicKey) keyPair.getPublic()); return new AsymmetricCipherKeyPair(priKey,pubKey); } /** * BCECPrivateKey类型私钥转化为ECPrivateKeyParameters类型的私钥, * 调用者若想将java.security.PrivateKey转化为ECPrivateKeyParameters, 调用时将其强制转换为BCECPrivateKey类型 * @param ecPriKey * @return ECPrivateKeyParameters * @author hongyu guo * @date 2021/3/7 **/ public static ECPrivateKeyParameters convertPrivateKeyToParameters(BCECPrivateKey ecPriKey) { ECParameterSpec parameterSpec = ecPriKey.getParameters(); ECDomainParameters domainParameters = new ECDomainParameters(parameterSpec.getCurve(), parameterSpec.getG(), parameterSpec.getN(), parameterSpec.getH()); return new ECPrivateKeyParameters(ecPriKey.getD(), domainParameters); } /** * BCECPublicKey类型私钥转化为ECPublicKeyParameters类型的私钥, * 调用者若想将java.security.PublicKey转化为ECPublicKeyParameters, 调用时将其强制转换为BCECPublicKey类型 * @param ecPubKey * @return ECPrivateKeyParameters * @author hongyu guo * @date 2021/3/7 **/ public static ECPublicKeyParameters convertPublicKeyToParameters(BCECPublicKey ecPubKey) { ECParameterSpec parameterSpec = ecPubKey.getParameters(); ECDomainParameters domainParameters = new ECDomainParameters(parameterSpec.getCurve(), parameterSpec.getG(), parameterSpec.getN(), parameterSpec.getH()); return new ECPublicKeyParameters(ecPubKey.getQ(), domainParameters); } /** * 生成一对sm2公私钥 * @param * @return minsecurity.crypto.sm2.SM2KeyPair * @throws * @author hongyu guo * @date 2021/3/15 **/ public static SM2KeyPair generateSM2KeyPair(){ return SM2KeyPair.generateKeyPair(); } }