Android中AES解密问题:无法解密API返回的密钥数据
解决方向
1. 修正实体类字段类型
你给出的words数组中的数值(如15677252277)远超出Java int类型的范围(-2147483648 ~ 2147483647),因此实体类EncryptionKeys里ciphertext、key、iv、salt的words字段必须定义为long[],而非int[],否则会出现数值溢出,导致转换后的字节数组完全错误。
2. 正确处理Word到字节的转换
CryptoJS的WordArray中每个word是32位无符号整数,JSON序列化时会转为带符号的long类型。转换时需先取每个long值的低32位,再按大端字节顺序拆分为4字节:
private byte[] wordArrayToByteArray(long[] wordArray, int sigBytes) { byte[] byteArray = new byte[sigBytes]; int byteIndex = 0; for (long word : wordArray) { // 取低32位转为无符号整数处理 int unsignedWord = (int) (word & 0xFFFFFFFFL); // 按大端顺序写入字节 for (int i = 3; i >= 0; i--) { if (byteIndex >= sigBytes) break; byteArray[byteIndex++] = (byte) ((unsignedWord >> (i * 8)) & 0xFF); } if (byteIndex >= sigBytes) break; } return byteArray; }
3. 按sigBytes截断有效字节
返回结构中的sigBytes代表该字段的实际有效字节长度,转换后必须截断到这个长度,不能直接使用所有word转换后的字节。比如key的sigBytes是32,即便words有12个元素,也只取前32字节。
修改decrypt方法的转换逻辑:
byte[] ciphertextBytes = wordArrayToByteArray(encryptionKeys.ciphertext.words, encryptionKeys.ciphertext.sigBytes); byte[] keyBytes = wordArrayToByteArray(encryptionKeys.key.words, encryptionKeys.key.sigBytes); byte[] ivBytes = wordArrayToByteArray(encryptionKeys.iv.words, encryptionKeys.iv.sigBytes);
4. 指定解密后的字符串编码
默认new String(decryptedBytes)会使用平台默认编码,可能引发乱码,建议显式指定UTF-8:
return new String(decryptedBytes, StandardCharsets.UTF_8);
5. 验证加密算法和填充方式
确认API使用的加密算法是否为AES/CBC/PKCS5Padding,如果是CryptoJS生成的加密数据,通常默认是AES/CBC/PKCS7Padding。Java的PKCS5Padding和PKCS7Padding在AES(块大小16字节)场景下兼容,若解密失败,可尝试指定AES/CBC/PKCS7Padding(需依赖BouncyCastle库)。
内容的提问来源于stack exchange,提问作者CodeX
相关产品推荐
相关产品推荐

