pem 키를 ssh-rsa 형식으로 변환


143

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
"이 명령으로 얻은 것"에 게시 한 방식이 아래 답변보다 나에게 더 효과적이었습니다.
Yoav Shapira

7
@YoavShipra. 예. 그러나 전체 질문은 공개 키 만 사용하여 변환하려고한다는 것입니다. 개인 키가없고 공개 키만 있고 PEM 형식에서 ssh-rsa 형식으로 변환하려고합니다.
deltamind106

10
AWS의 .pem이 주어지면 위에서 제공 한 명령이 ssh-keygen -y -f private_key1.pem > public_key1.pub훌륭했습니다.
Kzqai

1
모든 오답. 이것은 올바른 것입니다 : ssh-keygen -i -m PKCS8 -f public-key.pem
Boeboe

3
아름다움은 보는 사람의 눈에있다 . 우리는주의 할 필요가있는 PEM의 키 수 컨테이너 중 공개 키 또는 개인 키, 또는 두 가지 모두; 암호화되었거나 아닐 수도 있습니다. 다양한 형식으로 플러스. 또한 옵션의 의미는 / -m와 다릅니다 . 내 친구들, 당신이 원하는 것과 당신이 무엇을 알고 있는지 확인하십시오 . :-)-i-e
ryenus

답변:


129

컴파일 할 필요가 없습니다. 당신은 다음과 같이 할 수 있습니다 ssh-keygen:

ssh-keygen -f pub1key.pub -i

openssl 형식의 공개 키를 읽고 pub1key.pubOpenSSH 형식으로 출력합니다.

참고 : 경우에 따라 입력 형식을 지정해야합니다.

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

ssh-keygen 문서에서 (man 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필요했습니다
Ian Hunter

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

54

어떤 스크립트 나 다른 '트릭'의 필요성 : openssl와는 ssh-keygen충분하지 않습니다. 키의 암호가 없다고 가정합니다 (나쁜).

RSA 쌍 생성

다음의 모든 방법은 동일한 형식의 RSA 키 쌍을 제공합니다

  1. openssl 사용 ( man genrsa )

    openssl genrsa -out dummy-genrsa.pem 2048
    

    은 OpenSSL 1.0.1에서 genrsa 대체됩니다 에 의해 genpkey이 그것을 (할 수있는 새로운 방법입니다 그래서 남자 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을 PEM으로 변환

DER 형식의 RSA 키 쌍이있는 경우 아래 형식 변환을 허용하기 위해 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. PEM 형식으로 :

    openssl rsa -in dummy-xxx.pem -pubout
    
  2. OpenSSH v2 형식에서는 다음을 참조하십시오 .

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

노트

OS 및 소프트웨어 버전 :

[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.
Nathan Basanese

하나는 PEM 형식의 인증서를 가지고 일단 : @NathanBasanese, 예 (참조 점 2 "RSA 쌍 포맷 된 PEM에서 공개 키를 추출") ssh-keygen -y -f dummy-xxx.pem생산 ssh-rsa AAAA[...]==SSH의 적합을 authorized_keys파일.
토마스

유익한 정보 ...하지만 나는 그것이 짧은 질문뿐만 아니라 질문에 실제로 대답하지는 않는다고 생각합니다.
오우거 코드

23

내 자신의 질문에 대답하기 위해 openssl 메일 링리스트에 게시 한 후 다음을 얻었습니다.

다음은 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
Andreas Gohr

어디서 변수는 argv에 않습니다 [2]에서 ... 난 그냥 ----- BEGIN RSA 공개 키 ----- MIGJAoGBAMC62xWiOZYlhUhmk + JESy5eZunwGoG9kSHUMn67iBNZLEsR2qN44J1B TOtZRuEsSAKxu7alFlJVu5aSGbUvin3DusYAsl5sZjTf9VZgJHsVycOrtChC1tUi WMAWfv2BLTmK4zBEC33riEBLeX8Trphp3YbIMtzqV81ZrzHZbSnrAgMBAAE = ----- END RSA PUBLIC KEY--이 (ssh_key_description) --- 그것은 설명이 없습니다
braden

@ 브 래든 일반적으로 키 소유자의 이메일 주소 일뿐입니다. 그러나 당신은 당신이 원하는대로 무엇이든 넣을 수 있습니다.
deltamind106

여기에 PHP를 구현 opensshtopem github.com/131/yks/blob/master/class/stds/crypt.php#L346
131

아래 @mkalkov의 답변은 Linux 명령 줄 도구를 사용하여 변환합니다. 헤더를 제거하고 행을 입력으로 병합 한 공개 키 pem 파일 만 있으면됩니다.
alexandroid

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

3
나를 위해 작동하지 않았습니다 : "do_convert_from_pkcs8 : key.pem은 인식되는 공개 키 형식이 아닙니다". "ssh-keygen -y -f key.pem"은 authorized_keys에 필요한 ssh-rsa 텍스트를 출력합니다.
Curt

1
이 작동하지 않습니다do_convert_from_pkcs8: TEST.pem is not a recognised public key format
Jinna Balu

후 나를 위해 일한 openssl genrsa -out newkey.pem 2048openssl rsa -in newkey.pem -outform PEM -pubout -out newkeypublic.pem
xirix


6

나는 ~했다

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

신용은 여기에 간다


1
왜 위의 Victor에게 신용을주지 않았습니까? 그는 거의 8 개월 전에 같은 명령을 내 렸습니다.
jww

1
@jww Victor의 답변 편집 로그에서 원래 답변이 약간 다르다는 것을 알 수 있습니다. 이것이 이유 인 것으로 가정합니다
periklis

4

다음 스크립트는 base64로 인코딩 된 DER 형식의 ci.jenkins-ci.org 공개 키 인증서를 가져 와서 OpenSSH 공개 키 파일로 변환합니다. 이 코드는 2048 비트 RSA 키가 사용되는 것으로 가정하고이 Ian Boyd의 답변 에서 많은 것을 이끌어냅니다 . Jenkins Wiki 의이 기사 에 대한 의견에서 어떻게 작동하는지 조금 더 설명했습니다 .

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

세상에 이것이 가장 좋은 대답입니다! 그리고 작동합니다! (status = none을 status = noxfer로 바꿔야했습니다). "base64"로 시작하는 두 번째 명령을 사용하고 헤더가 제거되고 모든 행이 하나로 연결된 입력시 PEM 파일을 제공하십시오. @mkalkov 감사합니다!
Alexandroid

위의 명령은 2048 비트 키를 가정하며 다른 크기의 키가 제공되면 올바르게 작동하지 않습니다.
alexandroid

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는 Fedora가 vim-common패키지에 표시하는 것을 제외하고는 모든 최신 Linux 시스템에서 기본 설치의 일부로 보장됩니다 . 누군가가 그것을 청소하고 더 ​​좋게 만들고 싶다면 강사를주의하십시오.

#!/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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.