Java 加密/解密文件和不正确的数据
我使用这些函数对文件进行加密/解密,但在某些设备上我得到了不正确的数据 例如,我的正确数据是: 一个 两个 三 四 五 解密后: 一个 两个 三 ൰Ẓ㫩 ൰Ẓ㫩 我使用了postdayed()函数,但这并不重要Java 加密/解密文件和不正确的数据,java,android,encryption,Java,Android,Encryption,我使用这些函数对文件进行加密/解密,但在某些设备上我得到了不正确的数据 例如,我的正确数据是: 一个 两个 三 四 五 解密后: 一个 两个 三 ൰Ẓ㫩 ൰Ẓ㫩 我使用了postdayed()函数,但这并不重要 static void decrypt() throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException { FileInputStream fis = ne
static void decrypt() throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
FileInputStream fis = new FileInputStream("data/encrypted");
FileOutputStream fos = new FileOutputStream("data/decrypted");
SecretKeySpec sks = new SecretKeySpec("MyDifficultPassw".getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, sks);
CipherInputStream cis = new CipherInputStream(fis, cipher);
int b;
byte[] d = new byte[8];
while((b = cis.read(d)) != -1) {
fos.write(d, 0, b);
}
fos.flush();
fos.close();
cis.close();
}
文件大小为80 KB
它在模拟器上有问题!!
它在三星gt-s7562上有问题,但在galaxy s4上一切正常 我发现您的代码至少存在两个潜在的平台兼容性问题:
getBytes()
:
decrypt();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
getContentsFile();
}
}, 7000);
应该是:(例如)
旁注:您真的不应该从字符串的原始字节创建密钥。改为使用密码派生方法,如PBKDF2。我使用这两种方法进行加密/解密,它们在任何设备上都非常适合我。它的工作方式与您略有不同,因此请尝试比较这两种方法,看看哪些方法可能会出错 用于加密: 获取:
iv
向量和要加密的消息:
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
用于解密:
public String getEncrypt(final byte[] iv, final String message) throws GeneralSecurityException, NullPointerException {
if (key.isEmpty())
throw new NullPointerException();
final byte[] rawData = key.getBytes(Charset.forName("US-ASCII"));
if (rawData.length != 16) {
// If this is not 16 in length, there's a problem with the key size, nothing to do here
throw new IllegalArgumentException("You've provided an invalid key size");
}
final SecretKeySpec seckeySpec = new SecretKeySpec(rawData, "AES");
final Cipher ciph = Cipher.getInstance("AES/CBC/PKCS5Padding");
ciph.init(Cipher.ENCRYPT_MODE, seckeySpec, new IvParameterSpec(iv));
byte[] encryptedBA = ciph.doFinal(message.getBytes(Charset.forName("US-ASCII")));
try {
final String encryptedText = new String(Base64.encode(encryptedBA, Base64.DEFAULT), "UTF-8");
return encryptedText.toString();
}
catch (final UnsupportedEncodingException e1) { }
return "";
}
你在一台设备上加密,在另一台设备上解密吗?我在galaxy S4上加密文件,然后将文件上载到主机上,然后可以在每个设备上下载。我使用了这些功能,尝试将其添加到我发布的内容中,因为这些功能工作顺利。直接使用字符串字节作为密码是不好的。请不要建议使用“US-ASCII”或者实际上除了“UTF-8”之外的任何东西。@OlegEstekhin想解释一下原因吗?如果一个人与选择一致并且理解输入字符的范围,我不确定我是否看到了问题。“UTF-8”可能是相同的一致选择,并且它没有一个问题,因为不需要关心字符的范围。@OlegEstekhin在这些情况下,我经常建议使用“US-ASCII”,因为人们期望密码中的字符数和密钥中的字节数之间存在一对一的对应关系。无论如何,这里最大的犯罪是从原始字符串字节派生密码,而不是使用更安全的方法。@OlegEstekhin,尽管我的逻辑在这方面可能有缺陷(基于一些快速测试)。我假设16个字符与US-ASCII总是等同于16个字节,但事实似乎并非如此。我将把我的示例更新为UTF-8。
SecretKeySpec sks = new SecretKeySpec(
"MyDifficultPassw".getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
public String getEncrypt(final byte[] iv, final String message) throws GeneralSecurityException, NullPointerException {
if (key.isEmpty())
throw new NullPointerException();
final byte[] rawData = key.getBytes(Charset.forName("US-ASCII"));
if (rawData.length != 16) {
// If this is not 16 in length, there's a problem with the key size, nothing to do here
throw new IllegalArgumentException("You've provided an invalid key size");
}
final SecretKeySpec seckeySpec = new SecretKeySpec(rawData, "AES");
final Cipher ciph = Cipher.getInstance("AES/CBC/PKCS5Padding");
ciph.init(Cipher.ENCRYPT_MODE, seckeySpec, new IvParameterSpec(iv));
byte[] encryptedBA = ciph.doFinal(message.getBytes(Charset.forName("US-ASCII")));
try {
final String encryptedText = new String(Base64.encode(encryptedBA, Base64.DEFAULT), "UTF-8");
return encryptedText.toString();
}
catch (final UnsupportedEncodingException e1) { }
return "";
}
public String getDecrypt(final byte[] encrypted) throws GeneralSecurityException, NullPointerException {
if (key.isEmpty())
throw new NullPointerException();
final byte[] rawData = key.getBytes(Charset.forName("US-ASCII"));
if (rawData.length != 16) {
// If this is not 16 in length, there's a problem with the key size, nothing to do here
throw new IllegalArgumentException("Invalid key size.");
}
final SecretKeySpec seckeySpec = new SecretKeySpec(rawData, "AES");
final Cipher ciph = Cipher.getInstance("AES/CBC/PKCS5Padding");
ciph.init(Cipher.DECRYPT_MODE, seckeySpec, new IvParameterSpec(new byte[16]));
final byte[] decryptedmess = ciph.doFinal(encrypted);
return new String(decryptedmess, Charset.forName("US-ASCII"));
}