On March 23, 2004 01:22 pm, Rich Salz wrote:
> >>>The bug is: when flen is not the RSA key size (e.g., 32 bytes), the
> >>>function returns -1 and no encryption is done.
> >
> >     What is the principle behind this design?
>
> RSA works on input that has the same number of bits as the RSA key
> size. (An earlier message from you disagreed with this; you're wrong.)
>
> In other words, a 1024-bit RSA key works on 1024 bits of input and
> returns 1024 bits of output.  If your input is not the same size as the
> key, you must use padding to make it so.  If you do not use padding,
> than the RSA algorithm cannot be executed.

Are we perhaps talking at cross-purposes? The RSA algorithm can indeed be 
executed against any numeric input smaller than the modulus.

The difference here is that the RSA API in openssl operates on an 
endian-agnostic strings of bytes, whereas the RSA algorithm itself 
operates on multi-precision numbers smaller than the modulus. The 
mathematical requirements of RSA are a subset of the representation 
requirements of the API, which includes pre-processing and 
post-processing steps for numeric conversions and padding implementations 
(and checks).

Like the other padding modes, RSA_NO_PADDING is handled by a 
pre-processor, RSA_padding_add_none(), which insists that input and 
output byte buffers have the same length, and the way this is invoked 
from the RSA implementation in rsa_eay.c equates the output buffer length 
(which is not supplied as a parameter in the API) with the number of 
bytes of the RSA modulus. This is the real problem.

The limitation, in other words, is the API :-) I would actually agree that 
RSA_NO_PADDING is counter-intuitive, it really means RSA_ALREADY_PADDED. 
The problem is that RSA_[public|private]_[encrypt|decrypt], as well as 
RSA_sign and RSA_verify, only take a single length parameter. The 
function can not therefore know what length the output buffer is if it 
can't assume this to match the length of the input, and so it enforces 
the (draconian) rule that this input must be at least as large as the 
modulus. The reason? The output is always less than the modulus and so 
this is always "big enough". There is no compelling reason though that 
the input needs to be this big though. On the other side, the reason the 
input can not be larger than the modulus length is that if the numeric 
representation is larger than the modulus, the inverse operation won't 
match (though will be congruent). Of course "same length" can still mean 
"greater value" ... So putting the two together we force the lengths to 
match, which is purely a byte-representation and API problem. The real 
algorithmic check is buried further in the code, which requires that the 
numeric input (once converted from the byte string input) is smaller than 
'n'.

Sorry Rich, didn't mean to stir pointlessly. Your solution is right (from 
outside the API), zero-pad the input to be the same number of bytes as 
the RSA modulus. However, the explanation seemed wrong or at least 
misleading - the conceptual problem is not the algorithm, it's the API.

Cheers,
Geoff

-- 
Geoff Thorpe
[EMAIL PROTECTED]
http://www.geoffthorpe.net/

______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
Development Mailing List                       [EMAIL PROTECTED]
Automated List Manager                           [EMAIL PROTECTED]

Reply via email to