You are correct. The public part of the key is not required for
RSA signature. I have no idea why perl code produces different
signature.

Aleksey

Antti S. Lankila wrote:
I hit this small issue while using xmlsec1 to double-check an unrelated Perl implementation of XML-DSig. The basic work of what I'm doing is performed by the Perl class, but the results are always double-checked with xmlsec1 while developing.

It should be possible to sign an XML document with SHA1-RSA knowing nothing else but the private exponent and the modulus, right? That is, you need the private key to perform signature validation, but not the public key. The only new information the RSA public key provides is the public exponent.

So I go and extract the N and D parameters from some certificate, which are large integers, and encode them into Base64 and store them into a document like this:

<?xml version="1.0" encoding="UTF-8"?>
<Keys xmlns="http://www.aleksey.com/xmlsec/2002";>

<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#";>
   <KeyValue>
       <RSAKeyValue>
           <Modulus>$modulus</Modulus>
           <Exponent>AQAB</Exponent>
<PrivateExponent xmlns="http://www.aleksey.com/xmlsec/2002";>$exponent</PrivateExponent>
       </RSAKeyValue>
   </KeyValue>
</KeyInfo>

</Keys>

But here, I find I have to specify AQAB (base64 for 65537) as the Exponent, or the signature computation gets a different result from my Perl class. It appears that the differs if I substitute some other, valid Base64-encoded value here, such as 1, which is AQ==. Therefore, it seems clear that xmlsec1 makes some use of this information. The Perl code I got does not need or use the public exponent for signature computation, so what gives?

The command line I am using is:

% xmlsec1 sign --keys-file "the-above-file.xml" "file-to-be-signed.xml"

It's noteworthy that I am not necessarily operating with x509 certificates here. Sometimes yes, but often I only get the RSA parameters from some metadata files. Therefore, I need the most generic way to deal with this which is the construction of the keys file from the minimal set of data available.


For the record, the Perl code for calculating a signature is here:

       # Crypt::RSA is a stock module. It implements SHA1-RSA for us.
       my $pkcs = Crypt::RSA::SS::PKCS1v15->new();
       $signature = $pkcs->sign(
           Message => $xml_to_sign,
           Key => $self->{private_key},
       ) || die $pkcs->errstr;

$xml_to_sign is, naturally, the canonicalized version of the SignedInfo element. The instance variable $self->{private_key} is constructed from the RSA parameters as follows:

   my $key = Crypt::RSA::Key::Private->new();
   $key->n(Math::Pari::_hex_cvt($n));
   $key->d(Math::Pari::_hex_cvt($d));
   $self->{private_key} = $key;

(There is a bug in Crypt::RSA::Key::Private necessiating an explicit call to _hex_cvt(). The input $n and $d are hex strings like "0123456789abcdef". The lines simply set the n and d parameters into the key, nothing more.) The noteworthy fact here is the complete absence of the $e parameter.

_______________________________________________
xmlsec mailing list
[email protected]
http://www.aleksey.com/mailman/listinfo/xmlsec

Reply via email to