如何用java读取密码加密密钥?

时间:2010-04-16 17:23:03

标签: java bouncycastle private-key jce pkcs#8

我将私钥存储在PKCS8 DER格式的文件中,并受密码保护。最简单的阅读方式是什么?

以下是我用来加载未加密的代码的代码:

InputStream in = new FileInputStream(privateKeyFilename);
byte[] privateKeydata = new byte[in.available()];
in.read(privateKeydata);
in.close();
KeyFactory privateKeyFactory = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec encodedKeySpec = new PKCS8EncodedKeySpec(privateKeydata);
PrivateKey privateKey = privateKeyFactory.generatePrivate(encodedKeySpec);

它适用于具有相同规范的未加密密钥。顺便说一下,我正在使用BouncyCastle。

我可以使用以下openssl命令

查看此私钥
openssl pkcs8 -in ./privatekey.key -inform DER -passin pass:thisismypass

请帮助!!!

我已经在我自己对这个主题的回答中发布了一些解决方案。但是,如果没有额外的库,只有BouncyCastle可以帮助让它工作,我仍然没有回答问题。

2 个答案:

答案 0 :(得分:7)

我找到了解决方案!也许它不那么优雅,但...... 在这里,我将发布两个解决方案:

  1. 可以忍受但不能正常工作
  2. 工作一个,但需要额外的库
  3. <强> 第一

    我找到了一种解决方案here,但它会抛出异常。解决方案:

    import java.io.*;
    import java.security.*;
    import java.security.interfaces.RSAPrivateCrtKey;
    import java.security.interfaces.RSAPublicKey;
    import java.security.spec.*;
    
    import javax.crypto.*;
    import javax.crypto.spec.*;
    
    /*
     * This class demonstrates how to import an encrypted RSA private key as
     * generated by openssl. The input file is presumed to be in DER
     * format.
     */
    public class ImportEncryptedPrivateKey
    {
        public static byte[] readPK8FromFile(String fileName) throws IOException
        {
            File f = new File(fileName);
            DataInputStream dis = new DataInputStream(new FileInputStream(f));
            byte[] theData = new byte[(int) f.length()];
            dis.readFully(theData);
            return theData;
        }
    
        public static void main(String[] args) throws IOException,
                NoSuchAlgorithmException, NoSuchPaddingException,
                InvalidKeySpecException, InvalidKeyException,
                InvalidAlgorithmParameterException
        {
            byte[] encryptedPKInfo = readPK8FromFile("rsapriv.pk8");
            EncryptedPrivateKeyInfo ePKInfo = new EncryptedPrivateKeyInfo(
                    encryptedPKInfo);
            char[] password = { 'p', 'a', 's', 's', 'w', 'o', 'r', 'd' };
            Cipher cipher = Cipher.getInstance(ePKInfo.getAlgName());
            PBEKeySpec pbeKeySpec = new PBEKeySpec(password);
            // Now create the Key from the PBEKeySpec
            SecretKeyFactory skFac = SecretKeyFactory.getInstance(ePKInfo
                    .getAlgName());
            Key pbeKey = skFac.generateSecret(pbeKeySpec);
            // Extract the iteration count and the salt
            AlgorithmParameters algParams = ePKInfo.getAlgParameters();
            cipher.init(Cipher.DECRYPT_MODE, pbeKey, algParams);
            // Decrypt the encryped private key into a PKCS8EncodedKeySpec
            KeySpec pkcs8KeySpec = ePKInfo.getKeySpec(cipher);
            // Now retrieve the RSA Public and private keys by using an
            // RSA keyfactory.
            KeyFactory rsaKeyFac = KeyFactory.getInstance("RSA");
            // First get the private key
            RSAPrivateCrtKey rsaPriv = (RSAPrivateCrtKey) rsaKeyFac.generatePrivate(pkcs8KeySpec);
            // Now derive the RSA public key from the private key
            RSAPublicKeySpec rsaPubKeySpec = new RSAPublicKeySpec(rsaPriv.getModulus(), rsaPriv.getPublicExponent());
            RSAPublicKey rsaPubKey = (RSAPublicKey) rsaKeyFac.generatePublic(rsaPubKeySpec);
        }
    
    }
    

    我的例外:

    Exception in thread "main" java.security.NoSuchAlgorithmException: No such algorithm: 1.2.840.113549.1.5.13
    

    <强> 第二

    在此http://juliusdavies.ca/commons-ssl/pkcs8.html之后,您可以阅读第二个有效的解决方案

答案 1 :(得分:1)

这是我的代码,它的工作原理是:)

File f = new File(keyFile);
FileInputStream fis = new FileInputStream(f);
DataInputStream dis = new DataInputStream(fis);
byte[] keyBytes = new byte[(int)f.length()];
dis.readFully(keyBytes);
dis.close();
EncryptedPrivateKeyInfo encryptPKInfo = new EncryptedPrivateKeyInfo(keyBytes);
Cipher cipher = Cipher.getInstance(encryptPKInfo.getAlgName());
PBEKeySpec pbeKeySpec = new PBEKeySpec(passwd.toCharArray());
SecretKeyFactory secFac = SecretKeyFactory.getInstance(encryptPKInfo.getAlgName());
Key pbeKey = secFac.generateSecret(pbeKeySpec);
AlgorithmParameters algParams = encryptPKInfo.getAlgParameters();
cipher.init(Cipher.DECRYPT_MODE, pbeKey, algParams);
KeySpec pkcs8KeySpec = encryptPKInfo.getKeySpec(cipher);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(pkcs8KeySpec);