Pem anahtarını ssh-rsa formatına dönüştürme


143

Biçiminde bir sertifika var der, bu komutla ortak bir anahtar oluşturmak:

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

Bunun sonucu:

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

Bunun gibi bir ortak anahtarı nasıl edinebilirim? Sertifikadan mı yoksa bu ortak anahtardan mı?

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

Bu şu komutla elde edildi:

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

14
"Bu komutla elde edildi" şeklinde yayınladığınız yol benim için aşağıdaki cevaplardan daha iyi sonuç verdi.
Yoav Shapira

7
@YoavShipra. Evet ama asıl soru sadece açık anahtarı kullanarak dönüştürmek istemesi. Belki özel anahtarı yoktur ve sadece ortak anahtarı vardır ve PEM biçiminden ssh-rsa biçimine dönüştürmek ister.
deltamind106

10
AWS'den bir .pem verildiğinde, yukarıda verdiğiniz komut ssh-keygen -y -f private_key1.pem > public_key1.pubbenim için harika çalıştı.
Kzqai

1
Tüm yanlış cevaplar. Bu doğru olanı: ssh-keygen -i -m PKCS8 -f public-key.pem
Mart'ta Boeboe

3
Güzellik bakanın gözündedir . Bir pem anahtarının ortak anahtarı veya özel anahtarı veya her ikisini birden kaplayabildiğini not etmeliyiz ; şifreli ya da olmayabilir; artı çeşitli formatta. Ayrıca seçeneğin anlamı -miçin farklıdır -i/ ' -e. Bu yüzden dostlarım, lütfen ne istediğinizi ve neye sahip olduğunuzu bildiğinizden emin olun . :-)
ryenus

Yanıtlar:


129

Bir şeyler derlemeye gerek yok. Aynısını aşağıdakilerle de yapabilirsiniz ssh-keygen:

ssh-keygen -f pub1key.pub -i

genel anahtarı opensl biçiminde okuyacak ve pub1key.pubOpenSSH biçiminde çıkaracaktır .

Not : Bazı durumlarda giriş biçimini belirtmeniz gerekebilir:

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

Ssh-keygen belgelerinden (man ssh-keygen'den):

-m key_format -i (içe aktarma) veya -e (dışa aktarma) dönüştürme seçenekleri için bir anahtar biçimi belirtin. Desteklenen anahtar biçimler şunlardır: “RFC4716” (RFC 4716 / SSH2 genel veya özel anahtar), “PKCS8” (PEM PKCS8 genel anahtarı) veya “PEM” (PEM genel anahtarı). Varsayılan dönüşüm biçimi “RFC4716” şeklindedir.


3
ssh-keygen: illegal seçenek - m
mbonnin

1
Soru tersine gidiyor.
131

4
Gelecekteki web araştırmacıları için, bu sizin için işe yaramazsa, orijinal sorudaki yorumlar benim için çalıştı.
kristopolous

17
Benim durumumda -m PKCS8gerekliydi
Ian Hunter

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

54

Komut dosyalarına veya diğer 'numaralara' gerek yok: opensslve ssh-keygenyeterlidir. (Bu kötü) tuşları için hiçbir şifre varsayıyorum.

Bir RSA çifti oluşturun

Aşağıdaki tüm yöntemler aynı biçimde bir RSA anahtar çifti verir

  1. Openssl ile ( man genrsa )

    openssl genrsa -out dummy-genrsa.pem 2048
    

    OpenSSL v1.0.1'in genrsa yerini almıştır , genpkeybu yüzden bunu yapmanın yeni yolu ( man genpkey ):

    openssl genpkey -algorithm RSA -out dummy-genpkey.pem -pkeyopt rsa_keygen_bits:2048
    
  2. Ssh-keygen ile

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

DER'i PEM'e dönüştürme

DER biçiminde bir RSA anahtar çiftiniz varsa, aşağıdaki biçim dönüşümüne izin vermek için PEM'e dönüştürmek isteyebilirsiniz:

Nesil:

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

Dönüştürmek:

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

PEM biçimli RSA çiftinden ortak anahtarı ayıklayın

  1. PEM formatında:

    openssl rsa -in dummy-xxx.pem -pubout
    
  2. OpenSSH v2 formatında bakınız :

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

notlar

İşletim sistemi ve yazılım sürümü:

[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

Referanslar:


//, Bu gerçekten ssh-rsabiçiminde bir anahtar oluşturur mu? İyi referans, btw.
Nathan Basanese

@NathanBasanese, evet (bkz. "PEM biçimli RSA çiftinden ortak anahtarı ayıklama", 2. nokta): biri pem biçiminde sertifikaya sahip olduğunda: ssh dosyası için ssh-keygen -y -f dummy-xxx.pembir ssh-rsa AAAA[...]==uyum sağlar authorized_keys.
Thomas

İyi bilgilendirici parça ... ama soruyu yanı sıra yukarıdaki çok daha kısa parçayı gerçekten cevapladığını sanmıyorum.
Ogre Kodları

23

Kendi sorumu cevaplamak için, openssl posta listesine gönderdikten sonra şu var:

İşte bir OpenSSL genel anahtarından bir OpenSSH genel anahtarına dönüştürmek için C kodu. Kodu bu bağlantıdan alıp kendiniz derleyebilirsiniz:

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
Birinin bunu nasıl derleyeceğini merak etmesi durumunda (ben), derleyici çağrısı: gcc -o pubkey2ssh pubkey2ssh.c -lcrypto
Andreas Gohr

nerede olsun argv üzerinde yaptığı [2] dan ... Sadece bir ----- BEGIN RSA KAMU KEY ----- MIGJAoGBAMC62xWiOZYlhUhmk + JESy5eZunwGoG9kSHUMn67iBNZLEsR2qN44J1B TOtZRuEsSAKxu7alFlJVu5aSGbUvin3DusYAsl5sZjTf9VZgJHsVycOrtChC1tUi WMAWfv2BLTmK4zBEC33riEBLeX8Trphp3YbIMtzqV81ZrzHZbSnrAgMBAAE = ----- END RSA KAMU KEY-- var (ssh_key_description) --- bir açıklaması yok
braden

@braden. Genellikle anahtarın sahibinin e-posta adresidir. Ama ne istersen onu açıklama içine koyabilirsiniz.
deltamind106

Burada bir php uygulama opensshtopem github.com/131/yks/blob/master/class/stds/crypt.php#L346
131

Aşağıdaki mkalkov'un cevabı, Linux komut satırı araçlarını kullanarak dönüştürme yapıyor. Yalnızca üstbilgileri kaldırılmış ve satırlar bir girdi olarak birleştirilen ortak anahtar pem dosyasına ihtiyaç duyar.
alexandroid

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

3
Benim için çalışmadı: "do_convert_from_pkcs8: key.pem tanınmış bir ortak anahtar biçimi değil". İşe yarayan, yetkili_anahtarlar için gereken ssh-rsa metnini basan "ssh-keygen -y -f key.pem" idi.
Curt

1
Bu çalışmıyordo_convert_from_pkcs8: TEST.pem is not a recognised public key format
Jinna Balu

Sonra benim için çalıştı openssl genrsa -out newkey.pem 2048veopenssl rsa -in newkey.pem -outform PEM -pubout -out newkeypublic.pem
xirix


6

İle yaptım

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

Kredi buraya gidiyor


1
Neden Victor'a yukarıda kredi vermedin? Neredeyse 8 ay önce sana aynı emri verdi.
jww

1
@jww Victor'un cevabının düzenleme günlüğünden, cevabın biraz farklı olduğunu görebilirsiniz, bunun sebebi olduğunu varsayıyorum
periklis

4

Aşağıdaki komut dosyası, ci.jenkins-ci.org genel anahtar sertifikasını base64 kodlu DER biçiminde alır ve bunu bir OpenSSH genel anahtar dosyasına dönüştürür. Bu kod, 2048 bit RSA anahtarının kullanıldığını varsayar ve bu Ian Boyd'un cevabından çok şey çeker . Jenkins wiki'deki bu makalenin yorumlarında nasıl çalıştığını biraz daha açıkladım .

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 bu en iyi cevap! Ve çalışıyor! (Ben sadece status = none ile status = noxfer değiştirmek zorunda kaldım). Sadece "base64" ile başlayan ikinci komutu kullanın ve başlıklar çıkarılmış ve tüm satırlar birleştirilmiş olarak girdi üzerine bir PEM dosyası verin. Teşekkürler @mkalkov!
alexandroid

Yukarıdaki komutların 2048 bit anahtar olduğunu varsayar ve farklı boyutta bir anahtar verilirse düzgün çalışmaz.
alexandroid

1

FWIW, bu BASH betiği ilk argüman olarak PEM- veya DER-biçimli X.509 sertifikası veya OpenSSL ortak anahtar dosyası (ayrıca PEM formatı) alacak ve bir OpenSSH RSA ortak anahtarını silmeye başlayacaktır. Bu, @ mkalkov'un yukarıdaki cevabı üzerine genişliyor. Gereksinimler şunlardır cat, grep, tr, dd, xxd, sed, xargs, file, uuidgen, base64, openssl(1.0+) ve tabii ki bash. Dışındaki bütün openssl(içerir base64) hemen hemen belki hariç, tabanın bir kısmı herhangi bir modern Linux sisteminde yüklemek olmasını garanti altına alınmıştır xxd(ki Fedora gösterileri vim-commonpaketinde). Birisi temizlemek ve daha güzel yapmak istiyorsa, lektör ikaz edin.

#!/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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.