我想用AES算法加密和解密明文。我得到的密钥和iv来自API。我尝试了很多方法,但都不管用。怎么了?
https://github.com/simbiose/Encryption
https://github.com/scottyab/AESCrypt-Android
public class CryptoHandler {
private static CryptoHandler instance = null;
public static CryptoHandler getInstance() {
if (instance == null) {
instance = new CryptoHandler();
}
return instance;
}
public String encrypt(String message, String key, String IV) throws NoSuchAlgorithmException,
NoSuchPaddingException, IllegalBlockSizeException,
BadPaddingException, InvalidKeyException,
UnsupportedEncodingException, InvalidAlgorithmParameterException {
byte[] srcBuff = message.getBytes("UTF8");
//here using substring because AES takes only 16 or 24 or 32 byte of key
SecretKeySpec skeySpec = new
SecretKeySpec(key.substring(0,32).getBytes(), "AES");
IvParameterSpec ivSpec = new
IvParameterSpec(IV.substring(0,16).getBytes());
Cipher ecipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
ecipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivSpec);
byte[] dstBuff = ecipher.doFinal(srcBuff);
String base64 = Base64.encodeToString(dstBuff, Base64.DEFAULT);
return base64;
}
public String decrypt(String encrypted, String key, String IV) throws NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException,
InvalidAlgorithmParameterException, IllegalBlockSizeException,
BadPaddingException, UnsupportedEncodingException {
SecretKeySpec skeySpec = new
SecretKeySpec(key.substring(0,32).getBytes(), "AES");
IvParameterSpec ivSpec = new
IvParameterSpec(IV.substring(0,16).getBytes());
Cipher ecipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
ecipher.init(Cipher.DECRYPT_MODE, skeySpec, ivSpec);
byte[] raw = Base64.decode(encrypted.getBytes(), 0, 16, Base64.DEFAULT);
byte[] originalBytes = ecipher.doFinal(raw);
String original = new String(originalBytes, "UTF8");
return original;
}
}
API响应数据示例:
{
"key": "QaDtfPpeMW0VgMMd4XF88K6KkIPe5ZG0sitpyhuJf/E=",
"iv": "ccp2YePjewVL9X+vCms5BQ==",
"string": "5c2c82a6-66da-41f9-b20d-5d4ffd0c505a",
}
3条答案
按热度按时间oyt4ldly1#
尤努斯,我也面临同样的问题,晚了,但如果其他人再次面临,我分享我的解决方案。Key和IVkey已经转换为base64并准备解码,因此不需要substr过程。当你做substr的时候,你会失去整个键的一部分。
下面的键是从共享的首选项中读取的。
sharedprefs返回与您的键相同的键(编码为base64并且作为字符串-而不是bytearray-)
然后只需要encode:
或解码:
rjee0c152#
除了字符串化不正确(键和IV应该包含随机字节值,包括那些不属于可打印ASCII字符集的值)之外,我没有看到太多错误。
然而,最有可能的罪魁祸首是这一行:
由于PKCS#7总是取消填充,因此使用单个块可能意味着如果它出现在以下块之一中,则取消填充失败。只要解码整个基64,而不仅仅是16个字符。
CryptoHandler
绝对没有理由只有一个示例。您当前的getInstace
方法也不是线程安全的,因此无论如何都可能出现多个处理程序。只要使用普通的类,并考虑它们应该包含什么。这主要是一个所谓的“ Package 器类”。它没有任何用处。我建议编写特定于特定用例的加密相关类。相信我,当我说你可能最终重写一切以后,如果你不-我已经在那里。
xwbd5t1u3#
不需要任何第三方图书馆。
还有一种填充格式称为无填充。我们必须使用“AES/CBC/NoPadding”