java.security.InvalidKeyException:

我经历了许多类似的话题,但没有运气!!


我想使用 PEM 文件生成公钥和私钥。以下是我使用的代码:


        String pemFileNme = "C:\\Users\\amitmm\\Desktop\\clean\\key.pem";


        File pubKeyFile = new File(pemFileNme);

        File privKeyFile = new File(pemFileNme);


        // read public key DER file

        DataInputStream dis = new DataInputStream(new 

        FileInputStream(pubKeyFile));

        byte[] pubKeyBytes = new byte[(int)pubKeyFile.length()];

        dis.readFully(pubKeyBytes);

        dis.close();


        // read private key DER file

        dis = new DataInputStream(new FileInputStream(privKeyFile));

        byte[] privKeyBytes = new byte[(int)privKeyFile.length()];

        dis.read(privKeyBytes);

        dis.close();


        KeyFactory keyFactory = KeyFactory.getInstance("RSA");


        // decode public key

        X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(pubKeyBytes);

        RSAPublicKey pubKey = (RSAPublicKey) 

        keyFactory.generatePublic(pubSpec);


        // decode private key

        PKCS8EncodedKeySpec privSpec = new 

        PKCS8EncodedKeySpec(privKeyBytes);

        RSAPrivateKey privKey = (RSAPrivateKey) 

        keyFactory.generatePrivate(privSpec);

例外:


Exception in thread "main" java.security.spec.InvalidKeySpecException: 

java.security.InvalidKeyException: invalid key format

at

sun.security.rsa.RSAKeyFactory.engineGeneratePublic(RSAKeyFactory.java:205)

at java.security.KeyFactory.generatePublic(KeyFactory.java:334)

at main.java.me.txedo.security.Main2.f1(Main2.java:47)

at main.java.me.txedo.security.Main2.main(Main2.java:20)

Caused by: java.security.InvalidKeyException: invalid key format

at sun.security.x509.X509Key.decode(X509Key.java:387)

我尝试手动删除文件页眉和页脚。我尝试了 bouncycastle 的代码,没有运气,同样的错误。


12345678_0001
浏览 914回答 1
1回答

小唯快跑啊

部分欺骗从文件加载 RSA 公钥因此,您“编写”(我假设是复制)代码,明确说明您需要两个 DER 格式的文件,其中包含 PKCS8 和“X509”编码。(这里 Java 所说的 X.509 实际上是 X.509的 SubjectPublicKeyInfo组件。)你给它一个文件,以 PEM 形式而不是 DER,包含一个 PKCS1 编码而不是 PKCS8或X509——你很惊讶它不起作用?Python 之所以能工作,是因为它调用了 OpenSSL,而 OpenSSL 支持十多种私钥的编码和格式,包括这个;Java 仅支持一种(在密钥库之外),而不是这种。(裸)公钥好一点;libcrypto内部支持多种形式,但在实践中只使用了其中两种,其中一种匹配Java——虽然很多公钥都是以X.509证书的形式分发、存储和使用的,这提供了更多令人担忧的形式关于。您的情况大约有 7 种解决方案:最简单的是使用 OpenSSL 命令行将您的一个文件转换为 Java 想要的两个文件:  # (corrected! pkey is inconsistent!)   openssl pkcs8 -topk8 -nocrypt -in input.pem -outform der -out private.der  openssl pkey -in input.pem -pubout -outform der -out public.der  # or for very old versions (should not be needed now)  openssl rsa -in input.pem -pubout -outform der -out public.der现在可以通过您发布的代码读取这些文件(文件名分开除外)。请注意,此转换不必在同一系统上完成;如有必要,您可以在其他地方执行并复制文件,如果您使用适用于二进制文件的方法,即不剪切和粘贴。如果你真的只想要一个文件,但它可以被转换,private.der按照上面的方法创建文件并只用你的代码中与私钥相关的部分来读取它,然后执行:  RSAPrivateCrtKey priv2 = (RSAPrivateCrtKey)privKey;  PublicKey pubkey = keyFactory.generatePublic(new RSAPublicKeySpec(priv2.getModulus(), priv2.getPublicExponent()));您可以通过省略上述转换将文件转换为 PKCS8 和 'X509' PEM-outform der,然后读取这些文件并通过删除标题和尾部行并将 base64 转换为二进制(删除或跳过换行符)来手动“de-PEM” ; 这会生成二进制 PKCS8 和 X509 编码,您可以运行现有代码。这与 openssl 方面的工作一样多,而在 Java 方面的工作更多,因此没有明显的优势,除了 PEM 文件是有效的文本并且可以在必要时进行剪切和粘贴。结合这些,您可以仅转换为 PKCS8 PEM,阅读每个项目符号 3(de-PEM 然后是代码的私钥部分),然后从每个项目符号 2 的私钥中提取公钥在普通 Java 中使用您拥有的(未转换的)格式的一种方法是对每个项目符号 3 进行 de-PEM,为您提供 PKCS1 编码,然后手动构建 PKCS8 编码,然后像以前一样继续通过 PKCS8 运行 PKCS8KeyFactory并提取每个项目符号的公钥2. 请参阅我在Java 上的回答:将 DKIM 私钥从 RSA 转换为 JavaMail 的 DER,这是一种非常丑陋的方法(包括一种 de-PEM 方法)。如果您使用 BouncyCastle(它有一个用于此 ASN.1 类型的类),则有更好的方法,但如果您使用 BouncyCastle,则最好完全不要使用此方法,请参见下文。在普通 Java 中使用未转换格式的另一种方法是按第 3 项对 PEM 进行 de-PEM,然后解析PKCS1 的 ASN.1 结构并构造一个RSAPrivateCrtKeySpec您可以运行的KeyFactory 而不是PKCS8 编码,然后按第 2 项提取公钥。这甚至更复杂,虽然我想我在某处见过它;如果我找到它会添加。同样,BouncyCastle 可以改进这种方法,但不需要,见下文。最后,如果你有 BouncyCastle,那就太容易了。你没有说你试过什么“没有运气”,但下面的 BouncyCastle 代码是你所需要的,并且确实有效:  try( Reader r = new FileReader(filename) ){    KeyPair pair = new JcaPEMKeyConverter().getKeyPair((PEMKeyPair)new PEMParser(r).readObject());  }请注意,这为您KeyPair提供了一个文件中的私钥和公钥对象。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java