"Error while finalizing cipher" 解密文件时
"Error while finalizing cipher" when decrypting a file
每当我想解密我之前加密的文件时,我得到 "error while finalizing cipher"。
出于测试目的,我刚刚从 复制粘贴了 Pero 的代码。
我所做的更改只是删除了盐并将其替换为我的 md5 函数。
在那之前我用盐试过它,它给了我同样的错误:(
在那个问题中,问题似乎以某种方式解决了,但他没有进一步详细说明,这只是我什至没有使用的盐。
public static void encrypt(String path, String password) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
FileInputStream fis = new FileInputStream(path);
FileOutputStream fos = new FileOutputStream(path.concat(".scrypt"));
byte[] key = md5(password).getBytes("UTF-8");
MessageDigest sha = MessageDigest.getInstance("SHA-1");
key = sha.digest(key);
key = Arrays.copyOf(key,16);
SecretKeySpec sks = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, sks);
CipherOutputStream cos = new CipherOutputStream(fos, cipher);
int b;
byte[] d = new byte[8];
while((b = fis.read(d)) != -1) {
cos.write(d, 0, b);
}
cos.flush();
cos.close();
fis.close();
}
public static void decrypt(String path, String password) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
FileInputStream fis = new FileInputStream(path);
FileOutputStream fos = new FileOutputStream(path.replace(".scrypt", ""));
byte[] key = md5(password).getBytes("UTF-8");
MessageDigest sha = MessageDigest.getInstance("SHA-1");
key = sha.digest(key);
key = Arrays.copyOf(key,16);
SecretKeySpec sks = new SecretKeySpec(key, "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();
}
md5() 等同于 php 的 md5()
如果有人能帮助我,那就太棒了,我搜索了几个小时的解决方案:(
不同之处在于encrypt
:
byte[] key = md5(password).getBytes("UTF-8");
和decrypt
:
byte[] key = (salt + password).getBytes("UTF-8");
不用说,这会导致不同的密钥,从而无法正确解密。
这种从密码中派生出的密钥在远程并不安全。密码具有低熵,但密钥具有高熵。如果您想将密码转换为密钥,则需要使用计算密集型操作,这样攻击者就无法尝试所有简单的密码。这可以通过 PBKDF2、bcrypt、scrypt 或 Argon2 来完成。使用多次迭代或高成本因素,并始终使用随机生成的盐。盐不必是秘密的,但它必须与密文一起发送给接收者。可以写在密文前面,解密时读回来
始终使用完全限定的密码字符串,因为不同的 JVM 可能有不同的默认值。这将使互操作性成为一场噩梦。您当前的字符串可能默认为 Cipher.getInstance("AES/ECB/PKCS5Padding");
永远不要使用 ECB mode. It's deterministic and therefore not semantically secure. You should at the very least use a randomized mode like CBC or CTR. It is better to authenticate your ciphertexts so that attacks like a padding oracle attack are not possible. This can be done with authenticated modes like GCM or EAX, or with an encrypt-then-MAC 方案。
每当我想解密我之前加密的文件时,我得到 "error while finalizing cipher"。
出于测试目的,我刚刚从
我所做的更改只是删除了盐并将其替换为我的 md5 函数。 在那之前我用盐试过它,它给了我同样的错误:(
在那个问题中,问题似乎以某种方式解决了,但他没有进一步详细说明,这只是我什至没有使用的盐。
public static void encrypt(String path, String password) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
FileInputStream fis = new FileInputStream(path);
FileOutputStream fos = new FileOutputStream(path.concat(".scrypt"));
byte[] key = md5(password).getBytes("UTF-8");
MessageDigest sha = MessageDigest.getInstance("SHA-1");
key = sha.digest(key);
key = Arrays.copyOf(key,16);
SecretKeySpec sks = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, sks);
CipherOutputStream cos = new CipherOutputStream(fos, cipher);
int b;
byte[] d = new byte[8];
while((b = fis.read(d)) != -1) {
cos.write(d, 0, b);
}
cos.flush();
cos.close();
fis.close();
}
public static void decrypt(String path, String password) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
FileInputStream fis = new FileInputStream(path);
FileOutputStream fos = new FileOutputStream(path.replace(".scrypt", ""));
byte[] key = md5(password).getBytes("UTF-8");
MessageDigest sha = MessageDigest.getInstance("SHA-1");
key = sha.digest(key);
key = Arrays.copyOf(key,16);
SecretKeySpec sks = new SecretKeySpec(key, "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();
}
md5() 等同于 php 的 md5()
如果有人能帮助我,那就太棒了,我搜索了几个小时的解决方案:(
不同之处在于encrypt
:
byte[] key = md5(password).getBytes("UTF-8");
和decrypt
:
byte[] key = (salt + password).getBytes("UTF-8");
不用说,这会导致不同的密钥,从而无法正确解密。
这种从密码中派生出的密钥在远程并不安全。密码具有低熵,但密钥具有高熵。如果您想将密码转换为密钥,则需要使用计算密集型操作,这样攻击者就无法尝试所有简单的密码。这可以通过 PBKDF2、bcrypt、scrypt 或 Argon2 来完成。使用多次迭代或高成本因素,并始终使用随机生成的盐。盐不必是秘密的,但它必须与密文一起发送给接收者。可以写在密文前面,解密时读回来
始终使用完全限定的密码字符串,因为不同的 JVM 可能有不同的默认值。这将使互操作性成为一场噩梦。您当前的字符串可能默认为 Cipher.getInstance("AES/ECB/PKCS5Padding");
永远不要使用 ECB mode. It's deterministic and therefore not semantically secure. You should at the very least use a randomized mode like CBC or CTR. It is better to authenticate your ciphertexts so that attacks like a padding oracle attack are not possible. This can be done with authenticated modes like GCM or EAX, or with an encrypt-then-MAC 方案。