bcrypt in Go with KDF for specific output key-length - go

It seems like the Go ecosystem just has a basic bcrypt implementation (golang.org/x/crypto/bcrypt) and it's left as an exercise for the developer to extract the key from the encoded output string to then further expand it to satisfy a particular key length if you're going to be using it as an encryption key rather than just storing it as a password in a DB somewhere. It confounds me that there don't seem to be any quick treatments of this concept online for Go or just in general.
At the risk of introducing a bug by doing it myself, I suspect that I'm gonna be forced to use scrypt, where, at least in Go, it does take an output-length parameter.
Am I missing something? Is there an implementation of bcrypt somewhere in Go that takes a key-length parameter and manages producing a key of acceptable length directly?

Bcrypt is not a key derivation algorithm; it is a password hashing algorithm.
PBKDF2 can take a password and output n desired bits
scrypt can take a password and output n desired bits
These are key-derivation functions. They take a password and generate n bits that you can then use as an encryption key.
BCrypt cannot do that. BCrypt is not a key-derivation function. It is a password hashing function. It always outputs the same amount of bits.
Bonus: bcrypt always outputs exactly 24-bytes (192 bits), because the output from bcrypt is the result of encrypting OrpheanBeholderScryDoubt.
Note: It's not the result of hashing OrpheanBeholderScryDoubt - the bcrypt algorithm is actually encrypting OrpheanBeholderScryDoubt using the blowfish cipher (and repeating the encryption 64 times).
The strenght of bcrypt comes from the "expensive key setup".
Bonus: The strength of bcrypt comes from the fact that it is expensive. And "expensive" means memory. The more memory an algorithm requires, the stronger it is against bruteforce attacks.
SHA-2: can operate in 128 bytes of RAM
bcrypt: constantly touches 4 KB of RAM
scrypt: constantly touches 16 MB of RAM (in the default configuration in Android and LiteCoin)
Argon2: is usually recommended you configure it to touch 1 GB of RAM
Defending against bruteforce attacks means to defend against parallelization. An algorithm that requires 128 bytes can have 7 million parallel operations on a 1 GB video card.
Scrypt, requiring 16 MB of RAM, can only have 62 running in parallel.
Argon2, using 1 GB of RAM, can only have 1 running on a video card. And it runs faster on a CPU anyway.
Kludge bcrypt into a Key Derivation Function (KDF)
You could kludge bcrypt into being a key-derivation function. You can use the standard function PBKDF2 to do it for you.
Normally PBKDF2 is called as:
String password = "hunter2";
String salt = "sea salt 69 nice";
Byte[] key = PBKDF2(password, salt, 32, 10000); //32-bytes is 256 bits
But instead you can use the bcrypt string result as your salt:
String password = "hunter2";
String salt = bcrypt.HashPassword(password, 12);
Byte[] key = PBKDF2(password, salt, 32, 1); //32-bytes is 256-bits
And now you've generated a 256-bit key "using bcrypt". It's a neat hack.
In fact the hack is so neat, that it is literally what scrypt does:
String password = "hunter2";
String salt = ScryptExpensiveKeyHash(password, userSalt, ...);
Byte[] key = PBKDF2(password, salt, 32, 1); //32-bytes is 256-bits
Conclusion
Bcrypt is not a key derivation function. That is the goal of functions like PBKDF2, scrypt (which uses PBKDF2), and argon2.
Using bcrytp when you're only allowed NIST approved algorithms
There is another good reason to use this pbkdf2 construction with bcrypt.
Sometimes a "security expert", who has no idea what they're talking about, will insist that you use PBDKF2 for key derivation. (Yes, it does happen). And you'll try to tell them over and over that PBDKF2 is horribly weak system for key derivation (SHA2 that it is based on runs way too fast, and 10,000 or 100,000 iterations is nowhere near enough to protect you from brute-force attacks - that's what bcrypt, scrypt, and argon2 were invented for).
But this person won't let it go, and will demand the use of PBKDF2. With this construction you can still use bcrypt for security, and PBKDF2 for ignoramus who demands it be in there.
You just happen to use a strong "salt".

Related

How does the aes256 encryption algorithm deal with keys whose length is not equal to 32 bytes?

The reason why I ask this question is that we all know that this algorithm will fill the plaintext data into a multiple of 32 bytes,
so how will the key with less than 32 bytes or more be handled?
Because aes256 encryption algorithm is used in many websites or programs,
and usually we don't set a 32 byte password.
In that case, how should the algorithm go on?
Or is there any place where I can perfectly read the algorithms of all modes of aes256?
I am willing to check the source code of the algorithm by myself.
(this is not an advertisement)
but before that, I wrote an encryption algorithm myself.
I named it "sn_aes2048", Its function is:
"if the plaintext data is not a multiple of 256 bytes,
it will be filled with a multiple of 256 bytes, and the key is the same operation.
16 rounds of encryption will be performed by default,
and the data of the key will be updated in each round of encryption.
You may not believe that this algorithm is both symmetric encryption and asymmetric encryption.
Yes, yes, it is an encryption algorithm similar to aes256."
The reason why I ask this question is that we all know that this algorithm will fill the plaintext data into a multiple of 32 bytes,
AES is a block cipher, which must be used with a mode of operation to be used as a general cipher. Some mode of operations (ECB, CBC) require padding (or ciphertext stealing) to be able to operate. So AES - the block cipher algorithm - doesn't do that, and many more modes of operation (CTR, GCM) don't require padding at all.
so how will the key with less than 32 bytes or more be handled?
AES - the block cipher - supports key sizes of 128, 192 and 256 bits, and that's it. It doesn't perform any actions on the key itself.
and usually we don't set a 32 byte password.
Yes but a password is not a key. Both are secrets, but there are different requirements for keys and passwords. You can indeed use a password based key derivation function (PBKDF) as has been commented below. Other methods exist as well such as PAKE schemes.
You may not believe that this algorithm is both symmetric encryption and asymmetric encryption.
I don't believe it can be any good if you don't even understand the concepts of a symmetric key and a password - or the concept of padding which you're trying to re-invent, but feel free to publish a paper.
Or is there any place where I can perfectly read the algorithms of all modes of aes256?
Try "block cipher mode of operation" and "Padding" on Wikipedia for a start. Then buy a book or follow a course on Cryptography. It is an academic field - creating your own algorithm from scratch is like screwing together your own automobile.

A fast encryption/decryption algorithm that will NOT be used for security, but to combat spam

I am looking for a fast encryption/decryption algorithm to be used against spam.
I don't know enough about this field to try and make my own, and in any case, I understand that it would be a bad idea to use something new, so I need some suggestions.
I have looked around SO and tried google but most of the results were explaining how encryption/decryption is slow in order to be hard to break, which I understand, but there are cases when the data expires rapidly and the secret key(salt?) can change very fast, so a fast algorithm would be very useful.
Look at this article on block ciphers. Here is how you can make your own cipher:
Encryption:
Store your own private data, preferably randomly generated for each cipher.
Using your private data as a seed in a pseudorandom number generator. Produce a string of bits as long as the data you want to encode, a.k.a. the plaintext. This string of "random" bits is the key.
For each bit of the key, take the corresponding bit from the plaintext, which we will call a and b respectively. The XOR of the two yields the corresponding bit in the ciphertext.
Use the ciphertext as you wish.
Decryption:
Take the ciphertext and retrieve the private data for it.
Use the private data as a seed in the same pseudorandom number generator to produce the key from before.
Follow the steps above to get the plaintext instead of the ciphertext.
Example:
// ENCODE
plaintext (in bits) = 00100001111110
key (from pseudo-random number generator) = 10101110110101
ciphertext (XOR each bit) = 10001111001011
// DECODE
ciphertext = 10001111001011
key (from pseudo-random number generator) = 10101110110101
plaintext = 00100001111110

What does 'salt' refer to in string-to-key (s2k) specifier?

What does 'salt' refer to in string-to-key (s2k) specifier?
It appears to be a random number generator to shake things up, but I would like to know what 'salt' stands for?
For example it is written:
3.6.1.2. Salted S2K
This includes a "salt" value in the S2K specifier -- some arbitrary
data -- that gets hashed along with the passphrase string, to help
prevent dictionary attacks.
Octet 0: 0x01
Octet 1: hash algorithm
Octets 2-9: 8-octet salt value
Salted S2K is exactly like Simple S2K, except that the input to the
hash function(s) consists of the 8 octets of salt from the S2K
specifier, followed by the passphrase.
But salt is not defined, although its meaning seems clear.
From Wikipedia:
In cryptography, a salt comprises of random bits that are used as one of the inputs to a key derivation function. The other input is usually a password or passphrase. The output of the key derivation function is stored as the encrypted version of the password.
A salt is just some bits that are used to increase the security of the system. They help prevent pre-computed dictionary attacks.
The salt can be any consistent value.
Either a constant, or the user ID. Better if it includes both.
This is used to prevent pre generated rainbow tables from working.
I think you're asking the origin of the term, not the definition.
Time for a round of folk etymology! (Until someone gives the real answer.)
My guess is that it is an analogy from cooking: the salt is an improving additive. And a little bit goes a long way.

Simple integer encryption

Is there a simple algorithm to encrypt integers? That is, a function E(i,k) that accepts an n-bit integer and a key (of any type) and produces another, unrelated n-bit integer that, when fed into a second function D(E(i),k) (along with the key) produces the original integer?
Obviously there are some simple reversible operations you can perform, but they all seem to produce clearly related outputs (e.g. consecutive inputs lead to consecutive outputs). Also, of course, there are cryptographically strong standard algorithms, but they don't produce small enough outputs (e.g. 32-bit). I know any 32-bit cryptography can be brute-forced, but I'm not looking for something cryptographically strong, just something that looks random. Theoretically speaking it should be possible; after all, I could just create a dictionary by randomly pairing every integer. But I was hoping for something a little less memory-intensive.
Edit: Thanks for the answers. Simple XOR solutions will not work because similar inputs will produce similar outputs.
Would not this amount to a Block Cipher of block size = 32 bits ?
Not very popular, because it's easy to break. But theorically feasible.
Here is one implementation in Perl :
http://metacpan.org/pod/Crypt::Skip32
UPDATE: See also Format preserving encryption
UPDATE 2: RC5 supports 32-64-128 bits for its block size
I wrote an article some time ago about how to generate a 'cryptographically secure permutation' from a block cipher, which sounds like what you want. It covers using folding to reduce the size of a block cipher, and a trick for dealing with non-power-of-2 ranges.
A simple one:
rand = new Random(k);
return (i xor rand.Next())
(the point xor-ing with rand.Next() rather than k is that otherwise, given i and E(i,k), you can get k by k = i xor E(i,k))
Ayden is an algorithm that I developed. It is compact, fast and looks very secure. It is currently available for 32 and 64 bit integers. It is on public domain and you can get it from http://github.com/msotoodeh/integer-encoder.
You could take an n-bit hash of your key (assuming it's private) and XOR that hash with the original integer to encrypt, and with the encrypted integer to decrypt.
Probably not cryptographically solid, but depending on your requirements, may be sufficient.
If you just want to look random and don't care about security, how about just swapping bits around. You could simply reverse the bit string, so the high bit becomes the low bit, second highest, second lowest, etc, or you could do some other random permutation (eg 1 to 4, 2 to 7 3 to 1, etc.
How about XORing it with a prime or two? Swapping bits around seems very random when trying to analyze it.
Try something along the lines of XORing it with a prime and itself after bit shifting.
How many integers do you want to encrypt? How much key data do you want to have to deal with?
If you have few items to encrypt, and you're willing to deal with key data that's just as long as the data you want to encrypt, then the one-time-pad is super simple (just an XOR operation) and mathematically unbreakable.
The drawback is that the problem of keeping the key secret is about as large as the problem of keeping your data secret.
It also has the flaw (that is run into time and again whenever someone decides to try to use it) that if you take any shortcuts - like using a non-random key or the common one of using a limited length key and recycling it - that it becomes about the weakest cipher in existence. Well, maybe ROT13 is weaker.
But in all seriousness, if you're encrypting an integer, what are you going to do with the key no matter which cipher you decide on? Keeping the key secret will be a problem about as big (or bigger) than keeping the integer secret. And if you're encrypting a bunch of integers, just use a standard, peer reviewed cipher like you'll find in many crypto libraries.
RC4 will produce as little output as you want, since it's a stream cipher.
XOR it with /dev/random

Encryption algorithm that output byte by byte based on password and offset

Is there a well-known (to be considered) algorithm that can encrypt/decrypt any arbitrary byte inside the file based on the password entered and the offset inside the file.
(Databyte, Offset, Password) => EncryptedByte
(EncryptedByte, Offset, Password) => DataByte
And is there some fundamental weakness in this approach or it's still theoretically possible to build it strong enough
Update:
More datails: Any cryptographic algorithm has input and output. For many existing ones the input operates on large blocks. I want to operate on only one byte, but the system based on this can only can remap bytes and weak by default, but if we take the position in the file of this byte, we for example can take the bits of this position value to interpret them as some operation on some step (0: xor, 1: shitf) and create the encrypted byte with this. But it's too simple, I'm looking for something stronger.
Maybe it's not very efficient but how about this:
for encryption use:
encryptedDataByte = Encrypt(offset,key) ^ dataByte
for decryption use:
dataByte = Encrypt(offset,key) ^ encryptedDataByte
Where Encrypt(offset,key) might be e.g. 3DES or AES (with padding the offset, if needed, and throwing away all but one result bytes)
If you can live with block sizes of 16 byte, you can try the XTS-mode described in the wikipedia article about Disk encryption theory (the advantage being that some good cryptologists already looked at it).
If you really need byte-wise encryption, I doubt that there is an established solution. In the conference Crypto 2009 there was a talk about How to Encipher Messages on a Small Domain: Deterministic Encryption and the Thorp Shuffle. In your case the domain is a byte, and as this is a power of 2, a Thorp Shuffle corresponds to a maximally unbalanced Feistel network. Maybe one can build something using the position and the password as key, but I'd be surprised if a home-made solution will be secure.
You can use AES in Counter Mode where you divide your input into blocks of 16 bytes (128 bits) and then basically encrypt a counter on the block number to get a pseudo-random 16 bytes that you can XOR with the plaintext. It is critically important to not use the same counter start value (and/or initialization vector) for the same key ever again or you will open yourself for an easy attack where an attacker can use a simple xor to recover the key.
You mention that you want to only operate on individual bytes, but this approach would give you that flexibility. Output Feedback Mode is another common one, but you have to be careful in its use.
You might consider using the EAX mode for better security. Also, make sure you're using something like PBKDF-2 or scrypt to generate your encryption key from the password.
However, as with most cryptography related issues, it's much better to use a rigorously tested and evaluated library rather than rolling your own.
Basically what you need to do is generate some value X (probably 1 byte) based on the offset and password, and use this to encrypt/decrypt the byte at that offset. We'll call it
X = f(offset,password)
The problem is that an attacker that "knows something" about the file contents (e.g. the file is English text, or a JPEG) can come up with an estimate (or sometimes be certain) of what an X could be. So he has a "rough idea" about many X values, and for each of these he knows what the offset is. There is a lot of information available.
Now, it would be nice if all that information were of little use to the attacker. For most purposes, using a cryptographic hash function (like SHA-1) will give you a reasonable assurance of decent security.
But I must stress that if this is something critical, consult an expert.
One possibility is a One Time Pad, possibly using the password to seed some pseudo-random number generator. One time pads theoretically achieve perfect secrecy, but there are some caveats. It should do what you're looking for though.

Resources