Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

关于ECDHE_SM4_CBC_SM3的实现 #78

Open
tommy8421 opened this issue Sep 21, 2023 · 1 comment
Open

关于ECDHE_SM4_CBC_SM3的实现 #78

tommy8421 opened this issue Sep 21, 2023 · 1 comment

Comments

@tommy8421
Copy link

tommy8421 commented Sep 21, 2023

0、ECDHE交换算法测试过的主机:https://e.tf.cn(须指定ECDHE_SM4_CBC_SM3否则服务器协商优先ECC_SM4_CBC_SM3)和https://demo.gmssl.cn:1443
1、在ServerKeyExchange阶段,按下面描述保存服务器公钥(ephemeral):
// 03 -- ECCurveType-->named_curve(3) -- 目前只有这个合法值,其他要么废弃要么是RFU的了
// 00 17 -- secp256r1 (23) sm2p256v1(41) -- 按TLCP规范,这里是不用校验的
// 41 -- length
// 04 -- SM2 public key(point = x + y)
// 8fc16899e15b5110b1b3cf45a331bd8b9c25bf2afb0f0b31faa1e7106a7f36bae75bba7938ddacbe5868fe4e64755db631199c95802c550e4342dbcbd54b937a
// 00 47 -- 下面为ASN.1签名数据signed_param(用服务器签名公钥验签,验签数据:client random+server random + ECDHE parameter)
// 30 45
// 02 20 3ed134bc05dbc842a31c83bf6b5c89ba2c504257736ab436d6e65ecbcac53dc8 -R
// 02 21 00b2541eb483f7faaa5f22e0502049104944d8a423de69a2eac757d1c6cfca5e3f -S
2、在ClientKeyExchange阶段,计算PreMasterKey,借助于 BC库的 SM2KeyExchange类;然后把Ephemeral 的PublicKey发给服务器
PrivateKey localEncPVK = session.getKeyManager().getPrivateKey(GMConstants.CERT_ENC);
KeyPair localEphKP = Crypto.generateSM2KeyPair(); // Ephemeral key pair
PublicKey peerEphPUK = Crypto.loadPublicKey(session.getServerKEParam()); // 这里就是之前SKE的时候服务器的ECPoint为PublicKey
byte[] plainSecret = Crypto.generateECDHESecret(localEncPVK, localEphKP.getPrivate(), peerEncPUK, peerEphPUK);

核心代码如下:

public static KeyPair generateSM2KeyPair()
        throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
    KeyPairGenerator generator = KeyPairGenerator.getInstance(“EC”, GMProvider.BC_PROVIDER); // new BouncyCastleProvider()
    generator.initialize(new ECGenParameterSpec(GM_NAME));  // GM_NAME="sm2p256v1"

    return generator.generateKeyPair();
}

public static PublicKey loadPublicKey(byte[] pointBytes)
        throws InvalidKeySpecException, NoSuchAlgorithmException {
    ECParameterSpec ecParamSpec = org.bouncycastle.jce.ECNamedCurveTable.getParameterSpec(GM_NAME);
    ECPoint ecPoint = ecParamSpec.getCurve().decodePoint(pointBytes);
    ECPublicKeySpec ecPUKSpec = new ECPublicKeySpec(ecPoint, ecParamSpec);

    KeyFactory keyFactory = KeyFactory.getInstance("EC", GMProvider.BC_PROVIDER);
    return keyFactory.generatePublic(ecPUKSpec);
}

public static byte[] generateECDHESecret(PrivateKey localEncPVK, PrivateKey localEphPVK, PublicKey peerEncPUK, PublicKey peerEphPUK) {
    CipherParameters sm2kePvkParam = new SM2KeyExchangePrivateParameters(
            false,  // for client
            ((BCECPrivateKey) localEncPVK).engineGetKeyParameters(),
            ((BCECPrivateKey) localEphPVK).engineGetKeyParameters());
    CipherParameters pvkParamWithID = new ParametersWithID(sm2kePvkParam, GM_USERID);

    // 因为 BCECPublicKey.engineGetKeyParameters 没有公开,也可以用反射调用
    ECPublicKeyParameters peerPUKParam = new ECPublicKeyParameters(((BCECPublicKey) peerEncPUK).getQ(), ecDomainParameters);
    ECPublicKeyParameters peerEphPUKParam = new ECPublicKeyParameters(((BCECPublicKey) peerEphPUK).getQ(), ecDomainParameters);
    CipherParameters sm2kePukParam = new SM2KeyExchangePublicParameters(peerPUKParam, peerEphPUKParam);
    CipherParameters pukParamWithID = new ParametersWithID(sm2kePukParam, GM_USERID);// GM_USERID="1234567812345678".getBytes()

    SM2KeyExchange keyExchange = new SM2KeyExchange();
    keyExchange.init(pvkParamWithID);
    return keyExchange.calculateKey(GMConstants.ECDHE_KEY_BITS, pukParamWithID);   // pre-master key bits number, ECDHE_KEY_BITS=48*8
}
@tommy8421
Copy link
Author

可以看我的仓库,AndroidGMSSE。实现了E011/E051/E013/E053.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant