4
votes

I was wondering if anyone knows of a way to deterministically encrypt a value in Ruby using an asymmetric encryption algorithm.

For most use-cases one only cares that when you encrypt 'A' you get 'A' back when you decrypt it, that is you do not care about the encrypted value itself. You only care about the full roundtrip.

However, for an application that I'm developing I really need the output to be deterministic. That is, I need to encrypt something with RSA without a variable padding.

When I attempt to encrypt a value with OpenSSL::PKey::RSA::NO_PADDING an error is returned:

OpenSSL::PKey::RSAError Exception: data too small for key size

Anyone has an idea on how I can get a deterministic encrypted value using RSA?

Best regards,

DBA

2
Hi. What exaclty do you mean with "output to be deterministic" ? Do you want to have constant length of encrypted data? What are inputs?osgx
When encrypting a value (e.g. 'xpto') you get back a different value every time due to the Padding. For example: crypt 'xpto' #=> 'aaa'. I need that when I run crypt 'xpto' again it also returns 'aaa' and not 'abc'DBA
Got it. RSA tends to extend your message with random padding before the encryption. Does your code works, if you will disable "OpenSSL::PKey::RSA::NO_PADDING" ? Can you post the code?osgx
The source file is available at: gist.github.com/745868DBA
That padding is there for a security reason. You really should understand that before taking it out. The original data can be deterministically recovered even with random padding.President James K. Polk

2 Answers

2
votes

You could perform the padding to the appropriate key length yourself with non-random data

1
votes

This error comes from crypto/rsa/rsa_none.c

int RSA_padding_add_none(unsigned char *to, int tlen,
    const unsigned char *from, int flen)
    {
    if (flen > tlen)
            {
            RSAerr(RSA_F_RSA_PADDING_ADD_NONE,RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
            return(0);
            }

    if (flen < tlen)
            {
            RSAerr(RSA_F_RSA_PADDING_ADD_NONE,RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE);
            return(0);
            }

    memcpy(to,from,(unsigned int)flen);
    return(1);
    }

Called from rypto/rsa/rsa_eay.c

static int RSA_eay_public_encrypt(int flen, const unsigned char *from,
         unsigned char *to, RSA *rsa, int padding)
...
               i=RSA_padding_add_none(buf,num,from,flen);

The flen is a message len; and the tlen is from: num=BN_num_bytes(rsa->n);

So, You need your data have the same byte length as your N parameter of RSA key

Also, as I know, your data must be smaller than N (if considered as single long-long-long binary number)