using counter instead of salt for hashing - security

I'm developing own protocol for secure message exchanging.
Each message contains the following fields: HMAC, time, salt, and message itself. HMAC is computed over all other fields using known secret key.
Protocol should protect against reply attack. On large time interval "time" record protects against replay attack (both sides should have synchronized clocks). But for protection against replay attack on short time intervals (clocks are not too accurate) I'm planning replace "salt" field with counter increasing every time, when new message is send. Receiving party will throw away messages with counter value less or equal to the previous message counter.
What I'm doing wrong?
Initial counter value can be different (I can use party identifier as initial value), but it will be known to the attacker (party identifier transmitted in unencrypted form).
(https://security.stackexchange.com/questions/8246/what-is-a-good-enough-salt-for-a-saltedhash)
But attacker can precompute rainbow tables for counter+1, counter+2, counter+3... if I will not use really random salt?

I'm not certain of your design and requirements, so some of this may be off base; hopefully some of it is also useful.
First, I'm having a little trouble understanding the attack; I'm probably just missing something. Alice sends a message to Bob that includes a counter, a payload, and an HMAC of (counter||payload). Eve intercepts and replays the message. Bob has seen that one, so he throws it away. Eve tries to compute a new message with counter+1, but she is unable to compute the HMAC for this message (since the counter is different), so Bob throws it away. As long as there is a secret available, Eve should never be able to forge a message, and replaying a message does nothing.
So what is the "known secret key?" Is this key known to the attacker? (And if it is, then he can trivially forge messages, so the HMAC isn't helpful.) Since you note that you have DH, are you using that to negotiate a key?
Assuming I'm missing the attack, thinking through the rest of your question: If you have a shared secret, why not use that to encrypt the message, or at least the time+counter? By encrypting the time and counter together, a rainbow table should be impractical.
If there is some shared secret, but you don't have the processor available to encrypt, you could still do something like MD5(secret+counter) to prevent an attacker guessing ahead (you must already have MD5 available for your HMAC-MD5).
I have attacked this problem before with no shared secret and no DH. In that case, the embedded device needed a per-device public/private keypair (ideally installed during manufacturing, but it can be computed during first power-on and stored in nonvolatile memory; randomness is hard, one option is to let the server provide a random number service; if you have any piece of unique non-public information on the chip, like a serial number, that can be used to seed your key, too. Worst case, you can use your MAC plus the time plus as much entropy as you can scrounge from the network.)
With a public/private key in place, rather than using HMAC, the device just signs its messages, sending its public key to the server in its first message. The public key becomes the identifier of the device. The nice thing about this approach is that there is no negotiation phase. The device can just start talking, and if the server has never heard of this public key, it creates a new record.
There's a small denial-of-service problem here, because attackers could fill your database with junk. The best solution to that is to generate the keys during manufacturing, and immediately insert the public keys into your database. That's impractical for some contract manufacturers. So you can resort to including a shared secret that the device can use to authenticate itself to the server the first time. That's weak, but probably sufficient for the vast majority of cases.

Related

How to send data in secure way between client and server using only Symmetric cryptography

I'd take the following steps to send/received data between client and server. But I'm not sure if all the steps are secure enough and impossible to intercept. Please can you let me know how to patch up the security holes, if any?
Please note that:
This is all for Symmetric cryptography not the Public/Private Key method. So 'salt' and 'entropy' are the secrets between client and server.
For some reasons, I cannot/don't use SSL or TLS protocols. So there is no Certificate Authority etc.
Only standard cryptography functions and methods must be used (no inventions).
The data are not sent over a secure (HTTPS) connection.
I cannot use sessions here because they are two different applications.
First time - Sign up (user enters new username and new password)Client sideCreate a CSPRNG salt for the userSave salt on user's machineCreate an entropy in memory (base64 of a temporal value e.g. [hour of the day]+[day of the year])Post Password(base64 of the plaintext), and salt, and entropy to the serverServer sideFor the received message from the clietCheck if entropy matches (e.g. with base64 of [hour of the day]+[day of the year]) .Compute hash (SHA1) of salt and Password(base64 of the plaintext) - because hashing must always be done on the server.Save salt and the computed hash to the database
Next time - Log in (user enters his username and his password)Client sideRead salt from user's machineCompute hash (SHA1) of salt and entered password(base64 of the plaintext)Post password(base64 of the plaintext), and salt, and the computed hash to the serverServer sideRetrieve salt and 'stored hash' from the databaseFrom the received message from the clientSplit the message to 3 parts: password(base64 of the paintext); salt; 'received hash'Compare 'received hash' with 'stored hash'; if they match, the user is genuine not a hacker
Sending TemperProof queryString from user to serverClient sideRead salt from user's machineCreate an entropy in memory (base64 of a temporal value e.g. [hour of the day]+[day of the year])Compute hash (SHA1) of the queryString(base64 of the plaintext), and salt, and entropyPost querystring(base64 of the plaintext), and salt, and entropy, and the computed hash to the serverServer sideRetrieve salt from the databaseFor the received message from the clietSplit the message to 4 parts: queryString(base64 of the paintext); salt; entropy; 'received hash'Check if entropy matches (e.g. with base64 of [hour of the day]+[day of the year]) .Compute hash (SHA1) of queryString(base64 of the plaintext) and salt and entropy.Compare the computed hash with the 4th part of the splitted message ('received hash'); if they match, the queryString is genuine
Sending answer back to the user from serverServer sideCompute the answer using database queriesRetrieve salt from the databaseCreate an entropy in memory (base64 of a temporal value e.g. [hour of the day]+[day of the year])Compute hash (SHA1) of the answer(base64 of the plaintext), and salt, and entropyPost answer(base64 of the plaintext), and salt, and entropy, and the computed hash to the clientClient sideRead salt from user's machineCreate an entropy in memory (base64 of a temporal value e.g. [hour of the day]+[day of the year])Split the received message to 4 parts: answer(base64 of the paintext); salt; entropy; 'received hash'Check if entropy matches (e.g. with base64 of [hour of the day]+[day of the year]) .Compute hash (SHA1) of answer(base64 of the plaintext) and salt and entropy.Compare the computed hash with the 4th part of the splitted message ('received hash'); if they match, the answer is genuine
The followings areas are the weaknesses, I think. Can you please advise how these can be fixed and also point out the other possible holes?
A) First time - Sign up: The hacker can post rubbish to fill up the database, if he finds entropy in step 1.3
B) Next time - Log in: I cannot think of a way to add an entropy to the hashed password in step 1.2, because then I cannot compare with the one on the server database in step 2.2.2
Thanks
if you care about security at all, STOP now ...
what you need to do:
1) forget about designing your own crypto protocol ... relying on well known crypto ALSO means that you DO NOT design that kind of thing
2) think in layers ... you have the need to keep things secret while transporting them from A to B ... that means you have a transport layer ... if you want that secured, there is a name for that...
Transport Layer Security -> https://en.wikipedia.org/wiki/Transport_Layer_Security
3) when you make assumptions here like "i have 2 applications so i can not have sessions", please provide WHY you think it is that way... when you think of things like single-sign-on, you can have a lot of applications sharing one authentication method and even session data across a bunch of different plattforms ... maybe it's just you don't know that you actually can have sessions...
4) read up on the terms you use ... you misunderstood entropy ... there is no way of "checking if entropy matches" ... entropy in crypto related cases means randomness in terms of unpredictable input to a function ... if you have something like a date and the time, and even if you hash that, it might look random ... but it is very predictable by someone with a clock... if the communication can be related to the creation time of the value, then your value does not contain large amounts of entropy if it is based on the clock... again, do not design you own stuff here, and go for entropy sources that provide reliable, cryptographically secure randomness (CSPRNG ... not just PRNG)
5) ... you misunderstood/misused salt...
that is nothing to be generated on the client machine
that is nothing that needs to be kept on the client machine
7) password hashing
again ... DO NOT come up with you own stuff here ...
create a sufficently long random salt (at least hash length) for every password. use a slow hash function like PBKDF2 with a high iteration count parameter. the reason is that it becomes slow to test for passwords... your server has to calculate this once for every login attempt ... an attacker has to calculate this for every password testing attempt ... you can afford the test to take like 200ms ... for an attacker that means a lot more hardware will be needed to crack your password storage...
upd:
you want it, you get it ...
proof of concept attack on your schema by man-in-the-middle:
client: alice
server: bob
attacker/eavesdropper: eve
alice uses your sign up service and creates an account
1.1 alice creates a CSPRNG salt and stores that in a secure manner
1.2 alice gathers an arbitrary amount of entropy and encodes it with base64
1.3 alice sends Password(base64 of the plaintext), and salt, and entropy to bob
------------intercepted-------------
eve intercepts the communication between alice and bob and gains knowledge of...
2.1 ...the base 64 encoded password -> base64 decode -> the plaintext password
2.2 ...the salt
2.3 ...the entropy value
2.4 alice forwards the intercepted communication without changes to bob
--- protocol broken ---
now, bob is by no means able to distinguish between alice and eve in all further communication
upd2:
a look on your transfered (cleartext) messages:
Login:
Post password(base64 of the plaintext), and salt, and the computed hash to the server
Sending queryString from user to server:
Post querystring(base64 of the plaintext), and salt, and entropy, and the computed hash to the server
answer:
Post answer(base64 of the plaintext), and salt, and entropy, and the computed hash to the client
now for any of those messages, let's look at what information someone with malicious intent would learn from those:
all the information that is cleartext, which means, all of it ...
for the login, we gain the clear text password, means from now on an attacker can identify as a valid user
for the querystring and answer thing you want to provide a way to see if the request/answer is not tempered with.
so if an attacker now intercepts your communication how can he change the querystring without being noticed?
the attacker splits your message, and changes whatever he/she wants
then he/she computates the forged_hash as sha1(salt_from_the_original_message,tampered_querystring) and sends base64(tampered_querystring),salt_from_the_original_message,entropy_from_original_message,forged_hash to the server ...
for the answer it's the same deal:
the attacker intercepts the original answer, changes whatever in the answer and recomputes the hash based on known information (the changes, and the original salt)
The solution is to use HTTPS withTLS 1.2 and pin the certificate, there are certificate solutions that are free.
Using a hash (SHA1 in this case) to protect a password has not been good secure practice for some time. For my reference see DRAFT NIST Special Publication 800-63B Digital Authentication Guideline.
Passwords must be protected with an iterated HMAC, not a single hash. For more information on passwords see Toward Better Password Requirements by Jim Fenton, see slide 23 in particular. This seems to be at odds with the Pluralsight training, best practices have changes over time.

How to protect against Replay Attacks

I am trying to figure out a way to implement decent crypto on a micro-controller project. I have an ARMv4 based MCU that will control my garage door and receive commands over a WiFi module.
The MCU will run a TCP/IP server, that will listen for commands from Android clients that can connect from anywhere on the Internet, which is why I need to implement crypto.
I understand how to use AES with shared secret key to properly encrypt traffic, but I am finding it difficult to deal with Replay Attacks. All solutions I see so far have serious drawbacks.
There are two fundamental problems which prevent me from using well
established methods like session tokens, timestamps or nonces:
The MCU has no reliable source of entropy, so I can't generate
quality random numbers.
The attacker can reset the MCU by cutting power to the garage,
thus erasing any stored state at will, and resetting time counter to
zero (or just wait 49 days until it loops).
With these restrictions in mind, I can see only one approach that seems
ok to me (i.e. I don't see how to break it yet). Unfortunately, this
requires non-volatile storage, which means writing to external flash,
which introduces some serious complexity due to a variety of technical details.
I would love to get some feedback on the following solution. Even better, is there a solution I am missing that does not require non-volatile storage?
Please note that the primary purpose of this project is education. I realize that I could simplify this problem by setting up a secure relay inside my firewall, and let that handle Internet traffic, instead of exposing the MCU directly. But what would be the fun in that? ;)
= Proposed Solution =
A pair of shared AES keys will be used. One key to turn a Nonce into an IV for the CBC stage, and another for encrypting the messages themselves:
Shared message Key
Shared IV_Key
Here's a picture of what I am doing:
https://www.youtube.com/watch?v=JNsUrOVQKpE#t=10m11s
1) Android takes current time in milliseconds (Ti) (64-bit long) and
uses it as a nonce input into the CBC stage to encrypt the command:
a) IV(i) = AES_ECB(IV_Key, Ti)
b) Ci = AES_CBC(Key, IV(i), COMMAND)
2) Android utilizes /dev/random to generate the IV_Response that the
MCU will use to answer current request.
3) Android sends [<Ti, IV_Response, Ci>, <== HMAC(K)]
4) MCU receives and verifies integrity using HMAC, so attacker can't
modify plain text Ti.
5) MCU checks that Ti > T(i-1) stored in flash. This ensures that
recorded messages can't be replayed.
6) MCU calculates IV(i) = AES_ECB(IV_Key, Ti) and decrypts Ci.
7) MCU responds using AES_CBC(Key, IV_Response, RESPONSE)
8) MCU stores Ti in external flash memory.
Does this work? Is there a simpler approach?
EDIT: It was already shown in comments that this approach is vulnerable to a Delayed Playback Attack. If the attacker records and blocks messages from reaching the MCU, then the messages can be played back at any later time and still be considered valid, so this algorithm is no good.
As suggested by #owlstead, a challenge/response system is likely required. Unless I can find a way around that, I think I need to do the following:
Port or implement a decent PRGA. (Any recommendations?)
Pre-compute a lot of random seed values for the PRGA. A new seed will be used for every MCU restart. Assuming 128-bit seeds, 16K of storage buys be a 1000 unique seeds, so the values won't loop until the MCU successfully uses at least one PRGA output value and restarts a 1000 times. That doesn't seem too bad.
Use the output of PRGA to generate the challenges.
Does that sound about right?
Having an IV_KEY is unnecessary. IVs (and similar constructs, such as salts) do not need to be encrypted, and if you look at image you linked to in the youtube video you'll see their description of the payload includes the IV in plaintext. They are used so that the same plaintext does not encode to the same ciphertext under the same key every time, which presents information to an attacker. The protection against the IV being altered is the HMAC on the message, not the encryption. As such, you can remove that requirement. EDIT: This paragraph is incorrect, see discussion below. As noted though, your approach described above will work fine.
Your system does have a flaw though, namely the IV_Response. I assume, from that you include it in your system, that it serves some purpose. However, because it is not in any way encoded, it allows an attacker to respond affirmatively to a device's request without the MCU receiving it. Let's say that your device's were instructing an MCU that was running a small robot to throw a ball. Your commands might look like.
1) Move to loc (x,y).
2) Lower anchor to secure bot table.
3) Throw ball
Our attacker can allow messages 1 and 3 to pass as expected, and block 2 from getting to the MCU while still responding affirmatively, causing our bot to be damaged when it tosses the ball without being anchored. This does have an imperfect solution. Append the response (which should fit into a single block) to the command so that it is encrypted as well, and have the MCU respond with AES_ECB(Key, Response), which the device will verify. As such, the attacker will not be able to forge (feasibly) a valid response. Note that as you consider /dev/random untrustworthy this could provide an attacker with plaintext-ciphertext pairs, which can be used for linear cryptanalysis of the key provided an attacker has a large set of pairs to work with. As such, you'll need to change the key with some regularity.
Other than that, your approach looks good. Just remember it is crucial that you use the stored Ti to protect against the replay attack, and not the MCU's clock. Otherwise you run into synchronization problems.

Password security

Currently I am using a particular scheme for securing passwords, and I think I have some points for improvement. The implementation is in Java, so I prefer to use SHA-2 512 as encryption form.
Currently I have a client-server model, so these things can happen:
Client wants to login, he sends his password with one time normal SHA-2 512 encryption over the network.
The server has the passwords stored in the database as for example SHA-2_512(SHA-2_512(password) + salt), with the inner SHA-2_512(password) being the 'encrypted' password it receives over the network.
Password checks are done server side and there is no way anything can leak out from the server, the only possible vulnerability would be if someone could read out the RAM I think.
I have these questions:
An attacker usually creates collision attacks when wanting to hack a password. However how are collision attacks sufficient? If the password needs to be used for other applications like Outlook.com, Facebook or whatever (which likely use another salt as they have nothing to do with my applications), how is a collision attack enough then? Don't you need the real password?
Does SHA-2 512 already use iteration? And even if so, should I change my encryption methods to automatically use a number of iterations plus how many iterations is preferred? I have also read about using a random number of iterations (in a range), how do I store the random factor determenistically?
Should I store system secrets for every iteration in the server code? See http://blog.mozilla.org/webappsec/2011/05/10/sha-512-w-per-user-salts-is-not-enough/ . I could store an array which would hold a static secret for every iteration, with the nth secret being for the nth iteration. Nobody can know the secrets, they are computed once (I guess as encrypting some random string), and then basically stored in the Server's RAM.
Currently I send the typed password from the client to the server as just SHA-2_512(password), should this process be improved, and if so, how? I cannot use salts, because the client does not have the salt available.
Regards.
TLDR: You need to send the password using an encrypted channel, such as TLS. Consider using bcrypt for password hashing.
SHA-2 512 is not an encryption algortihm, it is a message digest algorithm. An encryption algorithm requires a key and a message to encrypt. It produces ciphertext. The important thing is that an encryption algorithm has a decryption algorithm.
ciphertext = E(key, plaintext);
plaintext = D(key, ciphertext);
A message digest takes a piece of plaintext and produces a message digest. There is no corresponding reverse mechanism to take a message digest and retrieve the original message. There is also no secret key.
digest = hash(plaintext);
If an attacker is able to access a database with hashes, the attacker can retrieve the original password by brute forcing, trying lots of guesses with the hash algorithm.
digest1 = hash(guess1);
digest2 = hash(guess2); //repeat with lots of guesses
Firstly, sending a hash over a network is not secure. It needs to be sent through some secure communications mechanism such as SSL. If an attacker can intercept the hash over the communications they may be able to work out the orignal password.
A hash collision is not the same as brute forcing the password. A hash collision is caused when two different messages produce the same message digest.
digest1 = hash(plaintext1);
digest2 = hash(plaintext2);
if ( ( plaintext1 != plaintext2 ) && ( digest1 == digest2 ) )
// hash collision
SHA-512 does not have iterations designed to prevent brute-forcing. The SHA set of algorithms are designed to be efficient. The reason for adding iterations when hashing passwords is to increase the time it takes to brute force a password. The idea being the cost to perform a legitimate login attempt and perform 100 iterations is tiny compared to an attacker who has millions of passwords, each of which requires 100 iterations. Adding more iterations helps reduce the impact of improved processor speeds (which would help an attacker try more iterations quicker).
You should make the number of iterations a configurable limit that is stored against each user. So you store the password hash, salt and iteration count for each user. This means that in the future you can increase the number of iterations to take into account increased hardware power.
Sending the SHA-2 512 in plaintext is not secure. You should send it within an encrypted channel, such as SSL.
Having said all that, SHA-2 is not designed to be a password hashing algorithm. It is designed for message validation and is to be efficient. Consider using a purpose built password hashing algorithm. One example is bcrypt. It is designed to be computationally difficult and has salt and iterations built in.

WPA2 - EAPOL password exchange

(I'm doing this on my network, just for science). I was using airodump-ng to capture handshake. After that, I was able to open file with captured information in WireShark and find part with 4 handshake messages of EAPOL protocol. I know about millions of years needed for brute-force and I know that I can use aircrack-ng for dictionary attack.
I would like to extract just password from those 4 messages. I assume it is transfered as some sort of salted hash value. What I don't know is, in which message password resides (wireless password, for connection) and how exactly is sent? For example SHA1 of "password"+"ssid"... I would like to be able to compute exact same hash in my program (of course, that would be possible only for my network because I know my password). I'm gonna need that also for some demonstration on university.
Thanks!
The 802.11i "4 way handshake" that you have captured is where both parties agree on shared Group (read: broadcast) and Pairwise (read: unicast) transient keys. I.e. the keys generated here only exist for the duration of the 802.11 Association, or until the next rekey is issued from the AP.
Before you can even begin to decrypt the 4 way handshake messages you need the pairwise master key (PMK), which is what gets derived from the user-entered passphrase using a key derivation function (PBKDF2), or is the result of a WPS exchange which is based on Diffie-Hellman.
The point here is the ASCII passphrase you are seeking to extract is not exchanged in any of the 4 messages, as it has already been shared amongst all parties involved in the transaction (client and AP in this case) and used to generate a 256 bit PMK. And unless you have this PMK, the contents of the 4 way handshake messages are as good as random data.
The best that you can do, if you already know the PMK, is extract the GTK and PTK from M2 and M3 of the 4 way handshake, and from those pull the temporal key which can be XORed with the payload in subsequent frames to get the plaintext data - which wireshark will also do for you if you enter the PMK or passphrase into the IEE802.11 settings and enable decryption.

Avoid that repeated same messages look always same after encryption, and can be replayed by an attacker?

I'm looking to authenticate that a particular message is coming from a particular place.
Example: A repeatedly sends the same message to B. Lets say this message is "helloworld" which is encrypted to "asdfqwerty".
How can I ensure that a third party C doesn't learn that B always receives this same encrypted string, and C starts sending "asdfqwerty" to B?
How can I ensure that when B decrypts "asdfqwerty" to "helloworld", it is always receiving this "helloworld" from A?
Thanks for any help.
For the former, you want to use a Mode of Operation for your symmetric cipher that uses an Initialization Vector. The IV ensures that every encrypted message is different, even if it contains the same plaintext.
For the latter, you want to sign your message using the private key of A(lice). If B(ob) has the public key of Alice, he can then verify she really created the message.
Finally, beware of replay attacks, where C(harlie) records a valid message from Alice, and later replays it to Bob. To avoid this, add a nonce and/or a timestamp to your encrypted message (yes, you could make the IV play double-duty as a nonce).
Add random value to the data being encrypted, and whenever it's decrypted, strip it from the original unencrypted data.
You need decent random number generator. I'm sure Google will help you on that.
C noticing that B receives twice the same encrypted message is an issue called traffic analysis and has historically been a heavy concern (but this was in times which predated public key encryption).
Any decent public encryption system includes some random padding. For instance, for RSA as described in PKCS#1, the encrypted message (of length at most 117 bytes for a 1024-bit RSA key) gets a header with at least eight random (non-zero) bytes, and a few extra data which allows the receiver to unambiguously locate the padding bytes, and see where the "real" data begins. The random bytes will be generated anew every time; hence, if A sends twice the same message to B, the encrypted messages will be different, but B will recover the original message twice.
Random padding is required for public key encryption precisely because the public key is public: if encryption was deterministic, then an attacker could "try" potential messages and look for a match (this is exhaustive search on possible messages).
Public key encryption algorithms often have heavy limitations on data size or performance (e.g. with RSA, you have a strict maximum message length, depending on the key size). Thus, it is customary to use a hybrid system: the public key encryption is used to encrypt a symmetric key K (i.e. a bunch of random bytes), and K is used to symmetrically encrypt the data (symmetric encryption is fast and does not have constraints on input message size). In a hybrid system, you generate a new K for every message, so this also gives you the randomness you need to avoid the issue of encrypting several times the same message with a given public key: at the public encryption level, you are actually never encrypting twice the same message (the same key K), even if the data which is symmetrically encrypted with K is the same than in a previous message. This would protect you from traffic analysis even if the public key encryption itself did not include random padding.
When symmetrically encrypting data with a key K, the symmetric encryption should use an "initial value" (IV) which is randomly and uniformly generated; this is integrated in the encryption mode (some modes only need a non-repeating IV without requiring a random uniform generation, but CBC needs random uniform generation). This is a third level of randomness, protecting you against traffic analysis.
When using asymmetric key agreement (static Diffie-Hellman), since are a bit more complex, because a key agreement results in a key K which you do not choose, and which could be the same ever and ever (between given sender and receiver). In that situation, protection against traffic analysis relies on the symmetric encryption IV randomness.
Asymmetric encryption protocols, such as OpenPGP, describe how the symmetric encryption, public key encryption and randomness should all be linked together, ironing out the tricky details. You are warmly encouraged not to reinvent your own protocol: it is difficult to design a secure protocol, mostly because one cannot easily test for the presence or absence of any weakness.
You may want to study block cipher modes of operation. However, the modes are designed to work on a data stream that is sent over a reliable channel. If your messages are sent out of order over an unreliable transport (e.g. UDP packets), I don't think you can use it.

Resources