从文件加载公钥数据加载、文件、公钥、数据

2023-09-07 16:15:03 作者:姑苏烟雨泪涟痕

在我的应用我生成公钥/私钥对,并将其存储在磁盘上以备以后使用。加载和重新初始化私钥工作正常,但私钥我得到一个未知KeySpec类型:java.security.spec.PKCS8En codedKeySpec - 我不知道为什么。

In my App I generate a public/private key pair and store them for later usage on disk. Loading and re-initialising the private key works fine but for the private key I get a Unknown KeySpec type: java.security.spec.PKCS8EncodedKeySpec - and I have no idea why.

这就是我如何创建并保存键(code有点简化为更易于阅读):

That's how I create and save the keys (code a bit simplified to be easier to read):

KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(4096);
KeyPair keyPair = kpg.generateKeyPair();
privKey =keyPair.getPrivate();
pubKey =keyPair.getPublic();        

DataOutputStream out=new DataOutputStream(ctx.openFileOutput(PRIVKEY_FILE,Context.MODE_PRIVATE));
byte[] data=privKey.getEncoded();
out.write(data);
out.close();

DataOutputStream out=new DataOutputStream(ctx.openFileOutput(PUBKEY_FILE,Context.MODE_PRIVATE));
byte[] data=pubKey.getEncoded();
out.write(data);
out.close();

私有密钥加载下正常工作:

Next loading of the private key works fine:

DataInputStream in=new DataInputStream(ctx.openFileInput(PRIVKEY_FILE));
byte[] data=new byte[in.available()];
in.readFully(data);

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(data);
KeyFactory kf = KeyFactory.getInstance("RSA");
privKey = kf.generatePrivate(keySpec);

decryptCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
decryptCipher.init(Cipher.DECRYPT_MODE, privKey);

类似code的公钥惨遭失败:

Similar code for the public key fails miserably:

DataInputStream in=new DataInputStream(ctx.openFileInput(PUBKEY_FILE));
byte[] data=new byte[in.available()];
in.readFully(data);

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(data);
KeyFactory kf = KeyFactory.getInstance("RSA");
pubKey = kf.generatePublic(keySpec); --> here the exception is thrown

encryptCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
encryptCipher.init(Cipher.ENCRYPT_MODE, pubKey);             

那么,我做错了什么?什么是从磁盘加载一个公共密钥数据的正确方法?

So what am I doing wrong? What is the proper way of loading a public keys data from disk?

谢谢!

推荐答案

公钥和私钥都设有codeD不同。虽然私钥是连接在PKCS#8 codeD,公钥都没有。他们是不是在连接X.509 codeD根据ASN.1规范。

Public and Private keys are encoded differently. Whilst private keys are encoded in PKCS #8, public keys are not. They are instead encoded in X.509 according to the ASN.1 specifications.

从Key.getFormat()方法说明:

Description from the Key.getFormat() method:

返回此密钥的基本编码格式,或者为null,如果此密钥不支持编码的名称。主要的编码格式是在合适的ASN.1数据格式条款命名,如果此密钥的ASN.1规范存在。例如,对于公钥的ASN.1数据格式的名称是SubjectPublicKeyInfo进行,由X.509标准所定义;在这种情况下,返回的格式是X.509。同样,对于私钥的ASN.1数据格式的名称是PrivateKeyInfo进行,由PKCS#8标准定义;在这种情况下,返回的格式是PKCS#8

Returns the name of the primary encoding format of this key, or null if this key does not support encoding. The primary encoding format is named in terms of the appropriate ASN.1 data format, if an ASN.1 specification for this key exists. For example, the name of the ASN.1 data format for public keys is SubjectPublicKeyInfo, as defined by the X.509 standard; in this case, the returned format is "X.509". Similarly, the name of the ASN.1 data format for private keys is PrivateKeyInfo, as defined by the PKCS #8 standard; in this case, the returned format is "PKCS#8".

根据这一点,而不是读取公钥作为PKCS#8,你应该读得X.509。

According to this, instead of reading public keys as PKCS #8, you should read it as X.509.

考虑从改变你的公钥阅读code:

Consider changing your public key reading code from:

PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(data);

X509EncodedKeySpec keySpec = new X509EncodedKeySpec(data);
 
精彩推荐
图片推荐