AES 解密错误:android 垫块损坏
Posted
技术标签:
【中文标题】AES 解密错误:android 垫块损坏【英文标题】:AES Decryption ERROR: android pad block corrupted 【发布时间】:2013-12-18 10:07:58 【问题描述】:我环顾堆栈以找到问题的答案,但没有任何效果。 我试图实现的是加密在 ASYNCtask 中下载的 XML 文件,然后再对其进行解密。
我已经检查过的内容:
-加密和解密时生成的密钥相同,并保存在与Base64的sharedpreferenced中。
-IV 是相同的,因为目前它在静态变量中用于测试目的。
-密码设置为 AES/CBC/PKCS5Padding
-密钥设置为 AES
decryptXml() 中出现错误: byte[] 解密 = cipher.doFinal(bytes);
我完全没有想法,似乎没有任何工作。我希望你们中的一些人能在我的代码中找到错误。感谢您的帮助!
代码:
generateKey()
SharedPreferences sharedPreferences = context.getSharedPreferences(GENERATED_KEY, Context.MODE_PRIVATE);
String keyStr = sharedPreferences.getString(GENERATED_KEY, null);
if (keyStr == null)
final int outputKeyLength = 128;
SecureRandom secureRandom = new SecureRandom();
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(outputKeyLength, secureRandom);
SecretKey key = keyGenerator.generateKey();
byte[] bytes = key.getEncoded();
keyStr = Base64.encodeToString(bytes, Base64.DEFAULT);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(GENERATED_KEY, keyStr);
editor.commit();
return key.toString();
else
return keyStr;
XML 加密:
connection = (HttpURLConnection) url.openConnection();
connection.connect();
SecretKey secretKey = getSecretKey(context);
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
spec = generateIv(cipher.getBlockSize());
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, spec);
input = connection.getInputStream();
cis = new CipherInputStream(input, cipher);
String FILEPATH = context.getFilesDir().getParentFile().getPath();
File file = new File(FILEPATH, "/download/" + id + "/");
if (!file.exists())
file.mkdirs();
xmlFile = new File(FILEPATH + "/download/" + id + "/", "xmldata.xml");
output = new FileOutputStream(xmlFile);
cos = new CipherOutputStream(output, cipher);
byte data[] = new byte[4096];
int count;
while ((count = cis.read(data)) != -1)
if (isCancelled()) throw new TaskCanceledException();
cos.write(data, 0, count);
progress = -1;
publishProgress();
if (isCancelled()) throw new TaskCanceledException();
解密:
public String decryptXml()
String data = null;
File file = new File(context.getFilesDir().getParentFile().getPath() + "/download/" + id + "/xmldata.xml");
int size = (int) file.length();
byte[] bytes = new byte[size];
try
SecretKeySpec secretKeySpec = new SecretKeySpec(getSecretKey(context).getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, DownloadBookAsyncTask.spec);
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
bis.read(bytes, 0, bytes.length);
bis.close();
byte[] decrypted = cipher.doFinal(bytes);
getSecretKey():
public SecretKey getSecretKey(Context context)
SharedPreferences sharedPreferences = context.getSharedPreferences(DashboardFragment.GENERATED_KEY, Context.MODE_PRIVATE);
String stringKey = sharedPreferences.getString(DashboardFragment.GENERATED_KEY, null);
byte[] encodedKey = Base64.decode(stringKey, Base64.DEFAULT);
return new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
编辑
添加 IV 生成器方法
public AlgorithmParameterSpec generateIv(int size) throws NoSuchAlgorithmException
AlgorithmParameterSpec ivspec;
byte[] iv = new byte[size];
new SecureRandom().nextBytes(iv);
ivspec = new IvParameterSpec(iv);
return ivspec;
【问题讨论】:
【参考方案1】:好的,我找到了问题所在。 我的代码不起作用的原因是我在加密中使用了 CipherInputStream,我不应该这样做。 我还重做了整个解密方法,现在看起来像这样:
byte[] wholeFileByte = null;
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
cipher.init(Cipher.DECRYPT_MODE, key, DownloadBookAsyncTask.ivspec);
File file = new File(context.getFilesDir().getParentFile().getPath() + "/download/" + id + "/xmldata.xml");
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
CipherInputStream cis = new CipherInputStream(fis, cipher);
byte data[] = new byte[4096];
int count;
while ((count = cis.read(data)) != -1)
bos.write(data, 0, count);
if(cis != null)
cis.close();
if(bos != null)
bos.close();
if(fis != null)
fis.close();
wholeFileByte = bos.toByteArray();
String kk = new String(wholeFileByte, "UTF-8");
我认为我犯的另一个错误是我在解密中使用了 doFinal,即使 Cipher 已经进行了解密,这是我的一些错误的根源。
感谢@GariBN,因为你让我走上了正轨,当我的代表允许我这样做时,你会支持你:)
【讨论】:
很高兴看到你成功了。【参考方案2】:您创建 IV 来加密明文。 我不确定您是否使用相同的 IV 来解密密文。
通常,您希望将 IV 连接到密文,并在解密时读取它(前 16 个字节),然后使用用 IV 初始化的密码解密所有其他字节(密文)用于加密。
例如,如果您使用以下命令进行加密:
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, spec);
首先,尝试解密(稍后):
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, spec);
cipher.doFinal(bytes)
如果你成功了,那么问题可能是因为IV不合适,你可以很容易地解决它。
【讨论】:
感谢您的帮助,但不幸的是,当我这样做时,我再次收到 BadPaddingException :C 请发送对您不起作用的基本加密代码(使用一些 IV)和解密。您的代码太长,并且包含许多不相关的细节。只需加密,然后解密。如果问题存在,我相信我能找到它或给你另一个工作代码。 这堵代码背后的原因是我不确定问题出在哪里。至于解密和加密方法,都带有注释。我确实在帖子开头提到过,decryptionXml() 行 byte[] decrypted = cipher.doFinal(bytes);. 从加密和解密字节开始。然后将 XML 加密和解密为字节。首先你应该成功完成第一项任务。 我现在正在尝试,现在简单字符串的解密正在工作,但有一个小问题。由于我要加密/解密的文件是 XML,所以我的字符串包含“”,解密后它们都没有出现。你知道为什么会这样吗?以上是关于AES 解密错误:android 垫块损坏的主要内容,如果未能解决你的问题,请参考以下文章