python - 如何使用 python 复制 ssh-keygen 的功能

标签 python cryptography rsa openssh ssh-keygen

我需要生成 RSA key 对以用于 SFTP 身份验证。 SFTP 使用 OpenSSH,根据其 IETF 规范, key 应该只能由 ssh-keygen 生成。 https://www.openssh.com/specs.html

但是,对于我当前的项目,我不能依赖像 ssh-keygen 这样的外部程序,即使是通过 python 的子进程模块之类的东西执行。这与部署环境的细节有关。无论如何,由于某种原因,我使用 python 的加密模块生成的 key 虽然看起来正确,但在 SFTP 登录期间被拒绝。

我不知道是什么让 ssh-keygen key 如此特别。我怀疑它要么与 key 大小/长度或公共(public)指数等参数有关,要么可能是由于字符编码问题。

这是生成 key 的代码

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 生成的 key 。

公钥:

(我修改了 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-----

最佳答案

OpenSSH ssh-keygen 使用的 header 是旧版 PEM 文件:

-----BEGIN RSA PRIVATE KEY-----

您的脚本创建的 header 是新的 PKCS#8 PEM 文件,如果您使用某些非标准工具连接到 sftp,它们并不完全兼容。

-----BEGIN PRIVATE KEY-----

您可以使用serialization.TraditionalOpenSSL创建相同的旧版PEM格式。 private_bytes 函数的参数。

关于python - 如何使用 python 复制 ssh-keygen 的功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56978048/

相关文章:

java - 将 HMAC 函数从 Java 转换为 JavaScript

java - 将字符串转换为字节数组

Java - 从 5 个 CRT 组件生成 RSA key 对

c - 我正在使用 RSA 算法的源代码。它编译正确,没有错误,但输出不正确

python - 在 C 中进行连接管理有哪些好方法?

python - 搜索 "(/(?:[a-zA-Z0-9_-]+/?)*)"之后且不以 "/xyz"开头的正则表达式

php - 使用 openssl 解密 mcrypt

c# - Rfc2898/PBKDF2 与 SHA256 作为 c# 中的摘要

python - AWS Lambda : Calling the invoke API action failed with this message: Network Error

python - 用于在 Python 中过滤对象的用户界面