Is it possible to sign my data using SSH private key in perl? [closed]

被刻印的时光 ゝ 提交于 2019-12-24 05:12:18

问题


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

My code as asked is

#!/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"; 

The error coming on running it is RSA.xs:178: OpenSSL error: unsupported encryption at test.pl line 7.

NOTE: As discussed in the comments, I am using a passphrase protected id_rsa.


回答1:


So, leaving out the perl, and just doing this by hand with openssl

Checking the key:

ssh-keygen -t rsa -f test_id

openssl rsa -in test_id -check
  RSA key ok

So we do have a 'valid' RSA private key there, which we should be able to use for encrpyting.

Generating a comparison key

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).

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 root@raspberrypi

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

This works.

Turning your OpenSSH private key into an RSA public key

So if we run your ssh private key through openssl:

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

We get:

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

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

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

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.

using an openssh key to verify

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

But the verify step won't work using the generated ssh key.

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.

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.

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)));

This seems to work. (note lack of pkcs padding line).

Encrypted private key (passphrase)

Following from comments:

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

You can decrypt this by hand using openssl again:

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

Or:

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

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.

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.

A bit of googling suggests that you might be able to use Crypt::PK::RSA instead.

And as an alernative - use IPC::Open2 and start an openssl process to do the things without using libraries at all.

e.g.

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

Not very nice, but it'll work. (and test it does actually work)



来源:https://stackoverflow.com/questions/27342257/is-it-possible-to-sign-my-data-using-ssh-private-key-in-perl

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!