SmUtil

Introduction

Hutool provides a simplified wrapper for Bouncy Castle to implement the SM2, SM3, and SM4 algorithms in the national cryptography standard.

The national cryptography algorithm tool encapsulation includes:

  • Asymmetric encryption and signature: SM2
  • Digest signature algorithm: SM3
  • Symmetric encryption: SM4

The national cryptography algorithm requires the introduction of the Bouncy Castle library dependency.

Usage

Introduce Bouncy Castle dependency

<dependency>
  <groupId>org.bouncycastle</groupId>
  <artifactId>bcprov-jdk15to18</artifactId>
  <version>1.69</version>
</dependency>

Note: Please search for the latest version of bcprov-jdk15to18 on the Maven Central Repository that corresponds to your JDK.

Asymmetric Encryption SM2

  1. Encrypt or decrypt using a randomly generated key pair
String text = "I am a test aaaa";

SM2 sm2 = SmUtil.sm2();
// Encrypt with public key and decrypt with private key
String encryptStr = sm2.encryptBcd(text, KeyType.PublicKey);
String decryptStr = StrUtil.utf8Str(sm2.decryptFromBcd(encryptStr, KeyType.PrivateKey));
  1. Encrypt or decrypt using a custom key pair
String text = "I am a test aaaa";

KeyPair pair = SecureUtil.generateKeyPair("SM2");
byte[] privateKey = pair.getPrivate().getEncoded();
byte[] publicKey = pair.getPublic().getEncoded();

SM2 sm2 = SmUtil.sm2(privateKey, publicKey);
// Encrypt with public key and decrypt with private key
String encryptStr = sm2.encryptBcd(text, KeyType.PublicKey);
String decryptStr = StrUtil.utf8Str(sm2.decryptFromBcd(encryptStr, KeyType.PrivateKey));
  1. SM2 signature and verification
String content = "I am Hanley.";
final SM2 sm2 = SmUtil.sm2();
String sign = sm2.signHex(HexUtil.encodeHexStr(content));

// true
boolean verify = sm2.verifyHex(HexUtil.encodeHexStr(content), sign);

Of course, you can also use a custom key pair:

String content = "I am Hanley.";
KeyPair pair = SecureUtil.generateKeyPair("SM2");
final SM2 sm2 = new SM2(pair.getPrivate(), pair.getPublic());

byte[] sign = sm2.sign(content.getBytes());

// true
boolean verify = sm2.verify(content.getBytes(), sign);
  1. Using SM2 Curve Point to Construct SM2

For point generation and verification in curve point construction, please refer to: https://i.goto327.top/CryptTools/SM2.aspx?tdsourcetag=s_pctim_aiomsg

String privateKeyHex = "FAB8BBE670FAE338C9E9382B9FB6485225C11A3ECB84C938F10F20A93B6215F0";
String x = "9EF573019D9A03B16B0BE44FC8A5B4E8E098F56034C97B312282DD0B4810AFC3";
String y = "CC759673ED0FC9B9DC7E6FA38F0E2B121E02654BF37EA6B63FAF2A0D6013EADF";

// Data and ID are represented in hexadecimal format here
String data = "434477813974bf58f94bcf760833c2b40f77a5fc360485b0b9ed1bd9682edb45";
String id = "31323334353637383132333435363738";

final SM2 sm2 = new SM2(privateKeyHex, x, y);
// The generated signature is 64 bits
sm2.usePlainEncoding();

final String sign = sm2.signHex(data, id);
// true
boolean verify = sm2.verifyHex(data, sign)
  1. Signing with Private Key D Value
// Plaintext to be signed, obtain the corresponding byte array
byte[] dataBytes = "我是一段测试aaaa".getBytes();
// Specified private key
String privateKeyHex = "1ebf8b341c695ee456fd1a41b82645724bc25d79935437d30e7e4b0a554baa5e";

// This constructor is available from version 5.5.9 onwards
final SM2 sm2 = new SM2(privateKeyHex, null, null);
sm2.usePlainEncoding();
byte[] sign = sm2.sign(dataBytes, null);
  1. Verifying Signature with Public Key Q Value
// Specified public key
String publicKeyHex ="04db9629dd33ba568e9507add5df6587a0998361a03d3321948b448c653c2c1b7056434884ab6f3d1c529501f166a336e86f045cea10dffe58aa82ea13d725363";
// Plaintext to be encrypted, obtain the corresponding byte array
byte[] dataBytes = "我是一段测试aaaa".getBytes();
// Signature value
String signHex ="2881346e038d2ed706ccdd025f2b1dafa7377d5cf090134b98756fafe084dddbcdba0ab00b5348ed48025195af3f1dda29e819bb66aa9d4d088050ff148482a";

final SM2 sm2 = new SM2(null, ECKeyUtil.toSm2PublicParams(publicKeyHex));
sm2.usePlainEncoding();

// true
boolean verify = sm2.verify(dataBytes, HexUtil.decodeHex(signHex));
  1. Other Key Formats

In the SM2 algorithm, the key formats are divided into the following types:

Private Key:

  • D Value: Typically a value generated directly by hardware
  • PKCS#8: Default private key format generated by JDK
  • PKCS#1: EC key format typically generated by OpenSSL

Public Key:

  • Q Value: Typically a value generated directly by hardware
  • X.509: Default public key format generated by JDK
  • PKCS#1: EC key format typically generated by OpenSSL

In the new version of Hutool, the SM2 constructor is compatible with all these key types, so users do not need to concern about the key type:

Hash Algorithm SM3

// Result: 136ce3c86e4ed909b76082055a61586af20b4dab674732ebd4b599eef080c9be
String digestHex = SmUtil.sm3("aaaaa");

Symmetric Encryption SM4

String content = "test中文";
SymmetricCrypto sm4 = SmUtil.sm4();

String encryptHex = sm4.encryptHex(content);
String decryptStr = sm4.decryptStr(encryptHex, CharsetUtil.CHARSET_UTF_8);