static void encrypt() throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
// Here you read the cleartext.
FileInputStream fis = new FileInputStream("data/cleartext");
// This stream write the encrypted text. This stream will be wrapped by another stream.
FileOutputStream fos = new FileOutputStream("data/encrypted");
// Length is 16 byte
SecretKeySpec sks = new SecretKeySpec("MyDifficultPassw".getBytes(), "AES");
// Create cipher
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, sks);
// Wrap the output stream
CipherOutputStream cos = new CipherOutputStream(fos, cipher);
// Write bytes
int b;
byte[] d = new byte[8];
while((b = fis.read(d)) != -1) {
cos.write(d, 0, b);
}
// Flush and close streams.
cos.flush();
cos.close();
fis.close();
}
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();
}
我将这些功能用于加密/解密文件,但在某些设备上我收到的数据不正确。
例如,我的正确数据是:
一个
2
3
4
5
解密后:
一个
2
3
൰Ẓ㫩
൰Ẓ㫩
我使用了postDelayed()函数但是没关系!
decrypt();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
getContentsFile();
}
}, 7000);
文件大小为80 Kilobytes!
它在模拟器上有问题!! 它在samsung gt-s7562上有问题,但是对于galaxy s4一切都还可以!!
答案 0 :(得分:0)
我发现您的代码至少存在两个潜在的平台兼容性问题:
如果没有声明字符集,请不要致电getBytes()
:
SecretKeySpec sks = new SecretKeySpec("MyDifficultPassw".getBytes(), "AES");
应该是:(例如)
SecretKeySpec sks = new SecretKeySpec(
"MyDifficultPassw".getBytes("UTF-8"), "AES");
始终指定完整转换,例如“AES / CBC / PKCS5Padding”:
Cipher cipher = Cipher.getInstance("AES");
应(例如)
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
这可能是导致问题的原因。不同的平台具有不同的默认字符集,这意味着您将获得密钥的不同字节串。
不常见的是,当您选择"AES"
时,不同的加密提供程序具有不同的默认值。有些人会进行ECB模式加密,有些人会进行CBC模式加密。最准确地宣布你想要的是最安全的。
旁注:你真的不应该从字符串的原始字节创建一个键。请改用密码派生方法,例如PBKDF2。
答案 1 :(得分:0)
我使用这两种方法进行加密/解密,它们可以在任何设备上完美地运行。它的完成方式略有不同,所以尝试比较两种方法,看看哪些方法可能有误。
加密:
获取:iv
向量和要加密的message
:
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"));
}