是否可以在 perl 中使用 SSH 私钥对我的数据进行签名? [英] Is it possible to sign my data using SSH private key in perl?
问题描述
我是 perl 新手,所以这可能是非常基本的,但我找不到解决这个问题的方法.我正在尝试使用我的 ssh 私钥(id_rsa)
对必须通过 https 连接发送的数据进行签名.我无法使用 perl 做到这一点,而且我已经使用了好几天了.请有人告诉我一种可能的方法.如果需要更多信息,请询问我.提前致谢
I am new to perl so this might be very basic, but i am finding no way around this problem. I am trying to sign my data which has to be send over https connection using my ssh private key(id_rsa)
. I am not able to do so using perl and i am at it for days. Please someone show me a possible way to do so. If any more info is needed please ask me. Thanks in advance
我问的代码是
#!/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.
The error coming on running it is RSA.xs:178: OpenSSL error: unsupported encryption at test.pl line 7.
注意:正如评论中所讨论的,我使用的是受密码保护的 id_rsa
.
NOTE: As discussed in the comments, I am using a passphrase protected id_rsa
.
推荐答案
所以,省略了 perl,直接用 openssl 来做这个
So, leaving out the perl, and just doing this by hand with openssl
ssh-keygen -t rsa -f test_id
openssl rsa -in test_id -check
RSA key ok
所以我们确实在那里有一个有效"的 RSA 私钥,我们应该能够将其用于加密.
So we do have a 'valid' RSA private key there, which we should be able to use for encrpyting.
但是如果您使用 openssl 生成密钥对
However if you use openssl to generate a key pair
openssl genrsa -out openssl_gen_rsa
openssl rsa -in openssl_gen_rsa -pubout -out openssl_gen_rsa.out
看起来你需要的命令是:
Looks like the command you need is:
openssl rsautl -inkey test_id -in test_file.txt -encrypt -out test_file.enc
(使用私钥加密,因此您可以使用公钥解密 - 这实际上与签名非常相似 - 通常您不会这样做).
(That encrypts with the private key, so you'd decrypt with the public key - that's actually pretty similar to signing - normally you wouldn't do this).
问题是 - 如果您比较生成的 -public- 密钥,它们不匹配.test_id.pub
看起来像(是的,这是真的,不,我只是将它用于测试!)
The problem is - if you compare your generated -public- keys they don't match. test_id.pub
looks like (Yes, this is the real one, and no, I did only use it for testing!)
<代码> SSH-RSA AAAAB3NzaC1yc2EAAAADAQABAAABAQDKfjRD + Gb5EE + SgOy7eoT0siQaAqfSY7KI2wkdrdygnJ + CCW/uMCtCVPhpz00u3EW2Gz1WI DteLKppjvUem1lKb8Tt2EWBQGyFOYKp44r3AJZgTcxLeDdqSUoiPsjWf1aUqy2Z1fBgtG + QOa7bpA8km6CbsORYX/TVg4B6vvdkkH K8WcmzBBF3rGsTCM3VXPp56bPoMCbwCsXvIjejmq + JdGHyxUmCxe1PrPyvmoYX3OUqpFBYIjeLWGDI9EXS6jA/r7viIAxdllvulPg IJ + 4mdYzKN + T1ME0X0c + ZdFTMdeUnB9/TZmJr1j8Q/4SQm + 3J9CiwtVXKxdkDsDObkcDp根@树莓派
我生成的密钥文件如下所示:
Where my generated key file looks like:
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDG8i33AuEp1wqbJgkEsnOmQim3
QT76B/oxsVGfJEDX3h4A6CD+ypBbfhhIn0GlfHanYvcGlpOJIlk3fzspbZNeoPJS
T4a0zQ0z8uJkugl8utyl9WR4tpgBRmzXZ42T/f4QSNqjDxUidRp5zPnXs9aRDtWb
XptswiGL3eVHMpbSnwIDAQAB
-----END PUBLIC KEY-----
我可以使用我生成的对(使用公钥加密,使用私钥解密):
I can use my generated pair (encrypting using public key, decrypting using private):
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
这有效.
因此,如果我们通过 openssl 运行您的 ssh 私钥:
So if we run your ssh private key through openssl:
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 文件远程相似的编码 - 因此我想为什么你会遇到这个问题.
Which isn't even a remotely similar encoding to the id_rsa.pub file - and I think therefore why you have this problem.
openssl rsautl -inkey test_id.openssl.pub -pubin -in test_file.txt -encrypt -out test_file.openssl.pub.enc
现在可以使用了,您可以使用您的 test_id
私钥对其进行解密:
Now works, and you can decrypt it using your test_id
private key:
openssl rsautl -inkey test_id -in test_file.openssl.pub.enc -decrypt
所以是的 - 由于某种原因,ssh-keygen 生成的公钥与 openssl 期望的格式不同,所以它不会工作.
So yes - for some reason the public key generated by ssh-keygen isn't the same format as openssl is expecting, so it's not going to work.
无论如何,回到你最初的例子——使用私钥生成签名:
Anyway, back to your original example - using the private key to generate a signature:
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 密钥工作.
But the verify step won't work using the generated ssh key.
那么这是否回答了您关于它是否可能
的问题?恐怕我不知道 ssh 公钥与普通" rsa 公钥有何不同.
So does this answer your question as to whether it's possible
? I'm afraid I don't know how the ssh public key differs from a 'normal' rsa public key.
我怀疑您的代码因此甚至不需要那么复杂 - 我认为您不需要 pkcs 填充您的密钥文件.
I suspect your code therefore doesn't even need to be as complicated as it - I don't think you need to pkcs pad your key file.
例如
#!/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 填充线).
This seems to work. (note lack of pkcs padding line).
来自评论:
如果您的 id_rsa
设置了密码,您将获得如下信息:
If your id_rsa
has a passphrase set you'll have something like this:
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,B44716076DD8B7D2B5E909BB8F70B48B
您可以再次使用 openssl 手动解密:
You can decrypt this by hand using openssl again:
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
执行此操作 - 似乎没有任何选项可以为私钥指定密码.
I'm less sure how you do this using Crypt::OpenSSL::RSA
- there doesn't seem to be any option to specify a passphrase to a private key.
我认为您因此需要先使用 Crypt::CBC
来解密私钥.我无法对此进行测试,因为我要安装大量依赖项.
I think you therefore need to use Crypt::CBC
to decrypt the private key first. I can't test this, because I've got a load of dependencies to install.
一些谷歌搜索表明您可以使用 Crypt::PK::RSA
代替.
A bit of googling suggests that you might be able to use Crypt::PK::RSA
instead.
作为替代方案 - 使用 IPC::Open2
并启动一个 openssl
进程来完成这些事情,而根本不使用库.
And as an alernative - use IPC::Open2
and start an openssl
process to do the things without using libraries at all.
例如
my $keystring = `openssl rsa -passin pass:testpass -in test_id.enc`;
不是很好,但它会起作用.(并测试它确实有效)
Not very nice, but it'll work. (and test it does actually work)
这篇关于是否可以在 perl 中使用 SSH 私钥对我的数据进行签名?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!