如何使用 python 复制 ssh-keygen 的功能
Posted
技术标签:
【中文标题】如何使用 python 复制 ssh-keygen 的功能【英文标题】:How to replicate the functionality of ssh-keygen using python 【发布时间】:2019-11-20 12:20:53 【问题描述】:我需要生成一个用于 SFTP 身份验证的 RSA 密钥对。 SFTP 使用 OpenSSH,根据其 IETF 规范,密钥应该只能由 ssh-keygen 生成。 https://www.openssh.com/specs.html
但是,对于我当前的项目,我不能依赖像 ssh-keygen 这样的外部程序,即使通过 python 的 subprocess 模块之类的东西执行。这与部署环境的细节有关。无论如何,由于某种原因,我使用 python 的加密模块生成的密钥虽然看起来正确,但在 SFTP 登录期间被拒绝。
我不知道是什么让 ssh-keygen 密钥如此特别。我怀疑它要么与密钥大小/长度或公共指数等参数有关,要么可能是由于字符编码问题。
这是生成密钥的代码
from cryptography.hazmat.primitives import serialization as crypto_serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.backends import default_backend as crypto_default_backend
key = rsa.generate_private_key(
backend=crypto_default_backend(), public_exponent=65537, key_size=2048)
private_key = key.private_bytes(
crypto_serialization.Encoding.PEM, crypto_serialization.PrivateFormat.PKCS8, crypto_serialization.NoEncryption()).decode("utf-8")
public_key = key.public_key().public_bytes(
crypto_serialization.Encoding.OpenSSH, crypto_serialization.PublicFormat.OpenSSH).decode("utf-8")
print(public_key)
print(private_key)
以下是 sftp 接受的 ssh-keygen 生成的密钥。
公钥:
(我修改了user@machine_name
部分,但我高度怀疑这是否相关,因为当我将公钥部署到 sftp 服务器时,我实际上是在剥离这部分)
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDWe1fmzvKHYu90YbGiDVD/k+Jj6OgQLUuleTIkAiljrN+Z6RTF9xK6bk5uEquB5TBWvl/i9kh8blCjkxnKI8ivvBZiX6ubuRraEtkmRR+/UmxHehKwE40eAtbFjY6q69PpNBg+iM7nXrTHK1vmD5VY8KsflfKBmS628V0QxxgQTdi/irb4AZLBqR7lAnanB15envtMBxoesoA6Duaj47TftzDP2j8iX7Jgj+WZqB85aqggbxUfV0kDVj9YbSuZk9ccA3udRlMpH2k1aiMemF0zB2jHXHPHTE+0sIoX0J331+yzWR+iJXwZeEdRREmeTc8FJN2/Rq1lLH87NPkB4uhH user@machine_name
私钥:
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA1ntX5s7yh2LvdGGxog1Q/5PiY+joEC1LpXkyJAIpY6zfmekU
xfcSum5ObhKrgeUwVr5f4vZIfG5Qo5MZyiPIr7wWYl+rm7ka2hLZJkUfv1JsR3oS
sBONHgLWxY2OquvT6TQYPojO5160xytb5g+VWPCrH5XygZkutvFdEMcYEE3Yv4q2
+AGSwake5QJ2pwdeXp77TAcaHrKAOg7mo+O037cwz9o/Il+yYI/lmagfOWqoIG8V
H1dJA1Y/WG0rmZPXHAN7nUZTKR9pNWojHphdMwdox1xzx0xPtLCKF9Cd99fss1kf
oiV8GXhHUURJnk3PBSTdv0atZSx/OzT5AeLoRwIDAQABAoIBADX/z924dK9JZWgz
wHlASQhPv0vQM7z+6nC61rjiInGJ8LHbUPOWhQyTAQQNh0io30a3n4SQ5ScOzxaf
znpqD/jOrgQOejI2pGALJsjP1nJg2goU3eeexIStykzqmuTFgxDPoNr9rrnpyjHq
5LRDcCJ4VV0ab3fZjT1Z/0heF9zihnnZ1eQ/4DCgkSQe9IVVmyoTCRAL57DE4JVa
XSq7rWjnFO9fFUFH2HaWUvZqZJcwStr4UrgxhE+x57b5ymhwcf+PQNyrGFSDHdFu
calbCZKyriTe3/CGyKy0TuHbjYd89cE/6kJ8UBuBdr40ttRKj50l3h2PDoYLgP3d
N+HPSyECgYEA9KH7DmRI5iFOul/nImy3MXkaruVehgXmFytCzrysNDNp66o+8dZ4
PBdZDmMhFLIwM/v7a1RLnEHOkF0oIXLWJaVaWqT64RipvtUvYie1zSTbviLLMaJT
FvrH9Xwx82HobkOyrLc26m/gSktKT2OmzJmt+YhByqsPim5L8u+QsAUCgYEA4HK0
F5I0WrLV3abN3g9VkSEfdp3QvF0eTzS7i9C83mAlVizt9PqGjvLIWUfSRiTZPCzX
vaT/sHX3xi2znDUYQ43aFouAzVyN9Qa76nxtuB6c2iBM6sW69Mcct8M9HdjcPF6O
v9XqXuZTn/AD9AHoTHZtGOnMKTX0YjEqeHbfRNsCgYAKDWHonHxWYIYAqJIx2u/I
K6bKCwjQTwu+ZfuvzRbyai5vDabafyqfpYH2UmJ4nD3Y1QDmzybwO9AGJJ3Sigp8
r4e/88mPWFkZS19QFDunO12AOaPJ3Va2ugVfdAQFcT+A0G1WJY0vIvu/ccqS6pBf
Fe2NNGknr9HKqW+bgvaaFQKBgQC7gVfOcUfnlYtxVo6ZurnDOqasU380PZ66kNU1
IrcGF9BZQ8OvazPKbCzP2V5jVxlcWiIJvrQU2RibqUZpcznIBdNyDi0WYwH89xk5
9aU7sedbmqxnXbSoFUd6hVKjgq3KiTw8KxtXGJg3/y1uRcGpTy4pJ/h1XSvCdEyE
wtoXDQKBgQC8RjCF3ZcZYIIii10K0BHX4YSiRC3PLi7rUQ9jVZN4FGwBB+NQzwSe
7iIW4lqUDZ6SKDwkNKi5vdnx2BBBadJO74vcqWxdanBk0SbEsJZDFVb2bGvjOVzH
CLhCavojqtFNMCFQTge9P6wff+qegY1RzTEkht3YiiWAGkFkDVp5gg==
-----END RSA PRIVATE KEY-----
下面是我的程序的输出
公钥:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDr0tbRIlabQr6xPudI3Gz9qN7hIeKhMdrxiKzXsgfBElRF6htfUebwFTcmRrPeb0mN+wCdcrnAF+iG+cYvpjhX6mQa+rBV79kiUZJg3n/BfjiMBko9q6QDrpOfNdKElnGVqBcTFSZKyzNfGpOTcpzCxXd76IyUx1MuY2A4MUC/TVBNpJnrEqvJjaAAbtTWDXYmzmApL3m308CH+SV2NKE5dzHNX+NvFeZ2Xlcv5ZRGB6jiUV+HI3QFPeaLJ+xneucc0rCrjF22RHvBFovnInFnIDXdadqsElxAKYviygpZL6ekJJETJhZjGzDNJh0b30OiZS493CDmd7Qb97MfN95/
私钥:
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDr0tbRIlabQr6x
PudI3Gz9qN7hIeKhMdrxiKzXsgfBElRF6htfUebwFTcmRrPeb0mN+wCdcrnAF+iG
+cYvpjhX6mQa+rBV79kiUZJg3n/BfjiMBko9q6QDrpOfNdKElnGVqBcTFSZKyzNf
GpOTcpzCxXd76IyUx1MuY2A4MUC/TVBNpJnrEqvJjaAAbtTWDXYmzmApL3m308CH
+SV2NKE5dzHNX+NvFeZ2Xlcv5ZRGB6jiUV+HI3QFPeaLJ+xneucc0rCrjF22RHvB
FovnInFnIDXdadqsElxAKYviygpZL6ekJJETJhZjGzDNJh0b30OiZS493CDmd7Qb
97MfN95/AgMBAAECggEAFJ5QjeR0sgp55cFcM3CiTuNO6VwvFmzneaq7gfhc2TKj
D6HSVtkwWdlhAwW3gEE2qyVA/oMjXno4qGR6QXxE/NrPedRlSn43+9op9DI/9Uj1
5LhAEXhKVNAUtBzelR0aPT1/FvoIaQ2vJieKs5+XuSfOtJS2heOPkES8Cu2zfYY3
/egSvYCCWoG12xYx7u67b0z4ZUV7a0sbLTov0+R3UAlI68hUy6z5Eu45QdZ83D9U
qO/JDeycSvOldpuV5kmRD0lTvsc0hDrlr0pA7yzf7/M+NI4r8cfXPpJZLK3Riott
GYS6YN4JmfO7D6nP2DjyrboDsVDy4TJkD/ZycMd/AQKBgQD8jmMAQFiJGoMlOqyC
YGxwOxL/qvFEQ2R1FDIywpDQnsK/Jrln6zgR88MWyuJyM+7MHgF5BP9u8hS3WQ0U
DF2sGBfFQNJUWJUKAtHpfA/qsep1PX6lr9mWZYFEIEugDZDRLVVDFvLG7tk8fauD
bvmMexy+0uT9dTsmx3GaLm9avwKBgQDvCgr51MHTj1E7Ynv0aI20ySI8vZnEHnPU
r36GIfqz5i67KLG3HTV0Awo4njXa6W6w+Kdg78saRXhVbZFlRfYIfsVT9OpRxKXM
QDElK0gtrJRIRgLz7/1lVUUE4Hj0a76p7GhfhES2qKYqIPnF/lpfMt44DE+ARmEK
ra03cecsQQKBgCGmZxJ1gFZkLe0b8Dg+2LPraxCdmh/aStw+oKGawujI/nGxmyp5
cLMTo3658Yn92Wdg6BlTzSTfJFt5hgCR1TlEzIX/qQaL9u+qiIVvfj9rDS4pz2IM
GBWt2JdXJjxhElaMj7uspxRSZqdkpyGP+7f3/1B9kP0kTYlRMZW1cijJAoGAMRvH
FXx4NZaEAcdB3/x64GFR/1iUdo4rDc7gF35zmvH3N8wsdooxqRvWxbr7JXY/n2v2
NxwMheEvz50q+btdyHEC6TSvzwyvYz7s2c4Cjh+edxqrEKKFVIQoIdBcCRr5mL9Q
0g7CbyRGvvD3X43Z0yUIMkuVKa1L0n3L0FA+RgECgYArd7mvlJTIu6b2TZdQsTLt
5Ygqpkgz5ZcFX3fuiaJLFqpUnYYns7aBmHbotBKijEN7ags7SMilMuXqY5+OraJG
+qoheN5EGgvgiT9KF6KBjZblUCUFak5SAS8F+/J5oIPNLzZmf+Q5CKncswBSBras
ka+XkZ5QzRm6hFZB7E7q6A==
-----END PRIVATE KEY-----
【问题讨论】:
我不知道您从哪里获得第一段中的信息,但这大多是错误的。为什么不直接使用您正在使用的任何 SSH 库来生成密钥? 我从那个链接得到了信息 你误会了。您在使用 Paramiko 进行 SFTP 吗? 没有。我正在使用 aws transfer sftp 服务 【参考方案1】:OpenSSH ssh-keygen 使用的标头是旧的 PEM 文件:
-----BEGIN RSA PRIVATE KEY-----
您的脚本创建的标头是新的 PKCS#8 PEM 文件,如果您使用一些非标准工具连接到 sftp,它们不完全兼容。
-----BEGIN PRIVATE KEY-----
您可以使用 serialization.TraditionalOpenSSL
参数为您的 private_bytes
函数创建相同的旧 PEM 格式。
【讨论】:
很棒的提示!我更改为private_key = key.private_bytes(crypto_serialization.Encoding.PEM, crypto_serialization.PrivateFormat.TraditionalOpenSSL, crypto_serialization.NoEncryption()).decode("utf-8")
,输出显示RSA PRIVATE KEY
,但它仍然无法正常工作。私钥文件实际上比 rsa-keygen 文件短几个字符
其实,我的错,它正在工作。您的解决方案已解决,谢谢!
仅供参考:此格式不是旧格式。这种格式是 PKCS #1,在任何地方都广泛使用。 PKCS #8 是另一种具有更多选择的格式。
@JohnHanley 没有什么不能让它成为传统格式,因为有一种被广泛接受作为现代一切事物的替代品。
您将您的意见作为事实来表达。 PKCS #1 是标准系列的一部分,是迄今为止最流行的格式。在大多数用例中,PKCS #8 只是包装了 PKCS #1。以上是关于如何使用 python 复制 ssh-keygen 的功能的主要内容,如果未能解决你的问题,请参考以下文章