I was reading about the implementation of AES GCM with CryptoSwift and it states that GCM is not reusable and you have to create an instance for every encrypt decrypt session. Doesn't this beat the purpose of having an AES key for both side of encryption and decryption? Im sure there is a part that my knowledge is too little to understand, so if someone could explain this to me that would be great.
This is the link: CryptoSwift GCM implementation
No, the AES key can be reused, you just need to re-create the instances, so you'll have to perform:
let gcm = GCM(iv: iv, mode: .combined)
let aes = try AES(key: key, blockMode: gcm, padding: .noPadding)
for both encryption and decryption (in separate functions, of course).
This is usually because the iv and inner state of these instances are changed during encryption / decryption. Otherwise the instances need to keep the IV and other parameters in memory so they can be reset to their initial state. Usually encrypt and decrypt functions are called in separate parts of the code anyway; to encrypt and then to immediately decrypt only makes sense during testing.
Ciphers are lightweight objects; it doesn't make much sense to reuse them - most of the complex stuff happens when processing the data. Instead we can just reuse the key.
Related
Recently I am trying to design a custom protocol for IoT devices with Python Twisted. Since most of the IoT devices (end node) are not powerful enough to support TLS, I have to implement a modified light weight transport security. However AES128/256 is used for data encryption as same as standrad TLS.
It is well known that TCP is a stream, and delivered messages may need delimiter in the TCP stream. In text oriented message like HTTP/FTP, \n\r is used. In binary message, we should define our own structure such as TLV and V stands for payload data. That can be implemented by Netty in Java, Twisted in Python.
When TCP is encrypted, things become complicated. In theory, plain text should be encrypted with AES, then carried on TCP stream. It is easy for text message, but in binary message, Type/Length fields are encrypted as well. Furthermore, AES is block oriented algorithm, which means a message may need next message to combile to be encrypted/decrypted. Although the AES could be transparent transport, but it is hard to implement for binary message slicing and parsing.
There is another way, we can leave TL fields in TLV as plain, while keep V encrypted by AES. But it only works for binary data. and it need padding in AES as well.
Is there any suggestions or references, including code or project ? Thanks!
AES is a block cipher, so read data in chunks of the block size. On the transmitter side, your AES encryption code should add padding as necessary, it should be part of the AES implementation. (I would recommend that you use AES-CBC for this application). On the transmitter, just read data in chunks of the block size.
In java I would use an DataInputStream from my socket, and do a readFully().
Socket socket;
DataInputStream ins = new DataInputStream(socket.getInputStream());
while(connectionOpen) {
byte[] aes = new Byte[blockSize];
ins.readFully(aes);
//Decrypt received data aes
...
}
Since you use readFully() above, you ensure you always receive data of the correct size, i.e. the block size.
I have a single-threaded client/server application that needs to do both encryption and decryption of their network communication. I plan on using OpenSSL's EVP API and AES-256-CBC.
Some sample pseudo-code I found from a few examples:
// key is 256 bits (32 bytes) when using EVP_aes_256_*()
// I think iv is the same size as the block size, 128 bits (16 bytes)...is it?
1: EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
2: EVP_CipherInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv, 1); //0=decrypt, 1=encrypt
3: EVP_CipherUpdate(ctx, outbuf, &outlen, inbuf, inlen);
4: EVP_CipherFinal_ex(ctx, outbuf + outlen, &tmplen));
5: outlen += tmplen;
6: EVP_CIPHER_CTX_cleanup(ctx);
7: EVP_CIPHER_CTX_free(ctx);
The problem is from all these examples, I'm not sure what needs to be done at every encryption/decryption, and what I should only do once on startup.
Specifically:
At line 1, do I create this EVP_CIPHER_CTX just once and keep re-using it until the application ends?
Also at line 1, can I re-use the same EVP_CIPHER_CTX for both encryption and decryption, or am I supposed to create 2 of them?
At line 2, should the IV be re-set at every packet I'm encrypting? Or do I set the IV just once, and then let it continue forever?
What if I'm encrypting UDP packets, where a packet can easily go missing or be received out-of-order: am I correct in thinking CBC wont work, or is this where I need to reset the IV at the start of every packet I send out?
Sorry for reviving an old thread, but I noticed the following error in the accepted answer:
At line 1, do I create this EVP_CIPHER_CTX just once and keep re-using it until the application ends?
You create it once per use. That is, as you need to encrypt, you use the same context. If you need to encrypt a second stream, you would use a second context. If you needed to decrypt a third stream, you would use a third context.
Also at line 1, can I re-use the same EVP_CIPHER_CTX for both encryption and decryption, or am I supposed to create 2 of them?
No, see above.
This is not necessary. From the man page for OpenSSL:
New code should use EVP_EncryptInit_ex(), EVP_EncryptFinal_ex(), EVP_DecryptInit_ex(), EVP_DecryptFinal_ex(),
EVP_CipherInit_ex() and EVP_CipherFinal_ex() because they can reuse an existing context without allocating and freeing it up on each call.
In other words, you need to re-initialize the context each time before you use it, but you can certainly use the same context over and over again without creating (allocating) a new one.
I have a single-threaded client/server application that needs to do both encryption and decryption of their network communication. I plan on using OpenSSL's EVP API and AES-256-CBC.
If you are using the SSL_* functions from libssl, then you will likely never touch the EVP_* APIs.
At line 1, do I create this EVP_CIPHER_CTX just once and keep re-using it until the application ends?
You create it once per use. That is, as you need to encrypt, you use the same context. If you need to encrypt a second stream, you would use a second context. If you needed to decrypt a third stream, you would use a third context.
Also at line 1, can I re-use the same EVP_CIPHER_CTX for both encryption and decryption, or am I supposed to create 2 of them?
No, see above.
The ciphers will have different states.
At line 2, should the IV be re-set at every packet I'm encrypting? Or do I set the IV just once, and then let it continue forever?
No. You set the IV once and then forget about it. That's part of the state the context object manages for the cipher.
What if I'm encrypting UDP packets, where a packet can easily go missing or be received out-of-order: am I correct in thinking CBC wont work...
If you are using UDP, its up to you to detect these sorts of problems. You'll probably end up reinventing TCP.
Encryption alone is usually not enough. You also need to ensure authenticity and integrity. You don't operate on data that's not authentic. That's what keeps getting SST/TLS and SSH in trouble.
For example, here's the guy who wrote the seminal paper on authenticated encryption with respect to IPSec, SSL/TLS and SSH weighing in on the Authenticate-Then-Encrypt (EtA) scheme used by SSL/TLS: Last Call: (Encrypt-then-MAC for TLS and DTLS) to Proposed Standard:
The technical results in my 2001 paper are correct but the conclusion
regarding SSL/TLS is wrong. I assumed that TLS was using fresh IVs and
that the MAC was computed on the encoded plaintext, i.e.
Encode-Mac-Encrypt while TLS is doing Mac-Encode-Encrypt which is
exactly what my theoretical example shows is insecure.
For authenticity, you should forgo CBC mode and switch to GCM mode. GCM is an authenticated encryption mode, and it combines confidentiality and authenticity into one mode so you don't have to combine primitives (like AES/CBC with an HMAC).
or is this where I need to reset the IV at the start of every packet I send out?
No, you set the IV once and then forget about it.
The problem is from all these examples, I'm not sure what needs to be done at every encryption/decryption, and what I should only do once on startup.
Create this once: EVP_CIPHER_CTX
Call this once for setup: EVP_CipherInit
Call this as many times as you'd like: EVP_CipherUpdate
Call this once for cleanup: EVP_CipherFinal
The OpenSSL wiki has quite a few examples of using the EVP_* interfaces. See EVP Symmetric Encryption and Decryption, EVP Authenticated Encryption and Decryption and EVP Signing and Verifying.
All the examples use the same pattern: Init, Update and then Final. It does not matter if its encryption or hashing.
Related: this should be of interest to you: EVP Authenticated Encryption and Decryption. Its sample code from the OpenSSL wiki.
Related: you can find copies of Viega, Messier and Chandra's Network Security with OpenSSL online. You might consider hunting down a copy and getting familiar with some of its concepts.
Sorry for reviving an old thread too, but LazerSharks asked twice about evp cipher context in comments. I don't have enough reputation points here to add some comments that's why I'll take an answer here. (Google search even now doesn't show needful information)
From the "Network Security with OpenSSL" book by Pravir Chandra, Matt Messier, John Viega:
Before we can begin encrypting or decrypting, we must allocate and initialize a cipher context. The cipher context is a data structure that keeps track of all relevant state for the purposes of encrypting or decrypting data over a period of time. For example, we can have multiple streams of
data encrypted in CBC mode. The cipher context will keep track of the key associated with each
stream and the internal state that needs to be kept between messages for CBC mode. Additionally, when encrypting with a block-based cipher mode, the context object buffers data that doesn't exactly align to the block size until more data arrives, or until the buffer is explicitly flushed, at which point the data is usually padded as appropriate.
The generic cipher context type is EVP_CIPHER_CTX. We can initialize one, whether it was allocated dynamically or statically, by calling EVP_CIPHER_CTX_init, like so:
EVP_CIPHER_CTX *x = (EVP_CIPHER_CTX *)malloc(sizeof(EVP_CIPHER_CTX));
EVP_CIPHER_CTX_init(x);
Just to complement bacchuswng's answer I have been recently experimenting with LibreSSL and it seems there is no problem with reusing an EVP_CIPHER_CTX but you need to make sure you call EVP_CIPHER_CTX_reset or EVP_CIPHER_CTX_cleanup before starting another encryption / decryption. This is because EVP_EncryptInit / EVP_DecryptInit will clear the context's memory effectively leaking the context's cipher_data previously being used.
Some ciphers don't need to allocate cipher_data but the one I was testing (EVP_aes_128_gcm) does need 680 bytes which can grow out of control quite rapidly.
I can't tell if this is the same behavior with OpenSSL but since documentation for this library is way too hard to come by, I figured I'd share this little quirk (bug perhaps?).
I developed an application in C++ using Crypto++ to encrypt information and store the file in the hard drive. I use an integrity string to check if the password entered by the user is correct. Can you please tell me if the implementation generates a secure file? I am new to the world of the cryptography and I made this program with what I read.
string integrity = "ImGood"
string plaintext = integrity + string("some text");
byte password[pswd.length()]; // The password is filled somewhere else
byte salt[SALT_SIZE]; // SALT_SIZE is 32
byte key[CryptoPP::AES::MAX_KEYLENGTH];
byte iv[CryptoPP::AES::BLOCKSIZE];
CryptoPP::AutoSeededRandomPool rnd;
rnd.GenerateBlock(iv, CryptoPP::AES::BLOCKSIZE);
rnd.GenerateBlock(salt, SALT_SIZE);
CryptoPP::PKCS5_PBKDF2_HMAC<CryptoPP::SHA512> gen;
gen.DeriveKey(key, CryptoPP::AES::MAX_KEYLENGTH, 32,
password, pswd.length(),
salt, SALT_SIZE,
256);
CryptoPP::StringSink* sink = new CryptoPP::StringSink(cipher);
CryptoPP::Base64Encoder* base64_enc = new CryptoPP::Base64Encoder(sink);
CryptoPP::CFB_Mode<CryptoPP::AES>::Encryption cfb_encryption(key, CryptoPP::AES::MAX_KEYLENGTH, iv);
CryptoPP::StreamTransformationFilter* aes_enc = new CryptoPP::StreamTransformationFilter(cfb_encryption, base64_enc);
CryptoPP::StringSource source(plaintext, true, aes_enc);
sstream out;
out << iv << salt << cipher;
The information in the string stream "out" is then written to a file. Another thing is that I don't know what the "purpose" parameter in the derivation function means, I'm guessing it is the desired length of the key so I put 32, but I'm not sure and I can't find anything about it in the Crypto++ manual.
Any opinion, suggestion or mistake pointed out is appreciated.
Thank you very much in advance.
A file can be "secure" only if you define what you mean by "secure".
Usually, you will be interested in two properties:
Confidentiality: the data that is encrypted shall remain unreadable to attackers; revealing the plaintext data requires knowledge of a specific secret.
Integrity: any alteration of the data should be reliably detected; attackers shall not be able to modify the data in any way (even "blindly") without the modification being noticed by whoever decrypts the data.
Your piece of code, apparently, fulfils confidentiality (to some extent) but not integrity. Your string called "integrity" is a misnomer: it is not an integrity check. Its role is apparently to detect accidental password mistakes, not attacks; thus, it would be less confusing if that string was called passwordVerifier instead. An attacker can alter any bit beyond the first 48 bits without the decryption process noticing anything.
Adding integrity (the genuine thing) requires the use of a MAC. Combining encryption and a MAC securely is subject to subtleties; therefore, it is recommended to use for encryption and MAC an authenticated encryption mode which does both, and does so securely (i.e. that specific combination was explicitly reviewed by hordes of cryptographers). Usual recommended AE modes include GCM and EAX.
An important point to note is that, in a context where integrity matters, data cannot be processed before having been verified. This has implications for big files: if your huge file is adorned with a single MAC (whether "manually" or as part of an AE mode), then you must first verify the complete file before beginning to do anything with the plaintext data. This does not work well with streamed processing (e.g. if playing a huge video). A workaround is to split the data into individual chunks, each with its own MAC, but then some care must be taken about the ordering of chunks (attackers could try to remove, duplicate or reorder chunks): things become complex. Complexity, on a general basis, is bad for security.
There are contexts where integrity does not matter. For instance, if your attack model is "the attacker steals the laptop", then you only have to care about confidentiality. However, if the attack model is "the attacker steals the laptop, modifies a few files, and puts it back in my suitcase without me noticing", then integrity matters: the attacker could plant a modification in the file, and infer parts of the secret itself based on your external behaviour when you next access the file.
For confidentiality, you use CFB, which is a bit old-style, but not wrong. For the password-to-key transform, you use PBKDF2, which is fine; the iteration count, though, is quite low: you use 256. Typical values are 20000 or more. The theory is that you should make actual performance measures to set this count to as high a value as you can tolerate: a higher value means slower processing, both for you and for the attacker, so you ought to crank that up (depending on your patience).
Mandatory warning: you are in the process of defining your own crypto, which is a path fraught with perils. Most people who do that produce weak systems, and that includes trained cryptographers; in fact, being a trained cryptographer does not mean that you know how to define a secure protocol, but rather that you know better than defining your own protocol. You are thus highly encouraged to rely on an existing protocol (or format), rather than making your own. I suggest OpenPGP, with (for instance) GnuPG as support library. Even if you need for some reason (e.g. licence issues) to reimplement the format, using a standard format is still a good idea: it avoids introducing weaknesses, it promotes interoperability, and it can be tested against existing systems.
My use of the Crypto++ library has gone very well, but I have a small question...
If I use RSAES_OAEP_Encryptor & RSAES_OAEP_Decryptor everything is fine. (I'm using a 2048-bit key from PEM files generated by OpenSSL).
My question is this: Will the length of ciphertext produced by encryptor.Encrypt(...) always equal decryptor.FixedCiphertextLength() or can be be less than that? I only ask as this is in a library used by a number of applications and I need to sanity check parameters.....
BTW. Is there any faster was to encrypt/decrypt using RSA which maintains at least the same level of security provided by OAEP? With a 1024 bit key, on an example test box, averaged over 1000 iterations, I'm finding it takes about 80uS to encode a short string and 1.03mS (12 times longer) to decrypt; with a 2048-bit key encryption takes 190uS and decryption, 4.3mS (22 times longer). I know that RSA decryption is slow, but.... the system is running XP Pro SP3/Xeon E5520 and was compiled with VS2008 with /MD rather than /MT. I can't use a shorter key than 2048-bits for compliance reasons...
Many thanks
Nick
Length of ciphertext produced by RSAES_OAEP_Encryptor?
In the case of RSA, I believe FixedPlaintextLength() and FixedCiphertextLength() call MaxPreImage() and MaxImage(). MaxPreImage() and MaxImage(), in turn, returns n - 1.
Will the length of ciphertext produced by encryptor.Encrypt(...) always equal decryptor.FixedCiphertextLength() or can be be less than that?
It depends on the cryptosystem being used. Usually, its the size of the key that determines if FixedCiphertextLength() holds (and not the size of the plain text). In the case of RSA/OAEP and others like ElGamal, I believe it holds.
I think the class of interest here is the PK_CryptoSystem Class Reference. Classes like RSAES_OAEP_Encryptor inherit from PK_CryptoSystem, and that's where FixedCiphertextLength() and friends come from.
With a 1024 bit key, on an example test box, averaged over 1000 iterations, I'm finding it takes about 80uS to encode a short string and 1.03mS (12 times longer) to decrypt; with a 2048-bit key encryption takes 190uS and decryption, 4.3mS (22 times longer)
This is a different question, but...
In the case of encryption or verification, the public exponent is used. The public exponent is, by default, 65537 (IIRC). That's got a low hamming weight (high density of 0's), so square and multiply exponentiation routines run relatively fast.
On the other hand, decryption and signing use the private exponent, which should have about a normal distribution of 1's and 0's. There's lots of squares and multiplies to perform, and those take extra time.
Taking advantage of those little timing differences is where your side channels come from if you are not careful. If you are not careful, then the NSA will thank you.
I can't use a shorter key than 2048-bits for compliance reasons
A 2048-bit modulus is about 10x slower than a 1024-bit modulus. Its why so many folks were reluctant to move from 1024-bit, and why 1024-bit is still kind of preferred.
Peter Gutmann has this to say about it in his Engineering Security book (p. 229):
Another example [of broken threat models] occurred with keys in
certificates, for which browser vendors (in response to NIST
requirements) forced CAs to switch from 1024-bit to 2048-bit keys,
with anything still using 1024-bit keys being publicly denounced as
insecure. As discussed in “Problems” on page 1, the bad guys didn’t
even notice whether their fraudulent certificates were being signed
with, or contained, 2048-bit keys or not.
I'm trying to encrypt http requests using crypto++ and decrypt them with pycrypto on the app engine server end. Using Arc4 encryption, I can successfully encrypt and decrypt on the iphone end but when I try decrypting on app engine, the result is garbled. The ciphertext after encrypting on the client is the same as the text received on the server when I check logging, so if they are visually the same, why would decrypting fail?
I thought maybe it has something to do with the encoding of the NSString, as I find I need to call encode() on the cipher on the server end before decrypting just to avoid decrypt() failing on it attempting to encode the cipher in ascii. I have a separate post that delves a bit into this. Can anyone offer some advice?
crypto++ / pycrypto with google app engine
Update:
I have discovered that the ciphertext resulting from encrypting in C with Crypto++ is not the same as the ciphertext from encrypting in python with PyCrypto. Could there be something I'm doing wrong with initializing the keys? I do something like:
ARC4::Encryption enc("a");
in C. And in python I do:
testobj=ARC4.new('a')
The %-encoded resulting cipher is different in C than in python. I noticed that in C, I can pass a 2nd parameter for keylength, which I guessed should be 1 for "a", resulting in a different cipher than when putting no parameter. The %-encoded result was still different from the python encoding, though.
Does anything look particularly amiss with my init perhaps?
I've discovered that the problem was not with the init of either crypto impl but rather mistakenly trying to stuff the encrypted cipher text into an NSString which cant simply take raw binary data with no particular encoding. The trick was to encode the data in base64 or base16 so that it is is readable, then use unhexlify on the server end before decrypting.