Convert RSA public key, from XML to PEM (PHP)

邮差的信 提交于 2019-12-03 21:12:15

we know

.pem - (Privacy Enhanced Mail) Base64 encoded DER certificate, enclosed between "-----BEGIN CERTIFICATE-----" and "-----END CERTIFICATE-----"

X.509

The SignatureValue element contains the Base64 encoded signature result - the signature generated with the parameters specified in the SignatureMethod element - of the SignedInfo element after applying the algorithm specified by the CanonicalizationMethod.

XML_Signature

so we end up with

$xml = simplexml_load_file($xmlFile); // or simplexml_load_string

$pem = "-----BEGIN CERTIFICATE-----\n";
$pem .= $xml->SignatureValue;
$pem .= "\n-----END CERTIFICATE-----";

// save to file

if your xml-file isn't a XML_Signature

$xml = simplexml_load_file($xmlFile); // or simplexml_load_string
$pem = "-----BEGIN CERTIFICATE-----\n";
$pem .= $xml->nodeWithWantedValue; // use base64_encode if needed
$pem .= "\n-----END CERTIFICATE-----";

I'm assuming that by XML format, you mean XML DSig RSAKeyValue, and that by PEM format you mean what OpenSSL exports in between -----BEGIN PUBLIC KEY----- and -----END PUBLIC KEY-----.

You need first to extract the modulus and public exponent from the XML.

   <RSAKeyValue>
     <Modulus>xA7SEU+e0yQH5rm9kbCDN9o3aPIo7HbP7tX6WOocLZAtNfyxSZDU16ksL6W
      jubafOqNEpcwR3RdFsT7bCqnXPBe5ELh5u4VEy19MzxkXRgrMvavzyBpVRgBUwUlV
      5foK5hhmbktQhyNdy/6LpQRhDUDsTvK+g9Ucj47es9AQJ3U=
     </Modulus>
     <Exponent>AQAB</Exponent>
   </RSAKeyValue>

You can easily convert these into a bit string using base64_decode.

Once this is done, you need to build the ASN.1 public key structure somehow.

What OpenSSL exports between BEGIN/END PUBLIC KEY is an X.509 SubjectPublicKeyInfo structure.

SubjectPublicKeyInfo ::= SEQUENCE {
   algorithm AlgorithmIdentifier,
   subjectPublicKey BIT STRING }

The subjectPublicKey is made of a sequnce is described in the PKCS#1 spec:

RSAPublicKey ::= SEQUENCE {
   modulus INTEGER,
   publicExponent INTEGER
}

The algorithm (an AlgorithmIdentifier) is also described in the PKCS#1 spec (see section A.1):

rsaEncryption
OBJECT IDENTIFIER ::= { pkcs-1 1 }

This structure needs to be serialized in DER form, then base64-encoded and then placed between the BEGIN/END delimiters.

I don't know of any PHP library to do the ASN.1/DER encoding unfortunately (the rest is relatively easy, but dealing with ASN.1 tends to be tedious).

The PHP/PEAR Crypt_RSA module can construct RSA public keys from modulus and exponent, but its toString() method uses a custom format (just the base64-encoding of the result of PHP serialize on the array structure, which has nothing to do with the ASN.1/DER encoding).

There is no standard for storing RSA public keys in XML. So the manner of conversion will depend on the XML you have.

fruzer

Here's an example of how to read XML RSA keys in PHP:

Just for completeness, here is a working example of creating the PEM from modulus in python. You could call it in a subprocess from PHP if necessary.

The meat of the solution is:

def big_endian(n):
    s = '%x' % n
    if len(s) & 1:
        s = '0' + s
    return s.decode('hex')

from M2Crypto import RSA

e = E_PREFIX + big_endian(public_exponent)
n = N_PREFIX + big_endian(modulus)

new = RSA.new_pub_key((e,n))
new.save_key('foo.pub')

Where E_PREFIX and N_PREFIX are constants that (as far as I can tell) depend on the exponent and key length. Here is a quick table I have constructed:

E_PREFIX = '\x00\x00\x00\x01' # 0x3 (3)
E_PREFIX = '\x00\x00\x00\x03' # 0x10001 (65537)

N_PREFIX = '\x00\x00\x00!\x00' # 256-bit
N_PREFIX = '\x00\x00\x00A\x00' # 512-bit (default)
N_PREFIX = '\x00\x00\x00\x81\x00' # 1024-bit
N_PREFIX = '\x00\x00\x01\x01\x00' # 2048-bit
N_PREFIX = '\x00\x00\x02\x01\x00' # 4096-bit

If someone knows a more general way to compute the prefixes, do tell.

mario

Maybe you should have a look here

Extract the two base64-encoded strings, convert and pass to PEAR::Crypt_RSA, then export as text file, then openssl convert?

Check this too

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!