在Java中将RSA密钥对象导出为XML

我在Java中成功运行RSA加密/解密。 这就是我生成密钥的方式。

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(path)); KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); kpg.initialize(1024); KeyPair keypair = kpg.generateKeyPair(); oos.writeObject(keypair); 

但现在我需要将我的系统与.Net代码集成。 是否可以按以下格式将此KeyPair对象导出为XML(因为.Net代码只能接受XML格式的密钥):

  ..... ...... 

.....

.... ....... ...... ......... ........

尝试这个:

 // key pair is in 'kp' KeyFactory kf = KeyFactory.getInstance("RSA"); RSAPrivateCrtKeySpec ks = kf.getKeySpec( kp.getPrivate(), RSAPrivateCrtKeySpec.class); System.out.println(""); System.out.println(" " + ks.getModulus() + ""); System.out.println(" " + ks.getPublicExponent() + ""); System.out.println(" 

" + ks.getPrimeP() + "

"); System.out.println(" " + ks.getPrimeQ() + ""); System.out.println(" " + ks.getPrimeExponentP() + ""); System.out.println(" " + ks.getPrimeExponentQ() + ""); System.out.println(" " + ks.getCrtCoefficient() + ""); System.out.println(" " + ks.getPrivateExponent() + ""); System.out.println("
");

这适用于内部使用“CRT”表示的所有RSA密钥对,并允许导出; 这是JDK默认使用您显示的代码生成的密钥对的情况。

(这里我打印出System.out上的密钥,而不是将其写入文件,但你明白了。)

Thomas Pornin的解决方案基本上是正确的,但对我来说不起作用,因为方法(例如getModulus())返回BigInteger,导致数字字符串,而标准.Net XML格式使用Base64编码字节。

我使用“getModulus()。toByteArray()”来获取字节。 然后我需要修剪数组的第一个元素(Exponent除外)因为有一个不需要的零字节。 (我认为因为BigInteger已签名,所以它会添加一个额外的字节,因此前导位可以指示符号)。

我已经在GitHub上发布了代码 。

主要是:

 static String getPrivateKeyAsXml(PrivateKey privateKey) throws Exception{ KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); RSAPrivateCrtKeySpec spec = keyFactory.getKeySpec(privateKey, RSAPrivateCrtKeySpec.class); StringBuilder sb = new StringBuilder(); sb.append("" + NL); sb.append(getElement("Modulus", spec.getModulus())); sb.append(getElement("Exponent", spec.getPublicExponent())); sb.append(getElement("P", spec.getPrimeP())); sb.append(getElement("Q", spec.getPrimeQ())); sb.append(getElement("DP", spec.getPrimeExponentP())); sb.append(getElement("DQ", spec.getPrimeExponentQ())); sb.append(getElement("InverseQ", spec.getCrtCoefficient())); sb.append(getElement("D", spec.getPrivateExponent())); sb.append(""); return sb.toString(); } static String getElement(String name, BigInteger bigInt) throws Exception { byte[] bytesFromBigInt = getBytesFromBigInt(bigInt); String elementContent = getBase64(bytesFromBigInt); return String.format(" <%s>%s%s", name, elementContent, name, NL); } static byte[] getBytesFromBigInt(BigInteger bigInt){ byte[] bytes = bigInt.toByteArray(); int length = bytes.length; // This is a bit ugly. I'm not 100% sure of this but I presume // that as Java represents the values using BigIntegers, which are // signed, the byte representation contains an 'extra' byte that // contains the bit which indicates the sign. // // In any case, it creates arrays of 129 bytes rather than the // expected 128 bytes. So if the array's length is odd and the // leading byte is zero then trim the leading byte. if(length % 2 != 0 && bytes[0] == 0) { bytes = Arrays.copyOfRange(bytes, 1, length); } return bytes; } static String getBase64(byte[] bytes){ return Base64.getEncoder().encodeToString(bytes); } 

您可以使用某种forms的XMLObjectOutputStream,使其输出到XML而不是像这里那样的专有二进制格式。