jce 私钥与OPENSSL私钥文件的版本兼容性及DER编码转换

因为openssl 1.0以前的版本对私钥编码方式和PKCS#8私钥编码方式有点不同.如果你查看PKCS#8,你可以看到私钥的ASN.1 module如下:

PrivateKeyInfo ::= SEQUENCE {
  version Version,
  privateKeyAlgorithm AlgorithmIdentifier {{PrivateKeyAlgorithms}},
  privateKey PrivateKey,
  attributes [0] Attributes OPTIONAL }

Version ::= INTEGER {v1(0)} (v1,...)

PrivateKey ::= OCTET STRING ----openssl的传统编码

Attributes ::= SET OF Attribute

    如果在Java程序中使用PrivateKey.getEncoded()方法的话,得到的是整个PKCS8的结构的ASN.1的DER编码.而openssl1.0以前的私钥编码方式中是直接对上面的那个OCTET STRING进行编码的,也就是说,里面只包含了RSA私钥的几个必须的BigInteger.如果需要用JCE生存私钥文件,再由Openssl1.0以前的来使用该私钥文件,则需要进行转换。基于BouncyCastle我们可以很方便的写出这样子的转换方法。

  public byte[] getOpensslEncodeKey(PrivateKey pKey){
try
{
RSAPrivateCrtKey rsaKey = (RSAPrivateCrtKey) pKey;
RSAPrivateKeyStructure rsastruct = new RSAPrivateKeyStructure(
rsaKey.getModulus(), rsaKey.getPublicExponent(),
rsaKey.getPrivateExponent(), rsaKey.getPrimeP(),
rsaKey.getPrimeQ(), rsaKey.getPrimeExponentP(),
rsaKey.getPrimeExponentQ(), rsaKey.getCrtCoefficient());
ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream();
DEROutputStream deroutputstream = new DEROutputStream(
bytearrayoutputstream);
deroutputstream.writeObject(rsastruct.getDERObject());
deroutputstream.close();
return bytearrayoutputstream.toByteArray();

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

return null;
}
 这样,就可以了。

  从openssl1.0以后的版本,对私钥编码就是按PKCS#8私钥编码来处理的了,这就和在Java程序中使用PrivateKey.getEncoded()方法是相同的,两者可以通用的。.

 最后需要说明的是,  如果要将私钥文件保存为PEM编码那么私钥的文件头也是一个很重要的问题。通过以上转换的getOpensslEncodeKey这个接口转换的私钥需要在头中指明私钥的算法类型,比如RSA的私要要用“-----BEGIN RSA PRIVATE KEY-----”和"-----END RSA PRIVATE KEY-----",否则openssl被报无法加载私钥文件的错误。对于采用PrivateKey.getEncoded()得到的私钥,又必须采用"-----BEGIN PRIVATE KEY-----"和"-----END PRIVATE KEY-----",否则openssl也将被报无法加载私钥文件的错误。


你可能感兴趣的:(java,exception,String,Module,Integer,attributes)