web-dev-qa-db-fra.com

Convertir la clé pem au format ssh-rsa

J'ai un certificat au format der, à partir de celui-ci, je génère une clé publique:

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

Ce qui résulte en 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 du certificat ou 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
120
Adrya

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

Voici le code C pour convertir une clé publique OpenSSL en une clé publique OpenSSH . Vous pouvez récupérer le code depuis 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;
}
21
Adrya

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

ssh-keygen -f pub1key.pub -i

lit la clé publique au format openssl à partir de pub1key.pub et la génère au format OpenSSH.

Remarque : Dans certains cas, vous devrez spécifier le format de saisie:

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

Depuis les documents ssh-keygen (à partir de man ssh-keygen):

-m key_format 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».

108
Victor Mataré

Pas besoin de scripts ou d'autres "astuces": openssl et ssh-keygen suffisent. J'assume 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 au même format

  1. Avec openssl ( man genrsa )

    openssl genrsa -out dummy-genrsa.pem 2048
    

    Dans OpenSSL v1.0.1 genrsaest remplacé par par genpkey, il s'agit donc d'une nouvelle façon de procéder ( man 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"
    

Conversion de DER en PEM

Si vous avez une paire de clés RSA au format DER, vous pouvez la convertir en fichier PEM pour autoriser 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 formatée 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
    

Remarques

OS et version 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:

39
Thomas

Toutes les mauvaises réponses. C'est le bon:

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

6
Boeboe

J'ai fait avec 

ssh-keygen -i -f $ sshkeysfile >>keke_autorisé

Le crédit va ici

6
periklis
ssh-keygen -f private.pem -y > public.pub
6
zkilnbqi

Le script suivant obtiendrait le certificat de clé publique ci.jenkins-ci.org au format DER codé en base64 et le convertirait en fichier de clé publique OpenSSH. Ce code suppose qu'une clé RSA de 2048 bits est utilisée et tire beaucoup de cette réponse de Ian Boyd answer . J'ai expliqué un peu plus comment cela fonctionne dans les commentaires de cet article sur le wiki 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
2
mkalkov

FWIW, ce script BASH prend comme premier argument un certificat X.509 au format PEM ou DER ou un fichier de clé publique OpenSSL (également au format PEM), puis dégorge une clé publique OpenSSH RSA. Cela développe la réponse de @ mkalkov ci-dessus. Les conditions requises sont les suivantes: cat, grep, tr, dd, xxd, sed, xargs, file, uuidgen, base64, openssl (1.0+), et bien sûr bash. Tous sauf openssl (contient base64) sont quasiment garantis de faire partie de l'installation de base sur tout système Linux moderne, à l'exception peut-être de xxd (que Fedora montre dans le paquet vim-common). Si quelqu'un veut le nettoyer et le rendre plus agréable, avertissez le lecteur.

#!/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
0
db_

Il suffit d'utiliser:

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

Le script est ici .

0
nicks91