Converti chiave pem in formato ssh-rsa


143

Ho un certificato in derformato, da esso con questo comando ho generato una chiave pubblica:

openssl x509 -inform der -in ejbcacert.cer -noout -pubkey > pub1key.pub

Che risulta in questo:

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7vbqajDw4o6gJy8UtmIbkcpnk
O3Kwc4qsEnSZp/TR+fQi62F79RHWmwKOtFmwteURgLbj7D/WGuNLGOfa/2vse3G2
eHnHl5CB8ruRX9fBl/KgwCVr2JaEuUm66bBQeP5XeBotdR4cvX38uPYivCDdPjJ1
QWPdspTBKcxeFbccDwIDAQAB
-----END PUBLIC KEY-----

Come posso ottenere una chiave pubblica come questa? O dal certificato o da questa chiave pubblica?

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC7vbqajDw4o6gJy8UtmIbkcpnkO3Kwc4qsEnSZp/TR+fQi62F79RHWmwKOtFmwteURgLbj7D/WGuNLGOfa/2vse3G2eHnHl5CB8ruRX9fBl/KgwCVr2JaEuUm66bBQeP5XeBotdR4cvX38uPYivCDdPjJ1QWPdspTBKcxeFbccDw==

Questo è stato ottenuto con questo comando:

ssh-keygen -y -f private_key1.pem > public_key1.pub

14
Il modo in cui hai pubblicato in "Questo è stato ottenuto con questo comando" ha funzionato per me meglio di una qualsiasi delle risposte di seguito.
Yoav Shapira,

7
@YoavShipra. Sì, ma l'intera domanda è che vuole convertire utilizzando solo la chiave pubblica. Forse non ha la chiave privata e ha solo la chiave pubblica e vuole convertire dal formato PEM al formato ssh-rsa.
deltamind106,

10
Dato un .pem di AWS, il comando che hai dato sopra ha ssh-keygen -y -f private_key1.pem > public_key1.pubfunzionato alla grande per me.
Kzqai,

1
Tutte le risposte sbagliate. Questo è quello corretto: ssh-keygen -i -m PKCS8 -f public-key.pem
Boeboe,

3
La bellezza è negli occhi di chi guarda . Dobbiamo notare che una chiave pem potrebbe contenere una chiave pubblica o privata o entrambe; crittografato o forse no; plus con vari formati. Anche il significato dell'opzione -mè diverso per -i/ -e. Quindi amici miei, per favore assicuratevi di sapere cosa volete e cosa avete . :-)
ryenus

Risposte:


129

Non è necessario compilare materiale. Puoi fare lo stesso con ssh-keygen:

ssh-keygen -f pub1key.pub -i

leggerà la chiave pubblica in formato openssl pub1key.pube la emetterà in formato OpenSSH.

Nota : in alcuni casi è necessario specificare il formato di input:

ssh-keygen -f pub1key.pub -i -mPKCS8

Dai documenti ssh-keygen (Da man ssh-keygen):

-m key_format Specifica un formato chiave per le opzioni di conversione -i (importazione) o -e (esportazione). I formati chiave supportati sono: "RFC4716" (chiave pubblica o privata RFC 4716 / SSH2), "PKCS8" (chiave pubblica PEM PKCS8) o "PEM" (chiave pubblica PEM). Il formato di conversione predefinito è "RFC4716".


3
ssh-keygen: opzione illegale - m
mbonnin,

1
La domanda va dall'altra parte.
131,

4
Per i futuri cercatori di web, se questo non funziona per te, i commenti nella domanda originale hanno funzionato per me.
kristopolous,

17
Nel mio caso, -m PKCS8era necessario
Ian Hunter il

1
$ ssh-keygen -f mykey.pub -i key_from_blob: invalid format decode blob failed.
Bastian Voigt,

54

Non c'è bisogno di script o altri "trucchi": openssle ssh-keygensono sufficienti. Non sto assumendo alcuna password per le chiavi (il che è male).

Genera una coppia RSA

Tutti i seguenti metodi forniscono una coppia di chiavi RSA nello stesso formato

  1. Con openssl ( man genrsa )

    openssl genrsa -out dummy-genrsa.pem 2048
    

    In OpenSSL v1.0.1 genrsa è sostituito da genpkeyquindi questo è il nuovo modo di farlo ( man genpkey ):

    openssl genpkey -algorithm RSA -out dummy-genpkey.pem -pkeyopt rsa_keygen_bits:2048
    
  2. Con ssh-keygen

    ssh-keygen -t rsa -b 2048 -f dummy-ssh-keygen.pem -N '' -C "Test Key"
    

Conversione di DER in PEM

Se si dispone di una coppia di chiavi RSA in formato DER, è possibile convertirla in PEM per consentire la conversione del formato di seguito:

Generazione:

openssl genpkey -algorithm RSA -out genpkey-dummy.cer -outform DER -pkeyopt rsa_keygen_bits:2048

Conversione:

openssl rsa -inform DER -outform PEM -in genpkey-dummy.cer -out dummy-der2pem.pem

Estrarre la chiave pubblica dalla coppia RSA formattata PEM

  1. in formato PEM:

    openssl rsa -in dummy-xxx.pem -pubout
    
  2. in formato OpenSSH v2 vedi :

    ssh-keygen -y -f dummy-xxx.pem
    

Appunti

Versione del sistema operativo e del software:

[user@test1 ~]# cat /etc/redhat-release ; uname -a ; openssl version
CentOS release 6.5 (Final)
Linux test1.example.local 2.6.32-431.el6.x86_64 #1 SMP Fri Nov 22 03:15:09 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
OpenSSL 1.0.1e-fips 11 Feb 2013

Riferimenti:


//, Questo genera effettivamente una chiave nel ssh-rsaformato? Buona referenza, tra l'altro.
Nathan Basanese,

@NathanBasanese, sì (vedi "Estrai la chiave pubblica dalla coppia RSA formattata PEM", punto 2): una volta che hai il certificato in formato pem: ssh-keygen -y -f dummy-xxx.pemproduce un ssh-rsa AAAA[...]==adattamento per il authorized_keysfile ssh .
Thomas,

Un buon pezzo informativo ... ma non credo che risponda davvero alla domanda, così come il pezzo molto più breve di cui sopra.
Codici Ogre,

23

Per rispondere alla mia domanda, dopo aver pubblicato sulla mailing list di openssl ho ottenuto questo:

Ecco il codice C per convertire da una chiave pubblica OpenSSL a una chiave pubblica OpenSSH. Puoi prendere il codice da questo link e compilarlo tu stesso:

static unsigned char pSshHeader[11] = { 0x00, 0x00, 0x00, 0x07, 0x73, 0x73, 0x68, 0x2D, 0x72, 0x73, 0x61};

static int SshEncodeBuffer(unsigned char *pEncoding, int bufferLen, unsigned char* pBuffer)
{
   int adjustedLen = bufferLen, index;
   if (*pBuffer & 0x80)
   {
      adjustedLen++;
      pEncoding[4] = 0;
      index = 5;
   }
   else
   {
      index = 4;
   }
   pEncoding[0] = (unsigned char) (adjustedLen >> 24);
   pEncoding[1] = (unsigned char) (adjustedLen >> 16);
   pEncoding[2] = (unsigned char) (adjustedLen >>  8);
   pEncoding[3] = (unsigned char) (adjustedLen      );
   memcpy(&pEncoding[index], pBuffer, bufferLen);
   return index + bufferLen;
}

int main(int argc, char**  argv)
{
   int iRet = 0;
   int nLen = 0, eLen = 0;
   int encodingLength = 0;
   int index = 0;
   unsigned char *nBytes = NULL, *eBytes = NULL;
   unsigned char* pEncoding = NULL;
   FILE* pFile = NULL;
   EVP_PKEY *pPubKey = NULL;
   RSA* pRsa = NULL;
   BIO *bio, *b64;

   ERR_load_crypto_strings(); 
   OpenSSL_add_all_algorithms();

   if (argc != 3)
   {
      printf("usage: %s public_key_file_name ssh_key_description\n", argv[0]);
      iRet = 1;
      goto error;
   }

   pFile = fopen(argv[1], "rt");
   if (!pFile)
   {
      printf("Failed to open the given file\n");
      iRet = 2;
      goto error;
   }

   pPubKey = PEM_read_PUBKEY(pFile, NULL, NULL, NULL);
   if (!pPubKey)
   {
      printf("Unable to decode public key from the given file: %s\n", ERR_error_string(ERR_get_error(), NULL));
      iRet = 3;
      goto error;
   }

   if (EVP_PKEY_type(pPubKey->type) != EVP_PKEY_RSA)
   {
      printf("Only RSA public keys are currently supported\n");
      iRet = 4;
      goto error;
   }

   pRsa = EVP_PKEY_get1_RSA(pPubKey);
   if (!pRsa)
   {
      printf("Failed to get RSA public key : %s\n", ERR_error_string(ERR_get_error(), NULL));
      iRet = 5;
      goto error;
   }

   // reading the modulus
   nLen = BN_num_bytes(pRsa->n);
   nBytes = (unsigned char*) malloc(nLen);
   BN_bn2bin(pRsa->n, nBytes);

   // reading the public exponent
   eLen = BN_num_bytes(pRsa->e);
   eBytes = (unsigned char*) malloc(eLen);
   BN_bn2bin(pRsa->e, eBytes);

   encodingLength = 11 + 4 + eLen + 4 + nLen;
   // correct depending on the MSB of e and N
   if (eBytes[0] & 0x80)
      encodingLength++;
   if (nBytes[0] & 0x80)
      encodingLength++;

   pEncoding = (unsigned char*) malloc(encodingLength);
   memcpy(pEncoding, pSshHeader, 11);

   index = SshEncodeBuffer(&pEncoding[11], eLen, eBytes);
   index = SshEncodeBuffer(&pEncoding[11 + index], nLen, nBytes);

   b64 = BIO_new(BIO_f_base64());
   BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
   bio = BIO_new_fp(stdout, BIO_NOCLOSE);
   BIO_printf(bio, "ssh-rsa ");
   bio = BIO_push(b64, bio);
   BIO_write(bio, pEncoding, encodingLength);
   BIO_flush(bio);
   bio = BIO_pop(b64);
   BIO_printf(bio, " %s\n", argv[2]);
   BIO_flush(bio);
   BIO_free_all(bio);
   BIO_free(b64);

error:
   if (pFile)
      fclose(pFile);
   if (pRsa)
      RSA_free(pRsa);
   if (pPubKey)
      EVP_PKEY_free(pPubKey);
   if (nBytes)
      free(nBytes);
   if (eBytes)
      free(eBytes);
   if (pEncoding)
      free(pEncoding);

   EVP_cleanup();
   ERR_free_strings();
   return iRet;
}

2
Nel caso qualcuno si stia chiedendo come compilare questo (ero), ecco la chiamata del compilatore: gcc -o pubkey2ssh pubkey2ssh.c -lcrypto
Andreas Gohr

da dove viene su Get argv [2] (ssh_key_description) da ... ho solo un ----- BEGIN RSA PUBBLICA CHIAVE ----- MIGJAoGBAMC62xWiOZYlhUhmk + JESy5eZunwGoG9kSHUMn67iBNZLEsR2qN44J1B TOtZRuEsSAKxu7alFlJVu5aSGbUvin3DusYAsl5sZjTf9VZgJHsVycOrtChC1tUi WMAWfv2BLTmK4zBEC33riEBLeX8Trphp3YbIMtzqV81ZrzHZbSnrAgMBAAE = ----- END RSA PUBBLICA KEY-- --- non ha una descrizione
braden

@braden. Di solito è solo l'indirizzo e-mail del proprietario della chiave. Ma puoi mettere quello che vuoi nella descrizione.
deltamind106,

Un'implementazione php apreshtopem qui github.com/131/yks/blob/master/class/stds/crypt.php#L346
131

La risposta di @mkalkov sotto fa la conversione usando gli strumenti da riga di comando di Linux. Ha solo bisogno del file pem di chiave pubblica con le intestazioni rimosse e le linee unite come input.
alexandroid,

13
ssh-keygen -i -m PKCS8 -f public-key.pem

3
Non ha funzionato per me: "do_convert_from_pkcs8: key.pem non è un formato di chiave pubblica riconosciuto". Ciò che ha funzionato è stato "ssh-keygen -y -f key.pem" che stampa il testo ssh-rsa necessario per le chiavi autorizzate.
Curt

1
Questo non funzionado_convert_from_pkcs8: TEST.pem is not a recognised public key format
Jinna Balu

Ha funzionato per me dopo openssl genrsa -out newkey.pem 2048eopenssl rsa -in newkey.pem -outform PEM -pubout -out newkeypublic.pem
xirix il


6

Ho fatto con

ssh-keygen -i -f $ sshkeysfile >> authorized_keys

Il merito va qui


1
Perché non hai dato credito a Victor sopra? Ti ha dato lo stesso comando quasi 8 mesi prima.
JWW

1
@jww Dal registro delle modifiche della risposta di Victor potresti vedere che originariamente la risposta era un po 'diversa, suppongo che questa sia la ragione
periklis,

4

Il seguente script otterrà il certificato di chiave pubblica ci.jenkins-ci.org in formato DER con codifica base64 e lo convertirà in un file di chiave pubblica OpenSSH. Questo codice presuppone che venga utilizzata una chiave RSA a 2048 bit e attinge molto dalla risposta di Ian Boyd . Ho spiegato un po 'di più come funziona nei commenti a questo articolo nella wiki di Jenkins.

echo -n "ssh-rsa " > jenkins.pub
curl -sfI https://ci.jenkins-ci.org/ | grep X-Instance-Identity | tr -d \\r | cut -d\  -f2 | base64 -d | dd bs=1 skip=32 count=257 status=none | xxd -p -c257 | sed s/^/00000007\ 7373682d727361\ 00000003\ 010001\ 00000101\ / | xxd -p -r | base64 -w0 >> jenkins.pub
echo >> jenkins.pub

OMG questa è la risposta migliore! E funziona! (Ho dovuto solo sostituire status = none con status = noxfer). Basta usare il secondo comando che inizia con "base64" e dargli un file PEM in input con le intestazioni eliminate e tutte le righe concatenate in una sola. Grazie @mkalkov!
alexandroid,

Si noti che i comandi sopra presuppongono una chiave a 2048 bit e non funzioneranno correttamente se viene fornita una chiave di dimensioni diverse.
alexandroid,

1

FWIW, questo script BASH prenderà un certificato X.509 in formato PEM o DER o un file di chiave pubblica OpenSSL (anche in formato PEM) come primo argomento e distribuirà una chiave pubblica RSA OpenSSH. Questo si espande sulla risposta di @ mkalkov sopra. I requisiti sono cat, grep, tr, dd, xxd, sed, xargs, file, uuidgen, base64, openssl(1.0+), e naturalmente bash. Tutti tranne openssl(contiene base64) sono praticamente garantiti per far parte dell'installazione di base su qualsiasi sistema Linux moderno, tranne forse xxd(che Fedora mostra nel vim-commonpacchetto). Se qualcuno vuole ripulirlo e renderlo più bello, attenzione.

#!/bin/bash
#
# Extract a valid SSH format public key from an X509 public certificate.
#

# Variables:
pubFile=$1
fileType="no"
pkEightTypeFile="$pubFile"
tmpFile="/tmp/`uuidgen`-pkEightTypeFile.pk8"

# See if a file was passed:
[ ! -f "$pubFile" ] && echo "Error, bad or no input file $pubFile." && exit 1

# If it is a PEM format X.509 public cert, set $fileType appropriately:
pemCertType="X$(file $pubFile | grep 'PEM certificate')"
[ "$pemCertType" != "X" ] && fileType="PEM"

# If it is an OpenSSL PEM-format PKCS#8-style public key, set $fileType appropriately:
pkEightType="X$(grep -e '-BEGIN PUBLIC KEY-' $pubFile)"
[ "$pkEightType" != "X" ] && fileType="PKCS"

# If this is a file we can't recognise, try to decode a (binary) DER-format X.509 cert:
if [ "$fileType" = "no" ]; then
        openssl x509 -in $pubFile -inform DER -noout
        derResult=$(echo $?)
        [ "$derResult" = "0" ] && fileType="DER"
fi

# Exit if not detected as a file we can use:
[ "$fileType" = "no" ] && echo "Error, input file not of type X.509 public certificate or OpenSSL PKCS#8-style public key (not encrypted)." && exit 1

# Convert the X.509 public cert to an OpenSSL PEM-format PKCS#8-style public key:
if [ "$fileType" = "PEM" -o "$fileType" = "DER" ]; then
        openssl x509 -in $pubFile -inform $fileType -noout -pubkey > $tmpFile
        pkEightTypeFile="$tmpFile"
fi

# Build the string:
# Front matter:
frontString="$(echo -en 'ssh-rsa ')"

# Encoded modulus and exponent, with appropriate pointers:
encodedModulus="$(cat $pkEightTypeFile | grep -v -e "----" | tr -d '\n' | base64 -d | dd bs=1 skip=32 count=257 status=none | xxd -p -c257 | sed s/^/00000007\ 7373682d727361\ 00000003\ 010001\ 00000101\ / | xxd -p -r | base64 -w0 )"

# Add a comment string based on the filename, just to be nice:
commentString=" $(echo $pubFile | xargs basename | sed -e 's/\.crt\|\.cer\|\.pem\|\.pk8\|\.der//')"

# Give the user a string:
echo $frontString $encodedModulus $commentString

# cleanup:
rm -f $tmpFile
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.