201 votes

Convertir une clé pem au format ssh-rsa

J'ai un certificat en der à partir duquel, avec cette commande, je génère une clé publique :

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

Ce qui donne ceci :

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

Comment puis-je obtenir une clé publique comme celle-ci ? Soit à partir d'un certificat, soit de cette clé publique ?

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

Ceci a été obtenu avec cette commande :

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

17 votes

La façon dont vous avez posté dans le "Ceci a été obtenu avec cette commande" a mieux fonctionné pour moi que toutes les réponses ci-dessous.

0 votes

Idem @YoavShapira. Etape supplémentaire si vous venez d'une clé privée openssl PKCS12 : "openssl pkcs12 -in private_key1.p12 -out private_key1.pem".

11 votes

@YoavShipra. Oui mais la question est qu'il veut convertir en utilisant seulement la clé publique. Peut-être qu'il n'a pas la clé privée et qu'il n'a que la clé publique et qu'il veut convertir le format PEM en format ssh-rsa.

180voto

Victor Mataré Points 449

Pas besoin de compiler des trucs. Vous pouvez faire la même chose avec ssh-keygen :

ssh-keygen -f pub1key.pub -i

va lire la clé publique au format openssl à partir de pub1key.pub et le sortir au format OpenSSH.

Note : Dans certains cas, vous devrez spécifier le format d'entrée :

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

À partir de la documentation de ssh-keygen (de man ssh-keygen) :

-m format_clé Spécifiez un format de clé pour les options de conversion -i (importation) ou -e (exportation). Les formats de clé pris en charge sont : "RFC4716" (clé publique ou privée RFC 4716/SSH2), "PKCS8" (clé publique PEM PKCS8) ou "PEM" (clé publique PEM). Le format de conversion par défaut est "RFC4716".

4 votes

Ssh-keygen : option illégale -- m

2 votes

La question va dans l'autre sens.

4 votes

Pour les futurs chercheurs sur le web, si cela ne fonctionne pas pour vous, les commentaires de la question originale ont fonctionné pour moi.

73voto

Thomas Points 362

Pas besoin de scripts ou autres "trucs" : openssl y ssh-keygen sont suffisantes. Je suppose qu'il n'y a pas de mot de passe pour les clés (ce qui est mauvais).

Générer une paire RSA

Toutes les méthodes suivantes donnent une paire de clés RSA dans le même format

  1. Avec openssl ( homme genrsa )

    openssl genrsa -out dummy-genrsa.pem 2048

    Dans OpenSSL v1.0.1 genrsa est supprimée por genpkey C'est donc la nouvelle façon de faire ( homme genpkey ):

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

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

Convertir DER en PEM

Si vous avez une paire de clés RSA au format DER, vous pouvez la convertir en PEM pour permettre la conversion de format ci-dessous :

Génération :

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

Conversion :

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

Extraire la clé publique de la paire RSA au format PEM.

  1. au format PEM :

    openssl rsa -in dummy-xxx.pem -pubout
  2. au format OpenSSH v2 voir :

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

Notas

Version du système d'exploitation et du logiciel :

[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

Références :

0 votes

// , Est-ce que cela génère réellement une clé dans le fichier ssh-rsa format ? Bonne référence, d'ailleurs.

0 votes

@NathanBasanese, oui (voir "Extraire la clé publique de la paire RSA au format PEM", point 2) : une fois que l'on a le certificat au format pem : ssh-keygen -y -f dummy-xxx.pem produit un ssh-rsa AAAA[...]== pour les ssh's authorized_keys fichier.

0 votes

Bon article informatif... mais je ne pense pas qu'il réponde vraiment à la question aussi bien que l'article ci-dessus, beaucoup plus court.

30voto

Adrya Points 573

Pour répondre à ma propre question, après avoir posté sur la liste de diffusion d'openssl, j'ai obtenu ceci :

Voici le code C pour convertir une clé publique OpenSSL en clé publique OpenSSH. Vous pouvez récupérer le code à partir de ce lien et le compiler vous-même :

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;
}

5 votes

Au cas où quelqu'un se demande comment compiler ceci (je l'ai fait), voici l'appel du compilateur : gcc -o pubkey2ssh pubkey2ssh.c -lcrypto

0 votes

Où obtient-on argv[2] (ssh_key_description) de... J'ai juste une -----BEGIN RSA PUBLIC KEY----- MIGJAoGBAMC62xWiOZYlhUhmk+JESy5eZunwGoG9kSHUMn67iBNZLEsR2qN44J1B TOtZRuEsSAKxu7alFlJVu5aSGbUvin3DusYAsl5sZjTf9VZgJHsVycOrtChC1tUi WMAWf2BLTmK4zBEC33riEBLeX8Trphp3YbIMtzqV81ZrzHZbSnrAgMBAAE= - ----END RSA PUBLIC KEY----- il n'a pas de description

0 votes

@braden. En général, il s'agit simplement de l'adresse électronique du propriétaire de la clé. Mais vous pouvez mettre ce que vous voulez dans la description.

8voto

mkalkov Points 166

Le script suivant obtiendrait le certificat de clé publique ci.jenkins-ci.org au format DER encodé en base64 et le convertirait en un fichier de clé publique OpenSSH. Ce code suppose qu'une clé RSA de 2048 bits est utilisée et s'inspire beaucoup de l'article de Ian Boyd intitulé réponse . J'ai expliqué un peu plus en détail comment cela fonctionne dans les commentaires de l'article suivant cet article dans le wiki de Jenkins.

echo -n "ssh-rsa " > jenkins.pub
curl -sfI https://ci.jenkins-ci.org/ | grep -i 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

1 votes

OMG c'est la meilleure réponse ! Et ça marche ! (J'ai seulement dû remplacer status=none par status=noxfer). Il suffit d'utiliser la deuxième commande commençant par "base64" et de lui donner un fichier PEM en entrée avec les en-têtes dépouillés et toutes les lignes concaténées en une seule. Merci @mkalkov !

0 votes

Notez que les commandes ci-dessus supposent une clé de 2048 bits et ne fonctionneront pas correctement si on leur donne une clé d'une taille différente.

7voto

periklis Points 4978

Je l'ai fait avec

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

Le crédit va ici

1 votes

Pourquoi n'avez-vous pas donné crédit à Victor ci-dessus ? Il vous a donné le même ordre presque 8 mois plus tôt.

1 votes

Dans le journal d'édition de la réponse de Victor, vous pouvez voir qu'à l'origine la réponse était un peu différente, je suppose que c'est la raison.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X