Hi,

I'm afraid Erwann is right: you are mistaken in your understanding of RSA and DER encoding rules. RSA specifies the size of the modulus and its two primes (in order to be immune against some factoring attacks) but it says nothing about the size of the exponents. Erwann's explanation of DER encoding is very clear. Even Microsoft implementation of Crypto API and CNG adheres to this. So, as he pointed it out, there must be another explanation for the .NET error you are encountering.

Cheers,
--
Mounir IDRASSI
IDRIX
http://www.idrix.fr


On 4/2/2012 3:28 PM, Tamir Khason via RT wrote:
Hello, Erwann
This is not related to .NET. Integer is not only value, but also size.
Both exponents and its coefficients should be the same length
(according RSA definition, both integers) so those numbers should be
serialized into ASN1_INTEGER. In for some reason, you want to have
integer with different size (for me it's wrong, but it might be your
decision because of size optimization), you should use variouse size
serialization.

This is what is this bug about.


On Mon, Apr 2, 2012 at 3:52 PM, Erwann Abalea via RT<r...@openssl.org>  wrote:
Bonjour,

Le 02/04/2012 13:21, Tamir Khason via RT a écrit :
There is a bug in ASN.1 DER serializer used to generate RSA private
keys. It trims trailing zeros despite the DER specification. Please
see the full info and reproduction steps in my blog
http://khason.net/dev/openssl-bug-or-why-some-private-keys-cannot-be-used-for-net/#comments

You're wrong. You're mixing things, length encoding and value encoding
(as in TLV).

In DER, there's no "indefinite length" objects, because the purpose of
DER is to have the only one non ambiguous representation of an object.
Since an "indefinite length" (i.e. not known in advance) object can also
be represented by its "definite length" counterpart by rewriting it once
the object length is known, then an "indefinite length" can't be the
only one representation of this object.

Next, when writing a DER object, its serialization needs to be unique. A
set of rules are applied to enforce this. For integers, these rules tell
us that the lowest number of bytes need to be used, also ensuring that
negative numbers are expressed in 2s complement form (highest bit set to
1). Therefore, while you can express the number 0x32 as the following
serialization forms all representing the same number:
   32
   0032
   000032
only the first representation is a DER one. The others encode the same
value, but with useless leading bytes.

Negative numbers cannot have a heading 00 octet, because the highest
order bit would then be equal to 0, and the number considered positive.

Therefore, the number 0x92 can be serialized as:
   92
   0092
   000092
only the second form is a DER one. The first has its highest order bit
set to 1, the number considered negative, its value is then -0x6E. The
third form has an unnecessary leading 00 octet.

Of course, adding trailing 00 octets are forbidden, this would
completely change the encoded number. Like writing "70" is not the same
as writing "7".

In your "bad" example key, exponent2's length is smaller than
exponent1's and coefficient's ones. They're not guaranteed to be of the
same length. Exponent{1,2} and coefficient are results of calculations
("d mod (p-1)", "d mod (q-1)", "q^-1 mod p" respectively), and their
magnitude can vary.
Any "a mod b" number cannot be the same size of "b" (consider for
example "2^32+1 mod 2^32", it's not a 32 bits integer).

If your "bad" key cannot be used in .NET, there's another reason.

--
Erwann ABALEA
-----
podoclaste: casse-pieds





______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
Development Mailing List                       openssl-dev@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to