python-java 的 AES-GCM 加解说明
内容
- 说明
- 测试数据
- python-PyCryptodome版本
- python-cryptography版本
- java版本
说明
- AES-GCM是一种NIST标准的认证加密算法, 是一种能够同时保证数据的保密性、 完整性和真实性的一种加密模式。它最广泛的应用是在TLS中。
- GCM详细说明
测试数据
AES加密模式:AEAD_AES_256_GCM
AES密钥:
aesKey = 1d35eefc2b8207d615028d056ce5296c
附加数据:
associatedData = 12345
随机数据:nonceData
nonceData = 1234567812345678
数据明文: 1234561234565
数据密文:X3lkQaqdASpIF0+XsOjwUhfCZdvXh3RQFXsH8o8=
python demo--PyCryptodome版本
import base64
from Crypto.Cipher import AES
aes_key = '1d35eefc2b8207d615028d056ce5296c'
associatedData = "12345"
nonce = "1234567812345678"
def aes_en_gcm_func():
de_data = '1234561234565'
cipher = AES.new(aes_key.encode(), AES.MODE_GCM, nonce=nonce.encode())
cipher.update(associatedData.encode())
ct, tag = cipher.encrypt_and_digest(de_data.encode('utf-8'))
return base64.b64encode(ct + tag).decode('utf-8')
def aes_de_gcm_func():
en_data = 'X3lkQaqdASpIF0+XsOjwUhfCZdvXh3RQFXsH8o8='
cipher = AES.new(aes_key.encode(), AES.MODE_GCM, nonce=nonce.encode())
cipher.update(associatedData.encode())
en_data = base64.b64decode(en_data.encode('utf-8'))
auth_tag = en_data[-16:]
_en_data = en_data[:-16]
plaintext = cipher.decrypt_and_verify(_en_data, auth_tag)
return plaintext.decode()
python demo--cryptography 版本
import base64
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
aes_key = '1d35eefc2b8207d615028d056ce5296c'
associatedData = "12345"
nonce = "1234567812345678"
def st_aes_en_func():
de_data = '1234561234565'
aesgcm = AESGCM(aes_key.encode())
ct = aesgcm.encrypt(nonce.encode(), de_data.encode(), associatedData.encode())
return base64.b64encode(ct).decode('utf-8')
def st_aes_de_func():
en_data = 'X3lkQaqdASpIF0+XsOjwUhfCZdvXh3RQFXsH8o8='
en_data = base64.b64decode(en_data.encode('utf-8'))
aesgcm = AESGCM(aes_key.encode())
ct = aesgcm.decrypt(nonce.encode(), en_data, associatedData.encode())
return ct.decode()
java demo
package tools;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class AesUtil {
static final int KEY_LENGTH_BYTE = 32;
static final int TAG_LENGTH_BIT = 128;
private final byte[] aesKey;
public AesUtil(byte[] key) {
if (key.length != KEY_LENGTH_BYTE) {
throw new IllegalArgumentException("无效的ApiV3Key,长度必须为32个字节");
}
this.aesKey = key;
}
public String decryptToString(byte[] associatedData, byte[] nonce, String ciphertext)
throws GeneralSecurityException, IOException {
try {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
SecretKeySpec key = new SecretKeySpec(aesKey, "AES");
GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH_BIT, nonce);
cipher.init(Cipher.DECRYPT_MODE, key, spec);
cipher.updateAAD(associatedData);
return new String(cipher.doFinal(Base64.getDecoder().decode(ciphertext)), "utf-8");
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
throw new IllegalStateException(e);
} catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
throw new IllegalArgumentException(e);
}
}
public String encryptToString(byte[] associatedData, byte[] nonce, String ciphertext)
throws GeneralSecurityException, IOException{
try {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
SecretKeySpec key = new SecretKeySpec(aesKey, "AES");
GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH_BIT, nonce);
cipher.init(Cipher.ENCRYPT_MODE, key, spec);
cipher.updateAAD(associatedData);
// return new String(cipher.doFinal(Base64.getDecoder().decode(ciphertext)), "utf-8");
return new String(Base64.getEncoder().encode(cipher.doFinal(ciphertext.getBytes())), "utf-8");
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
throw new IllegalStateException(e);
} catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
throw new IllegalArgumentException(e);
}
}
public static void main(String[] args) throws Exception {
String key = "1d35eefc2b8207d615028d056ce5296c";
String associatedData = "12345";
String nonce = "1234567812345678";
AesUtil aesUtils = new AesUtil(key.getBytes());
String enData = aesUtils.encryptToString(associatedData.getBytes(), nonce.getBytes(), "1234561234565");
System.out.println("加密后密文:" + enData);
String deData = aesUtils.decryptToString(associatedData.getBytes(), nonce.getBytes(), enData);
System.out.println("解密后明文:" + deData);
}
}
网友评论