Java “如何修复”;无效的密钥格式";从文件中读取公钥或私钥时?
我已经创建了公钥和私钥。php代码生成的公钥和私钥:Java “如何修复”;无效的密钥格式";从文件中读取公钥或私钥时?,java,php,cryptography,rsa,phpseclib,Java,Php,Cryptography,Rsa,Phpseclib,我已经创建了公钥和私钥。php代码生成的公钥和私钥: <?php require __DIR__ . '/vendor/autoload.php'; use phpseclib\Crypt\RSA; $rsa = new RSA(); extract($rsa->createKey()); $rsa->setPrivateKeyFormat(RSA::PRIVATE_FORMAT_PKCS8); $rsa->setPubl
<?php
require __DIR__ . '/vendor/autoload.php';
use phpseclib\Crypt\RSA;
$rsa = new RSA();
extract($rsa->createKey());
$rsa->setPrivateKeyFormat(RSA::PRIVATE_FORMAT_PKCS8);
$rsa->setPublicKeyFormat(RSA::PUBLIC_FORMAT_PKCS8);
file_put_contents("privateKey.pem",$privatekey);
file_put_contents("publicKey.pem", $publickey);
它生成java.security.InvalidKeyException:无效密钥格式。
我需要帮助。提前感谢。首先,如评论中所述,没有PKCS#8公钥。这意味着PHP库不知道它在说什么。相反,如果neubert是正确的,您似乎得到的是一个为X.509证书定义的结构,名为
X509EncodedKeySpec
。在Java代码中,您确实试图使用它来读取公钥
但是,您忘记的是X509EncodedKeySpec
是ASN.1 DER中指定的二进制格式。您收到的是一个使用ASCII保护的PEM编码密钥。换句话说,二进制文件已编码为base64,并添加了页眉和页脚行。这样做是为了使其与文本接口(如邮件(隐私增强邮件或PEM))兼容
所以你要做的就是移除盔甲。最好使用Bouncy Castle提供的PEM阅读器来实现这一点
PemReader=newpemreader(newfilereader(“spki.pem”);
PemObject readPemObject=reader.readPemObject();
字符串类型=readPemObject.getType();
字节[]subjectPublicKey=readPemObject.getContent();
系统输出打印项次(类型);
X509EncodedKeySpec=新X509EncodedKeySpec(主题公钥);
KeyFactory kf=KeyFactory.getInstance(“RSA”);
RSAPublicKey publikey=(RSAPublicKey)kf.generatePublic(spec);
System.out.println(pubKey);
哪张照片
公钥
接
Sun RSA公钥,1024位
参数:null
模数:11944573232327954598056145200053932732877863846799652384989588303752732874397055988321114648728631716814244695550890293603512470937221178664495142802998472668683753168203283261713419770651542536651368444940702230798655555555555555717164202446955555555555590239046794919
公众指数:65537
对于怀疑论者——以下是主题PublicKeyInfo的定义:
SubjectPublicKeyInfo::=序列{
算法识别器,
subjectPublicKey位字符串}
其中subjectPublicKey
包含PKCS#1格式的编码公钥-当然是RSA公钥
是纽伯特钥匙的解码版本,你可以比较一下。Java中解析的密钥是同一个密钥。能否包含“PKCS#8编码”公钥?因为没有PKCS#8编码的公钥;PKCS#8仅用于私钥/密钥(实际上,其标题是“私钥信息语法规范1.2版”)。因此,这是另一个PHP决定“有所作为”而不是因为代码不正确而失败的例子。@Maarten-Monica-在本例中,PKCS#8所指的是使用以下ASN.1格式的密钥:当然,PKCS#8可能不是最好的描述,但idk应该是什么。此类密钥以
----开始公钥------
开始。这与Xihar的库所称的PKCS#1密钥形成了对比,PKCS#1密钥以---BEGIN RSA公钥------
或---BEGIN EC公钥------
或其他任何形式开始。我明白了-PKCS#1只讨论RSA而不是EC公钥,但你还打算称它为什么?@Maarten-Monica-尽管如此,我还是希望它是OP(Xihar)所讨论的格式的密钥。@neubert最后一个是名为SubjectPublicKeyInfo
的结构,它是X.509证书格式的一部分(因此,X509EncodedKeySpec
在Java中)@Maarten-Monica-最佳名称的构成有点主观。对于私钥PKCS#8最终是一种包装格式,包含特定于算法的信息,作为需要单独解码的八位字节字符串。从精神上讲,这与Java的X509EncodedKeySpec
是一样的,在某些方面我觉得它是y是一个更好的名字,因为X509EncodedKeySpec
可能会在不应该出现的时候出现整个X.509规范的图像。非常感谢您提供的详细解决方案。它工作正常。
import java.io.*;
import java.security.*;
import java.security.spec.*;
public class PublicKeyReader {
public static PublicKey get(String filename)
throws Exception {
File f = new File(filename);
FileInputStream fis = new FileInputStream(f);
DataInputStream dis = new DataInputStream(fis);
byte[] keyBytes = new byte[(int)f.length()];
dis.readFully(keyBytes);
dis.close();
X509EncodedKeySpec spec =
new X509EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePublic(spec);
}
public static void main (String [] args) throws Exception {
PublicKeyReader publicKeyReader = new PublicKeyReader();
PublicKey publicKey = publicKeyReader.get("key/testPub.pem");
System.out.println(publicKey);
}
}