How do I do deterministic RSA in Go - 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.

Related

Deterministically expand the number of public/private keys

I need to deterministically extend public and private keys (ethereum). How can I do this, who can suggest an algorithm?
The blog post linked in the question comments mentions risks related to generating vanity addresses from a deterministic source of randomness.
A vanity address is an address that contains a predefined set of bytes, for example starts with 4 zeros. These vanity tools use a loop to generate a random private key, its corresponding address, and validate if the address matches the criteria. If the address doesn't match the criteria, it runs another iteration of the loop.
Simplified example, looking for address starting with 0x1
Generate private key 0x123, its corresponding address is 0x456. Doesn't match the criteria, trying again.
Generate private key 0xd3f, its corresponding address is 0xb7c. Doesn't match the criteria, trying again.
Generate private key 0x837, its corresponding address ix 0x154. Success.
Some of these vanity tools generate private keys by using a deterministic seed generating algorithm, so it is possible (with some brute force guessing) to recreate the specific private keys that were used and reclaim access to these addresses.
A solution that is considered safe is to let each user generate their own pseudo-random seed. A great example is tracking the movements of their mouse cursor as you can see on this page.
Or generally, accept the seed from multiple sources - e.g. /dev/random from multiple physical machines.
Edit: Generating multiple addresses from an xpub:
const HDNode = ethers.utils.HDNode.fromExtendedKey("xpub661MyMwAqRbcGXSTUwJkaLaZFy6xdVk8XuRuSEFThgCPFEjrh9WAyREtMhuHA7XMMDXXTm41GfjKDCsLJ2fGfVp1ACyuDKwsShNcGWenHET");
const address0 = HDNode.derivePath("0").address;
const address1 = HDNode.derivePath("1").address;

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

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

Creating an id from name and address data. Hash/Digest

My problem:
I'm looking for a way to represent a person's name and address as an encoded id. The id should contain only alpha-numeric characters, be collision-proof, and be represented in a smallest number of characters possible. My first thought was to simply use a cryptographic hash function like MD5 or SHA1, but this seems like overkill (security isn't important - doesn't need to be one-way) and I'd prefer to find something that would produce a shorter id. Does anyone know of an existing algorithm that fits this problem?
In other words, what is the best way to implement the following function so that the return value is the same consistently for the same input, collisions are unlikely, and ids are less than 20 characters?
>>> make_fake_id(fname = 'Oscar', lname = 'Grouch', stnum = '1', stname = 'Sesame', zip = '12345')
N1743123734
Application Context (for those that are interested):
This will be used for a record linkage app. Given an input name and address we search a very large database for the best match and return the database id and other data (how we do this is not important here). If there isn't a match I need to generate this psuedo/generated/derived id from the search input (entity's name and address data). Every search record should result in an output record with either a real (the actual database id resulting from a match/link) or this generated psuedo/generated/derived id. The psuedo id will be prefixed with a character (e.g. N) to differentiate it from a real id.
I know you said no to MD5 and SHA1, but I think you should consider them anyway. As well as being well studied hashing algorithms, the length gives you more protection against possible collisions. No hash is collision-proof, but the cryptographic ones generally are less collision-prone than something you couuld come up with yourself.
Use a cryptographic hash for its collision resistance, not its other qualities
Use as many bytes from the hash as you want (truncate)
convert to alpha-numeric characters
You can also truncate the alpha-numeric string instead of the hash
An easy way to do this: hash the data, encode in base64, remove all non-alpha-numeric characters, truncate.
N_HASH_CHARS = 11
import hashlib, re
def digest(name, address):
hash = hashlib.md5(name + "|" + address).digest().encode("base64")
alnum_hash = re.sub(r'[^a-zA-Z0-9]', "", hash)
return alnum_hash[:N_HASH_CHARS]
How many alpha-numeric characters should you keep? Each character gives you around 5.95 bits of entropy (log(62,2)). 11 characters give you 65.5 bits of entropy, which should be enough to avoid a collision for the first 2**32.7 users (about 7 billion).
A good solution is somewhat dependent on your application. Do you know how many users and what the set of all users is? If you provide more details you would get better help.
I agree with the other poster suggesting serial numbers. OTOH, if you really, really really want to do something else:
Create a SHA1 hash from the data, and store it in a table with a serial number field.
Then, when you get the data, calculate the hash, look it up on the table, get the serial, and that's your id. If it's not on the table, insert it.
I wonder whether you intend to "assign" these ids to the users? If so, I would expect your users to hate anything that you propose; who would want a user id of "AAAAA01"?
So, if these ids are visible to the user, then you should just let them pick what they like and check them for uniqueness (easy). If they are not visible to the user (e.g., internal primary key), then just generate them sequentially using an appropriate technique such as an Oracle Sequence or SQL Server AutoNumber (also easy).
If these ids are an attempt to detect a user that is registering more than once, then I would agree that you should consider a cryptographic hash followed by a full comparison of the registration data (name, address, etc.). However, to be usable, you will need to translate the data into a canonical form (standardized letter case, whitespace, canonical street address, etc.) before computing the hash or making the comparison. Otherwise, you will mismatch based on trivial differences.
EDIT: Now that I understand the problem space better based on your edits, I think that it is highly unlikely that your algorithm (so far) will catch most matches. Beyond my suggestion to canonicalize the inputs, I recommend that you consider an approach that results in a ranked list of a handful of possible matches (to be resolved by a human if possible) rather than an all-or-nothing attempt at a single match. In other words, I recommend a search approach rather than a lookup approach.
Is that feasible in your situation?
Well, if there's more than one person at the same address with the same name, you're toast here, (w/o adding code to detect this and add a discriminator of some kind).
but assuming that issue is not, then the street address and zip code portion of the full addresss is sufficient to guaranteee uniqueness there, so adding enough data from the name should take care of the issue...
Do you have access to a database, or other persistence mechanism, where you could generate and maintain key values for each address? Then keep the address and individual entities in two keyed dictionary structures, where the key is autogenerated for each new distinct address, person encountered... and then use the autogenerated alpha-numeric key...
You could use AAAAA01 for first person at first address,
AAAAA02 for second person at first address,
AAAAB07 for the seventh resident at the second adresss, etc.
If you donlt have any way to generate and maintain these entity-Key mappings then you need to use the full street address/Zip and fullNAme, or a hash value of the same, although the Hash value approach has a smnall chance of generating duplicates...

Resources