在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>%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而不是像这里那样的专有二进制格式。