是否可以使用perl中的SSH私钥签署我的数据?

时间:2014-12-07 11:41:39

标签: perl ssh sign

我是perl的新手所以这可能是非常基本的,但我找不到解决这个问题的方法。我正在尝试使用我的ssh private key(id_rsa)签署我的数据,该数据必须通过https连接发送。我无法使用perl这样做,而且我已经使用了好几天。请有人告诉我一个可行的方法。如果需要更多信息,请问我。提前致谢

我的代码是

#!/usr/bin/perl
use File::Slurp   qw(read_file);
use Crypt::OpenSSL::RSA;
use MIME::Base64 qw( decode_base64 encode_base64 );

my $keystring = read_file( 'id_rsa' );
my $privatekey = Crypt::OpenSSL::RSA->new_private_key($keystring);
$privatekey->use_pkcs1_padding();
my $datatosign = "hello";
my $signature = $privatekey->sign($datatosign);
my $base64 = encode_base64($signature);
print "$base64"; 

运行它时出错RSA.xs:178: OpenSSL error: unsupported encryption at test.pl line 7.

注意:正如评论中所讨论的,我使用的是密码保护id_rsa

1 个答案:

答案 0 :(得分:3)

所以,省略perl,并用openssl手动执行此操作

检查密钥:

ssh-keygen -t rsa -f test_id

openssl rsa -in test_id -check
  RSA key ok

所以我们确实有一个'有效'的RSA私钥,我们应该可以用它来加密。

生成比较密钥

但是,如果您使用openssl生成密钥对

openssl genrsa -out openssl_gen_rsa
openssl rsa -in openssl_gen_rsa -pubout -out openssl_gen_rsa.out 

看起来你需要的命令是:

openssl rsautl -inkey test_id  -in test_file.txt -encrypt -out test_file.enc

(用私钥加密,所以你用公钥解密 - 实际上与签名非常相似 - 通常你不会这样做。)

问题是 - 如果你比较你生成的 - 公钥 - 它们是不匹配的。 test_id.pub看起来像(是的,这是真实的,不,我只是用它进行测试!)

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKfjRD+Gb5EE+SgOy7eoT0siQaAqfSY7KI2wkdrdygnJ+ccW/uMCtCVPhpz00u3EW2Gz1WI    DteLKppjvUem1lKb8Tt2EWBQGyFOYKp44r3AJZgTcxLeDdqSUoiPsjWf1aUqy2Z1fBgtG+QOa7bpA8km6CbsORYX/TVg4B6vvdkkH    K8WcmzBBF3rGsTCM3VXPp56bPoMCbwCsXvIjejmq+JdGHyxUmCxe1PrPyvmoYX3OUqpFBYIjeLWGDI9EXS6jA/r7viIAxdllvulPg    IJ+4mdYzKN+T1ME0X0c+ZdFTMdeUnB9/TZmJr1j8Q/4SQm+3J9CiwtVXKxdkDsDObkcDp root@raspberrypi

我生成的密钥文件的位置如下:

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDG8i33AuEp1wqbJgkEsnOmQim3
QT76B/oxsVGfJEDX3h4A6CD+ypBbfhhIn0GlfHanYvcGlpOJIlk3fzspbZNeoPJS
T4a0zQ0z8uJkugl8utyl9WR4tpgBRmzXZ42T/f4QSNqjDxUidRp5zPnXs9aRDtWb
XptswiGL3eVHMpbSnwIDAQAB
-----END PUBLIC KEY-----

我可以使用我生成的对(使用公钥加密,使用私钥解密):

openssl rsautl -inkey openssl_gen_rsa.out -pubin  -in test_file.txt -encrypt -out test_file.enc2
openssl rsautl -inkey openssl_gen_rsa -in test_file.enc2 -decrypt

这很有效。

将您的OpenSSH私钥转换为RSA公钥

因此,如果我们通过openssl运行您的ssh私钥:

openssl rsa -in test_id -pubout -out test_id.openssl.pub

我们得到:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyn40Q/hm+RBPkoDsu3qE
9LIkGgKn0mOyiNsJHa3coJyfnHFv7jArQlT4ac9NLtxFths9ViA7XiyqaY71HptZ
Sm/E7dhFgUBshTmCqeOK9wCWYE3MS3g3aklKIj7I1n9WlKstmdXwYLRvkDmu26QP
JJugm7DkWF/01YOAer73ZJByvFnJswQRd6xrEwjN1Vz6eemz6DAm8ArF7yI3o5qv
iXRh8sVJgsXtT6z8r5qGF9zlKqRQWCI3i1hgyPRF0uowP6+74iAMXZZb7pT4CCfu
JnWMyjfk9TBNF9HPmXRUzHXlJwff02Zia9Y/EP+EkJvtyfQosLVVysXZA7Azm5HA
6QIDAQAB
-----END PUBLIC KEY-----

这甚至不是id_rsa.pub文件的远程类似编码 - 我认为为什么你有这个问题。

 openssl rsautl -inkey test_id.openssl.pub -pubin  -in test_file.txt -encrypt -out test_file.openssl.pub.enc

现在有效,您可以使用test_id私钥对其进行解密:

openssl rsautl -inkey test_id -in test_file.openssl.pub.enc -decrypt

所以是的 - 由于某种原因,ssh-keygen生成的公钥与openssl期望的格式不同,所以它不会起作用。

使用openssh密钥验证

无论如何,回到原来的例子 - 使用私钥生成签名:

openssl rsautl -sign -inkey test_id -in test_file.txt -out test_file.sig
openssl rsautl -verify -in test_file.sig -inkey test_id.openssl.pub -pubin

但验证步骤将不会使用生成的ssh密钥。

这是否回答了你的问题是possible?我担心我不知道ssh公钥与“普通”rsa公钥的区别。

我怀疑你的代码甚至不需要像它那样复杂 - 我认为你不需要pkcs填充你的密钥文件。

E.g。

#!/usr/bin/perl
use strict;
use warnings;
use File::Slurp   qw(read_file);
use Crypt::OpenSSL::RSA;
use MIME::Base64 qw( decode_base64 encode_base64 );

my $keystring = read_file ('test_id');
my $privatekey = Crypt::OpenSSL::RSA->new_private_key($keystring);
my $datatosign = "hello";
my $signature = $privatekey->sign($datatosign);
my $base64 = encode_base64($signature);
print "Signature:\n";
print "$base64";

my $public_key_text = $privatekey-> get_public_key_string();
print "Public Key:\n";
print $public_key_text;

my $rsa_pub = Crypt::OpenSSL::RSA->new_public_key ( $public_key_text );
print "Signed correctly\n" if ($rsa_pub->verify($datatosign, decode_base64($base64)));

这似乎有效。 (注意缺少pkcs填充线)。

加密私钥(密码)

以下评论:

如果您的id_rsa设置了密码短语,那么您将拥有以下内容:

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,B44716076DD8B7D2B5E909BB8F70B48B

您可以再次使用openssl手动解密:

openssl rsa -in test_id.enc
Enter pass phrase for test_id.enc:

或者:

openssl rsa -in test_id.enc -passin pass:testpass

我不太确定如何使用Crypt::OpenSSL::RSA执行此操作 - 似乎没有任何选项可以为私钥指定密码。

我认为您需要先使用Crypt::CBC来解密私钥。我无法测试这个,因为我有很多依赖项需要安装。

一些谷歌搜索表明您可以使用Crypt::PK::RSA代替。

作为alernative - 使用IPC::Open2并启动openssl进程来完成这些操作而不使用库。

e.g。

my $keystring = `openssl rsa -passin pass:testpass -in test_id.enc`;

不是很好,但它会起作用。 (并测试它确实有效)

相关问题