import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.security.*;
import java.util.Arrays;
/**
* @version: V1.0
*/
public class SM4Helper {
public static final BouncyCastleProvider BOUNCY_CASTLE_PROVIDER = new BouncyCastleProvider();
private static final String ALGORITHM = "SM4";
//private static final String ALGORITHM_NAME_ECB_PADDING = "SM4/ECB/PKCS5Padding";
//银联标准PIN加密的时候要使用SM4/ECB/NoPadding
private static final String ALGORITHM_NAME_ECB_PADDING = "SM4/ECB/NoPadding";
private static final String ENCODING = "UTF-8";
private static final int KEY_SIZE = 128;
private static final int MAC_SIZE = 16;
static {
Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
Security.addProvider(BOUNCY_CASTLE_PROVIDER);
}
public static String generaterKey() {
try {
KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM, BouncyCastleProvider.PROVIDER_NAME);
keyGenerator.init(KEY_SIZE, new SecureRandom());
return encode(keyGenerator.generateKey().getEncoded());
} catch (NoSuchAlgorithmException | NoSuchProviderException e) {
//TODO
}
}
public static String encrypt(String key, String plainText) {
try {
return encode(encrypt(decode(key), plainText.getBytes(ENCODING)));
} catch (IOException | DecoderException e) {
//TODO
}
}
public static byte[] encrypt(byte[] key, byte[] plainText) {
try {
Cipher cipher = getCipher();
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, ALGORITHM));
return cipher.doFinal(plainText);
} catch (NoSuchAlgorithmException | BadPaddingException | InvalidKeyException | NoSuchPaddingException | NoSuchProviderException | IllegalBlockSizeException e) {
//TODO
}
}
public static String mac(String key, String plainText) {
try {
return encode(Arrays.copyOf(encrypt(decode(key), plainText.getBytes(ENCODING)), MAC_SIZE));
} catch (IOException | DecoderException e) {
//TODO
}
}
public static String decrypt(String key, String cipherText) {
try {
return new String(decrypt(decode(key), decode(cipherText)), ENCODING);
} catch (IOException | DecoderException e) {
//TODO
}
}
public static byte[] decrypt(byte[] key, byte[] cipherText) {
try {
Cipher cipher = getCipher();
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, ALGORITHM));
return cipher.doFinal(cipherText);
} catch (NoSuchAlgorithmException | BadPaddingException | InvalidKeyException | NoSuchPaddingException | NoSuchProviderException | IllegalBlockSizeException e) {
//TODO
}
}
/**
* encode
*
* @param bytes
* @return
*/
public static String encode(byte[] bytes) {
return Hex.encodeHexString(bytes);
}
/**
* decode
*
* @param str
* @return
* @throws IOException
*/
public static byte[] decode(String str) throws DecoderException {
return Hex.decodeHex(str.toCharArray());
}
private static Cipher getCipher() throws NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException {
return Cipher.getInstance(ALGORITHM_NAME_ECB_PADDING, BouncyCastleProvider.PROVIDER_NAME);
}
}