I assume that in XML format you mean XML DSig RSAKeyValue , and in PEM format you mean that OpenSSL exports between -----BEGIN PUBLIC KEY----- and -----END PUBLIC KEY----- .
First you need to extract the module and public exponent from XML.
<RSAKeyValue> <Modulus>xA7SEU+e0yQH5rm9kbCDN9o3aPIo7HbP7tX6WOocLZAtNfyxSZDU16ksL6W jubafOqNEpcwR3RdFsT7bCqnXPBe5ELh5u4VEy19MzxkXRgrMvavzyBpVRgBUwUlV 5foK5hhmbktQhyNdy/6LpQRhDUDsTvK+g9Ucj47es9AQJ3U= </Modulus> <Exponent>AQAB</Exponent> </RSAKeyValue>
You can easily convert them to a bit string using base64_decode .
Once this is done, you need to somehow build the ASN.1 structure.
What OpenSSL exports between the BEGIN / END PUBLIC KEY is the X.509 SubjectPublicKeyInfo structure .
SubjectPublicKeyInfo ::= SEQUENCE { algorithm AlgorithmIdentifier, subjectPublicKey BIT STRING }
subjectPublicKey consists of the sequnce described in PKCS # 1 spec :
RSAPublicKey ::= SEQUENCE { modulus INTEGER, publicExponent INTEGER }
algorithm (a AlgorithmIdentifier ) is also described in the PKCS # 1 specification (see section A.1):
rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 }
This structure must be serialized in the form of DER, then base64 encoded, and then placed between the BEGIN / END delimiters.
I do not know any PHP library to make ASN.1 / DER encoding, unfortunately (the rest is relatively simple, but working with ASN.1 tends to be tedious).
the PHP / PEAR module Crypt_RSA can create public RSA keys from the module and exponent, but its toString() method uses a custom format (only base64 encoded PHP result serialize in an array structure that has nothing to do with ASN.1 / DER encoding).