package org.zz.gmhelper; import org.bouncycastle.crypto.agreement.SM2KeyExchange; import org.bouncycastle.crypto.params.ECPrivateKeyParameters; import org.bouncycastle.crypto.params.ECPublicKeyParameters; import org.bouncycastle.crypto.params.ParametersWithID; import org.bouncycastle.crypto.params.SM2KeyExchangePrivateParameters; import org.bouncycastle.crypto.params.SM2KeyExchangePublicParameters; import java.util.Arrays; public class SM2KeyExchangeUtil { /** * @param initiator true表示发起方,false表示响应方 * @param keyBits 生成的密钥长度 * @param selfStaticPriv 己方固定私钥 * @param selfEphemeralPriv 己方临时私钥 * @param selfId 己方ID * @param otherStaticPub 对方固定公钥 * @param otherEphemeralPub 对方临时公钥 * @param otherId 对方ID * @return 返回协商出的密钥,但是这个密钥是没有经过确认的 */ public static byte[] calculateKey(boolean initiator, int keyBits, ECPrivateKeyParameters selfStaticPriv, ECPrivateKeyParameters selfEphemeralPriv, byte[] selfId, ECPublicKeyParameters otherStaticPub, ECPublicKeyParameters otherEphemeralPub, byte[] otherId) { SM2KeyExchange exch = new SM2KeyExchange(); exch.init(new ParametersWithID( new SM2KeyExchangePrivateParameters(initiator, selfStaticPriv, selfEphemeralPriv), selfId)); return exch.calculateKey( keyBits, new ParametersWithID(new SM2KeyExchangePublicParameters(otherStaticPub, otherEphemeralPub), otherId)); } /** * @param initiator true表示发起方,false表示响应方 * @param keyBits 生成的密钥长度 * @param confirmationTag 确认信息,如果是响应方可以为null;如果是发起方则应为响应方的s1 * @param selfStaticPriv 己方固定私钥 * @param selfEphemeralPriv 己方临时私钥 * @param selfId 己方ID * @param otherStaticPub 对方固定公钥 * @param otherEphemeralPub 对方临时公钥 * @param otherId 对方ID * @return */ public static ExchangeResult calculateKeyWithConfirmation(boolean initiator, int keyBits, byte[] confirmationTag, ECPrivateKeyParameters selfStaticPriv, ECPrivateKeyParameters selfEphemeralPriv, byte[] selfId, ECPublicKeyParameters otherStaticPub, ECPublicKeyParameters otherEphemeralPub, byte[] otherId) { SM2KeyExchange exch = new SM2KeyExchange(); exch.init(new ParametersWithID( new SM2KeyExchangePrivateParameters(initiator, selfStaticPriv, selfEphemeralPriv), selfId)); byte[][] result = exch.calculateKeyWithConfirmation( keyBits, confirmationTag, new ParametersWithID(new SM2KeyExchangePublicParameters(otherStaticPub, otherEphemeralPub), otherId)); ExchangeResult confirmResult = new ExchangeResult(); confirmResult.setKey(result[0]); if (initiator) { confirmResult.setS2(result[1]); } else { confirmResult.setS1(result[1]); confirmResult.setS2(result[2]); } return confirmResult; } /** * @param s2 * @param confirmationTag 实际上是发起方的s2 * @return */ public static boolean responderConfirm(byte[] s2, byte[] confirmationTag) { return Arrays.equals(s2, confirmationTag); } public static class ExchangeResult { private byte[] key; /** * 发起方没有s1 */ private byte[] s1; private byte[] s2; public byte[] getKey() { return key; } public void setKey(byte[] key) { this.key = key; } public byte[] getS1() { return s1; } public void setS1(byte[] s1) { this.s1 = s1; } public byte[] getS2() { return s2; } public void setS2(byte[] s2) { this.s2 = s2; } } }