如何使用Android中的AES-256-GCM用口音加密文本
我尝试用口音加密文本,而节点JS服务器未能解密它,我会得到响应“错误:不支持状态或无法验证数据”。我该怎么办?
这是加密文本的Android文件。
public static String encrypt(String text, String masterKey) throws InvalidKeySpecException, NoSuchAlgorithmException, IOException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, InvalidAlgorithmParameterException, NoSuchPaddingException {
byte[] iv = generateIv(16);
byte[] salt = generateIv(64);
SecretKey key = getKeyFromPassword(masterKey, salt);
byte[] cipher = encryptHelper("AES/GCM/NoPadding", text, key, new GCMParameterSpec(GCM_TAG_LENGTH * 8, iv));
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] ciphertext = Arrays.copyOfRange(cipher, 0, text.length());
byte[] tag = Arrays.copyOfRange(cipher, text.length(), cipher.length);
outputStream.write(salt);
outputStream.write(iv);
outputStream.write(tag);
outputStream.write(ciphertext);
String base64Encrypted;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
base64Encrypted = Base64.getEncoder().encodeToString(outputStream.toByteArray());
}else{
base64Encrypted = android.util.Base64.encodeToString(outputStream.toByteArray(), android.util.Base64.DEFAULT);
}
return base64Encrypted;
}
public static byte[] encryptHelper(String algorithm, String input, SecretKey key,
GCMParameterSpec gcmParameterSpec) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, key, gcmParameterSpec);
return cipher.doFinal(input.getBytes(StandardCharsets.UTF_8));
}
这是node js文件以解密文本。
function decryptDataTestWork(encdata, masterkey) {
// body...
// base64 decoding
const bData = Buffer.from(encdata, 'base64');
// convert data to buffers
const salt = bData.slice(0, 64);
const iv = bData.slice(64, 80);
const tag = bData.slice(80, 96);
const text = bData.slice(96);
/*console.log(salt);
console.log(iv);
console.log(tag);
console.log(text);*/
// derive key using; 32 byte key length
const key = crypto.pbkdf2Sync(masterkey, salt, 2145, 32, 'sha512');
// AES 256 GCM Mode
const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
decipher.setAuthTag(tag);
// encrypt the given text
return decipher.update(text, 'binary', 'utf8') + decipher.final('utf8');
};
我在这里得到了此回应
Error: Unsupported state or unable to authenticate data
,这是文字和钥匙
"description":"Désolé"
"key":"tIJg9tyj2setkg7gknVreP5PXzRQV5J3"
我该怎么做? 谢谢!
I try to encrypt the text with accent and the node js server fails to decrypt it I get the response "Error: Unsupported state or unable to authenticate data". How can I do?
Here is Android file to encrypt text.
public static String encrypt(String text, String masterKey) throws InvalidKeySpecException, NoSuchAlgorithmException, IOException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, InvalidAlgorithmParameterException, NoSuchPaddingException {
byte[] iv = generateIv(16);
byte[] salt = generateIv(64);
SecretKey key = getKeyFromPassword(masterKey, salt);
byte[] cipher = encryptHelper("AES/GCM/NoPadding", text, key, new GCMParameterSpec(GCM_TAG_LENGTH * 8, iv));
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] ciphertext = Arrays.copyOfRange(cipher, 0, text.length());
byte[] tag = Arrays.copyOfRange(cipher, text.length(), cipher.length);
outputStream.write(salt);
outputStream.write(iv);
outputStream.write(tag);
outputStream.write(ciphertext);
String base64Encrypted;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
base64Encrypted = Base64.getEncoder().encodeToString(outputStream.toByteArray());
}else{
base64Encrypted = android.util.Base64.encodeToString(outputStream.toByteArray(), android.util.Base64.DEFAULT);
}
return base64Encrypted;
}
public static byte[] encryptHelper(String algorithm, String input, SecretKey key,
GCMParameterSpec gcmParameterSpec) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, key, gcmParameterSpec);
return cipher.doFinal(input.getBytes(StandardCharsets.UTF_8));
}
And here is node js file to decrypt text.
function decryptDataTestWork(encdata, masterkey) {
// body...
// base64 decoding
const bData = Buffer.from(encdata, 'base64');
// convert data to buffers
const salt = bData.slice(0, 64);
const iv = bData.slice(64, 80);
const tag = bData.slice(80, 96);
const text = bData.slice(96);
/*console.log(salt);
console.log(iv);
console.log(tag);
console.log(text);*/
// derive key using; 32 byte key length
const key = crypto.pbkdf2Sync(masterkey, salt, 2145, 32, 'sha512');
// AES 256 GCM Mode
const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
decipher.setAuthTag(tag);
// encrypt the given text
return decipher.update(text, 'binary', 'utf8') + decipher.final('utf8');
};
I get this response
Error: Unsupported state or unable to authenticate data
Here is the text and key
"description":"Désolé"
"key":"tIJg9tyj2setkg7gknVreP5PXzRQV5J3"
How can i do please?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
问题是在Java代码中以及Ciphertext和Tag的错误分离中。
您可以从明文大小(由于缺乏填充物而进行GCM)确定Ciphertext大小,但然后假设字符串
text
具有与字节阵列text.get.bybytes的大小相同(standardCharsets.utf_8)
,如果在多个字节上编码文本字符,通常不是这种情况。以下实现使用标签大小将两个部分分开:
随着此更改,使用NodeJS代码的解密在我的计算机上成功,假设使用相同的密钥(请注意,由于
getKeyfeyfrompassword()
is,无法检查键推导爪哇一侧缺少)。The problem is in the Java code and in the wrong separation of ciphertext and tag.
You determine the ciphertext size from the plaintext size (which is possible for GCM because of the absent padding), but then assume that the string
text
has the same size as the byte arraytext.getBytes(StandardCharsets.UTF_8)
, which is generally not the case if the text characters are encoded on more than one byte.The following implementation uses the tag size to separate both parts:
With this change, decryption with the NodeJS code is successful on my machine assuming the same key (note that key derivation cannot be checked because
getKeyFromPassword()
is missing on the Java side).修复后,建议代码的工作非常
感谢@topaco!你救了我!
After the fix suggested the code works works very
Thanks you @Topaco! You saved me!