How Do I Calculate the SM3 Digest During SM2 Signature?
SM2 keys can only be used to sign message digests.
According to the GBT32918 standard, in SM2 signature value calculation, the message digest is not an SM3 digest calculated based on the original message. Instead, it is a digest of the concatenation of Z(A) and M. Here M indicates the original message to be signed, and Z(A) indicates the hash value of user A defined in GBT32918.
public class Sm2SignDataPreprocessing {
private static final String ECC_A = "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC";
private static final String ECC_B = "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93";
private static final String ECC_GX = "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7";
private static final String ECC_GY = "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0";
// Signer ID. In this example, the default value "1234567812345678" is used.
private static final String SM2_ID = "31323334353637383132333435363738";
public static void main(String[] args) throws Exception {
// SM2 public key in BASE64 encoding format. The value is only an example. Replace it with the actual value.
String sm2PubKey = "MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEsuOq/EjQeYUD9h7lIyqi3pQ6SWL7hTXjUJWmSIZAcnj" +
"h9c0QcdbwzaCfI8iyyPCetX0QZl5NHrBoYLYxJpvbFg==";
byte[] pubKeyBytes = Base64.decodeBase64(sm2PubKey.getBytes(StandardCharsets.UTF_8));
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pubKeyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("EC", new BouncyCastleProvider());
ECPublicKey ecPublicKey = (ECPublicKey) keyFactory.generatePublic(keySpec);
// Original message to be signed, which is only an example. Replace it with the actual one.
byte[] dataToDigest = new byte[]{1, 2, 3, 4};
// Z(A) is the hash value of user A defined in GBT32918.
byte[] zsm = getSm2Z(ecPublicKey.getQ().getAffineXCoord().getEncoded(),
ecPublicKey.getQ().getAffineYCoord().getEncoded());
// Calculate the digest of the concatenation of Z(A) and M and print the digest.
byte[] dataToSign = getSm3SignData(zsm, dataToDigest);
System.out.println(Base64.encodeBase64String(dataToSign));
// If this example is implemented or executed in other languages, the following output should be displayed: He+qiM2MmtNxlV/EB4vqkcP60XgG08z/8nWQdp/IS5c=
}
// Calculate Z(A).
private static byte[] getSm2Z(byte[] x, byte[] y) throws DecoderException {
SM3Digest sm3 = new SM3Digest();
byte[] userId = Hex.decodeHex(SM2_ID.toCharArray());
byte[] byteEccA = Hex.decodeHex(ECC_A);
byte[] byteEccB = Hex.decodeHex(ECC_B);
byte[] byteEccGx = Hex.decodeHex(ECC_GX);
byte[] byteEccGy = Hex.decodeHex(ECC_GY);
int len = userId.length * 8;
sm3.update((byte) (len >> 8 & 255));
sm3.update((byte) (len & 255));
sm3.update(userId, 0, userId.length);
sm3.update(byteEccA, 0, byteEccA.length);
sm3.update(byteEccB, 0, byteEccB.length);
sm3.update(byteEccGx, 0, byteEccGx.length);
sm3.update(byteEccGy, 0, byteEccGy.length);
sm3.update(x, 0, x.length);
sm3.update(y, 0, y.length);
byte[] md = new byte[sm3.getDigestSize()];
sm3.doFinal(md, 0);
return md;
}
// Calculate the digest of the concatenated value of Z(A) and M.
private static byte[] getSm3SignData(byte[] z, byte[] sourceData) {
SM3Digest sm3 = new SM3Digest();
sm3.update(z, 0, z.length);
sm3.update(sourceData, 0, sourceData.length);
byte[] md = new byte[sm3.getDigestSize()];
sm3.doFinal(md, 0);
return md;
}
}
Did this article solve your problem?
Thank you for your score!Your feedback would help us improve the website.