I'm a little bit confused how to use AES and HMAC (based on SHA-256) in a proper way when transmitting the encrypted message from server to client or vice versa
Correct me please if the following method is wrong:
Take the secure key from the key file (for example we suggest to use the AES-256 and we already have a valid 256 bit length key)
Generate random IV for AES-256 to be sure that the same plain text will have different encryption output.
Calculate HMAC-SHA-256 using the plain text and secure key. (The first question: should I use IV for HMAC calculation? For example append to secure key?)
Encrypt the plain text using AES-256.
Compose message for client as following: HMAC + IV+ ENCRYPTED_MESSAGE
The biggest question is: is it possible somehow not to send IV to client but instead generate it the same way and still be crypto safe? Or is it ok to send the IV too?
I've end up with random IV generation, because it is needed that the same plain text will end up in different encryption results.
Don't send hmac(message),aes(message). If you send the same message twice, anyone can tell. Moreover, you need to mac the cipher-text to prevent attacks such as the padding oracle attack.
IV: In general, the easy way to deal with the iv is to prepend it, since it's fixed length, to the cipher text.You can then just read off those bytes before decrypting. IV's can be public, but they must be random.
HMAC: Easiest way, if your library supports it, is to use AES in GCM mode (or, less preferably EAX). This is not actually an HMAC, but it provides authenticated encryption which is just as good.If these are not supported :
You do need to compute the hmac over both the iv and the cipher text. if || is concatenation ( which you could do with say array copy if dealing with byte arrays) then you want
CipherText = iv|| aes(key1,iv,message)
tag = hmac(key2,ciphertext)
And then send (tag,CipherText). On the other end, you run the same hmac call to regenerate the tag and the compare the received tag with the computed one. Compare the sha1 or sha256 hashes of the tags instead of directly so you don't leak where the comparison fails.
You should use a different key for the hmac. In practice tacking the sha1 sum of your encryption key is good enough.
Related
I have a word and i guess its encrypted with rot18. (Im not sure which encrypting method used). Im trying to decrypt this word with online decrypters but i couldnt get a string. after decryption, i got another word like encrypted with rot18 again.
by the way i dont know my word's encryption key to decrypt it directly.
my question is which encrypting method used? and how can i decrypt it to a string?
this is my key to decode --> Iuhzhuuhidez98735
result after decoding process --> 5h4m4hh4501m98735
I'm writing that generates public and private key pair, then send the public key over the socket to another programs to be used to encrypt string data.
I'm using RSA in VB.NET and I was able to generate the required keys:
My public key v+u4Lt4nyLXincU+wbReOTU3nwiTZ7MlFkA7cytLOjuviHrAdnaVAV8+WoFhy9nADGtk1K0OLAE1ZwGzt/kgUw==
My question is: is the public key enough for encryption by other users? and if so, how can I import it to RSA parameters to encrypt data?
Edit:
I used the following code in an attempt to import the public key but it failed:
Dim Parameters As New RSAParameters
Parameters.Modulus = encoder.GetBytes(publicKey)
RSA.ImportParameters(Parameters)
My question is: is the public key enough for encryption by other
users?
The answer is as so often: It depends.
The way you describe your proposed protocol this would be widely open to man-in-the-middle-attacks. Eve could just intercept the message on the wire and replace the key by her own.
From a theoretical point of view, it is sufficient to encrypt data. However, to be useful in real world scenarios, you have to use symmetric encryption as well.
So here is my advice:
Don't do your own protocols if you have to ask such questions. Never. Not once. Use Well known, established technology like TLS!
I had a similar project in VB.net, you will not be able to send messages of a large length because if you are using 2048bit RSA, the maximum size of data you would be able to send would be 245 bytes. https://security.stackexchange.com/questions/33434/rsa-maximum-bytes-to-encrypt-comparison-to-aes-in-terms-of-security
I used the RSA public key so each client would use AES encryption and pass their own keys which are encrypted with RSA, the server would then decrypt the key and use that to resolve data. This uses both asymmetric(RSA) and symmetric encryption(AES). Here is a link with a useful video that explains this when I was doing this project. https://www.youtube.com/watch?v=6H_9l9N3IXU&t=271s
The way I imported the keys was using the .toXMLString and .fromXMLString in the RSA CryptoServiceProvider. Here is a great link explaining it, probably doing a better job that I could. https://msdn.microsoft.com/en-us/library/system.security.cryptography.rsa.toxmlstring(v=vs.110).aspx
I found this page that was very useful for me here
Also I found that I was making the mistake of converting the encrypted byte array to string after encryption then back to byte array just before decryption. The last byte array didn't have the same size as the original.
My goal is a lightweight kind of message signing, comparable to PGP, except there is only a need for one private-key, no public-key associate. The goal is merely to prevent tampering of a string between two trusted entities. It starts from a trusted source, goes over the internet, then arrives at another trusted destination.
I would like to know if my naive approach is secure. In that the signing algorithm would not be practically brute forced.
1) Both source and destination have a "private key" which is just a very random number generated by uuidgen.
2) Source has a string it intends to send to destination.
3) Source concatenates the payload string with the private key, and then sha1's the result, to produce a signature.
4) The resulting plain-text value + signature are sent to destination in a pair. "hello//SIG:12345ABCDEFG"
5) Desination receives the signed-variable, generates a signature with its known private-key, and compares agains the signature paired with the received data. If they match, it is accepted.
A variation of this will incorporate a unix timestamp rounded to the hour, making the signature expire.
My concern is if it would be feasible to bruteforce the private key given a selective set of data payloads and analyzing the resulting signatures with this approach.
Thanks
It seems like what you want to achieve is very similar to an HMAC (article on Wikipedia).
For an HMAC, you perform some additional steps to combine message and secret key into a hash. This makes the resulting hash harder to attack than one which results from simply concatenating original message and secret key and hashing that.
If you want to use cryptographic standards as much as possible (which - in my opinion - is almost always a good thing), I would look into doing it the way the HMAC definition prescribes. To make the signature expire, I would simply attach the expiration date to the message and then build the HMAC of that combined string.
In theory, let's say I'm using a commutative symmetrical cipher to create my own kind of encrypted file. I know that an encrypted rar/zip would do what I'm thinking of, but I'm looking to understand the under the hood details. If I just encrypt the file with no meta data, then how can I know when I decrypt it that it's properly decrypted?
One approach I thought of was to place the key used at the front of the file and then encrypt the key along with the file. When I decrypt, I can compare the decryption key with the beginning of the file and know if it worked, but I'm uncomfortable with actually placing the key inside the file.
Another idea would be placing a static section of data at the beginning of the file, but that can be used as an indicator when trying to brute force the file to when a collision in keys (or the actual key) is discovered if anybody knows the static section of data and I don't like security through obscurity.
My last thought is to include the hash of the initial unencrypted file, but for large files that can slow down the process. With this approach, I have to hash and encrypt the file and that seems inefficient. I'm hoping there's a better technique.
What would be the best approach to verify that an file that was encrypted with a commutative symmetrical cipher was decrypted successfully (without having the original file to compare to)?
Use a header with a well defined, but random format. One standard way to do this is with random data and cryptographic hashes (pseudo-code follows):
byte[] header = new byte[64];
header[0..31] = RandomBytes(32); // 32 cryptographically random bytes
header[32..63] = SHA256(header[0..31]); //Hash of your random data
This gives 64 bytes of high entropy data. There is no way this can be used crib for brute-forcing the encryption. To validate you have the proper key, just decrypt the header and check to make sure that the second 32 bytes are a valid SHA256 hash of the first.
I would still recommend storing a hash or checksum. If you put it at the end of the encrypted data, you can generate the checksum as you read the file during the encryption, so it doesn't require any extra passes through the file. (There will be CPU overhead for the checksum, but that'll be minimal. You don't need to use something as expensive as SHA for this purpose; CRC32 will do.)
The checksum will help detect errors in transit. If a single bit in the encrypted data is altered, the decrypted data past that point will probably be garbage. A magic header won't detect that, but a checksum will.
There are cipher modes like CCM that provide integrity. I'm not sure how they would fit with your requirement for commutativity.
I am implementing a simple license-file system, and would like to know if there are any mistakes I'm making with my current line of implementation.
The message data is smaller than the key. I'm using RSA, with a keysize of 3072bits.
The issuer of the licenses generates the message to be signed, and signs it, using a straightforwards RSA-based approach, and then applies a similar approach to encrypt the message. The encrypted message and the signature are stored together as the License file.
Sha512 the message.
Sign the hash with the private key.
Sign the message with the private key.
Concatenate and transmit.
On receipt, the verification process is:
Decrypt the message with the public key
Hash the message
Decrypt the hash from the file with the public key, and compare with the local hash.
The implementation is working correctly so far, and appears to be valid.
I'm currently zero-padding the message to match the keysize, which is probably
a bad move (I presume I should be using a PKCS padding algorithm, like 1 or 1.5?)
Does this strategy seem valid?
Are there any obvious flaws, or perspectives I'm overlooking?
The major flaw I noticed: you must verify the padding is still there when you decrypt.
(If you know the message length in advance then you might be able to get away with using your own padding scheme, but it would probably still be a good idea to use an existing one as you mentioned).
I am not sure why you're bothering to encrypt the message itself - as you've noted it can be decrypted by anyone with the public key anyway so it is not adding anything other than obfuscation. You might as well just send the message and the encrypted-padded-hash.
I would recommend using a high level library that provides a "sign message" function, like cryptlib or KeyCzar(if you can). These benefit from a lot more eyeballs than your code is likely to see, and take care of all the niggly padding issues and similar.