我在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格式的密钥):
<RSAKeyValue>
<Modulus>.....</Modulus>
<Exponent>......</Exponent>
<P>.....</P>
<Q>....</Q>
<DP>.......</DP>
<DQ>......</DQ>
<InverseQ>.........</InverseQ>
<D>........</D>
</RSAKeyValue>
答案 0 :(得分:14)
试试这个:
// key pair is in 'kp'
KeyFactory kf = KeyFactory.getInstance("RSA");
RSAPrivateCrtKeySpec ks = kf.getKeySpec(
kp.getPrivate(), RSAPrivateCrtKeySpec.class);
System.out.println("<RSAKeyValue>");
System.out.println(" <Modulus>" + ks.getModulus() + "</Modulus>");
System.out.println(" <Exponent>" + ks.getPublicExponent() + "</Exponent>");
System.out.println(" <P>" + ks.getPrimeP() + "</P>");
System.out.println(" <Q>" + ks.getPrimeQ() + "</Q>");
System.out.println(" <DP>" + ks.getPrimeExponentP() + "</DP>");
System.out.println(" <DQ>" + ks.getPrimeExponentQ() + "</DQ>");
System.out.println(" <InverseQ>" + ks.getCrtCoefficient() + "</InverseQ>");
System.out.println(" <D>" + ks.getPrivateExponent() + "</D>");
System.out.println("</RSAKeyValue>");
这适用于内部使用“CRT”表示的所有RSA密钥对,并允许导出;这是JDK默认使用您显示的代码生成的密钥对的情况。
(这里我打印出System.out
上的密钥,而不是将其写入文件,但你明白了。)
答案 1 :(得分:4)
我使用&#34; getModulus()。toByteArray()&#34;得到字节。然后我需要修剪数组的第一个元素(Exponent除外),因为它有一个不需要的零字节。 (我认为因为BigInteger已经签名,所以它会添加一个额外的字节,因此前导位可以指示符号)。
我已经在GitHub上发布了the code。
主要是:
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("<RSAKeyValue>" + 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("</RSAKeyValue>");
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);
}
答案 2 :(得分:0)
您可以使用某种形式的XMLObjectOutputStream,使其输出为XML而不是here中的专有二进制格式。