将RSA公钥从XML转换为PEM(PHP)

sla*_*mer 2 php xml rsa pem public-key

如何将RSA公钥从XML转换为PEM(PHP)?

Bru*_*uno 10

我假设,通过XML格式,你的意思是XML DSig的RSAKeyValue,并通过PEM格式你的意思OpenSSL的出口之间-----BEGIN PUBLIC KEY----------END PUBLIC KEY-----.

首先需要从XML中提取模数和公共指数.

   <RSAKeyValue>
     <Modulus>xA7SEU+e0yQH5rm9kbCDN9o3aPIo7HbP7tX6WOocLZAtNfyxSZDU16ksL6W
      jubafOqNEpcwR3RdFsT7bCqnXPBe5ELh5u4VEy19MzxkXRgrMvavzyBpVRgBUwUlV
      5foK5hhmbktQhyNdy/6LpQRhDUDsTvK+g9Ucj47es9AQJ3U=
     </Modulus>
     <Exponent>AQAB</Exponent>
   </RSAKeyValue>
Run Code Online (Sandbox Code Playgroud)

您可以使用轻松地将这些转换为位串base64_decode.

完成此操作后,您需要以某种方式构建ASN.1公钥结构.

BEGIN/END PUBLIC KEY之间的OpenSSL导出是X.509 SubjectPublicKeyInfo结构.

SubjectPublicKeyInfo ::= SEQUENCE {
   algorithm AlgorithmIdentifier,
   subjectPublicKey BIT STRING }
Run Code Online (Sandbox Code Playgroud)

subjectPublicKey是由在中描述了一种sequnce的PKCS#1规格:

RSAPublicKey ::= SEQUENCE {
   modulus INTEGER,
   publicExponent INTEGER
}
Run Code Online (Sandbox Code Playgroud)

所述algorithm(一个AlgorithmIdentifier)也是在PKCS#1的规格(参见A.1)中所描述:

rsaEncryption
OBJECT IDENTIFIER ::= { pkcs-1 1 }
Run Code Online (Sandbox Code Playgroud)

这种结构需要以DER形式序列化,然后进行base64编码,然后放在BEGIN/END分隔符之间.

不幸的是,我不知道任何PHP库来进行ASN.1/DER编码(其余的相对简单,但处理ASN.1往往很乏味).

PHP/PEAR Crypt_RSA模块可以构建从模数和指数的RSA公共密钥,但它的toString()方法使用自定义格式(刚刚编码的base64 PHP的结果的serialize在阵列结构,该结构无关与ASN.1/DER编码).


tee*_*one 5

我们知道

.pem - (隐私增强邮件)Base64编码的DER证书,包含在"----- BEGIN CERTIFICATE -----"和"----- END CERTIFICATE -----"之间

X.509

SignatureValue元素包含Base64编码的签名结果 - 使用SignatureMethod元素中指定的参数生成的签名 - 应用了CanonicalizationMethod指定的算法后的SignedInfo元素.

XML_Signature

所以我们最终得到了

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

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

// save to file
Run Code Online (Sandbox Code Playgroud)

如果您的xml文件不是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-----";
Run Code Online (Sandbox Code Playgroud)