4

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

osgx
  • 90,338
  • 53
  • 357
  • 513
DBA
  • 653
  • 1
  • 5
  • 14
  • 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 Dec 17 '10 at 22:53
  • 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 Dec 17 '10 at 22:56
  • 1
    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 Dec 17 '10 at 22:58
  • 1
    The source file is available at: https://gist.github.com/745868 – DBA Dec 17 '10 at 23:03
  • 1
    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 Dec 18 '10 at 00:18
  • I know Greg. Thanks for the heads up, though. – DBA Dec 18 '10 at 01:24

2 Answers2

2

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

Basic
  • 26,321
  • 24
  • 115
  • 201
1

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)

osgx
  • 90,338
  • 53
  • 357
  • 513
  • Do you see any way for me to get around this issue? A fixed padding would allow me to get around this issue, though I fail to see how can I do that using the Ruby OpenSSL lib. – DBA Dec 17 '10 at 23:23
  • Sorry for long editing and digging code, it is my first look inside `rsa.c`. Read the last line. – osgx Dec 17 '10 at 23:24
  • AHHH of course. Now I feel stupid!.. Thanks for the enlightenment =) – DBA Dec 17 '10 at 23:35
  • 1
    Thanks you for wonderful tour into the world of RSA C sources and digging in it ;) – osgx Dec 17 '10 at 23:39