I'm planning to use the crypto_box() functions of Nacl to encrypt messages as part of a client/server protocol. The server has to deal with multiple clients and each message from a client to the server is encrypted using the public key of the server and signed with the private key of the client.
The cypto_box() functions also require me to provide a nonce. The current message number could be used as a nonceāto my understanding, the nonce is necessarily known to an attacker who is capable of keeping track of how many messages were exchanged. Both, the client and server would then maintain a message counter and simply use the newest counter value as a nonce.
However, I must deal with the case where messages are reordered or lost. Therefore I'd send the nonce in plaintext alongside the encrypted message. As long as the same nonce is not used twice, I don't see any problems with this approach. Did I miss out on something?
No, nonce's and IV's may be considered public knowledge. I've just checked the NaCl site and I don't see any explicit remarks that contradict this.
CBC mode of operation has some additional requirements for the IV (non-predictability) but that's of course not an issue in NaCl.
You should make sure that you don't accept any nonces <= the last received nonce though, otherwise an attacker could probably resend or reorder messages.
Related
Let's say we have a client that uses asymmetric cryptography to communicate with a server. This could be SSL or just a custom encryption.
Now if we assume that the client's source code is easy to disassemble, can we extract the public key and hence send bogus messages to the server?
Anyway to avoid this? Consider that it is really hard to keep the client's source code safe.
I have been trying to find out exactly how SSL works, and have found descriptions of the packet sequence that starts the conversation, but not how requests are processed. Here is a link to an example showing the initial handshake:
https://www.eventhelix.com/RealtimeMantra/Networking/SSL.pdf
Once communication is established, both sides are sharing a private session key which is updated every so often. I would like to know details on:
I assume that an attacker cannot just replicate an observed packet and execute it multiple times? This is a so-called replay attack.
How is encryption done using AES-256? If both sides simply applied the algorithm, then a replay attack would work. So I assume there is some kind of chaining so that each packet uses different encryption.
The session key switches every interval (like once every 30 or 60 minutes. How does this exchange work? What messages are exchanged, and what happens if a method is sent before the exchange that arrives after the switch?
The underlying mechanism most recently is TLS 1.2. Is this the same for SSL and SSH, or are the two protocols different?
An explanation is always good but a link to relevant documentation would also be extremely helpful. If these interlocking parts are too much, I can split out into a separate question, but there is a lot of overlapping information in the above sections.
I assume that an attacker cannot just replicate an observed packet and execute it multiple times? This is a so-called replay attack.
Correct. TLS is immune from replay attacks.
How is encryption done using AES-256? If both sides simply applied the algorithm, then a replay attack would work. So I assume there is some kind of chaining so that each packet uses different encryption.
There is chaining, and sequence numbers, and also a MAC for each message.
The session key switches every interval (like once every 30 or 60 minutes. How does this exchange work? What messages are exchanged
Another ClientHello with the same sessionID, and an 'abbreviated handshake' after that, that changes the session key. Details in RFC 2246.
and what happens if a method is sent before the exchange that arrives after the switch?
The switch is by mutual agreement, and any message that arrives before the same sender's ChangeCipherSpec message is decrypted under the old parameters.
The underlying mechanism most recently is TLS 1.2. Is this the same for SSL and SSH, or are the two protocols different?
They are different.
For a personal MMO game project I am implementing a homebrew reliable UDP-based protocol in java. Given my current setup I beleive it would be relatively simple for a snooper to hijack a session, so in order to prevent this I am taking the opportunity to learn a little cryptology. Its very interesting.
I can successfully create a shared secret key between the client and server using a Diffie-Hellman key exchange (a very clever concept), but now I need to use this to guarantee the authenticity of the packets. My preliminary testing so far has shown that the couple of different ciphers Ive tried bloat the amount of data a bit, but I would like to keep things as small and fast as possible.
Given that I am only trying to authenticate the packet and not nessecarily conceal the entire payload, I have the idea that I could put an 8 byte session ID generated from the secret key into the packet header, encrypt the whole packet, and hash it back down to 8 bytes. I take the unencrypted packet and put the 8 byte hash into the place of the session ID and then send it off.
Would this be secure? It feels a little inelegant to encrypt the whole packet only to send it unencrypted - is there a better/faster way to achieve my goal? Please note I would like to do this myself since its good experience so Im not so interested in 3rd party libraries or other protocol options.
If both peers have access to a shared secret (which they should, since you're talking about Diffie-Hellman), you could simply store a hash of the datagram in its header. The receiver checks to see if it matches.
As an added security measure, you could also add a "challenge" field to your datagram and use it somewhere in the hashing process to prevent replays.
So this hash should cover:
The shared secret
A challenge
The contents of the datagram
EDIT
The "challenge" is a strictly incrementing number. You add it to your datagram simply to change the hash every time you send a new message. If someone intercepts a message, it cannot resend it: the receiver makes sure it doesn't accept it.
I need to implement a very secured Web Service using WCF. I have read a lot of documents about security in WCF concerning authorization, authentication, message encryption. The web service will use https, Windows Authentication for access to the WS, SQL Server Membership/Role Provider for user authentication and authorization on WS operations and finally message encryption.
I read in one of documents that it is good to consider security on each layer indenpendently, i.e. Transport Layer security must be thought without considering Message Layer. Therefore, using SSL through https in combination with message encryption (using public/private key encryption and signature) would be a good practice, since https concerns Transport Layer and message encryption concerns Message Layer.
But a friend told me that [https + message encryption] is too much; https is sufficient.
What do you think?
Thanks.
If you have SSL then you still need to encrypt your messages if you don't really trust the server which stores them (it could have its files stolen), so this is all good practice.
There comes a point where you have a weakest link problem.
What is your weakest link?
Example: I spend $100,000,000 defending an airport from terrorists, so they go after a train station instead. Money and effort both wasted.
Ask yourself what the threat model is and design your security for that. TLS is a bare minimum for any Internet-based communications, but it doesn't matter if somebody can install a keystroke logger.
As you certainly understand, the role of Transport-Level Security is to secure the transmission of the message, whereas Message-Level Security is about securing the message itself.
It all depends on the attack vectors (or more generally the purpose) you're considering.
In both cases, the security models involved can have to purposes: protection against eavesdropping (relying on encryption) and integrity protection (ultimately relying on signatures, since based on public-key cryptography in most cases).
TLS with server-certificate only will provide you with the security of the transport, and the client will know that the communication really comes from the server it expects (if configured properly, of course). In addition, if you use client-certificate, this will also guarantee the server that the communication comes from a client that has the private key for this client certificate.
However, when the data is no longer in transit, you rely on the security of the machine where it's used and stored. You might no longer be able to assert with certainty where the data came from, for example.
Message-level security doesn't rely on how the communication was made. Message-level signature allows you to know where the messages came from at a later date, independently of how they've been transferred. This can be useful for audit purposes. Message-level encryption would also reduce the risks of someone getting hold of the data if it's stored somewhere where some data could be taken (e.g. some intranet storage systems).
Basically, if the private key used to decrypt the messages has the same protection as the private key used for SSL authentication, and if the messages are not stored for longer time than the connection, in that case it is certainly overkill.
OTOH, if you've got different servers, or if the key is stored e.g. using hardware security of sorts, or is only made available by user input, then it is good advice to secure the messages themselves as well. Application level security also makes sense for auditing purposes and against configuration mistakes, although personally I think signing the data (integrity protection) is more important in this respect.
Of course, the question can also become: if you're already using a web-service that uses SOAP/WSDL, why not use XML encrypt/sign? It's not that hard to configure. Note that it does certainly take more processor time and memory. Oh, one warning: don't even try it if the other side does not know what they are doing - you'll spend ages explaining it and even then you run into trouble if you want to change a single parameter later on.
Final hint: use standards and standardized software or you'll certainly run into crap. Spend some time getting getting to know how things work, and make sure you don't accept ill formatted messages when you call verify (e.g. XML signing the wrong node or accepting MD5 and such things).
I want to secure the communication of a TCP-based program using a shared passphrase/key. The easiest way to do that without having to deal with block size, padding, ... is to directly use a stream cipher. Doing that way, the amount of data is not changed between clear and encrypted data and the modification is trivial.
Using only a stream cipher means that there is no authentication and I have always considered/heard that encryption without authentication is not secure enough and should not be used.
If adding authentication to a stream cipher is mandatory, we lose the simplicity that stream cipher has added because we must add an HMAC or use an authenticated encryption method (like crypto_secretbox from NaCl), there is a minimum message length, we must handle padding, ...
What would you recommend? Is it safe to only use stream cipher without authentication in some particular cases?
Using some kind of message authenticator is particularly important with stream ciphers, because the relationship between changes to the ciphertext and changes to the plaintext is so simple.
You can't just blindly go and apply the stream cipher without adding any extra information to the stream, anyway - remember the most important rule of stream ciphers:
NEVER RE-USE THE SAME KEYSTREAM
So unless you are only ever going to encrypt a single connection, and throw the passphrase away afterwards, you will need to generate a session key for each connection from the shared secret. This implies that you will need to send some extra information at the start of the connection, and since you're sending that anyway, sending a HMAC after each message should be no big deal.
Using a stream cipher because it seems simpler is usually a mistake, anyway. You mentioned crypto_secretbox from NaCl - I recommend using that, it will take care of the authentication and padding issues for you.
You could consider using AES in GCM-mode. That will give you a stream-cipher with built-in authentication.