I'm writing a module that creates a secure communication channel using ZeroMQ sockets and Pycryptodome.
The initial handshake between client and server would follow these steps :
Both parties send their public RSA key to each other.
The server generates an AES session key and a signature for that key.
The server RSA-encrypts the session key and the signature before sending it to the client. (*)
The client verifies the signature and stores the session key.
The client generates a token, generates its signature and sends both AES-encrypted to the server.
The server verifies the signature and echoes back the token.
If the token received matches the one sent, the handshake is considered successful.
I found on this thread that it was preferable to sign the message then encrypt it, rather than encrypting then signing it.
The problem is that the signature, for a 2048 bits RSA key, is 256 bytes long. The maximum encryption size for the same key is 190 bytes. This means I can't encrypt the signature as suggested in the thread.
Should I encrypt the signature with the AES session key ? Should I proceed another way ?
I know there are "standardized" key exchange protocols (ECDH for example) but they are not available in Pycryptodome yet.
Cipher: RSA PKCS1 OAEP
Signing : PKCS1 PSS w/ BLAKE2b hash
Given a AES secret key, is it possible to fake a data that can be decrypt using that key? the decrypted data doesn't need to be meaningful, just want to know if can fake a encrypted data.
AES is a symmetrical cipher, i.e. the same key is used to both encrypt and decrypt data. As such, the key must be known to both ends of communication, and no one else. Authentication and key-exchange is done via public-key protocols, such as Diffie-Hellman key exchange.
Given these, if you are the third person to possess an AES key, I assume that you cannot send "fake data" to the recipient, as authentication will fail (no negotiation has taken place). If you have established such a connection, you can send whatever you want (you can encrypt gibberish and send it). If you mean to alter an encrypted packet, you can do it without decrypting it and re-encrypting it, but it's most likely to fail integrity tests (e.g. if hashes or CRC are present).
When I want to encrypt large files, I have found the following command:
openssl smime -encrypt -binary -aes-256-cbc \
-in large_file.img -out large_file.img.dat \
-outform DER \
public-rsa2048.pem
The private/public keys have been created like this:
openssl req -x509 -nodes -newkey rsa:2048 \
-keyout private-rsa2048.pem -out public-rsa2048.pem
So I am using aes-256-cbs as well as an rsa-key.
Which one is now responsible for the encrpytion?
Which one does impact the performance and how?
If I increase/lower the public key (rsa512 vs rsa4096), does this impact the performance?
If I choose a different aes algorithm, does this impact the performance as well?
Could someone bring some light into this matter please?
Are there any other methods to encrypt large files?
Using the openssl smime command to encrypt data encrypts it in such a way that it can be received and decrypted by a recipient using email. This means that it uses certificates representing various entities (sender, recipient) and containing keys uniquely associated with those entities to both sign, encrypt, decrypt, and verify signatures on the contained data.
As Artjom pointed out in their comment, a hybrid cryptosystem is used. This means a combination of symmetric and asymmetric encryption algorithms are used, as each has benefits and drawbacks. Symmetric encryption (such as AES) is extremely fast in comparison to asymmetric encryption (such as RSA). However, AES/CBC provides only confidentiality, not integrity, authentication, or non-repudiation. Asymmetric encryption can provide integrity, authentication, and non-repudiation. Asymmetric encryption also has fairly low limits for the amount of data it can encrypt (for example, an RSA-4096 bit key can encrypt at most 446 bytes at once). By combining both methods, we can exercise each for their strengths and mitigate the weaknesses of the other.
In this case, let our message be M. An AES/CBC key Kaes of length 256 bits is generated and used to encrypt the raw data such that the cipher text C is C = E(Kaes, M). The recipient's public key Krpub is then used to encrypt Kaes as C' = E(Krpub, Kaes). The cost of encrypting this small amount of data is relatively low, even though we are using an expensive operation.
Note prior to encrypting the ephemeral session key, it is likely signed using the sender's private key Kspriv unless digital signing is disabled. I am not 100% certain with S/MIME, but this is how PGP works, as when sending to multiple recipients, it would be much more expensive to encrypt the session key with n recipient's public keys and then sign each encrypted key with the sender's private key O(2n) vs. O(n+1) (not really Big-O notation, but effective for communicating the point). The signature of the session key is the same regardless of recipient because it depends only on the sender's private key.
Now all that is left is to concatenate the encrypted session key C' and the cipher text C and transmit them to the recipient. In a real S/MIME message, the identifying information about the sender's public key is transmitted as well in order to facilitate signature verification. The recipient parses the complete encrypted message, decrypts the session key using the recipient's private key Krpriv and then uses the session key Kaes to decrypt the cipher text C.
However, it seems like all of this may be overkill for your situation. If you do not need to integrate with an email communication system and are simply trying to encrypt large files for storage, openssl also offers a simple enc command. You can use it as follows:
Password-based encryption:
$ openssl enc -aes-256-cbc -in large_plain_file.dmg -out large_encrypted_file.enc -k thisIsABadPassword
-k allows you to enter a password on the command line from which the key will be derived. OpenSSL uses a deterministic key derivation function (KDF) (effectively key, iv = MD5(password||salt)). You can run this command with -p on the end to get the key, salt, and IV printed to the console. The IV is deterministically derived from the password and salt. A KDF like PBKDF2 is recommended but the library function in OpenSSL does not expose it to the command-line tool for some reason.
Warning you can run this and specify -nosalt to skip the salt generation, but this is not recommended as it makes an already extremely weak KDF even weaker.
Keyed encryption:
$ openssl enc -aes-256-cbc -in large_plain_file.dmg -out large_encrypted_file.enc K 0123456789ABCDEFFEDCBA98765432100123456789ABCDEFFEDCBA9876543210 -IV 0123456789ABCDEFFEDCBA9876543210
Running with the actual key and IV provided. The key is 32 bytes (256 bits) and the IV is 16 bytes (the size of one AES block).
To decrypt the data, run the command with the -d flag:
$openssl enc -aes-256-cbc -d -in large_encrypted_file.dmg -out large_decrypted_file.enc
This is going to be simpler for you (no certificates/key pairs needed) and faster (no RSA encryption).
Something to keep in mind for all of this is that the password/key will be kept in terminal history if you provide it in the command invocation. Running without -k or -K will prompt the password to be entered in a secure prompt. Or use -pass to read from an environment variable, file, or file descriptor.
Update to address original questions explicitly:
The AES key is responsible for encrypting the data. The RSA key is used to encrypt the AES key.
Both impact the performance. The AES key is encrypting much more data, but is much faster than RSA encryption.
Yes, changing the size of the RSA key impacts performance, (higher key sizes are slower), but for a large file this is unlikely to be the limiting factor on performance.
Yes, changing the AES mode of operation may have a substantial impact on performance. AES/CBC, AES/OFB, and AES/CFB are similar in that they are serial operations (depending on the result of one block operation to proceed to the next), but AES/CTR operates as a stream cipher and can be parallelized to provide both encryption and decryption.
See answer above.
I would like to implement something-like-pay-TV encryption. In this system, the user has a smart card providing private key can decrypt the signal. However, I cannot find out its encryption-decryption step. Therefore, I invent some -_-!
In my system, there is a central server, a broadcast center and users. The central server generate a pair of RSA public-private key and send the public key to broadcast center. When a user want to connect to broadcast center, a request will be sent to central server. Then, the server will send the private key for user. User and broadcast center use this pair of key to encrypt-decrypt a data symmetric key (for example AES key).
Is it a good implementation if the RSA private key is used by multiple users?
RSA won't fit your needs. In RSA you would have to encrypt the data for every single user. RSA is an encryption standard with private/public keys. Each private key depends on his public key.
You can't modify RSA so that you need only one encryption. In PGP (uses RSA) for example when sending a PGP mail to five recipients, the mail is encrypted five times with different keys.
On pay TV they use conditional access http://en.wikipedia.org/wiki/Conditional_access.
By the way: do not implement your own encryption implementation. Use existing algorithms and implementations. They are proven secure.
I'm currently developing a system to transmit data between client and server, and was wondering what the strength of the encryption I planned to use was.
My thought was to have a private/public RSA key pair and hand out the public key to each client (leaving the private key solely on the server). Each client would then generate their own AES key and RSA encrypt it. They would then AES encrypt their data and send the encrypted data and encrypted AES key to the server. The server would then decrypt the AES key using the private key, and then decrypt the data using the AES key.
now question is how to send aes key?