java用AES-GEM-256进行加解密
public class AesGcm256Utils {
private static final SecureRandom SECURE_RANDOM = new SecureRandom();
// Pre-configured Encryption Parameters
public static int NonceBitSize = 128;
public static int MacBitSize = 128;
public static int KeyBitSize = 256;
private AesGcm256Utils() {
}
/**
* 生成随机key
* @return
*/
public static byte[] newKey(int len) {
byte[] key = new byte[len];
SECURE_RANDOM.nextBytes(key);
return key;
}
/**
* 生成随机nonce
* @return
*/
public static byte[] newNonce(int len) {
byte[] iv = new byte[len];
SECURE_RANDOM.nextBytes(iv);
return iv;
}
/**
* 加密
* @param PlainText
* @param key
* @param iv
* @return
*/
public static byte[] encrypt(String PlainText, byte[] key, byte[] iv) {
try {
byte[] plainBytes = PlainText.getBytes("UTF-8");
GCMBlockCipher cipher = new GCMBlockCipher(new AESFastEngine());
AEADParameters parameters = new AEADParameters(new KeyParameter(key), MacBitSize, iv, null);
cipher.init(true, parameters);
byte[] encryptedBytes = new byte[cipher.getOutputSize(plainBytes.length)];
int retLen = cipher.processBytes(plainBytes, 0, plainBytes.length, encryptedBytes, 0);
cipher.doFinal(encryptedBytes, retLen);
return encryptedBytes;
} catch (Exception e) {
System.out.println(e.getMessage());
}
return null;
}
/**
* 解密
* @param EncryptedText
* @param key
* @param iv
* @return
*/
public static byte[] decrypt(byte[] EncryptedText, byte[] key, byte[] iv) {
try {
GCMBlockCipher cipher = new GCMBlockCipher(new AESFastEngine());
AEADParameters parameters = new AEADParameters(new KeyParameter(key), MacBitSize, iv, null);
cipher.init(false, parameters);
byte[] plainBytes = new byte[cipher.getOutputSize(EncryptedText.length)];
int retLen = cipher.processBytes(EncryptedText, 0, EncryptedText.length, plainBytes, 0);
cipher.doFinal(plainBytes, retLen);
return plainBytes;
} catch (IllegalArgumentException | IllegalStateException | DataLengthException | InvalidCipherTextException ex) {
System.out.println(ex.getMessage());
}
return null;
}
}
@Slf4j
public class AesGcm256Test {
public static void main(String[] args) throws Exception {
// 生成随机32位key和12位nonce
byte[] key = AesGcm256Utils.newKey(32);
byte[] nonce = AesGcm256Utils.newNonce(12);
String text = "123456";
// 用key和nonce对text进行加密
byte[] encrypt = AesGcm256Utils.encrypt(text, key, nonce);
// 转成hex
log.info(Utils.bytesToHex(encrypt));
// 用key和nonce对text进行解密
byte[] res = AesGcm256Utils.decrypt(encrypt, key, nonce);
log.info(new String(res));
}
}
用AES-GEM-256可以对接口的数据体进行加密,我在工作中跟同事对接的时候,他的消息结构如下:
Req:
{
"data":"", -- Hex: AES-256-GCM加密, 业务JSON数据
"security":{
"key":"", -- AES Key encrypto by codeplus
"nonce":"" -- Random number encrypto by codeplus
},
"sign":"" -- Hex : sha256(scard + data + security(key + nonce)
-- Signature by User private key generate via user codeplus
}
Resp:
{
"data":"",
"sign":"" -- Hex : by SCPGS private key
"security":{
"key":"",
"nonce":""
}
}
他是用椭圆曲线非对称的加密方式。服务器有一对通讯层的公私钥,公钥是公开提供给客户端,私钥则是服务器自己保存的。其中业务JSON数据data就是用AES-256-GCM进行加密的,key和nonce是hex字符串,用服务器提供的通讯公钥来进行加密的。
而客户端自己也有秘钥对,公钥是给服务器那边保存,私钥则是客户端保存。
总体的流程是:客户端请求时用通讯公钥对key和nonce加密,用私钥进行签名;验签则是用通讯公钥,然后用自己的私钥对key和nonce解密。