skeeto / passphrase2pgp

Generate a PGP key from a passphrase
The Unlicense
187 stars 14 forks source link

Request #2

Open PowerPress opened 5 years ago

PowerPress commented 5 years ago

Would you please consider adding subkey encryption keys being created and restored with this tool? I Know its not ideal but it would be a big help to people using Tails OS for Amnesia and not having to trust loading their keys of potentially malicious usb devices. That could really help a lot of people in dangerous countries or even the UK which can require people to hand over a password if an GPG key is found.

skeeto commented 5 years ago

There's a --subkey (-s) option for this. An encryption subkey is always generated. It's just not output by default. Is this insufficient?

PowerPress commented 5 years ago

I believe it is but I want to make sure I full get it. Would mind sharing the exact command I would run to to create the key@foo.com and restore the key after tails reboots so I could use it for decryption of emails?

On Wed, Sep 18, 2019 at 8:59 AM Christopher Wellons < notifications@github.com> wrote:

There's a --subkey (-s) option for this. An encryption subkey is always generated. It's just not output by default. Is this insufficient?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/skeeto/passphrase2pgp/issues/2?email_source=notifications&email_token=ABQHJ32QGB2M5XIKL3IJDPLQKIX2PA5CNFSM4IX65EY2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD7AFBIY#issuecomment-532697251, or mute the thread https://github.com/notifications/unsubscribe-auth/ABQHJ3YDWGTSFGLJ6Z5FZX3QKIX2PANCNFSM4IX65EYQ .

skeeto commented 5 years ago

First generate the key. I've used an empty passphrase so you can do the same to see exactly the same output.

$ passphrase2pgp --subkey --uid key@foo.com | gpg --import
passphrase: 
passphrase (repeat): 
gpg: /home/foo/.gnupg/trustdb.gpg: trustdb created
gpg: key BFB69BB42424AA60: public key "key@foo.com" imported
gpg: key BFB69BB42424AA60: secret key imported
gpg: Total number processed: 1
gpg:               imported: 1
gpg:       secret keys read: 1
gpg:  secret keys unchanged: 1

Note, this doesn't protect the key with a passphrase, so it will be stored unencrypted on the GnuPG keyring. Whether or not that matters depends on your computer's configuration and how you use your computer. Use passphrase2pgp's --protect (-e) option to add protection if needed. (I really wish GnuPG had an option to add protection to secret keys as they're being imported. Sadly, it does not.)

So far everything looks good. We've got an a sign/certify/authenticate Ed25519 primary key and an encryption Curve25519 subkey:

$ gpg --list-keys
/home/foo/.gnupg/pubring.kbx
------------------------------
pub   ed25519 1970-01-01 [SCA]
      32FE19AE744B5F668F299CBABFB69BB42424AA60
uid           [ unknown] key@foo.com
sub   cv25519 1970-01-01 [E]

If you have a notion of what your fingerprint should be, listing the keys like this will let you triple check that you've entered your passphrase correctly.

Now to encrypt a message, hello.txt. It will prompt me about trust since imported keys aren't trusted by default. To disable this, use GnuPG's --trusted-key, select a different --trust-model, or use --edit-key to change the trust on your key. (There's nothing passphrase2pgp can do to force a key to be trusted.)

$ echo hello > hello.txt
$ gpg --encrypt --recipient key@foo.com hello.txt 
gpg: 971FB333228465B2: There is no assurance this key belongs to the named user

sub  cv25519/971FB333228465B2 1970-01-01 key@foo.com
 Primary key fingerprint: 32FE 19AE 744B 5F66 8F29  9CBA BFB6 9BB4 2424 AA60
      Subkey fingerprint: 526A C547 E142 64D6 7448  F9B1 971F B333 2284 65B2

It is NOT certain that the key belongs to the person named
in the user ID.  If you *really* know what you are doing,
you may answer the next question with yes.

Use this key anyway? (y/N) y

That produces hello.txt.gpg. In another session, you can regenerate the key per the above instructions, and then decrypt like so:

$ gpg --decrypt hello.txt.gpg 
gpg: encrypted with 256-bit ECDH key, ID 971FB333228465B2, created 1970-01-01
      "key@foo.com"
hello
PowerPress commented 5 years ago

Awesome Thanks! May I forward this email to the tails mailing list to request inclusion and how easy it is do?

On Wed, Sep 18, 2019 at 9:32 AM Christopher Wellons < notifications@github.com> wrote:

First generate the key. I've used an empty passphrase so you can do the same to see exactly the same output.

$ passphrase2pgp --subkey --uid key@foo.com | gpg --import passphrase: passphrase (repeat): gpg: /home/foo/.gnupg/trustdb.gpg: trustdb created gpg: key BFB69BB42424AA60: public key "key@foo.com" imported gpg: key BFB69BB42424AA60: secret key imported gpg: Total number processed: 1 gpg: imported: 1 gpg: secret keys read: 1 gpg: secret keys unchanged: 1

Note, this doesn't protect the key with a passphrase, so it will be stored unencrypted on the GnuPG keyring. Whether or not that matters depends on your computer's configuration and how you use your computer. Use passphrase2pgp's --protect (-e) option to add protection if needed. (I really wish GnuPG had an option to add protection to secret keys as they're being imported. Sadly, it does not.)

So far everything looks good. We've got an a sign/certify/authenticate Ed25519 primary key and an encryption Curve25519 subkey:

$ gpg --list-keys /home/foo/.gnupg/pubring.kbx

pub ed25519 1970-01-01 [SCA] 32FE19AE744B5F668F299CBABFB69BB42424AA60 uid [ unknown] key@foo.com sub cv25519 1970-01-01 [E]

If you have a notion of what your fingerprint should be, listing the keys like this will let you triple check that you've entered your passphrase correctly.

Now to encrypt a message, hello.txt. It will prompt me about trust since imported keys aren't trusted by default. To disable this, use GnuPG's --trusted-key, select a different --trust-model, or use --edit-key to change the trust on your key. (There's nothing passphrase2pgp can do to force a key to be trusted.)

$ echo hello > hello.txt $ gpg --encrypt --recipient key@foo.com hello.txt gpg: 971FB333228465B2: There is no assurance this key belongs to the named user

sub cv25519/971FB333228465B2 1970-01-01 key@foo.com Primary key fingerprint: 32FE 19AE 744B 5F66 8F29 9CBA BFB6 9BB4 2424 AA60 Subkey fingerprint: 526A C547 E142 64D6 7448 F9B1 971F B333 2284 65B2

It is NOT certain that the key belongs to the person named in the user ID. If you really know what you are doing, you may answer the next question with yes.

Use this key anyway? (y/N) y

That produces hello.txt.gpg. In another session, you can regenerate the key per the above instructions, and then decrypt like so:

$ gpg --decrypt hello.txt.gpg gpg: encrypted with 256-bit ECDH key, ID 971FB333228465B2, created 1970-01-01 "key@foo.com" hello

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/skeeto/passphrase2pgp/issues/2?email_source=notifications&email_token=ABQHJ3ZEE3IFGQREXNRKARLQKI3W5A5CNFSM4IX65EY2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD7AIWGQ#issuecomment-532712218, or mute the thread https://github.com/notifications/unsubscribe-auth/ABQHJ3YMQ7P5ANCCDLHLEKDQKI3W5ANCNFSM4IX65EYQ .

skeeto commented 5 years ago

Sure, you can consider my response here as being under the exact same license as the project itself (UNLICENSE public domain dedication). Transform and share it in whatever way is convenient.

jonathancross commented 3 years ago

Is it possible to generate sign + authenticate as subkeys?

skeeto commented 3 years ago

There's no technical barrier to this, though passphrase2pgp isn't currently set up to do it. It would require deriving additional key material for the additional subkeys.

However, I'm trying to imagine the use case and workflow for this. As I see it: You derive a primary key and a signing subkey, publish your primary public key, load the subkey into GnuPG, then destroy the primary key. The primary key is safe since it's never instantiated during regular use. If you lose your subkey then you can regenerate it. Similarly you can also generate a revocation certificate on demand using only your passphrase.

However, if the purpose is to protect the primary key, and the signing subkey was compromised, then what? It's still bound to your passphrase and now you have to remember not to use it (read: error prone).

If I've understood this correctly then it makes more sense to generate a short-term random subkey rather than to derive it from the passphrase. In that model you load your passphrase-derived primary key into GnuPG, use GnuPG to generate a signing subkey, destroy your primary key, then use the subkey for day-to-day signing.

If you lose the subkey, just generate a new one as before. Your identity is intact since it's still authenticated by the primary key. I believe you can still generate a revocation certificate using the primary key so long as you still have access to at least the public subkey. If you set a short expiration date then you don't even need to worry about this much. So the only advantage I can see is that you can recover a signing subkey, but those are disposable in nature anyway.

I haven't needed this yet, but I've had similar thoughts about encryption "session" subkeys used for a single conversation thread, then discarded:

https://github.com/skeeto/dotfiles/blob/7e22d9f/bin/gensession

Side note: Revisiting this now, I realize that without also generating a signing "session" subkey that message origin can't be authenticated back to the primary key. Then to also protect against non-repudiation attacks, the signing session private subkey would need to be published when the conversation completes in order to deliberately compromise it, providing repudiation. (Actually doing all this with GnuPG would be a lot of manual, error-prone work.)

jonathancross commented 3 years ago

I was thinking that this could be used to generate so-called "Laptop Keys" (subkeys with striped primary key) on an air-gapped machine while having a simple backup / restore method for the private keys. Passphrase could just be written on paper, so no storage would be needed if I am understanding correctly.

In my case I have a primary [C] key and 3 subkeys [S],[E],[A] and the backup from the air-gapped machine is challenging / error-prone. The 3 subkeys are loaded onto a hardware device such as Yubikey for everyday use.

I'd like my next key to use Curve25519 and have a more future-proof, simple, paper backup (without trusting a printer). Trying to figure out if passphrase2pgp would be the way to go as there doesn't seem to be a good mnemonic standard (like we have in Bitcoin's BIP39).