encryption/decryption with multiple keys - encryption

Is it possible to encrypt data, such that it can be decrypted with several different keys?
Example:
I've encrypted data with key1, but I want to be able to decrypt with keys 2, 3, and 4.
Is this possible?

GnuPG does multi-key encryption in standard.
The following command will encrypt doc.txt using the public key for Alice and the public key for Bob. Alice can decrypt using her private key. Bob can also decrypt using his private key.
gpg --encrypt --recipient alice#example.com \
--recipient bob#example.com doc.txt
This feature is detailed in the user guide section entitled "Encrypting and decrypting documents"

Yes it's possible
Yes encryption for multiple recipients is possible. Also it seems logical when you think that you might want to be able to read what you've sent to someone and to do so you need to be in the recipients list.
Command line
Here is how to do it through gpg command line (as described in David Segonds' answer):
gpg --encrypt \
--recipient alice#example.com \
--recipient bob#example.com \
clear-message.txt
GUI client
Your GUI must provide a way to encrypt for several people
Mechanism
There is a question on Information Security, GPG File size with multiple recipients?, that explain the encryption mechanism:
GPG encrypts the file once with a symmetric key, then places a header
identifying the target keypair and an encrypted version of the
symmetric key.
[...] When encrypted to multiple recipients, this
header is placed multiple times providing a uniquely encrypted version
of the same symmetric key for each recipient.

GnuPG and PGP clients in general usually encrypt the actual data with a symmetric key called a "session key". The session key is then encrypted with each "recipient key" (i.e. the ones you specify with -r/--recipient). This is sometimes referred to as a hybrid cipher. Right now, I believe GnuPG by default uses an 256 bit session keys and AES to encrypt the plaintext data to that AES-256 session key, and your recipient keys are your RSA/DSA/ECDSA/etc. assymetric key in this case.
One reason for doing it this way is that symmetric cryptographic algorithms like AES are generally a lot faster than asymmetric ones like RSA. GnuPG thus only has to encrypt ~256 bits (the session key) with RSA, and can use AES to encrypt the data (as large as you want it to be!) with that session key. Intel machines even have a built in instruction, AES-NI, to do some steps of the algorithm in hardware, which makes GnuPG extra snappy at encrypting/decrypting data.
Another reason for doing it this way is that it allows PGP-encrypted documents to be encrypted to multiple parties without having to double the size of the document. Notice that when you specify multiple recipients for an encrypted document (e.g. gpg -ea -r Alice -r Bob -o ciphertext.asc), the encrypted document that gets stored (ciphertext.asc) is not 2x as large as if you had just encrypted it to Alice.
See also the --show-session-key parameter in the gpg man page to be able to decrypt just the session key, for example to allow a third party to decrypt a document that is encrypted to you without having to transfer to them your private key or the plaintext data.

Yes, it's possible. Google "multiparty encryption" for a start.
AFAIK, there are no drop 'em in and use 'em packages for it though.
-- MarkusQ
P.S. For a sketch of how it could be done, consider this. The encrypted message consists of:
the payload, encrypted with a one-time pad
the one time pad, encrypted with key1
the one time pad, encrypted with key2
...
the one time pad, encrypted with keyN
The recipient who hold key i just decrypts their copy of the pad with their key, and then decrypts the payload.
However, this is just a proof that it could be done and would suck as an actual implementation. If at all possible, you should avoid rolling your own encryption. If you don't understand why, you should definitely avoid rolling your own encryption.
-----Edit ------------
If I'm wrong and the Gnu tools do that, use them. But I can't seem to find any information on how to do it.

Multiple (more than two) key RSA is maybe like this - well i'm not a mathematician, so this algorithm is not necessarily secure, i just want to give an idea with it.
m=p*q*r; p,q,r are big prime numbers
fi(m)=(p-1)(q-1)(r-1)
d==(e1*e2*e3*...*ei)^(-1) (mod fi(m)); e1...ei are arbitrary numbers, d is calculated to fulfill the equation
y1==x^e1 (mod m)
y2==y1^e2 (mod m)
y3==y2^e3 (mod m)
...
x==yi^d (mod m)
This algorithm could be used for example to increase the speed of The Onion Router.

Related

Cryptography: Securing Digital Signature and Key Pair

I have developed an encryption solution which is based on Hybrid Encryption as:
Sender end:
The message hash will be calculated.
Hash will be signed with private key of sender.
Hash will be encrypted with private key of sender.
A symmetric key will be generated.
Symmetric key will encrypt the message.
Symmetric key will then be encrypted with public key of receiver.
Recevier end:
Decryption of Hash with public key of sender.
Verification of sign with public key of sender.
Decryption of Symmetric key with private key of receiver.
Decryption of message with Symmetric key.
Now I want to save the hash in a file, the digital sign in a file, key encryption in file, actual message encrypted in a file and the key pairs.
In what file type shall I save all of these?
whether it shall be a CSV, TXT file or something else?
I have to keep the keys secure and the digital signature too..
Please guide!
As for the sender: Steps 1, 2 and 3 are commonly combined into a single signature generation operation. You don't do them separately. The same for step 1 and 2 of the receiver for signature verification (where you are missing the hashing step of the message, by the way).
Modern cryptography is based on bytes, so generally you define a single binary container format so that you don't have to expand the ciphertext (compared to the plaintext) needlessly. Such a container can contain multiple values: encrypted key, and encrypted content that consists of the message and signature. Generally there is also a header containing a version string and an ID of the required keys to name just a few.
Of course many container formats have been defined for the hybrid cryptography that you're currently using, with CMS (with a hierarchical PKI) and (Open)PGP (with a web-of-trust based PKI) being the most well known ones.
Otherwise it is up to you. Generally you'd encode the ciphertext / signatures using base 64 if you require text based storage. Do include a version string somewhere in the header and create a document to describe your protocol.

How do I encrypt an email using a Yubikey?

I am fairly new to PGP encryption. I generated a new key pair last week on a Yubikey, while previously I had only used a private key that I generated on my machine. I use thunderbird enigmail for key management. This is probably a stupid question but I don't actually understand how to encrypt an email using the private key stored on my Yubikey. I can decrypt just fine but can't figure out how to compose an encrypted email from the new key. Using my old key pair, it's automatic - how do I actually encrypt using the right private key? At what point do I enter the Yubikey and pin? (I'm not all that technical and I use encryption for one specific project, so I appreciate dumbing down something that is probably very obvious.)
Using keys generated on a Yubikey is a practically identical process to using your old keys, with one extra step of set up.
To use keys stored on a Yubikey, you need "key stubs" registered on your PGP system. Basically, these are references that tell your PGP software "This private key is located on smartcard number #123456." Once you have the stubs to the keys you need, Enigmail should treat the Yubikey-stored keys like any other PGP key.
I'm only familiar with GnuPG, so specifics may vary, but using GPG you need to
Have a copy of the public key imported to your system from a key server or the like.
Import key stubs from your smart card (in this case, your Yubikey) using:
gpg --card-status
After that, checking your private keyring should reflect that you have stubs pointing to private keys stored on a smart card (denoted by the > after sub). I.E.
gpg --list-secret-keys
----------------------------------------------------
sec# rsa2048 2018-01-02 [C] [expires: 2020-01-02]
ABCDEF123456789ABCDEF123456789ABCDEF1234
uid [ ultimate] My Name (My PGP key) <anAddress#somesite.com>
ssb> rsa2048 2018-01-02 [S] [expires: 2018-12-31]
ssb> rsa2048 2018-01-02 [E] [expires: 2018-12-31]
ssb> rsa2048 2018-01-02 [A] [expires: 2018-12-31]
At this point you can use sub keys of CDEF1234 as if there were on your system. Your PGP software ought to handle checking the card is inserted and dealing with PIN entry.

Symmetric Encryption with GPGME

According to the documentation the gpgme_op_encrypt method of GPGME is able to perform symmetric encryption tasks:
gpgme_op_encrypt (gpgme_ctx_t ctx, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, gpgme_data_t plain, gpgme_data_t cipher)
If recp is NULL, symmetric rather than public key encryption is
performed. Symmetrically encrypted cipher text can be deciphered with
gpgme_op_decrypt. Note that in this case the crypto backend needs to
retrieve a passphrase from the user. Symmetric encryption is currently
only supported for the OpenPGP crypto backend.
But where does the key used for the symmetric encryption come from? Is it somehow possible to fetch this key and transfer it to another device (where I would like to decrypt the text) ?
The session key for symmetric encryption is derived from a passphrase, which will be queried from the user through one of the pinentry methods. Specifically highlighting a part of the text you already quoted:
If recp is NULL, symmetric rather than public key encryption is performed. Symmetrically encrypted cipher text can be deciphered with gpgme_op_decrypt. Note that in this case the crypto backend needs to retrieve a passphrase from the user. Symmetric encryption is currently only supported for the OpenPGP crypto backend.
I'm not aware you can extract the session key through GPGME, but you don't really need to: all you need to know at the other end is the passphrase used, and the session key can be derived again. You could of course also reimplement the string-to-key-function used for OpenPGP.

Why do AES decryption methods take IVs as arguments

I'm still new to encryption in general, and I understand why an IV is necessary, but isn't the IV embedded in the encrypted data? Thus, shouldn't any decryption implementation first extract the IV from the data rather than needing to have it supplied?
The reason I assume the IV is embedded in the data is because certain libraries/tools do not require that it be supplied, for instance CryptoJS for JavaScript: CryptoJS.AES.decrypt("U2FsdGVkX1/l3HWODO9GX23rvF0KHmDR6z8XTpYYpe8=", "password").toString(CryptoJS.enc.Utf8));
and openssl: echo "U2FsdGVkX1++pGg+oWqZbIjccV1NiV2pc1QrQtw0wp4=" | openssl aes-256-cbc -d -a -pass pass:password
and really any actual app that does AES encryption, like TrueCrypt.
Libraries that seem to require the IV:
mcrypt for PHP: http://us2.php.net/manual/en/function.mcrypt-decrypt.php
SymmetricAlgorithm in .Net: http://msdn.microsoft.com/en-us/library/79w421xb%28v=vs.110%29.aspx
am i getting something confused?
No, the IV may be derived as well. The only reason to include the IV with the ciphertext is when the key is reused for encryption and when the IV cannot be derived. It is common but not standardized or required to prefix it if it is present. But that's when you need the IV, so it's the de-facto standard none-the-less.
In your OpenSSL example a random salt is used to generate a key from a password. In that case the salt is different for each encrypt, so the key is random as well. In that case an randomized IV is not needed, although it can (and will be for OpenSSL) derived from the salt and password as well.
Other protocols contain a counter, and in that case a single block encrypt over the counter can be used to create an IV for CBC mode encryption. As long as the counter stays the same at sender/receiver, there is no need to send the IV.
And there are plenty cryptograhic implementations that get it wrong and don't use a random IV for CBC mode. PHP mcrypt_encrypt is special in the sense that it even requires an IV for ECB mode, which is then thouroughly ignored as ECB does not use an IV anywhere in the algorithm.

Encrypting a file with RSA in Python without storing any password

I have asked a similar question in post Encrypting a file with RSA in Python , but this question has a different connotation.
I am encrypting a file with AES, using RSA to encrypt the AES password.
The only difference is that i really DON'T want to store the AES password. The user must give both the path to his RSA key, and the password.
So what do you think about this scheme?
path_to_RSA_key = ... # Given by the user
pwd = ... # This will be used to encrypt the file. Also given by user.
rsa_enc = RSA.importKey(path_to_RSA_key)
# Encrypt the Password with RSA, keep the last 32 characters
rsa_pwd = rsa_enc.encrypt(pwd)[-32:]
# Aes, with the encrypted password
aes_enc = AES.new(rsa_pwd, AES.MODE_CBC)
# Encrypt the file with AES...
# Store only the encrypted file
# Don't store the password in any way, don't store the path to RSA key
The alternative would be the classic scheme, when you generate a random password, encrypt the file with AES using the random pass, encrypt the random pwd with RSA and store only the encrypted results.
If you really need to know why i need this, it's a project of mine, http://code.google.com/p/scrambled-egg
What do you think about the scheme ? Thank you in advance !
There seems to be some confusion. You mention that you don't want to store the 'password', but you're working with RSA and not a symmetric algorithm. The term 'password' strongly implies a shared secret as used in symmetric encryption, and it appears that you're trying really hard to fit RSA into the mould you've created.
The issue I see is that this functionality may not fit into your planned use very well. Your plan seems focused on symmetric ciphers. Further, using asymmetric keys this way may be a problem. I think asymmetric encryption is used to encrypt nonces for a reason; it may not be robust to attacks that can be waged against a scheme like the one you propose.
Asymmetric keys are often used as follows:
Generate a purely random 32-'character' key and call it "nonce".
Encrypt the message with the "nonce" and call it ciphertext.
Encrypt the "nonce" with your asymmetric key (presumably the public key, but you should specify).
The result consists of the ciphertext and the asymmetrically encrypted "nonce".
Decrypting requires only the paired opposite of the asymmetric key used to encrypt.
If you're hardcore, you could encrypt (using AES + a password or similar) the public or private key that can be used to decrypt the nonce and send it along for a ride too. Sadly that isn't really increasing security over AES+password, and you are increasing the bloat in your message by a lot.

Resources