托馬斯Pornin的解決方案基本上是正確的,但我沒有工作,因爲這些方法,例如getModulus(),返回BigInteger,它會生成一個數字字符串,而標準的.Net XML格式使用Base64編碼的字節。
我用「getModulus()。toByteArray()」來獲取字節。然後我需要修剪數組的第一個元素(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);
}
存儲密鑰對這種方式不加密(因此留下你的私鑰暴露)是一個非常,非常糟糕的主意。 – Hut8 2011-03-03 09:23:03
爲實現Serializable接口的密鑰對創建自己的包裝類。覆蓋'readObject()','writeObject()'和'readObjectNoData()'方法。 – 2011-03-03 13:00:24
@ bowenl2你能提出任何與其他平臺集成的好方法嗎? – dvl 2011-03-05 07:18:58