What is a PGP Secret Key? - encryption

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.

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.

Public / Private Key Cryptography for offline systems

Hi Crypto experts out there, are there any best practices around distributing an ecnrypted package to multiple end user systems, specially if the end system are offline ones? in context of assymetric crypto.
is it must to create unique pub/pvt key sets [ per end user system] and encrypt the same package many times uniquely with the pub keys, resulting in a specific package per end user system? how will this scale?
will it be a good practice to sign the original private key[ corresponding to pub keys used to encrypt the package] with senders private keys and then enrypt using end user systems pub keys and share it directly with end user? through trusted communication.
or, encrypt the pvt key with end user systems public key, sign with senders private key and re-encrypt[symmetric] this with the hash of certain string uniquely identifying a end user system? This hash should be programtically reproducible using system unique identifiers later during decryption processes. This way, to retreive the original private key to decrypt the package, it will require both a corresponding pub key[end user clients] as well as end user machine [the hash of string to be generated at runtime on end user system.] and senders public key to manage the authenticity?
Thank you for any feedback!
I am not an expert, but as I understand asymmetric encryption, you can generate a key pair in the distribution center.
The private key stays secret in the distribution center.
To each offline client you provide the public key (as a file).
Each client generates a secure password for symmetric encryption, and encrypts it using the public key.
The encrypted symmetric key is sent to the distribution center.
The distribution center should associate the encrypted symmetric password to the client that sent it.
At the time of encrypting the package for the specific client, the distribution center will decrypt the symmetric password using the private key, and use it to encrypt the package.
Then the package can be sent to the client, who will use it's own password to decrypt the package.

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.

Can I use asymmetric encryption with two private keys?

According to wikipedia (and other sources), asymmetric encryption always works like this:
Party A has a public and private key
Party B encrypts stuff with A's public key
Party A decrypts stuff with their private key
However, I don't want party A to be able to encrypt their own data and only want to them to be able to decrypt it. Using the asymmetric logic this would result in:
Party A has a private key
Party B has a private key (which is party A's public key)
Party B encrypts stuff with their private key
Party A decrypts stuff with their private key
We will be using this for some sort of license generation/checking. Our clients may not generate a license, but the license file must be readable on the client side.
Is this still asymmetric encryption or should I be looking at different methods?
Party A being able to encrypt messages using the public key is absolutely no problem.
Only you could decrypt them (with your private key) and since you have no reason to do so encrypting something with the public key embedded in your application would cause no harm - just a bunch of useless data the user has since he cannot decrypt it.
For the licensing you simply encrypt (or sign - that's enough and then people will be able to read the restrictions etc in the license file but not modidy them) your license file using your private key. The application then decrypts the file using the embedded public key (or validates the signature).
A user extracting the public key and signing a custom license file with it could not use it since it would only work if your private key was embedded in the application (since that's the key necessary to decrypt something encrypted with the public key).
However, he could very well replace your public key with a custom one (where he has the private key, too) and then sign/encrypt his own license file using his private key. That's not a cryptographical issue though - you simply need to add some anti-cracking/modification measures to make it harder to replace the embedded public key. You could do some checksum validations for example.
You have your private key in the safe, and publish your public key. When you create a license you encrypt it with your private key. The client can only decrypt it with your public key.
If you want to restrict your license to a client, ask the client to generate their keypair, and send their public key to you. You then encrypt the license with their public key, then sign it (or encrypt it again) with your private key.
When the client receives the license they will have to
1. verify the signature of (or decrypt) the license you sent them
2. decrypt the verified data using their own private key.
This ensures that 1. only you can send them the license and 2. only they can decrypt it.
What you'd generally do is generate you license on your side, and encrypt it with your private key. Then your client can read it using your public key. This is (very broadly speaking) how certificate schemes (such as used in secure online browsing with HTTPS) work. And yes, that still absolutely counts as asymmetric encryption.
Based on what you're saying, asymmetric encryption is still what you want, it just needs to be done in a different way than you're used to thinking about it.
Let's say you generate a key pair for A. You send A one half of the pair: it doesn't really matter but we'll call it the private half. You encrypt using the public half and send it on to A. Then A can decrypt it. But A won't be able to encrypt a message that appears to come from the A public key since they only have the private half of the key and you can't figure out the other half of the key if you only have half of it, no matter which half you have. So A could only encrypt messages that could be decrypted by the public key that you have kept as a secret.
Of course, as other posters have already said, there are better ways to set up this protocol. Just trying to explain why this is not really an issue once you understand the details of asymmetric encryption and look past what we like to call the key halves and how we usually use them.
You could have a look at Rhino licensing : http://hibernatingrhinos.com/open-source/rhino-licensing/introduction
The other answers already said how to do it ... here just a note that (at least with RSA) the scheme you described in your question is not secure, if it depends on B's key staying secret.
For RSA, the public and private keys are really asymmetric, and you can't simply swap them and expect the same security properties.
If your party B (Bob) encrypts multiple messages with the same public key, an attacker which reads these (ciphertext) messages can with little effort get your public key. The attacker does not get the plaintexts or the private key, but the public key will always become really "public".
For A (Alice), it is even possible to create the public key from the private one, without any message being encrypted with the public one.
I suppose similar caveats are there for other asymmetric cryptosystems - always use them only like they are specified, and proven.
In this case, you would combine two key pairs: B's one to sign/verify the message (to make sure the message was sent by B), and A's one to encrypt/decrypt the message (to make sure only A can read it).
Yes. You can do it with RSA - to do a Diffie-Hellman-like exchange, because not only do the keys from 1 associated pair commute, but keys from different keypairs can commute as well.
alice -> bob: alice.pub
bob -> alice: bob.pub
alice: r = random.secret()
alice -> bob: ( r * (alice.priv * bob.pub) )
bob: r = ( (r * (alice.priv * bob.pub)) * (bob.priv * alice.pub) )
Notice that we did something odd here. We mixed RSA operations from different keypairs in one operation. The objects in parenthesis are effectively a new virtual RSA key, and neither one of these keys is public. Had we tried to create that RSA key directly, either alice or bob would know both keys of the pair. This keypair is effectively a secret key where you write to one end and only the other side can decrypt it, yet you cant decrypt what you wrote yourself, and nobody else can encrypt messages to the other side.
I have never seen anyone mix keypairs like this, but I tested this by writing the code. I had to do something unusual though because normally, applying the private key to the message is for 'signing'. But signing usually hashes the secret and applies the private key to a hash of it; something we do not want. So in my code, once I had the RSA components (D,E,N) extracted into arbitrary precision numbers... ie: decrypt,encrypt,modulus ... I just did:
wormholeSend(me,you,msg) =
(((me ^ {me_D}) \% me_N) ^ {you_E}) \% you_N
The thing that makes it a little tricky is that E (encrypt exponent) is actually a predictable value, but the modulus N is in the public key (E,N). D is private to each party. We need to be careful here, because you and I have a different modulus N.
I did this because I wanted a system where a program is authorized to encrypt keys that can be decrypted by users. Doing this, the user cannot encrypt keys, and the program cannot decrypt them.

Resources