java - AES 256 GCM Java 实现
问题描述
我正在尝试将以下 AES-256-GCM 加密实现从 NodeJS 重写为 Java。
我得到了不同的输出,特别是 auth 标签部分。从它的外观来看,Java 库没有任何方法来获取 auth 标记,并且我尝试从输出中对其进行子串化失败。此外,我实际上不确定第一次使用公钥的 AES 加密(为 GCM 生成随机缓冲区)是否与 NodeJS 对应项相同。谁能指出我正确的方向?
节点JS:
public encryptPassword(password: string, encryptionKey: string, encryptionKeyId: string): { time: string, encrypted: string } {
const randKey = crypto.randomBytes(32);
const iv = crypto.randomBytes(12);
const rsaEncrypted = crypto.publicEncrypt({
key: Buffer.from(encryptionKey, 'base64').toString(),
// @ts-ignore
padding: crypto.constants.RSA_PKCS1_PADDING,
}, randKey);
const cipher = crypto.createCipheriv('aes-256-gcm', randKey, iv);
const time = Math.floor(Date.now() / 1000).toString();
cipher.setAAD(Buffer.from(time));
const aesEncrypted = Buffer.concat([cipher.update(password, 'utf8'), cipher.final()]);
const sizeBuffer = Buffer.alloc(2, 0);
sizeBuffer.writeInt16LE(rsaEncrypted.byteLength, 0);
const authTag = cipher.getAuthTag();
return {
time,
encrypted: Buffer.concat([
Buffer.from([1, encryptionKeyId]),
iv,
sizeBuffer,
rsaEncrypted, authTag, aesEncrypted])
.toString('base64'),
};
}
爪哇:
private static Pair<Long, String> encryptPaswword(String password, String encryptionPubKey, String encryptionKeyId) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidCipherTextException, InvalidAlgorithmParameterException {
byte[] passwordAsByte = password.getBytes();
String decoededPubKey = new String(Base64.decode(encryptionPubKey, Base64.NO_WRAP), StandardCharsets.UTF_8);
decoededPubKey = decoededPubKey.replace("-----BEGIN PUBLIC KEY-----", "");
decoededPubKey = decoededPubKey.replace("-----END PUBLIC KEY-----", "");
SecureRandom random = new SecureRandom();
byte[] randKey = new byte[32];
random.nextBytes(randKey);
byte[] iv = new byte[12];
random.nextBytes(iv);
long date = new Date().getTime() / 1000;
ByteBuffer header = ByteBuffer.allocate(2);
header.put(Integer.valueOf(1).byteValue());
header.put(Integer.valueOf(Integer.parseInt(encryptionKeyId)).byteValue());
ByteBuffer timeAAD = ByteBuffer.allocate(10);
timeAAD.put(String.valueOf(date).getBytes());
X509EncodedKeySpec publicSpec = new X509EncodedKeySpec(Base64.decode(decoededPubKey, Base64.NO_WRAP));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(publicSpec);
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
rsaCipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] rsaEncrypted = rsaCipher.doFinal(randKey);
ByteBuffer sizeBuff = ByteBuffer.allocate(2);
sizeBuff.put(Integer.valueOf(rsaEncrypted.length).byteValue());
final Cipher gcmCipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec parameterSpec = new GCMParameterSpec(16 * Byte.SIZE, iv);
gcmCipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(randKey, "AES"), parameterSpec);
gcmCipher.updateAAD(timeAAD);
byte[] gcmText= gcmCipher.doFinal(passwordAsByte);
ByteBuffer result = ByteBuffer.allocate(2+12+2+256+gcmText.length);
result.put(header);
result.put(iv);
result.put(sizeBuff);
result.put(rsaEncrypted);
result.put(Arrays.copyOfRange(gcmText, gcmText.length - (16 / Byte.SIZE), gcmText.length));
result.put(Arrays.copyOfRange(gcmText, 0, gcmText.length - (16 / Byte.SIZE)));
return new Pair(new Long(date), Base64.encodeToString(result.array(), Base64.NO_WRAP));
解决方案
推荐阅读
- rust - Rust:创建一个整数向量
- linux - 一个衬垫将文件夹(无文件)从一个位置复制到另一个位置
- reactjs - React - 我们是否应该在更新状态之前检查组件是否已安装?
- reactjs - 如何将 BrowserRouter 从 react-router-dom 更改为 Router 以使用自定义历史对象?
- artifactory - Docker 中的 Artifactory 在启动期间产生错误
- html - 我怎样才能将链接添加到这些框
- html - 在页面上垂直居中 flex 容器
- typescript - 如何期望 3 个对象与 expect.objectContaining({...?
- php - 通过转发器字段的 acf 关系子字段过滤 wordpress 自定义帖子类型
- php - 检查从数据库检索到的 URL 的数组列表中是否存在 url