Конвертировать открытый ключ RSA из XML в PEM (PHP) - PullRequest
2 голосов
/ 25 августа 2010

Как преобразовать открытый ключ RSA из XML в PEM (PHP)?

Ответы [ 6 ]

10 голосов
/ 26 августа 2010

Я предполагаю, что под форматом 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 изготовлен из последовательности, описанной в спецификации PKCS # 1 :

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

algorithm (AlgorithmIdentifier) также описывается в спецификации PKCS # 1 (см. Раздел A.1):

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

Эта структура должна быть сериализована в виде DER, затем закодирована в base64 и затем помещена между BEGIN/ END delimiters.

Я не знаю ни одной библиотеки PHP, которая бы выполняла кодирование ASN.1 / DER, к сожалению (остальноеочень просто, но работа с ASN.1, как правило, утомительна).

Модуль PHP / PEAR Crypt_RSA может создавать открытые ключи RSA по модулю и показателю степени, но его метод toString() используетпользовательский формат (только base64-кодировка результата PHP serialize в структуре массива, который не имеет ничего общего с кодировкой ASN.1 / DER).

5 голосов
/ 25 августа 2010

мы знаем

.pem - (улучшенная конфиденциальность почты) Base64 закодированный сертификат DER, прилагается между "----- НАЧАТЬ СЕРТИФИКАТ -----" и "----- КОНЕЦ СЕРТИФИКАТА -----"

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-----";
1 голос
/ 02 октября 2010

Вот пример того, как читать ключи XML RSA в PHP:

1 голос
/ 25 августа 2010

Не существует стандарта для хранения открытых ключей RSA в XML. Таким образом, способ преобразования будет зависеть от вашего XML.

0 голосов
/ 20 ноября 2010

Просто для полноты, вот рабочий пример создания 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

Если кто-то знает более общий способ вычисления префиксов, скажите:

0 голосов
/ 25 августа 2010

Может быть, вы должны посмотреть здесь

Извлеките две строки в кодировке base64, преобразуйте их и передайте в PEAR :: Crypt_RSA, затем экспортируйте как текстовый файл, затем openssl convert?

Проверьте это тоже

...