繁体   English   中英

在java中加密文件并使用密钥aes在openssl中解密

[英]Encrypt file in java and decrypt in openssl with key aes

我引用链接在java中加密文件(已成功创建加密文件)

后来我想用openssl解密它。 我尝试了以下命令,但它们似乎都不起作用。 请建议正确的命令以在 openssl 中解密。

openssl aes-256-cbc -d -in sample.crypt -out sample.txt -k testpass

显示“坏幻数”

openssl enc -aes-256-cbc -base64 -pass pass:testpass -d -p -in sample.crypt -out sample.txt

显示“错误读取输入文件”

这是我的加密java代码:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Base64;

import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import static java.nio.charset.StandardCharsets.US_ASCII;
import static java.nio.charset.StandardCharsets.UTF_8;

public class EncryptTest {

    private static final String SALTED_STR = "Salted__";
    private static final byte[] SALTED_MAGIC = SALTED_STR.getBytes(US_ASCII);
    static String password = "testpass";

    public static String encryptfile(Context context, String path, int category) {
            try {
                FileInputStream fis = new FileInputStream(path);
                FileOutputStream fos = new FileOutputStream(path.concat(".crypt"));
                final byte[] pass = password.getBytes(US_ASCII);
                final byte[] salt = (new SecureRandom()).generateSeed(8);

                final byte[] passAndSalt = array_concat(pass, salt);
                byte[] hash = new byte[0];
                byte[] keyAndIv = new byte[0];
                for (int i = 0; i < 3 && keyAndIv.length < 48; i++) {
                    final byte[] hashData = array_concat(hash, passAndSalt);
                    final MessageDigest md = MessageDigest.getInstance("MD5");
                    hash = md.digest(hashData);
                    keyAndIv = array_concat(keyAndIv, hash);
                }

                final byte[] keyValue = Arrays.copyOfRange(keyAndIv, 0, 32);
                final byte[] iv = Arrays.copyOfRange(keyAndIv, 32, 48);
                final SecretKeySpec key = new SecretKeySpec(keyValue, "AES");

                final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
                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();
                Log.e(TAG, "encrypt done " + path);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (NoSuchPaddingException e) {
                e.printStackTrace();
            } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
                e.printStackTrace();
            }
        }

        return path;
}   

OpenSSL 需要一种特殊格式,即Salted__的 ASCII 编码值,后跟 8 个字节的 salt,后跟实际的密文。 在发布的 Java 代码中,没有写入第一个块(ASCII 编码的Salted__加盐),即必须添加,例如:

...
final byte[] salt = (new SecureRandom()).generateSeed(8);
fos.write(SALTED_MAGIC);
fos.write(salt);
...

通过此更改,密文包含使用 OpenSSL 解密所需的信息和格式。

应该注意的是,OpenSSL 在早期版本中使用 MD5 作为默认摘要,从 v1.1.0 版本开始使用 SHA256。 对于后面的版本,因此必须-md md5添加到 OpenSSL 语句中(对于早期版本,它是可选的)。

两个发布的 OpenSSL 语句都成功解密了在我的机器上使用(修改过的)Java 代码创建的密文(在第二个语句中,必须删除-base64选项,因为 Java 代码没有对密文进行 Base64 编码):

openssl aes-256-cbc -d -in sample.crypt -out sample.txt -k testpass -md md5
openssl enc -aes-256-cbc -pass pass:testpass -d -p -in sample.crypt -out sample.txt -md md5

还应该提到的是,OpenSSL 应用EVP_BytesToKey()函数来导出密钥和 IV。 此功能不是标准,被认为相对不安全,请参见例如此处 新版本的 OpenSSL 会生成相应的警告(警告:不推荐使用的密钥派生)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM