Como posso transformar os dois estilos de formato de chave pública, um formato é:
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
o outro formato é:
-----BEGIN RSA PUBLIC KEY-----
...
-----END RSA PUBLIC KEY-----
por exemplo, gerei o par id_rsa / id_rsa.pub usando o comando ssh-keygen, calculei a chave pública de id_rsa usando:
openssl rsa -in id_rsa -pubout -out pub2
em seguida, calculei novamente a chave pública de id_rsa.pub usando:
ssh-keygen -f id_rsa.pub -e -m pem > pub1
o conteúdo é pub1 é:
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEA61BjmfXGEvWmegnBGSuS+rU9soUg2FnODva32D1AqhwdziwHINFa
D1MVlcrYG6XRKfkcxnaXGfFDWHLEvNBSEVCgJjtHAGZIm5GL/KA86KDp/CwDFMSw
luowcXwDwoyinmeOY9eKyh6aY72xJh7noLBBq1N0bWi1e2i+83txOCg4yV2oVXhB
o8pYEJ8LT3el6Smxol3C1oFMVdwPgc0vTl25XucMcG/ALE/KNY6pqC2AQ6R2ERlV
gPiUWOPatVkt7+Bs3h5Ramxh7XjBOXeulmCpGSynXNcpZ/06+vofGi/2MlpQZNhH
Ao8eayMp6FcvNucIpUndo1X8dKMv3Y26ZQIDAQAB
-----END RSA PUBLIC KEY-----
e o conteúdo do pub2 é:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA61BjmfXGEvWmegnBGSuS
+rU9soUg2FnODva32D1AqhwdziwHINFaD1MVlcrYG6XRKfkcxnaXGfFDWHLEvNBS
EVCgJjtHAGZIm5GL/KA86KDp/CwDFMSwluowcXwDwoyinmeOY9eKyh6aY72xJh7n
oLBBq1N0bWi1e2i+83txOCg4yV2oVXhBo8pYEJ8LT3el6Smxol3C1oFMVdwPgc0v
Tl25XucMcG/ALE/KNY6pqC2AQ6R2ERlVgPiUWOPatVkt7+Bs3h5Ramxh7XjBOXeu
lmCpGSynXNcpZ/06+vofGi/2MlpQZNhHAo8eayMp6FcvNucIpUndo1X8dKMv3Y26
ZQIDAQAB
-----END PUBLIC KEY-----
De acordo com meu entendimento, pub1 e pub2 contêm as mesmas informações de chave pública, mas eles estão em formatos diferentes. Eu me pergunto como posso transformar entre os dois formatos? Alguém pode me mostrar uma introdução concisa sobre os formatos de reboque?
Respostas:
Usando phpseclib, uma implementação PHP RSA pura ...
O material codificado em base64 parece corresponder, embora o cabeçalho diga BEGIN PUBLIC KEY e não BEGIN RSA PUBLIC KEY. Então talvez use str_replace para consertar isso e você estará pronto para começar!
fonte
Eu queria ajudar a explicar o que está acontecendo aqui.
Uma "chave pública" RSA consiste em dois números:
Usando sua chave pública RSA como exemplo, os dois números são:
A questão então é como queremos armazenar esses números em um computador. Primeiro, convertemos ambos em hexadecimal:
RSA inventou o primeiro formato
RSA inventou um formato primeiro:
Eles escolheram usar o tipo DER do padrão de codificação binária ASN.1 para representar os dois números [1] :
A codificação binária final em ASN.1 é:
Se você executar todos esses bytes juntos e codificá-los em Base64, obterá:
Os laboratórios RSA disseram então para adicionar um cabeçalho e um trailer:
Cinco hífens e as palavras
BEGIN RSA PUBLIC KEY
. Esta é a sua chave pública PEM DER ASN.1 PKCS # 1 RSANão apenas RSA
Depois disso, outras formas de criptografia de chave pública surgiram:
Quando chegou a hora de criar um padrão de como representar os parâmetros desses algoritmos de criptografia, as pessoas adotaram muitas das mesmas ideias que a RSA definiu originalmente:
BEGIN PUBLIC KEY
Mas em vez de usar:
-----BEGIN RSA PUBLIC KEY-----
-----BEGIN DH PUBLIC KEY-----
-----BEGIN EC PUBLIC KEY-----
Em vez disso, eles decidiram incluir o Identificador de Objeto (OID) do que está por vir. No caso de uma chave pública RSA, isto é:
1.2.840.113549.1.1.1
Portanto, para a chave pública RSA era essencialmente:
Agora eles criaram SubjectPublicKeyInfo que é basicamente:
Na definição DER ASN.1 real é:
Isso dá a você um ASN.1 de:
A codificação binária final em ASN.1 é:
E como antes, você pega todos esses bytes, codifica-os em Base64 e acaba com seu segundo exemplo:
Adicione o cabeçalho e o trailer ligeiramente diferentes e você terá:
E esta é sua chave pública X.509 SubjectPublicKeyInfo / OpenSSL PEM [2] .
Faça certo ou hackear
Agora que você sabe que a codificação não é mágica, pode escrever todas as partes necessárias para analisar o módulo RSA e o expoente. Ou você pode reconhecer que os primeiros 24 bytes são apenas novos itens adicionados ao padrão PKCS # 1 original
Esses primeiros 24 bytes são coisas "novas" adicionadas:
E devido a uma extraordinária coincidência de fortuna e boa sorte:
Porque em Base64: 3 bytes se transformam em quatro caracteres:
Isso significa que se você pegar sua segunda chave pública X.509, os primeiros 32 caracteres corresponderão apenas às coisas recém-adicionadas:
Se você remover os primeiros 32 caracteres e alterá-los para BEGIN RSA PUBLIC KEY :
Você tem exatamente o que queria - o
RSA PUBLIC KEY
formato antigo .fonte
Achei este site uma boa explicação técnica dos diferentes formatos: https://polarssl.org/kb/cryptography/asn1-key-structures-in-der-and-pem
"BEGIN RSA PUBLIC KEY" é PKCS # 1, que só pode conter chaves RSA.
"BEGIN PUBLIC KEY" é PKCS # 8, que pode conter uma variedade de formatos.
Se você deseja apenas convertê-los com a linha de comando, "openssl rsa" é bom para isso.
Para converter de PKCS # 8 para PKCS # 1:
Para converter de PKCS # 1 para PKCS # 8:
fonte
unknown option -RSAPublicKey_in
Embora os comentários acima sobre cabeçalhos de 32 bytes, formatos OID e outros sejam interessantes, eu pessoalmente não vejo o mesmo comportamento, presumindo que estou entendendo. Achei que poderia ser útil explorar isso mais a fundo no que a maioria pode considerar um excesso de detalhes. Nada excede como o excesso.
Para começar, criei uma chave privada RSA e verifiquei:
(Oh, horrores! Eu expus uma chave privada. Meh ...)
Extraio e exibo sua chave pública:
Acontece que há outro parâmetro de saída de chave pública (conforme mencionado em um comentário anterior). Eu extraio e exibo a chave pública usando essa palavra-chave:
Bem bem. Esses dois valores de chave pública não são iguais, embora sejam derivados da mesma chave privada. Ou eles são a mesma coisa? Eu recorto e colo as duas strings de chave pública em seus próprios arquivos e, em seguida, faço uma verificação de módulo em cada uma:
O 'pubin' diz ao rsa que esta é realmente uma chave pública e não reclame que não é uma chave privada.
Agora pegamos a chave pública RSA, exibimos o módulo e a transformamos em uma "chave pública" simples e antiga (novamente, temos que dizer que a entrada é uma chave pública):
Mesmo módulo e mesmo valor de 'chave pública' exibido. Para tornar as coisas mais interessantes (para mim, pelo menos), quando adicionamos a palavra-chave RSAPublicKey_out obtemos:
... e quando transformamos a velha "chave pública" em uma chave pública RSA:
... marchando implacavelmente, e embora tenhamos feito isso alguns comandos atrás, para esclarecer que invertemos as coisas para que a transmogrificação seja de RSA para a velha 'chave pública':
... o que nos leva de volta ao ponto de partida. O que aprendemos?
Resumo: as chaves internamente são as mesmas, apenas parecem diferentes. Um comentário anterior apontou que o formato da chave RSA foi definido no PKCS # 1, e o antigo formato de 'chave pública' foi definido no PKCS # 8. No entanto, editar um formulário não o transforma no outro. Espero que eu já tenha vencido essa distinção até a morte.
No caso de ainda haver uma centelha de vida restante, no entanto, vamos bater um pouco mais e consultar o certificado que foi gerado originalmente com a chave privada RSA há muito tempo, examinando sua chave pública e módulo:
... e todos viveram felizes para sempre: o certificado tem o mesmo valor de módulo que a chave pública RSA, a chave privada RSA e a velha 'chave pública'. O certificado contém o mesmo valor de 'chave pública' simples e antigo que vimos anteriormente, embora tenha sido assinado com um arquivo marcado como uma chave privada RSA. É seguro dizer que há um consenso.
Não há palavra-chave equivalente 'RSAPublicKey_out' no quadrante X509 da galáxia OpenSSL, então não podemos tentar isso, embora o valor do módulo seja descrito como o "módulo da chave RSA" que suponho ser o mais próximo que conseguiremos.
Como isso ficaria com um certificado assinado por DSA, eu não sei.
Sei que isso não responde à pergunta original, mas talvez forneça algumas informações úteis. Se não, minhas desculpas. No mínimo, coisas a não fazer e suposições a não fazer.
Sem dúvida, notou-se a repetição um pouco irritante de "escrever chave RSA", quando não está fazendo nada disso. Suponho que o que isso significa é que o módulo rsa reconhece a chave pública antiga como uma chave RSA verdadeira e é por isso que ele fica repetindo "chave RSA" (além disso, é o módulo rsa, afinal). Se bem me lembro, a estrutura EVP_PKEY genérica tem uma união para todos os tipos de chave, com cada tipo de chave tendo seu próprio conjunto especial de valores (o útil denominado g, w, q e outras consoantes).
Em conclusão, noto que houve uma reclamação sobre programação e desenvolvimento; agora, cada comando OpenSSL obviamente tem um código correspondente, e se alguém deseja explorar todas as maravilhas que é a programação OpenSSL hoje, a linha de comando parece um lugar razoável para começar. Neste caso específico (como estou usando um cygwin recente no momento), pode-se começar revisando \ openssl-1.0.2f \ apps \ rsa.c e (dado que um tem uma alta tolerância para macros) \ openssl-1.0. 2f \ crypto \ pem \ pem_all.c
fonte
A única diferença entre o seu pub1 e Pub2, além do cabeçalho / rodapé, é esta cadeia adicional em Pub2:
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
. Se você remover isso, a Base 64 é idêntica à do pub1.A string extra corresponde ao identificador do algoritmo de acordo com esta Resposta .
fonte