Exporting RSA key object to XML in Java

前端 未结 3 1490
独厮守ぢ
独厮守ぢ 2020-12-30 11:09

I am successfully running RSA encryption/decryption in Java. This is how I generated the key.

        ObjectOutputStream oos = new ObjectOutputStream(new Fil         


        
相关标签:
3条回答
  • 2020-12-30 11:35

    Thomas Pornin's solution is essentially correct but didn't work for me because the methods, e.g. getModulus(), return BigInteger which results in a numeric string, whereas the standard .Net XML format uses Base64 encoded bytes.

    I used "getModulus().toByteArray()" to get the bytes. Then I needed to trim the first element of the array (except for Exponent) because there's an unwanted zero byte. (I presume because BigInteger is signed it adds an extra byte so the leading bit can indicate sign).

    I've posted the code on GitHub.

    The main bit is:

    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);
    }
    
    0 讨论(0)
  • 2020-12-30 11:43

    Try this:

    // 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>");
    

    This will work for all RSA key pairs which internally use the 'CRT' representation, and allow export; this is the case for the key pairs that the JDK will generate by default with the code you show.

    (Here I print out the key on System.out instead of writing it to a file, but you get the idea.)

    0 讨论(0)
  • 2020-12-30 11:49

    You can have some form of XMLObjectOutputStream such that it outputs to XML instead of a proprietary binary format as in here.

    0 讨论(0)
提交回复
热议问题