Symmetric Encryption with GPGME - encryption

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.

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.

Why encrypt message digest in digital signature?

I am trying to understand the following:
Why should a message digest in cryptography be encrypted with the private key from the sender?
The receiver can decrypt it with the public key of the sender, but anyone else can do that too. Even the man in the middle, so I don't really see the point of encrypting the message digest in the sense of Digital Signature.
Try to separate encryption and signing. Even mathematically they are similar operations, there are some important differences. I will try to summarize basics
mesaage and uses his own private key to encrypt the message digest
Actually - person A creates a hash of the content and signs the hash. It means executing a decryption operation with signing padding with its private key, creating a signature
Now person B will make a hash value of the message to compare it to the message digest.
And this is wrong. Whoever (any attacker) could modify/falsify the content and create a valid digest.
Person B
creates a hash value of the content
validates the provided signature - encrypts the provided signature with A's public key which should result to the hash and signing padding
but anyone else can do that too
Signing ensures, that only A could sign the mesage digest, because only with private key you could "decrypt" - create an output, which after "encryption" could lead to some specific value (digest).
It is as well important to use full specification for RSA operations (PSS padding), not text-book RSA (without nonce and padding). Otherwise if some could trick A to decrypt any input, leading to creating a signature or revealing the private key.
Edit:
why isnt it enoug to encrypt with pulic key
Encrypting ensures, that only the addressee could decrypt the message, but it doesn't say who is sending the message. (A can believe that only B reads the message, but B may not be sure it is a message from A)
Signing undeniably identifies the sender. (B can be sure the message is sent by A)
There are some caveats in this approach (signing a directly encrypted message), but details could be better explained in the crypto OS forum.

bcrypt vs pbkdf2 for encrypting private keys

I'm building an application in which a password is used on the client side to encrypt a private key of a elliptic curve key pair. Then the password is bcrypted and sent to the server (along with the encrypted private key) and the public key.
Originally, I was using pbkdf2 to hash the password before encrypting the private key, but since I'm also bcrypting the password, could I use the bcrypted one instead?
According to https://medium.com/#mpreziuso/password-hashing-pbkdf2-scrypt-bcrypt-1ef4bb9c19b3#.sj4jcbynx the answer is not only yes, but bcrypt is even better as it's more GPU-ASIC resilient. Anything I'm missing?
You should not be using the bcrypt hash output as an encryption key; it is not meant to be key material:
BCrypt is not a key-derivation function
BCrypt it is a password storage function
You have an elliptic curve private key that you want to encrypt using a user's password. Of course you don't want to use the password directly - you want to use the password to derive an encryption key. For that you can use:
PBKDF2
scrypt
These are both key-derivation functions (e.g. password-based key derivation function). Their purpose is to generate an encryption key given a password. They are designed to be "hard".
You feed both these algorithms:
a password
cost parameters
salt
desired number of bytes (e.g. 32 ==> 32 bytes ==> 256 bits)
and it returns you a 256-bit key you can use as an encryption key to AES-256.
You then want to backup the user's key
I gather that you then want to:
store the encrypted elliptic curve private key on your server
store a hash of their password on your server
And your question was: since you already ran their password through "a hashing funtion" can't you just use that hash as their stored password?
No! That hash is also the encryption key protecting their private key. You don't want that private key transmitted anywhere. You don't want it existing anywhere. That 32-byte encryption key should be wiped from memory as soon as you're done with it.
What you should do, if you also wish to store a hash of the user's password is use an algorithm that is typically used for password storage:
pbkdf2 (a key-derivation function abused into password storage)
bcrypt (better than pbkdf2)
scrypt (a key-derivation function abused into password storage; better than bcrypt)
argon2 (better than scrypt)
Update: Argon2/Argon2i/Argon2d/Argon2id is weaker than bcrypt for password authentication (read more)
You should separately run the user's password through one of these password storage algorithms. If you have access to bcrypt; use that over pbkdf2. If you have scrypt, use that for both:
derivation of an encryption key
hashing of the password
The security of your system comes from (in addition to the secrecy of the password), the computational distance between the user's password and the encryption key protecting their private key:
"hunter2" --PBKDF2--> Key material
"hunter2" ---------bcrypt-------> Key material
"hunter2" ----------------scrypt----------> Key material
You want as much distance between the password and the key.
Not-recommended cheat
If you're really desperate to save CPU cycles (and avoid computing scrypt twice), you technically could take:
Key Material ---SHA2---> "hashed password"
And call the hash of the encryption key your "hashed password" and store that. Computation of a single SHA2 is negligible. This is acceptable because the only way an attacker can use this is by trying to guess every possible 256-bit encryption key - which is the problem they can't solve in the first place. There's no way to bruteforce a 256-bit key. And if they were to try to brute-force it, the extra hashed version doesn't help them, as they could just test their attempt by trying to decrypt the private key.
But it's much less desirable because you're storing (a transformed) version of the encryption key. You want that key (and any transformed versions of it) stored as little as possible.
To sum up
generate EC key pair
encryptionKey = scryptDeriveBytes(password, salt, cost, 32)
encryptedPrivateKey = AES256(privateKey, encryptionKey)
passwordHash = scryptHashPassword(password, salt, cost)
and upload
encryptedPrivateKey
passwordhash

What is a PGP Secret Key?

I am working on a C# app that encrypts/decrypts messages using PGP implemented by the Bouncy Castle (BC) library. I know PKI but the secret key in PGP throws me off a bit. I looked at the BC examples/source code and the PGP RFC but came away with more questions.
Is Secretkey == Session key?
Is Secretkey == Symmetric key?
Is Secretkey == private key (pub/priv key pairs)? At least the following seems to suggest that the secret key is a private key.
internal static PgpPrivateKey FindSecretKey(PgpSecretKeyRingBundle pgpSec, long keyID, char[] pass)
The RFC says the secretkey contains, among others, information about the publickey or may be the public key itself (at least that's my reading).
Also, somewhere I read the Secretkey is basically a password encrypted privatekey.
When/why would I need a secret key in the PGP protocol? Signing or encrypting?
Thanks
Quoting RFC 4880, OpenPGP, 5.5.1.3. Secret-Key Packet:
A Secret-Key packet contains all the information that is found in a
Public-Key packet, including the public-key material, but also
includes the secret-key material after all the public-key fields.
and 11.2. Transferable Secret Keys:
[...] The format of a transferable
secret key is the same as a transferable public key except that
secret-key and secret-subkey packets are used instead of the public
key and public-subkey packets. Implementations SHOULD include self-
signatures on any user IDs and subkeys, [...]
With other words, the secret key contains the public/private key pair (eg., RSA), but should also contain user IDs and self-signatures. 12.1. Key Structures gives more details on how exported keys are constructed. A helpful tool for understanding the composition of OpenPGP packets are gpg --list-packets [file] or pgpdump [file], which dump the packet structure of their input.
In this case the secret key is a private key. The private key can be used for signing or decryption. Encryption and verification is performed using the public key of the other party. A secret key is nowadays mostly thought of to be a symmetric key, but it can also mean private, especially in older protocols.
There is a lot of this kind of confusion in cryptography, the best thing to do is to look at the context. For instance, if there is a public key, the key cannot be symmetric.

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