我正在尝试将以下AES-256-GCM加密的实现从NodeJS重写为Java。
我得到了不同的输出,特别是auth标记部分。从外观上看,Java库没有任何方法可以获取auth标记,而我尝试从输出中对它进行字符串化的尝试失败。另外,我实际上不确定用公钥进行的第一个AES加密(为GCM生成随机缓冲区)是否与NodeJS对应的相同。 谁能指出我正确的方向?
NodeJS:
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'),
};
}
Java:
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));