Thinking about these below two cases, which one is best and most secure one
1st case
//key1 generated from static salt and user password, because in case attacker don't know about source code (bad assumption, but still my assumption), attacker have only hashed or encrypted data + random generated salt
staticSalt = "StaticSalt"
key1 = pbkdf2(userPassword, staticSalt, iteration)
//key2 generated from key1 and randomSalt, this will be actual key to be used for encryption
randomSalt = GenerateRandomSalt()
key2 = pbkdf2(key1, randomSalt, iteration)
aes.Key = Key2
aes.IV = aes.GenerateIV()
or
2nd case
//directly generate key from randomSalt and password
randomSalt = GenerateRandomSalt()
key1 = pbkdf2(userPassword, randomSalt, iteration)
aes.Key = Key1
aes.IV = aes.GenerateIV()
My question is, is there any drawback in using 1st case, will it increasing or decreasing entropy, or making is less secure?
or 2nd case is far more better and secure way to do
Looking for answer from some crypto expert.
This question is more appropriate for Sec.SE.
If you are using this code to store passwords, see this question in particular on how to properly hash and store passwords.
The first case appears to add obscurity, instead of security. Which may actually decrease security in the long run, by increasing the attack area (i.e. more places for bugs to happen).
Remember, you don't want to be a Dave.
Related
Does it make a problem about security as long as key and iv kept secret but same?
Thanks.
UPDATE: I did some research and learned why iv used. As mentioned in the answer below it's a protection way against frequency attacks. And there is two requirements when creating iv: uniqueness and unpredictability.
The algorithm that I thought for creating aes key and iv is:
Get two values from a certain elliptic curve point that agreed before by using asymetric encryption.(x,y)
Aes.Key <- HASH(x)
(string)unique <- timestamp()
(string)unpre <- y
Aes.IV <- HASH(unique + unpre)
And share data as {encryptedmessage, timestamp}
Is this logic alright?
You need a random (or at least pseudo-random) Initialization Vector for block ciphers like AES.
Ripped straight from Wikipedia:
Randomization is crucial for encryption schemes to achieve semantic
security, a property whereby repeated usage of the scheme under the
same key does not allow an attacker to infer relationships between
segments of the encrypted message.
I am trying to implement simple El-Gamal cryptosystem.
And I can't understand how to represent message as an integer between 1 and n-1.
The only thing that comes to my mind is:
if n bit length is k, then divide input message m on t | t < k bits and each piece of bits use as integer number.
I think It is wrong.
So how to represent message as an integer between 1 and n-1?
You could do that which is essentially the equivalent of using ECB mode in block ciphers, but there are attacks on this. An attacker may reorder the different blocks of the ciphertext and you would decrypt it without problem, but the received plaintext would be broken without you knowing this. This may also open the door for replay attacks since the blocks are all encrypted independently. You would need some kind of authenticated encryption.
Back to your original question. Such a problem is usually solved by using hybrid encryption. A block cipher like AES is used to encrypt the whole plaintext with a random key. This random key is in turn encrypted through ElGamal since the key is small enough to be represented in < k bits.
Now depending on the mode of operation of the block cipher this could still be malleable. You would either need to put a hash of the ciphertext/plaintext next to the random key as an integrity check. Or otherwise use an authenticated mode of operation like GCM and add the resulting tag next to the random key. Depending on k, this should fit.
Note that you should use some kind of padding for random key | hash/tag if it doesn't reach k.
I am working on a Java project where I must ensure the confidentiality and integrity of users password saved in a plaintext file.
To do so, I will write only a hash of the password in the file. More specifically, my intention is to write the hash of the password and a random salt, plus the random salt itself, to avoid the use of rainbow and lookup tables. I also want to use key-stretching with PBKDF2, to make the computation of the hash computationally expensive.
Finally, I would like to use a keyed hash algorithm, HMAC, for a final layer of protection.
I am trying to implement my thoughts in a Java code, and I have found some examples of the operations that I have presented above:
private static byte[] pbkdf2(char[] password, byte[] salt, int iterations, int bytes)
throws NoSuchAlgorithmException, InvalidKeySpecException
{
PBEKeySpec spec = new PBEKeySpec(password, salt, iterations, bytes * 8);
SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
return skf.generateSecret(spec).getEncoded();
}
The thing that I really cannot understand is how to input my secret key as the key used by the HMAC algorithm, as it doesn't seem an input to the function. I have looked through the Java documentation, but I cannot find a solution to my question.
At this point, I am not really sure if I understood correctly how the different part of the encryption mechanism work, so I would accept any help on the topic.
I think I see the confusion. You're apparently expecting your code to apply PBKDF2 then HMAC-SHA-1. That's not how it works: HMAC-SHA-1 is used inside PBKDF2.
The gist of PBKDF2 is to apply a function repeatedly which has the following properties:
it takes two arguments;
it returns a fixed-size value;
it is practically undistinguishable from a pseudo-random function.
HMAC-SHA-1 is such a function, and a common choice. There are other variants of PBKDF2, using HMAC-MD5, HMAC-SHA-256, or other functions (but these variants aren't in the basic Java library).
PBKDF2 takes two data inputs (plus some configuration inputs): the password, and a salt. If you want to include a secret value in the calculation, PBKDF2's input is the place for it: don't tack on a custom scheme on top of that (doing your own crypto is a recipe for doing it wrong). Append the pepper (secret value common to all accounts) to the salt (public value that varies between accounts).
Note that pepper is of limited usefulness. It's only useful if the hashes and the pepper secret value are stored in different places — for example, if the hashes are in a database and the pepper is in a disk file that is not directly vulnerable to SQL injection attacks.
Is it possible to restore the key from blowfish encrypted ciphertext and plaintext pairs?
I have several strings both encrypted and plain. But I can't remember key.
example of encrypted string 24026B7101030657757D01
decrypted string is AC C1312463
$key = '';
$plaintext = '';
$crypttext = '24026B7101030657757D01';
$cache = array();
while($plaintext != 'AC C1312463')
{
$key = random_string();
while(array_search($key,$cache) !== FALSE)
{
$key = random_string();
}
$cache[] = $key;
$bf = new Crypt_Blowfish($key);
$plaintext = $bf->decrypt($crypttext);
}
print_r($key);
die();
Let's say I have algorithm like this. How should function random_string should look like to get 32bit random key?
No decent cipher (including Blowfish) allows efficient key recovery no matter how many (plaintext, ciphertext) pairs you know.
What remains is a brute-force attack where you guess the key and then check if it matches a known pair. For sufficiently complex keys this becomes prohibitively expensive. So this will only work if your key was bad.
What you are proposing is esentially a known-plaintext attack, that said, as the wiki article points out, they haven't been a successful key recovery mechanism since the days of the Enigma.
To even get close to a modern key recovery system, you need to use a chosen plaintext attack like Differential cryptanalysis, which analyzes differences in ciphertext between specially chosen plaintext pairs to gain info about the key. That said, Blowfish isn't particularly susceptible to such attacks, so it won't help much anyways.
If you want to recover your key, you should consider the mechanisms that were used to generate it (is it derived from a password, how big is it, etc) and then come up with a way to brute force it, whether through a dictionary attack, iterating through all 32 bit integers, etc. a program called John the Ripper may help with applying this brute forcing as efficiently as possible.
Trying to find out what kind of hash/encryption this is in a SQL db. We want to create an app to do password resets but I cannot for the life of me find how they are generating this value.
Here are multiple examples
{enc:1}gdyb21LQTcIANtvYMT7QVQ==
{enc:1}ZEImYhrd/Ot/LcewJCFdMw==
{enc:1}+IOSBzegAx7nSytO1J3GEw==
{enc:1}6ULa1IFMxavY7SE66K3UDg==
{enc:1}UEFeGim2M8d0Iee7ejFRUw==
{enc:1}RjqL5rXOBpqJAKPjYkwLtw==
{enc:1}V/PEslecyYxFki03H4ctAQ==
{enc:1}VDEm9QmD+L7tsqcPz/S9XQ==
{enc:1}YkQuEPpL6dRfDLwKMEVMMg==
{enc:1}86rG96EP7T3tx9e8C7513g==
{enc:1}xvSwvsmkgwtXwVISvg7mJQ==
{enc:1}KjCF0RD4tcUGEP4Bpafw5A==
{enc:1}z9pGrdm4QAoomrFCJCXQIQ==
{enc:1}yhLv0HeW90FENKJjV9Nb+g==
{enc:1}EtYMl5FOW+zdpVvWsIj3Rw==
Let's take it apart:
{enc:1}gdyb21LQTcIANtvYMT7QVQ==
The {enc:1} part is likely to be versioning of some form. This is reasonably common so that you can upgrade whatever hashing/encryption algorithm you use over time. Each value identifies the algorithm used to produce the hash - if the implementation decides to use a different approach, it would know to validate a password using the first version, but could then replace the {enc:1} with {enc:2} or whatever, along with the new form of the hash.
The rest is base64 - and it's 24 characters ending in ==, which means the original value is 16 bytes.
So it's a 16 byte (128 bit) hash of some kind, with a versioning prefix. That's pretty much all we can tell... it could be any 128 bit hash, or possibly 128 bits of a longer hash (although you'd have to wonder why they threw away data at that point).
You could perform further tests if you can create your own users with passwords. For example, do two users with the same password end up with the same hash? If not, if you change from password X to password Y and then back to password X for a single user, does that get to the same hash? (There's no obvious salt in the value, although the username could be used as the salt.)