Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I convert an XML RSA key to a PEM file?

I have two XML files, structured as follows:

My Key

<RSAKeyValue>
  <Modulus> ... </Modulus>
  <Exponent> ... </Exponent>
  <P> ... </P>
  <Q> ... </Q>
  <DP> ... </DP>
  <DQ> ... </DQ>
  <InverseQ> ... </InverseQ>
  <D> ... </D>
</RSAKeyValue>

A Public Key

<RSAKeyValue>
   <Modulus> ... </Modulus>
   <Exponent> ... </Exponent>
</RSAKeyValue>

I am using the xmlseclibs library by Robert Richards which requires a .PEM representation of the key in order to encrypt and decrypt things.

As an encryption novice, I'm not sure where to begin, and a cursory Google search did not reveal anything particularly obvious...

Thanks!

like image 439
Philip Avatar asked Jun 22 '10 14:06

Philip


People also ask

What is PEM format RSA?

PEM encoded RSA private key is a format that stores an RSA private key, for use with cryptographic systems such as SSL. A public key can be derived from the private key, and the public key may be associated with one or more certificate files.


2 Answers

For those who want the resulting PEM to be readable by BouncyCastle:

  1. use XMLSec2PEM tool to get a pem file
  2. convert pem to pkcs8 and back (!)

The final solution I am happy with:

  1. java XMLSec2PEM my.xml > my.pem
  2. edit my.pem manually a bit
  3. org.bouncycastle.openssl.PEMReader.readObject() returns null :-(
  4. openssl pkcs8 -topk8 -inform pem -in my.pem -outform pem -nocrypt -out my.pkcs8
  5. openssl pkcs8 -inform pem -nocrypt -in my.pkcs8 -out my.pkcs8.pem
  6. now my.pkcs8.pem is readable with the PEMReader
like image 84
Pavel Vlasov Avatar answered Oct 25 '22 17:10

Pavel Vlasov


my solution in python works like this:

  1. extract modulus and exponent from xml
    xml = etree.fromstring(key_bin)
    modulus = xml.find('Modulus').text
    exponent = xml.find('Exponent').text
    
  2. decode them in base64 and iterate the result to save it as a character string of length 2:
    mod_b64 = b64decode(modulus.encode())
    exp_b64 = b64decode(exponent.encode())
    exp = ''.join(['{:02x}'.format(x) for x in exp_b64])
    mod = ''.join(['{:02x}'.format(x) for x in mod_b64]) 
    
  3. Convert the hexadecimal string to integer and generate the rsa public key with the rsa library:
    exp_num = int(exp, 16)
    mod_num = int(mod, 16)
    rsa_key = rsa.PublicKey(mod_num, exp_num)
    
  4. Finally any text can be encrypted:
    msg_cryp = rsa.encrypt(msg.encode('ascii'), rsa_key)
    msg_cryp_str = b64encode(msg_cryp).decode('ascii') 
    

I did this development to consume a web service which requires that an encrypted password be sent from a public key in XML format. In this way I managed to encrypt the password and consume the web service without problems.

like image 35
BDLG Avatar answered Oct 25 '22 16:10

BDLG