使用私钥文件解密:无效的流标头

时间:2018-02-23 10:55:30

标签: java encryption openssl cryptography

在命令行中,我可以使用openssl加密和解密我的文件,如下所示:

创建密钥:

openssl req -x509 -newkey rsa:2048 -keyout myKey.key -out myKey.crt -pubkey

加密:

cat myText.txt | openssl rsautl -encrypt -inkey myKey.crt -pubin >> encryptedtxt.enc

解密:

openssl rsautl -decrypt -inkey myKey.key -in encryptedtxt.enc > decryptedtxt.txt

我关注this tutorial

public static void main(String[] args) {

        String encryptedData = "..\\encryptedtxt.enc";
        File encryptedFIle = new File(encryptedData);

        try {
            byte[] data = Files.readAllBytes(encryptedFIle.toPath());
            PrivateKey privateKey = getPrivateKey();
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            byte[] decryptedData = cipher.doFinal(data);
            System.out.println(">" + new String(decryptedData));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    private static PrivateKey getPrivateKey() {
        String privateKeyFilename = "\\myKey.key";
        FileInputStream fis = null;
        ObjectInputStream ois = null;
        File privateKeyFile = new File(privateKeyFilename);
        try {
            fis = new FileInputStream(privateKeyFile);
            ois = new ObjectInputStream(fis);
            BigInteger modulus = (BigInteger) ois.readObject();
            BigInteger exponent = (BigInteger) ois.readObject();
            RSAPrivateKeySpec rsaPrivateKeySpec = new RSAPrivateKeySpec(modulus, exponent);
            KeyFactory fact = KeyFactory.getInstance("RSA");
            PrivateKey privateKey = fact.generatePrivate(rsaPrivateKeySpec);
            return privateKey;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

运行此操作时,会出现以下问题:

java.io.StreamCorruptedException: invalid stream header: 2D2D2D2D
    at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:857)
    at java.io.ObjectInputStream.<init>(ObjectInputStream.java:349)
    at Decryptor.getPrivateKey(TestClass.java:38)
    at Decryptor.main(TestClass.java:20)
java.security.InvalidKeyException: No installed provider supports this key: (null)
    at javax.crypto.Cipher.chooseProvider(Cipher.java:893)
    at javax.crypto.Cipher.init(Cipher.java:1249)
    at javax.crypto.Cipher.init(Cipher.java:1186)
    at Decryptor.main(TestClass.java:22)

有任何建议请我如何解决这个问题?

更新:

我修改了获取私钥的方法如下:

private static PrivateKey getPrivateKey() {
        String privateKeyFilename = "myKey.key";
        FileInputStream fis = null;
        ObjectInputStream ois = null;
        File privateKeyFile = new File(privateKeyFilename);
        try {
            String key = readFileAsString(privateKeyFilename);
            BASE64Decoder b64 = new BASE64Decoder();
            byte[] pkcs8EncodedBytes = b64.decodeBuffer(key);

            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pkcs8EncodedBytes);
            KeyFactory kf = KeyFactory.getInstance("RSA");
            PrivateKey privKey = kf.generatePrivate(keySpec);
            System.out.println(privKey);
            return privKey;

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

但随后出现以下错误:

java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : Short read of DER length
    at sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:217)
    at java.security.KeyFactory.generatePrivate(KeyFactory.java:372)
    at Decryptor.getPrivateKey(TestClass.java:61)
    at Decryptor.main(TestClass.java:19)
Caused by: java.security.InvalidKeyException: IOException : Short read of DER length
    at sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:351)
    at sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:356)
    at sun.security.rsa.RSAPrivateCrtKeyImpl.<init>(RSAPrivateCrtKeyImpl.java:91)
    at sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(RSAPrivateCrtKeyImpl.java:75)
    at sun.security.rsa.RSAKeyFactory.generatePrivate(RSAKeyFactory.java:316)
    at sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:213)
    ... 3 more
java.security.InvalidKeyException: No installed provider supports this key: (null)
    at javax.crypto.Cipher.chooseProvider(Cipher.java:893)
    at javax.crypto.Cipher.init(Cipher.java:1249)
    at javax.crypto.Cipher.init(Cipher.java:1186)
    at Decryptor.main(TestClass.java:21)

1 个答案:

答案 0 :(得分:3)

您正尝试使用ObjectInputStream阅读密钥。此类用于通用解码;它只解码特定于Java的序列化格式。您看到的错误是ObjectInputStream,通知您正在读取的数据不是序列化的Java对象。

OpenSSL生成的密钥文件不是Java序列化对象。相反,它使用PEM编码。有关从PEM文件中读取密钥的更多信息,请查看Decrypting an OpenSSL PEM Encoded RSA private key with Java?