पीएम कुंजी को ssh-rsa फॉर्मेट में बदलें


142

मेरे पास derप्रारूप में एक प्रमाण पत्र है , इस आदेश से मैं एक सार्वजनिक कुंजी उत्पन्न करता हूं:

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

जो इस में परिणाम:

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

मैं इस तरह से एक सार्वजनिक कुंजी कैसे प्राप्त कर सकता हूं? या तो प्रमाण पत्र से या इस सार्वजनिक कुंजी से?

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

यह इस आदेश के साथ प्राप्त किया गया था:

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

14
जिस तरह से आपने "यह इस कमांड के साथ प्राप्त किया था" में पोस्ट किया गया था, मेरे लिए नीचे दिए गए किसी भी उत्तर से बेहतर था।
योव शपीरा

7
@YoavShipra। हां, लेकिन पूरा सवाल यह है कि वह केवल सार्वजनिक कुंजी का उपयोग करके कनवर्ट करना चाहता है। हो सकता है कि उसके पास निजी कुंजी न हो और उसके पास केवल सार्वजनिक कुंजी हो और वह PEM प्रारूप से ssh-rsa प्रारूप में परिवर्तित करना चाहता हो।
deltamind106

10
AWS के -pem को देखते हुए, आपके द्वारा ऊपर दी गई कमांड ssh-keygen -y -f private_key1.pem > public_key1.pubमेरे लिए बहुत काम की है।
कजकाई

1
सभी गलत जवाब। यह सही है: ssh-keygen -i -m PKCS8 -f public-key.pem
Boeboe

3
सौंदर्य देखने वाले की आंखों में है । हमें यह ध्यान देने की आवश्यकता है कि एक पीईएम कुंजी सार्वजनिक कुंजी या निजी कुंजी या दोनों को शामिल कर सकती है; एन्क्रिप्टेड या शायद नहीं; विभिन्न प्रारूप के साथ प्लस। इसके अलावा विकल्प -mका अर्थ -i/ के लिए अलग है -e। तो मेरे दोस्तों, कृपया सुनिश्चित करें कि आप जानते हैं कि आपको क्या चाहिए और आपके पास क्या है । :-)
रेयनस

जवाबों:


129

सामान संकलित करने की आवश्यकता नहीं है। आप इसके साथ भी ऐसा कर सकते हैं ssh-keygen:

ssh-keygen -f pub1key.pub -i

सार्वजनिक कुंजी को इससे खुलने वाले प्रारूप में पढ़ेगा pub1key.pubऔर इसे OpenSSH प्रारूप में आउटपुट करेगा।

नोट : कुछ मामलों में आपको इनपुट प्रारूप को निर्दिष्ट करने की आवश्यकता होगी:

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

Ssh-keygen डॉक्स से (आदमी ssh-keygen से):

-m key_format -i (आयात) या -e (निर्यात) रूपांतरण विकल्पों के लिए एक मुख्य प्रारूप निर्दिष्ट करें। समर्थित मुख्य प्रारूप हैं: "RFC4716" (RFC 4716 / SSH2 सार्वजनिक या निजी कुंजी), "PKCS8" (PEM PKCS8 सार्वजनिक कुंजी) या "PEM" (PEM सार्वजनिक कुंजी)। डिफ़ॉल्ट रूपांतरण प्रारूप "RFC4716" है।


3
ssh-keygen: अवैध विकल्प - m
mbonnin

1
सवाल दूसरे तरीके से जाता है।
131

4
भविष्य के वेब-खोजकर्ताओं के लिए, यदि यह आपके लिए काम नहीं करता है, तो मूल प्रश्न में टिप्पणियों ने मेरे लिए काम किया।
kristopolous

17
मेरे मामले में, -m PKCS8आवश्यक था
इयान हंटर

1
$ ssh-keygen -f mykey.pub -i key_from_blob: invalid format decode blob failed.
बस्तियन वोइगट

53

स्क्रिप्ट या अन्य 'ट्रिक्स' के लिए कोई ज़रूरत नहीं है: opensslऔरssh-keygen पर्याप्त हैं। मैं कुंजी (जो बुरा है) के लिए कोई पासवर्ड नहीं मान रहा हूँ।

RSA जोड़ी बनाएँ

निम्नलिखित सभी विधियाँ एक ही प्रारूप में एक आरएसए कुंजी जोड़ी देती हैं

  1. खुलने के साथ ( पुरुष जिन्न )

    openssl genrsa -out dummy-genrsa.pem 2048
    

    OpenSSL में v1.0.1 genrsa को अलग कर दिया जाता है genpkeyइसलिए यह इसे करने का नया तरीका है ( मैन जिन्नकी ):

    openssl genpkey -algorithm RSA -out dummy-genpkey.pem -pkeyopt rsa_keygen_bits:2048
    
  2. Ssh-keygen के साथ

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

पीईआर को डीईआर परिवर्तित करना

यदि आपके पास DER प्रारूप में RSA कुंजी जोड़ी है, तो आप इसे नीचे प्रारूप प्रारूप की अनुमति देने के लिए PEM में परिवर्तित कर सकते हैं:

पीढ़ी:

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

रूपांतरण:

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

PEM स्वरूपित RSA जोड़ी से सार्वजनिक कुंजी निकालें

  1. पीईएम प्रारूप में:

    openssl rsa -in dummy-xxx.pem -pubout
    
  2. OpenSSH v2 प्रारूप में देखें :

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

टिप्पणियाँ

ओएस और सॉफ्टवेयर संस्करण:

[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

संदर्भ:


//, क्या यह वास्तव में ssh-rsaप्रारूप में एक कुंजी उत्पन्न करता है? अच्छा संदर्भ, btw।
नाथन बसानी 5

@NathanBasanese, हाँ (देखें "PEM स्वरूपित RSA जोड़ी से सार्वजनिक कुंजी निकालें", बिंदु 2): एक बार जब pem प्रारूप में प्रमाण पत्र होता है: ssh की फ़ाइल के लिए ssh-keygen -y -f dummy-xxx.pemएक ssh-rsa AAAA[...]==फिट का उत्पादन करता है authorized_keys
थॉमस

अच्छा जानकारीपूर्ण टुकड़ा ... लेकिन मुझे नहीं लगता कि यह वास्तव में सवाल का जवाब देता है और साथ ही बहुत छोटे टुकड़े का भी।
ओग्रे कोड्स

23

अपने स्वयं के प्रश्न का उत्तर देने के लिए, Opensl मेलिंग सूची पर पोस्ट करने के बाद यह मिला:

यहाँ एक OpenSSL सार्वजनिक कुंजी से एक OpenSSH सार्वजनिक कुंजी में बदलने के लिए C कोड है। आप इस लिंक से कोड को पकड़ सकते हैं और इसे स्वयं संकलित कर सकते हैं:

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
यदि कोई सोच रहा है कि यह कैसे संकलित किया गया है (मैं था), यहाँ संकलक कॉल है: gcc -o pubkey2ssh pubkey2ssh.c -lcrypto
एंड्रियास गोहर

कहां से मिल argv पर करता है [2] से ... मैं बस एक ----- BEGIN RSA सार्वजनिक कुंजी ----- MIGJAoGBAMC62xWiOZYlhUhmk + JESy5eZunwGoG9kSHUMn67iBNZLEsR2qN44J1B TOtZRuEsSAKxu7alFlJVu5aSGbUvin3DusYAsl5sZjTf9VZgJHsVycOrtChC1tUi WMAWfv2BLTmK4zBEC33riEBLeX8Trphp3YbIMtzqV81ZrzHZbSnrAgMBAAE = ----- END RSA सार्वजनिक KEY-- है (ssh_key_description) --- इसमें विवरण नहीं है
ब्रैडेन

@braden। आमतौर पर यह कुंजी के मालिक का सिर्फ ईमेल पता होता है। लेकिन आप जो चाहें int वह वर्णन कर सकते हैं।
deltamind106

यहाँ एक php कार्यान्वयन खुलता है। github.com/131/yks/blob/master/class/stds/crypt.php#L346
131

नीचे @mkalkov से उत्तर लिनक्स कमांड लाइन टूल का उपयोग करके रूपांतरण करता है। इसे केवल हेडर निकालने और इनपुट के रूप में मर्ज की गई लाइनों के साथ सार्वजनिक कुंजी pem फ़ाइल की आवश्यकता है।
अलेक्जेंड्रोइड

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

3
मेरे लिए काम नहीं किया: "do_convert_from_pkcs8: key.pem एक मान्यता प्राप्त सार्वजनिक कुंजी प्रारूप नहीं है"। क्या काम किया गया "ssh-keygen -y -f key.pem" जो अधिकृत_की के लिए आवश्यक ssh-rsa पाठ को प्रिंट करता है।
कर्ट

1
यह काम नहीं कर रहा हैdo_convert_from_pkcs8: TEST.pem is not a recognised public key format
जिन्ना बलू

मेरे बाद काम किया openssl genrsa -out newkey.pem 2048औरopenssl rsa -in newkey.pem -outform PEM -pubout -out newkeypublic.pem
xirix


6

मैंने साथ दिया

ssh-keygen -i -f $ sshkeysfile >> प्राधिकृत_के

श्रेय यहाँ जाता है


1
आपने ऊपर विक्टर को श्रेय क्यों नहीं दिया? उसने आपको लगभग 8 महीने पहले वही कमान दी थी।
jww

1
@jww विक्टर के उत्तर के संपादित लॉग से आप देख सकते हैं कि मूल रूप से उत्तर थोड़ा अलग था, मुझे लगता है कि यही कारण है
पेरिक्लीस

4

निम्न स्क्रिप्ट बेस 64-एन्कोडेड DER प्रारूप में ci.jenkins-ci.org सार्वजनिक कुंजी प्रमाणपत्र प्राप्त करेगी और इसे OpenSSH सार्वजनिक कुंजी फ़ाइल में रूपांतरित करेगी। यह कोड मानता है कि 2048-बिट RSA कुंजी का उपयोग किया जाता है और इस इयान बॉयड के उत्तर से बहुत कुछ खींचता है । मैंने थोड़ा और समझाया है कि यह जेनकिंस विकी में इस लेख की टिप्पणियों में कैसे काम करता है ।

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 यह सबसे अच्छा जवाब है! और यह काम करता है! (मुझे केवल स्टेटस = कोई नहीं स्टेटस = नोक्सफर के साथ बदलना पड़ा)। बस "base64" से शुरू होने वाली दूसरी कमांड का उपयोग करें और इसे हेडर के साथ इनपुट पर PEM फ़ाइल दें और सभी लाइनों को एक में समाहित कर दिया जाए। थैंक यू @mkalkov!
अलेक्जेंड्रोइड

ऊपर दिए गए आदेशों पर ध्यान दें 2048-बिट कुंजी मान लें और यदि अलग आकार की कुंजी दी जाए तो यह सही ढंग से काम नहीं करेगी।
अलेक्जेंड्रोइड

1

FWIW, यह BASH स्क्रिप्ट पहले तर्क के रूप में PEM- या DER- प्रारूप X.509 प्रमाणपत्र या OpenSSL सार्वजनिक कुंजी फ़ाइल (भी PEM प्रारूप) लेगी और OpenSSH RSA सार्वजनिक कुंजी को अस्वीकृत कर देगी। यह ऊपर @ mkalkov के उत्तर का विस्तार करता है। आवश्यकताओं के हैं cat, grep, tr, dd, xxd, sed, xargs, file, uuidgen, base64, openssl(1.0+), और निश्चित रूप से bash। सभी को छोड़कर openssl(शामिल base64) किसी भी आधुनिक लिनक्स सिस्टम पर बेस इंस्टाल का हिस्सा बनने के लिए बहुत अधिक गारंटीकृत हैं, शायद xxd( सिवाय vim-commonपैकेज में फेडोरा शो )। अगर कोई इसे साफ करना चाहता है और इसे अच्छा बनाना चाहता है, तो कैटरर लेक्टर।

#!/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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.