Как преобразовать открытый ключ RSA, от XML до PEM (PHP)?
мы знаем
.pem – (конфиденциальная расширенная почта). Сертификат DER с кодировкой Base64, заключенный между «—– BEGIN CERTIFICATE —–» и «—– КОНЕЦ СЕРТИФИКАТА —–»
X.509
Элемент SignatureValue содержит результат подшивки Base64 – подпись, сгенерированную с параметрами, указанными в элементе SignatureMethod, – элемента SignedInfo после применения алгоритма, указанного в методе CanonicalizationMethod.
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
если ваш 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-----";
Я предполагаю, что в формате 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>
Вы можете легко преобразовать их в битовую строку, используя base64_decode
.
Как только это будет сделано, вам необходимо как-то создать структуру открытого ключа ASN.1 .
Экспорт OpenSSL между BEGIN / END PUBLIC KEY представляет собой структуру X.509 SubjectPublicKeyInfo .
SubjectPublicKeyInfo ::= SEQUENCE { algorithm AlgorithmIdentifier, subjectPublicKey BIT STRING }
subjectPublicKey
сделан из sequnce описан в спецификации PKCS # 1 :
RSAPublicKey ::= SEQUENCE { modulus INTEGER, publicExponent INTEGER }
algorithm
( AlgorithmIdentifier
) также описан в спецификации PKCS # 1 (см. Раздел A.1):
rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 }
Эта структура должна быть сериализована в форме DER, затем закодирована base64, а затем помещена между разделителями BEGIN / END.
К сожалению, я не знаю какой-либо библиотеки PHP для кодирования ASN.1 / DER (остальное относительно просто, но работа с ASN.1 имеет тенденцию быть утомительной).
Модуль PHP / PEAR Crypt_RSA может создавать открытые ключи RSA от модуля и экспоненты, но его метод toString()
использует настраиваемый формат (только base64-кодирование результата serialize
PHP в структуре массива, что не имеет ничего общего с ASN.1 / DER).
Нет стандарта для хранения открытых ключей RSA в XML. Таким образом, способ преобразования будет зависеть от XML, который у вас есть.
Вот пример того, как читать XML-ключи RSA в PHP:
Просто для полноты, вот рабочий пример создания PEM из модуля в python. Вы можете вызвать его в подпроцессе из PHP, если это необходимо.
Мясо раствора:
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')
Где E_PREFIX
и N_PREFIX
– это константы, которые (насколько я могу судить) зависят от экспоненты и длины ключа. Вот краткая таблица, которую я построил:
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
Если кто-то знает более общий способ вычисления префиксов, скажите.
Может быть, вы должны посмотреть здесь
Извлеките две строки, закодированные в base64, конвертируйте и перейдите в PEAR :: Crypt_RSA, затем экспортируйте в текстовый файл, затем openssl convert?
Проверьте это тоже