【问题标题】:Why ssh-keygen does not output 32 bytes but instead 1612 chars?为什么 ssh-keygen 不输出 32 个字节而是输出 1612 个字符?
【发布时间】:2021-11-01 20:17:20
【问题描述】:

我的目标是创建自己的 TLS 握手服务器,这样我就可以了解服务器-客户端之间的加密是如何工作的。我正在关注this 参考。在参考资料的Server Key Exchange Generation 部分中,私钥长度被称为 32 字节。但示例长度为 64 字节。此外,ssh-keygenprivate.key 输出 1612 个字符,为private.pub 输出 567 个字符。

我的预期结果:private.pub 应该在参考的Server Hello 部分中使用,它将长度为 32 字节的公钥发送给客户端。

我的实际结果:ssh-keygen 甚至 keytool(我无法使用 IntelliJ IDEA 读取文件,所以现在我正在避免它)输出超过 32 个字节。

使用的cmd

ssh-keygen
keytool -genkeypair -keyalg RSA -validity 7 -keystore keystore 

测试\实验\tls\tls\TLSHandshake.java

class TLSHandshakeTest {

  @Test
  void doHandshake() {
    String key = "MC4CAQAwBQYDK2VuBCIEIJCRkpOUlZaXmJmam5ydnp+goaKjpKWmp6ipqqusra6v";
    byte[] bytes = key.getBytes();
    System.out.println(Arrays.toString(bytes));
    // output: 64 instead of 32, does this mean that the `private.pub` file must be processed with an encoder?
    System.out.println(bytes.length);
  }
}

【问题讨论】:

标签: java ssl tls1.2


【解决方案1】:

“服务器密钥交换生成”步骤中生成的 32 字节(128 位)密钥不是 RSA 私钥。它实际上是用于保护应用程序数据的对称加密算法的密钥。

发生的情况是 RSA 非对称算法用于建立身份并保护协商。在此过程中,对称算法得到同意,并生成和交换 128 位密钥(安全地)。会话建立后,128 位密钥用于加密和解密通过连接发送的数据。

他们为什么不对所有事情都使用 RSA?

基本上,使用 RSA(或任何其他非对称算法)进行批量数据加密/解密的计算成本太高。对称(块密码)算法效率更高。 (因此您可以将初始协商视为会话私钥的“密钥分发机制”。)

至于ssh-keygen生成的私钥和公钥文件的大小:

  1. 文件包含不止一个键:
    • 公钥文件包含modulus 的值和公共指数e
    • 私钥文件通常包含moduluse的值和私有指数d以及更多的值(pqdpdq、@ 987654332@)。这就是为什么私钥文件比公钥文件大的部分原因!
  2. 文件内容以 ASN.1 编码,增加了一些额外的类型标头。
  3. (二进制)ASN.1 编码数据然后进行 base64 编码,每 6 位数据使用大约一个 ASCII 字符(加上一些填充)。
  4. 添加了一些额外的东西:
    • 私钥添加了换行符,以及“PEM”标题和尾行。
    • 公钥具有算法的名称(例如“ssh-rsa”)和添加的“注释”,用于识别密钥所属的人。 (该注释在很大程度上被 SSH 忽略了……但当您从“授权密钥”文件中手动添加或删除密钥时,它很有用。)

对于更高版本的 OpenSSH,可以使用 OpenSSH 密钥格式代替 OpenSSL 密钥格式。这些使用 XDR 编码代替 ASN.1。如果您尝试编写自己的 SSH 实现,这可能与您有关1


正如我们所见,ssh-keygen 生成的“私钥”文件实际上包含密钥对的公钥和私钥。实际上,可以从私钥文件中恢复密钥对的公钥;例如

ssh-keygen -f ~/.ssh/id_rsa -y > ~/.ssh/id_rsa.pub

详情请参阅Create a public ssh key from the private key


1 - 老实说,我看不出这样做的意义。这是一个很大的努力......只是为了学习一堆你很可能不需要知道的细节。

【讨论】:

  • 基本正确,但是:RSA 中的“素数”通常表示 因数 p,q,而这些都不在公钥中。公钥具有模数和公共指数 e,而私钥通常具有模数 e和私有指数d多个值(p,q,dp ,dq,qinvp) 用于中国剩余定理 aka CRT,在几个堆栈上有许多现有的 Q。 e 和 d 都不一定是素数,尽管 e经常被选为固定的小素数。 ...
  • 谢谢。合并了这些细节(以缩短的形式)。
  • ... OpenSSH 的旧版本创建了 OpenSSL 格式的私钥文件,正如您所描述的那样,但 6.5 或 7.8 或更高版本默认使用非 ASN.1 编码的不同格式;它使用 OpenSSH 定义的 XDR 样式编码,然后以相同的方式(并具有大致相同的扩展)“PEM 化”(带有换行符、标题和尾部的 base64 编码)。 OpenSSH 格式的公钥是 never ASN.1。此外,对称(会话)密钥通常称为秘密,而不是私有。
猜你喜欢
  • 2012-04-29
  • 1970-01-01
  • 2020-01-10
  • 1970-01-01
  • 1970-01-01
  • 2018-02-27
  • 2011-12-04
  • 1970-01-01
  • 2014-12-14
相关资源
最近更新 更多