What is the minimum size a message should be in order to remain secure when sent over SSL/HTTPS? My understanding is that having a very small message can make cracking it easier because there are fewer possible values the initial payload could have, making it possible to just brute force encrypt them all and check the result of each.
My guess is it would be about the size of the key used to encrypt it, so if my site is protected with 256-bit SSL, what is the minimum size of payload I should send, even if I just fill it with random data?
SSL messages get filled with random data anyway in most if not all cipher suites anyway. If you send one byte over SSL it becomes about 43 bytes on the wire due to padding, MACs, headers, and whatever else, depending again on the cipher suite.
Related
When receiving the credentials for a new device as described in http://cumulocity.com/guides/reference/device-credentials/ we also get the new password, that the cumulocity server has generated for the device.
We would assume that this password contains only printable characters, even though that might not be a general requirement, if seen from a machine2machine point of view.
Is that assummption correct?
If not, are there some characters that we can be sure will never appear in those passwords?
Background: we want to encrypt this password and need to chose a padding strategy. It would be easy, if we knew which bytes are safe to use, because they cannot be part of any of the generated passwords.
PKCS#7 padding is safe because the padding bytes are the length of padding.
Note that padding must be applied to every encryption so the padding length is always present. That means that if the data to be encrypted is a block size multiple an entire block of padding myst be added.
But since the application is not fully provided there may be better ways of handling the encryption. One assumption is that HTTPS can not be used for the transport because if it was that would provide the necessary transport security.
There is also how the encryption is done, it is not easy to get security correct.
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.
used java code to request a https site, do tcpdump and find "Client Key Exchange, Change Cipher Spec, Encrypted Handshake Message" will be set to two records:
1. Client Key Exchange
2. Change Cipher Spec, Encrypted Handshake Message
how to combined these three Handshake messages to a record in java?
Why do you care how those are put on the wire? Are you trying to save just a few bytes or have a legitimate real reason for that?
I don't know the specifics of Java's implementation and whether you can influence it through config/params, but from the TLS protocol perspective, it doesn't make any difference how you send handshake messages on the wire. In the case of separate records, you just send some extra bytes, that's all.
Furthermore, for those three in particular, they cannot be combined in a single record and there is a reason for that. The ClientKeyExchange is a plaintext message, so it goes into a record. The ChangeCipherSpec is not a handshake message, rather a record type, therefore it cannot go into the same record as the CKE. Since CCS is a record type on its own, you need to follow it with another handshake message wrapped into a record, therefore you see 3 separate records. Also, the Finished message is encrypted, so you need to add a MAC at the record layer, and cannot be combined with plaintext handshake messages into the same record.
I hope this clears it up a bit.
I have a small confusion on SSL handshake between browser and server in a typical https web scenario:
What I have understood so far is that in the process of SSL handshake, client (browser in this case) encrypts a randomly selected symmetric key with the public key (certificate received from server). This is sent back to the server, server decrypts it (symmetric key) with the private key. This symmetric key is now used during rest of the session to encrypt/decrypt the messages at both the ends. One of main reasons to do so is given as faster encryption using symmetric keys.
Questions
1) How does browser pick and generates this "randomly" selected symmetric key?
2) Do developers (or/and browser users) have control on this mechanism of generating symmetric keys?
Here is a very good description of how HTTPS connection establishment works. I will provide summary how session key is acquired by both parties (client and server), this process is known as "a key agreement protocol", here how it works:
The client generates the 48 byte “pre-master secret” random value.
The client pads these bytes with random data to make the input equal to 128 bytes.
The client encrypts it with server's public key and sends it to the server.
Then master key is produced by both parties in following manner:
master_secret = PRF(
pre_master_secret,
"master secret",
ClientHello.random + ServerHello.random
)
The PRF is the “Pseudo-Random Function” that’s also defined in the
spec and is quite clever. It combines the secret, the ASCII label, and
the seed data we give it by using the keyed-Hash Message
Authentication Code (HMAC) versions of both MD5 and SHA-1 hash
functions. Half of the input is sent to each hash function. It’s
clever because it is quite resistant to attack, even in the face of
weaknesses in MD5 and SHA-1. This process can feedback on itself and
iterate forever to generate as many bytes as we need.
Following this procedure, we obtain a 48 byte “master secret”.
Quoting from a this great video on network video, minute 1:18:07
Well where do you get randomness on your computer because your
computer is a deterministic device?
Well it collects entropies like your mouse stroke movements, your key
stroke movements and the timing of your hard disk, it tries to collect
all that randomness from the universe into a pull so that it can generate random keys just for one connection [this session]. And if that randomness is broken and its happened many times
in the last 30 years, then none of this works. If the adversary can
figure what your randomness can be then they can guess your keys. So use good randomness.
Note: the keys are created per session.
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.