Ruby RSA public key encryption to Golang - ruby

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).

Related

Reversible Hashed to convert integer ID to alphabets/alphanumeric

I need a Delphi reversible Hashed ID function that is quick.
Short, obfuscated and efficient IDs
No collisions (at least up to 32-bit unsigned integer at least)
Reversible
Fast
preferably something that has an input Key, so it can be randomised a bit...
otherwise, a '3' will always be 23zkJ5 on all my software modules.
works cross-platform
Something like Youtube's video identifier.
Encode(3); // => "23zkJ5"
Decode('23zkJ5'); // => 3
PHP seems to have quite a few of these; I can't find one for Delphi.
I look at this but not really what I wanted, plus I need something in Delphi.
Reversible hash function?
$generator->encode(6); // => "43Vht7"
$generator->decode('43Vht7'); // => 6
I need something like what PHP offers:
https://github.com/delight-im/PHP-IDs
I can't use MD5 as it's not reversible; using Lockbox encryption/decryption seems a bit over-kill? (if really no choice, which algorithm in Lockbox would be the best choice for this?)
Use AES and convert the cypher byte array to a hex string or to Base64.
for a code example see here
AES encrypt string in Delphi (10 Seattle) with DCrypt, decrypt with PHP/OpenSSL

How do I do deterministic RSA in Go

I have two go services, let's call them A and B. B holds an RSA key pair, while A only knows the public key. I want them to know if they agree on some value V.
I want to do this by having B encrypt encrypt V using the public key and have A do a comparison, but all the crytpo/rsa functions take an RNG which adds entropy and makes each hash of V different. That means I can't compare the hashes.
Is there a function in the go standard library that will deterministicly hash V?
Note: I can achieve this by using a fresh RNG seeded with the same value everytime I hash V, but I want to be able to compute this hash from other languages and that would tie me to Go's RNG.
I want to do this by having B encrypt encrypt V using the public key and have A do a comparison…
You're using the wrong primitive.
If you want the owner of a private key to prove that they have some data, have them Sign that data. The recipient can Verify that signature using the public key.
Use the SignPSS and VerifyPSS methods to do this. The signature will not be deterministic, but it doesn't need to be -- the recipient will still be able to verify it.
Take a look at the docs for EncryptOAEP:
The random parameter is used as a source of entropy to ensure that encrypting the same message twice doesn't result in the same ciphertext.
So the random data does not affect the reader's ability to decrypt the message with only the public key. The cipher text bytes will be different each time you encrypt the same value, which is a good thing.
Take a look at the examples on Encrypt/Decrypt OAEP in those docs. It should be sufficient to get you moving the right direction.

Storing crypto/rand generated string issues

So I have the following go file(s) as part of my project to be used for hashing passwords, I also wrote some tests that to my knowledge have yet to fail.
Currently the issue is that I am trying to store the password and salt in some database as strings, and every time I retrieve them to be compared against a another string I keep getting the message in the picture from golang's bcrypt package. The tests I wrote are running fine and produce the appropriate effect. I would have supplied a go playground link but bcrypt package is part of the standard library.
I know the gibberish from crypto/rand is pretty much the same from the initial look but I am not sure if there is anything being changed on the database. I am using redis fyi.
Edit: based on the request of #3of3, I am including the DAO code from my project. Also the bcrypt only solution worked with this code but as I stated in the comments, I am aiming to stick to Mozilla's guide.
The salt does not roundtrip through the JSON encode / decode because the salt is not valid UTF8.
There are a few ways to fix the problem:
Hex or base64 encode / decode the salt in hasher.
Use the []byte type for salt throughout the code. The JSON encoder encodes []byte values using base64.
Use the gob encoder instead of the JSON encoder.
Mozilla recommends storing the extra salt separate from the bcrypted password. By storing the extra salt with the bcrypted password, the system is no more secure than using bcrypt alone.
To hex encode the salt, change
return string(p), string(salt), nil
to
return string(p), hex.EncodeToString(salt), nil
and change
s := []byte(salt)
to
s, err := hex.DecodeString(salt)
if err != nil {
return err
}
It seems you forgot that the generated hashes are hex encoded, thus when casting the []byte variable to a string you'll get something weird. Using the hex package you can create the actual string you want:
hex.EncodeToString(hash)

"Recalculate" SHA512+salt string to BLOWFISH+salt - is this possible?

Maybe this is a stupid question, but I wouldn't be shocked if some excellent brains come around with a proper solution or an idea: Is it possible to recalculate/transcode a salted sha512 string into a salted blowfish string ?
The (imo quite interesting) background is: I have a big database of SHA512+salt strings like that $6$rounds=5000$usesomesillystri$D4IrlXatmP7rx3P3InaxBeoomnAihCKREY4... (118 chars) and want to move to another hash/salt algorithm, generating strings like $2a$07$usesomesillystringfore2uDLvp1Ii2e./U9C8sBjqp8I90dH6hi (60 chars).
I'm intentionally NOT asking this on security.stackexchange.com as this is not a security question. It's about transcoding/recalculation.
Is it possible to recalculate/transcode a salted sha512 string into a salted blowfish string ?
Nope.
SHA2-512 is a cryptographic hash. Data goes in, but there's no way to get it back out. Do note that the thing you're using is a proposed but not standardized form of crypt that uses SHA2, and is not a raw SHA2 hash.
bcrypt (which is derived from, but is not Blowfish) is a key derivation function, which while a different thing than a cryptographic hash, still has the same result: data goes in, but there's no way to get it back out.
There is no way to simply convert one of these password hash types to another. This is true of almost every hash type. If you need to change the hash type, do so when the user next logs in.

Salt a key for secure encryption Cocoa?

I was reading a tutorial on how to salt a key to make your encryption secure, but couldn't make much of it. I don't know a lot about cryptography, and need some help. I am using commoncrypto to encrypt files, and am done, except for the fact that it isn't secure...
This is what I have:
- (NSData *)AES256EncryptWithKey:(NSString *)key
{
// 'key' should be 32 bytes for AES256, will be null-padded otherwise
char keyPtr[kCCKeySizeAES256 + 1]; // room for terminator (unused)
bzero( keyPtr, sizeof( keyPtr ) ); // fill with zeroes (for padding)
NSLog(#"You are encrypting something...");
// fetch key data
[key getCString:keyPtr maxLength:sizeof( keyPtr ) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
//See the doc: For block ciphers, the output size will always be less than or
//equal to the input size plus the size of one block.
//That's why we need to add the size of one block here
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc( bufferSize );
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt( kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES256,
NULL /* initialization vector (optional) */,
[self bytes], dataLength, /* input */
buffer, bufferSize, /* output */
&numBytesEncrypted );
if( cryptStatus == kCCSuccess )
{
//the returned NSData takes ownership of the buffer and will free it on deallocation
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free( buffer ); //free the buffer
return nil;
}
If someone can help me out, and show me exactly how I would implement salt, that would be great! Thanks again!
dYhG9pQ1qyJfIxfs2guVoU7jr9oniR2GF8MbC9mi
Enciphering text
AKA jumbling it around, to try and make it indecipherable. This is the game you play in cryptography. To do this, you use deterministic functions.
Encrypting involves using a function which takes two parameters: usually a short, fixed length one, and an arbitrary length one. It produces output the same size as the second parameter.
We call the first parameter the key; the second, the plaintext; and the output, the ciphertext.
This will have an inverse function (which is sometimes the same one), which has the same signature, but given instead ciphertext will return the plaintext (when using the same key).
Obviously the property of a good encryption function is that the plaintext is not easily determinable from the ciphertext, without knowing the key. An even better one will produce ciphertext that is indistinguishable from random noise.
Hashing involves a function which takes one parameter, of arbitrary size, and returns an output of fixed size. Here, the goal is that given a particular output, it should be hard to find any input that will produce it. It is a one-way function, so it has no inverse. Again, it's awesome if the output looks completely random.
The problem with determinism
The above is all very well and good, but we have a problem with our ultimate goals of indecipherability when designing implementations of these functions: they're deterministic! That's no good for producing random output.
While we can design functions that still produce very random-looking output, thanks to confusion and diffusion, they're still going to give the same output given the same input. We both need this, and don't like it. We would never be able to decipher anything with a non-deterministic crypto system, but we don't like repeatable results! Repeatable means analysable... determinable (huh.). We don't want the enemy to see the same two ciphertexts and know that they came from the same input, that would be giving them information (and useful techniques for breaking crypto-systems, like rainbow tables). How do we solve this problem?
Enter: some random stuff inserted at the start.
That's how we defeat it! We prepend (or sometimes better, append), some unique random input with our actual input, everytime we use our functions. This makes our deterministic functions give different output even when we give the same input. We send the unique random input (when hashing, called a salt; when encrypting, called an Initialisation Vector, or IV) along with the ciphertext. It's not important whether the enemy sees this random input; our real input is already protected by our key (or the one-way hash). All that we were actually worried about is that our output is different all the time, so that it's non-analysable; and we've achieved this.
How do I apply this knowledge?
OK. So everybody has their app, and within it their cryptosystem protecting parts of the app.
Now we don't want to go reinventing the wheel with cryptosystems (Worst. Idea. Ever.), so some really knowledgable people have already come up with good components that can build any system (i.e, AES, RSA, SHA2, HMAC, PBKDF2). But if everyone is using the same components, then that still introduces some repeatability! Fortunately, if everyone uses different keys, and unique initial random inputs, in their own cryptosytem, they should be fine.
Enough already! Talk about implementation!
Let's talk about your example. You're wanting to do some simple encryption. What do we want for that? Well, A) we want a good random key, and B) we want a good random IV. This will make our ciphertext as secure as it can get. I can see you haven't supplied a random IV - it's better practice to do so. Get some bytes from a [secure/crypto]-random source, and chuck it in. You store/send those bytes along with the ciphertext. Yes, this does mean that the ciphertext is a constant length bigger than the plaintext, but it's a small price to pay.
Now what about that key? Sometimes we want a remember-able key (like.. a password), rather than a nice random one that computers like (if you have the option to just use a random key - do that instead). Can we get a compromise? Yes! Should we translate ASCII character passwords into bytes to make the key? HELL NO!
ASCII characters aren't very random at all (heck, they generally only use about 6-7 bits out of 8). If anything, what we want to do is make our key at least look random. How do we do this? Well, hashing happens to be good for this. What if we want to reuse our key? We'll get the same hash... repeatability again!
Luckily, we use the other form of unique random input - a salt. Make a unique random salt, and append that to your key. Then hash it. Then use the bytes to encrypt your data. Add the salt AND the IV along with your ciphertext when you send it, and you should be able to decrypt on the end.
Almost done? NO! You see the hashing solution I described in the paragraph above? Real cryptographers would call it amateurish. Would you trust a system which is amateurish? No! Am I going to discuss why it's amateurish? No, 'cus you don't need to know. Basically, it's just not REALLY-SUPER-SCRAMBLED enough for their liking.
What you need to know is that they've already devised a better system for this very problem. It's called PBKDF2. Find an implementation of it, and [learn to] use that instead.
Now all your data is secure.
Salting just involves adding a random string to the end of the input key.
So generate a random string of some length:
Generate a random alphanumeric string in cocoa
And then just append it to the key using:
NSString *saltedKey = [key stringByAppendingString:salt];
Unless salt is being used in a different way in the article you read this should be correct.
How a random salt is normally used:
#Ca1icoJack is completely correct in saying that all you have to do is generate some random data and append it to the end. The data is usually binary as opposed to alphanumeric though. The salt is then stored unencrypted alongside each hashed password, and gets concatenated with the user's plaintext password in order to check the hash every time the password gets entered.
What the is the point of a SALT if it's stored unencrypted next to the hashed password?
Suppose someone gets access to your hashed passwords. Human chosen passwords are fairly vulnerable to being discovered via rainbow tables. Adding a hash means the rainbow table needs to not only include the values having any possible combination of alphanumeric characters a person might use, but also the random binary salt, which is fairly impractical at this point in time. So, basically adding a salt means that a brute force attacker who has access to both the hashed password and the salt needs to both figure how how the salt was concatenated to the password (before or after, normally) and brute force each password individually, since readily available rainbow tables don't include any random binary data.
Edit: But I said encrypted, not hashed:
Okay, I didn't read very carefully, ignore me. Someone is going to have to brute-force the key whether it's salted or not with encryption. The only discernable benefit I can see would be as that article says to avoid having the same key (from the user's perspective) used to encrypt the same data produce the same result. That is useful in encryption for different reasons (encrypted messages tend to have repeating parts which could be used to help break the encryption more easily) but the commenters are correct in noting that it is normally not called an salt in this instance.
Regardless, the trick is to concatenate the salt, and store it alongside each bit of encrypted data.

Resources