Question

Currently in my project DSA signature is being generated via perl and verified via perl on other server. It works fine.

Some days ago i've tried to migrate one service from perl to php, and found that php generates signs, that perl is not able to verify. More over, if i generate sign in console (with openssl command) - perl also says that signature is not valid. So, it looks like that:

PHP Signature <= ok => console signature <= not ok! => perl signature

Why this is happening?

Private key, that is being used for signing is the same.

Perl code:

my $pk = Crypt::OpenSSL::DSA->read_priv_key('private.key');
print encode_base64( $pk->sign( md5($data) ) );

PHP code:

$pk = openssl_get_privatekey('private key string');
openssl_sign(md5($data, true), $signature, $pk, OPENSSL_ALGO_DSS1));
echo base64_encode($signature);

Console code (verification):

openssl dsa -in private_key.pem -pubout -out dsa_public_key.pem
openssl dgst -dss1 -verify dsa_public_key.pem -signature sign.bin data.md5

Totally lost.. 2nd day i am not able to find any answer :( Could you please advise a way to dig?

Was it helpful?

Solution

Please note that in your example you are doing double digest as you are signing: dss1(md5(message)) - where dss1 in fact means sha1

So, you create signature like this:

echo -n 'data you want to sign' | openssl dgst -md5 -binary | openssl dgst -dss1 -sign openssl_dsa1_pri.pem > signature.bin

You can verify it by openssl comman like this:

echo -n 'data you want to sign' | openssl dgst -md5 -binary | openssl dgst -dss1 -verify openssl_dsa1_pub.pem -signature signature.bin

Using Crypt::OpenSSL::DSA you can verify it like this:

my $signature = read_file("signature.bin");
my $message = 'data you want to sign';
my $pub = Crypt::OpenSSL::DSA->read_pub_key('openssl_dsa1_pub.pem');
warn "Verified=", $pub->verify(sha1(md5($message)), $signature), "\n";

Of course double digest is not necessary, you can use:

echo -n 'data you want to sign' | openssl dgst -dss1 -sign openssl_dsa1_pri.pem > signature2.bin

echo -n 'data you want to sign' | openssl dgst -dss1 -verify openssl_dsa1_pub.pem -signature signature2.bin

my $signature = read_file("signature2.bin");
my $message = 'data you want to sign';
my $pub = Crypt::OpenSSL::DSA->read_pub_key('openssl_dsa1_pub.pem');
warn "Verified=", $pub->verify(sha1($message), $signature), "\n";
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top