为什么我的OpenSSH密钥指纹与AWS EC2控制台密钥对指纹不匹配?


73

当我将OpenSSH公钥导入AWS EC2的密钥环时,AWS显示的指纹与我从中看到的指纹不匹配:

ssh-keygen -l -f my_key

它是不同的长度,并且具有不同的字节。

为什么?我确定我上传了正确的密钥。

Answers:


102

AWS EC2显示SSH2指纹,而不是每个人都期望的OpenSSH指纹。它在用户界面中没有说明。

它还显示两种完全不同的指纹,具体取决于密钥是在AWS上生成并下载的,还是您上载了自己的公钥的。

产生的指纹

ssh-keygen -l -f id_rsa

符合什么EC2节目。您可以使用AWS API工具通过ec2-fingerprint-key命令生成指纹,也可以使用OpenSSL进行指纹识别。

请注意,如果您最初是在AWS上生成密钥,然后又将其上传(例如,到另一个区域),则您将获得一个不同的指纹,因为它将使用SSH2 RSA指纹,而不是它为您显示的密钥显示的sha1在AWS上生成。

好玩,嘿? 此屏幕快照中包含相同密钥的两个副本,但指纹不同

以上test-generated是使用AWS EC2生成的。test-generated-reuploaded是AWS生成,提取ssh-keygen -y并再次上传的私钥中的公钥。第三个密钥test-uploaded是本地生成的密钥,但是本地ssh-keygen -l指纹是b2:2c:86:d6:1e:58:c0:b0:15:97:ab:9b:93:e7:4e:ea

$ ssh-keygen -l -f theprivatekey
2048 b2:2c:86:d6:1e:58:c0:b0:15:97:ab:9b:93:e7:4e:ea
$ openssl pkey -in theprivatekey -pubout -outform DER | openssl md5 -c
Enter pass phrase for id_landp:
(stdin)= 91:bc:58:1f:ea:5d:51:2d:83:d3:6b:d7:6d:63:06:d2

本地生成的密钥

正如Daniel在AWS论坛上演示的那样,您可以使用OpenSSL 以AWS所使用的形式生成指纹,以显示上载的公共密钥(SSH2 MD5)的指纹,例如:

7a:58:3a:a3:df:ba:a3:09:be:b5:b4:0b:f5:5b:09:a0

可以通过从私钥中提取公共部分并使用以下方式对其进行散列来生成它们:

openssl pkey -in id_rsa -pubout -outform DER | openssl md5 -c

在AWS上生成的密钥

如果AWS控制台上显示的密钥指纹更长,则它是在AWS上生成的私钥,例如:

ea:47:42:52:2c:25:43:76:65:f4:67:76:b9:70:b4:64:12:00:e4:5a

在这种情况下,您需要使用以下命令(也由Daniel在AWS论坛上显示)根据私钥生成sha1哈希:

openssl pkcs8 -in aws_private.pem -nocrypt -topk8 -outform DER | openssl sha1 -c

在下载的AWS生成的私钥/证书文件上。它也适用于您转换为OpenSSH格式的密钥。

参考文献

看到:


4
遗憾的是,AWS缺乏对此的明确性,他们正在开启潜在的安全漏洞,使密钥验证变得更加困难
Jaime Hablutzel 2014年

好答案!在初始ssh命令上,如果使用的是最新版本,则需要-E选项来指定md5格式: ssh-keygen -E md5 -l -f id_rsa
RichVel

13

如果只有公共密钥,则可以按以下方式生成AWS指纹:

ssh-keygen -e -f id_rsa.pub -m pkcs8 | openssl pkey -pubin -outform der | openssl md5 -c

2

AWS文档上有资源http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html#verify-key-pair-fingerprints

如果使用AWS创建了密钥对,则可以使用OpenSSL工具从私钥文件生成指纹:

复制

$ openssl pkcs8 -in path_to_private_key -inform PEM -outform DER -topk8 -nocrypt | openssl sha1 -c

如果您使用第三方工具创建了密钥对并将公钥上载到AWS,则可以使用OpenSSL工具从本地计算机上的私钥文件生成指纹:

复制

$ openssl rsa -in path_to_private_key -pubout -outform DER | openssl md5 -c

输出应与控制台中显示的指纹匹配。


2

这是我用的:

openssl rsa -RSAPublicKey_in -in <(ssh-keygen -f ~/.ssh/id_rsa.pub -e -m PEM) -inform PEM -outform DER 2>/dev/null | openssl md5 -c | awk '{print $2}'

与上面的某些类似,这将从公钥生成指纹。


1

对于那些使用Python的人

from Crypto.PublicKey import RSA
import hashlib
import base64

#Load your key from disk, or a string, or generate.
my_key = RSA.importKey(open(my_rsa_private_key, 'r').read())

# Normal md5 fingerprint
fp_plain = hashlib.md5(base64.b64decode(my_key.exportKey('OpenSSH').strip().split()[1].encode('ascii'))).hexdigest()
print ':'.join(a+b for a,b in zip(fp_plain[::2], fp_plain[1::2]))

#AWS' EC2 fingerprint
public_only_key = RSA.importKey(my_key.exportKey('OpenSSH'))
fp_plain = hashlib.md5(public_only_key.exportKey('DER')).hexdigest()
print ':'.join(a+b for a,b in zip(fp_plain[::2], fp_plain[1::2]))

不幸的是,这在使用最新的Homebrew Python 2.7.13的macOS 10.11上对我失败,出现以下错误:ValueError: PEM encryption format not supported.
RichVel

@RichVel,我无法重现该错误。我刚刚在virtualenv中使用自制python 2.7.13在macOS 10.12上进行了测试,并且工作正常。如果我不得不猜测,也许您不满足pycrypto的一些C要求。也许会有所帮助?
安迪

1
#!/bin/bash
key_file=$1
if [[ -n $key_pub_file ]]; then
    ssh-keygen -e -f $key_pub_file -m pkcs8 | openssl pkey -pubin -outform der | openssl md5 -c
else
    echo "pass the pub file as argument"
fi

这是我使用的脚本,将脚本路径添加到env。感谢J.Doe的回答



0

Java(使用BouncyCastle)。如果AWS控制台显示较短的键,请尝试使用MD5。(SHA1:20个字节,MD5:16个字节)。

  /**
   * @return the SHA1 digest of the DER encoded RSA private key, e.g. 16:61:7d:1c:e7:d1:3b:93:b6:81:bf:64:7a:a0:38:fa:b6:6c:9e:e4
   */
  private String getAwsFingerprint(File rsaPrivateKeyFileFromAws) throws Exception {
    try(FileReader reader = new FileReader(rsaPrivateKeyFileFromAws)) {
      java.security.KeyPair keyPair = new JcaPEMKeyConverter().getKeyPair((PEMKeyPair) new PEMParser(reader).readObject());
      String hex = Hex.toHexString(MessageDigest.getInstance("SHA1").digest(keyPair.getPrivate().getEncoded()));
      StringBuilder sb = new StringBuilder();
      for(int i = 0; i < hex.length();) {
        sb.append(hex.charAt(i++));
        sb.append(hex.charAt(i++));
        sb.append(i % 2 == 0 && i != hex.length() ? ":" : "");
      }
      return sb.toString();
    }
  }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.