我需要生成用于SFTP身份验证的RSA密钥对。 SFTP使用OpenSSH,并且根据其IETF规范,密钥应该仅由ssh-keygen生成。 https://www.openssh.com/specs.html
但是,对于我当前的项目,即使通过python的subprocess模块之类的东西执行,我也不能依赖ssh-keygen这样的外部程序。这与部署环境的细节有关。无论如何,由于某种原因,我用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-----
答案 0 :(得分:0)
使用OpenSSH ssh-keygen的标头是旧版PEM文件:
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
class MapsDemo extends StatefulWidget {
@override
State createState() => MapsDemoState();
}
class MapsDemoState extends State<MapsDemo> {
final Set<Marker> _markers = {};
void _onAddMarkerButtonPressed() {
print('in _onAddMarkerButtonPressed()');
setState(() {
_markers.add(Marker(
// This marker id can be anything that uniquely identifies each marker.
markerId: MarkerId("111"),
position: LatLng(30.666, 76.8127),
infoWindow: InfoWindow(
title: "bingo! This works",
),
icon: BitmapDescriptor.defaultMarker,
));
});
print('setState() done');
}
GoogleMapController mapController;
//Map<PermissionGroup, PermissionStatus> permissions = await PermissionHandler().requestPermissions([PermissionGroup.contacts]);import 'package:permission_handler/permission_handler.dart';
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: GoogleMap(
markers: _markers,
onMapCreated: (GoogleMapController controller) {
mapController = controller;
},
initialCameraPosition:
CameraPosition(target: LatLng(30.666, 76.8127), zoom: 15),
),
),
],
),
floatingActionButton: FloatingActionButton(onPressed: () {
print('in fab()');
double mq1 = MediaQuery.of(context).devicePixelRatio;
_onAddMarkerButtonPressed();
mapController.animateCamera(
CameraUpdate.newCameraPosition(
CameraPosition(
target: LatLng(30.666, 76.8127),
zoom: 15.0,
),
),
);
}));
}
}
您的脚本创建的标头是新的PKCS#8 PEM文件,如果您使用某些非标准工具连接到sftp,则它们并不完全兼容。
-----BEGIN RSA PRIVATE KEY-----
您可以使用-----BEGIN PRIVATE KEY-----
函数的serialization.TraditionalOpenSSL
参数来创建相同的旧版PEM格式。