Ruby/Rails OpenSSL::PKey::RSAError: data greater than mod len - ruby

I think I started getting this error when I switched from MySQL to PostgreSQL.
I had written code to encrypt decrypt model attributes containing sensitive data and I had it working until the db switch.
I have the following code:
#pbk = OpenSSL::PKey::RSA.new File.read("#{RAILS_ROOT}/cert/pb_sandwich.pem")
#pvk = OpenSSL::PKey::RSA.new File.read("#{RAILS_ROOT}/cert/tuna_salad.pem"), 'pass45*'
model.sendata = Base64.encode64 #pbk.public_encrypt(model.sendata)
I run that code on save. I've also tried with and with out first using Base64.
Then when I try to read:
#pvk.private_decrypt Base64.decode64(model.sendata)
I get this error:
OpenSSL::PKey::RSAError: data greater than mod len
I never got that before when I used MySQL. I can't really remember what datatype the sendata column was in MySQL but in my current PostgreSQL setup that column is datatype bytea
I'm assuming that is the problem since it used to work fine with MySQL. What datatype should the column be if I wanted to skip having to do that extra step to Base64 encode/decode? If that is the problem that is.
Another thing of note is that I've tried generating the private key with mod lengths: 2048, 4096, and 5120 and I always get the same error. Also, the sendata field isn't very long before encoding, it's under 40 chars.
I'm stumped right now, any ideas?

You are probably not storing the keys properly in the Database. There's probably some field that is being truncated.
The message you are getting probably means that the data is too long to be encrypted with such a small key. If this is the case, you should encrypt the data with AES and encrypt the AES key with RSA. Then send both the encryted data and the encrypted key.

Related

Generating Google2fa secrets based on a fixed string

We're building a system to validate mobile phone numbers.
To achieve this, when a user adds his number, we are sending him a text message with a 6 digit code.
We don't want this code to go in our database as we don't like to clutter our database with fields that have no business meaning.
So we came up with the idea to reuse pragmarx/google2falibrary, have it generate an OTP code, dispatch it to the user by a text message, and then the circle would be round.
So basically we wanted to use the phone number, prefixed by somehting secret as the "secret" for the pragmarx/google2fa library:
$secret = '1263' . $mobile->country_code . $mobile->subscriber;
$google2fa = new Google2FA();
$google2fa->setEnforceGoogleAuthenticatorCompatibility(false);
$google2fa->getCurrentOtp($secret);
The above results in a secretsimilar to 12633232970987. However, the call to getCurrentOtp throws an exception Invalid characters in the base32 string. which is obviously not what I was hoping for.
So, I tried adding
$secret = base_convert($secret, 10, 32)
and pass that to the getCurrentOtpmethod, but that returned the same error. Checking into the library code, I see the following constant:
const VALID_FOR_B32 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
My base_convert returns a string that has other characters in there though. Are these really the only valid characters?
My alternative would be to just have the library generate a random secret, but we don't really want to do that, as that would require us to keep that secret somewhere in the database (or at least in cache), which we would like to avoid. The idea is that we could generate the code for a mobile number using the number as the secret, and let the OTP mechanism deal with expiring codes.
Anyone has any suggestion how I can resolve this?

Ruby RSA public key encryption to Golang

I'm currently working on a project where I have to "convert" some code from Ruby(version 1.9.3p194) to Golang(version 1.7). There is this part where Ruby uses RSA public key encryption and I always get a consistent result every time it gets executed. This is the function used:
Edit: I overlooked that after the public key encryption, there is a base 64 encoding as well
public_key = OpenSSL::PKey::RSA.new(public_encryption_key)
public_encrypted_text = public_key.public_encrypt(text, OpenSSL::PKey::RSA::NO_PADDING)
base64_encrypted_text = Base64.encode64(public_encrypted_text).gsub("\n", "")
escaped_encrypted_text = URI.escape(encrypted_key, "/+=")
However in Golang, due to the rsa library I can't get a consistent result since the function to encrypt takes a random parameter to generate different result each time. I understand why it needs to be different every time, but i can't get anything remotely similar to what ruby generates. These are the functions used in Golang:
//keyBytes is the public key as []byte
block, _ := pem.Decode(keyBytes)
key, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, err
}
pubKey, ok := key.(*rsa.PublicKey)
if !ok {
return nil, errors.New("Cannot convert to rsa.PublicKey")
}
result, err := rsa.EncryptPKCS1v15(cryptorand.Reader, pubKey, text)
encryptedText := base64.URLEncoding.EncodeToString(result)
encryptedText = strings.TrimRight(encryptedText, "=")
One of the problems is that ruby can encrypt the text with no problem, and in golang I'm getting an error that the key is too short to encrypt everything.
If I encrypt something else, like "Hello". When decrypting I get from ruby the error "padding check failed". The decryption is being handle like follows:
private_key.private_decrypt(Base64.decode64(text))
EDIT: Thanks to the answer of gusto2 I now know better what is going on since I didn't have much understanding of RSA.
Now in Golang I was able to encrypt the text using PKCS1 v1.5, and just to be sure I tried to decrypt that as well, also in Golang, with no problem.
However in Ruby I still wasn't able to decrypt using the private key. So I figured that the base64 encoding used in Golang was the issue. So I changed that part to this:
encryptedText := base64.StdEncoding.EncodeToString(result)
And also I removed the last line were the equal sign was being trimmed.
With that done it worked like a charm.
I am no knowledgeable about golang, however I may know something about RSA.
The difference seems to be in the padding.
For ruby - no padding is used
For golang - PKCS1v15 padding is used
In the rubyexample you use OpenSSL::PKey::RSA::NO_PADDING is used which is VERY VERY unsafe. It is called textbook RSA and is not inteded in real-life use as it has many weaknesses and dangerous traps. So the ruby example is very dangerously unsafe because of using the textbook RSA. As well it is limited to encrypting small messages (much smaller than the keyspace).
There are two padding types used with RSA:
PKCS1 v1 (commonly referred as PKCS1) - this is a deterministic padding (the output is always the same), many cryptographers consider this option obsolete as some weaknesses has been found when not used properly, but it is still in use and not considered broken.
PKCS1 v2 (commonly refered as OAEP or PSS) which is stochastic (randomized) padding. You can distinguish the last two as the output of OAEP is always different.
One of the problems is that ruby can encrypt the text with no problem, and in golang I'm getting an error that the key is too short to encrypt everything
You've provided only a small part of the golang example, so here I may only assume many things.
As you claim the golang example outputs randomized output and according to the parameters PKCS1 v1.5 is used, I'd assume the implementation is doing hybrid encryption which is good and much safer way to encrypt data with RSA (using symmetric encryption with random key and wrap/encrypt the key with RSA).

Laravel Password Hashing

I have a external service which wishes to create user via a bespoke API that I have created in my Laravel application.
Rather than the remote end sending me the password in plain text I would like the remote end to hash the password first however I am unsure on how of the hashing using.
The remote end is using ASP.NET to make things slightly more complicated.
I am guessing Laravel is using CRYPT_BLOWFISH as that is the strongest available on the server but unsure how the salt works. Could anyone advise?
http://php.net/manual/en/function.crypt.php
CRYPT_BLOWFISH - Blowfish hashing with a salt as follows: "$2a$", "$2x$" or "$2y$", a two digit cost parameter, "$", and 22 characters from the alphabet "./0-9A-Za-z". Using characters outside of this range in the salt will cause crypt() to return a zero-length string. The two digit cost parameter is the base-2 logarithm of the iteration count for the underlying Blowfish-based hashing algorithmeter and must be in range 04-31, values outside this range will cause crypt() to fail. Versions of PHP before 5.3.7 only support "$2a$" as the salt prefix: PHP 5.3.7 introduced the new prefixes to fix a security weakness in the Blowfish implementation. Please refer to » this document for full details of the security fix, but to summarise, developers targeting only PHP 5.3.7 and later should use "$2y$" in preference to "$2a$".
Example hash from Laravel:
$2y$10$RXyfF5/5qdBeGbwKgU5NR.p1OcgT5t3N.M5ql5PHm.UoxYGOogDWi
2y = blowfish prefix
10 = cost parameter
RXyfF5/5qdBeGbwKgU5NR. = 22 char salt
p1OcgT5t3N.M5ql5PHm.UoxYGOogDWi = bcrypt hash

SAS session encoding LATIN1 failing for unicode characters

My SAS session details are:-
ENCODING=LATIN1
LOCALE=EN_US
I am reading encrypted customer names, decrypting them using a java code that has
been implemented in the sas code using javaobj.
data outlib.X1 ( ENCODING = 'asciiany' );
set inlib.INP1 (ENCODING = 'asciiany' ) end=eof;
length decryptedvalue $100;
declare javaobj jObj("<jarname>");
jObj.callstringmethod("<method>", FIRST_NAME , decryptedvalue);
run;
The jObj.callstringmethod returns the decrypted first_name value in the string decryptedvalue. I do a proc export at the end of my SAS code and store all the decrypted names as csv files.
In the last run some of the names have special characters e.g. RÉAL.
This is causing SAS execution to fail with following error :-
ERROR: Transcoding failure at line 30 column 2.
ERROR: DATA STEP Component Object failure. Aborted during the EXECUTION phase.
Is there some way to make SAS session (LATIN1) accept these unicode characters? Can i set
the encoding of the decryptedvalue variable? I dont want to run my entire SAS session in unicode using sas_u8. I only want to accept these characters
Even reading these problematic values as blank is ok.
I have already tried following things :-
Set inencoding= utf8 for the libname
Make ENCODING = 'asciiany' for the input dataset.
Any inputs would be useful.
Thanks in advance!
SAS Tech support suggested this :-
Adding export EASYSOFT_UNICODE=YES in the sasenv_local file .
We are now able to run the entire SAS code (including SQL queries) in the sas u8 session.
Thanks to all for your support.

How to decrypt a string with known key and a IV in java?

I have a string that is encrypted in c#.net which I have to decrypt in java using a key and a IV provided by the client. Used algorithm is AES.
I have tried few things. The key looks something like
key = "QWEEqweASDreefERTfdf45fefdWERfsdf34fedfdwn5=" //length 44 bytes
iv = "nkfghER24dfdfdf56YUIgH==" // lenght=24 bytes
When I use this with Cipher class with algorith AES/CBC/PKCS5Padding
passing the above key to Secretkeyspec class it says invalid key lenth 44 bytes
I am not able makeout whats wrong with the key. Tried all suggested solutions for few days nothing works. Can some one help please? Thank you.
Use java native for C# code.
First write C# code for decrypt the key.
and calling the code in java using native.
for reference
http://www.codeproject.com/Articles/378826/How-to-wrap-a-Csharp-library-for-use-in-Java

Resources