Using Rust to seed RSA and X25519 cryptographic keys wrapped in a GPG certificate

4/3/2021

Sometime last year, I backed the DiceKeys project, and last month, my dice arrived. To summarize, there are 25 dice, each with 6 possible faces and 4 possible orientations, adding up to an astronomical number of possible combinations. The pitch is that you roll these dice generating real-world entropy, then lock them in place and put them somewhere safe. You then use the rolled dice as a seed to generate passphrases from, using what they call recipes (think of them as hash functions that produce passphrases).

So how is this different than using a password manager and why would you go through all the trouble? First, the dice aren't meant to replace your password manager, but can be used, for instance, to produce the primary passphrase you use with one. If you ever forget your passphrase, you just run your recipe again and regenerate the same passphrase. And from time to time, when you should update your password manager's primary passphrase, you just need to run the recipe with a different iteration value, which will result in a new seed, and thus, produce a new passphrase. It reduces cognitive load by providing a secure default process for passphrase generation. This makes it easier not to reuse the same primary passphrase with your personal password manager, your business password manager, your storage encryption, or anything else. It also makes it easier to rotate those passwords once in a while.

You don't even need to buy the physical dice, you can try the concept for yourself at https://dicekeys.app/. But you could, for instance, put the physical dice in a vault or safety security box.

A sample dice roll using DiceKeys

Anyway, the software that supports the dice (including that website) is all open source but also fairly rudimentary. It's just an arbitrary application of the entropy that the dice generate by a function that produces passphrases; but what if you want to do something else with that entropy, like generate a reproducible cryptographic key? Turns out nobody wants you to do that and tools like openssl and gpg don't have any support for it, which made me want to do it all the more.

First, let me  say that I think it's a very bad idea to seed a cryptographic key with a normal password. The reason it's safe to generate RSA or X25519 keys and feel reasonably certain that the key will be unique is that their algorithms are seeded by cryptographically secure pseudorandom number generators (CSPRNG). Now if we start using passwords to seed with instead, we dramatically reduce the pool of keys that are likely to be generated (due to average password lengths and characters), and thus, increase the chances of keys colliding. That being said, 1) I'm using the SHA hash of a passphrase, 2) I'm generating the passphrase itself from a source of real entropy, and 3) this seems to be a very niche thing to do so I'm not too worried about colliding against others doing it.

Okay, so how can we create keys from a passphrase? If you want to cheat, you can just install Rust then run cargo install cfs_openpgp, which will download cfs_openpgp, a little program I wrote for this purpose. 

Here's a full usage example:

cfs_openpgp --username "Alice" --email "alice@example.com" --key-sig-time 0 --weeks-subkeys-exp-in 52 --secret "a super-secure secret phrase that's been generated from real entropy"

This command will output the ASCII-armored presentation of the PGP private certificate, public certificate, revocation signature, and each attached key and fingerprints (separate keys for certifying, signing, and encrypting, and two for authentication (RSA and x25519). The associated user will be alice@example.com, all keys will be signed as having been generated in 1970, and the subkeys will expire in a year. I've attached some sample output at the end of this post.

Honestly, it's just a thin wrapper around the sequoia_openpgp library (much thanks to Neal Walfield of the Sequoia project, who answered a million of my questions about the library). The code boils down to the generator functions. For instance, here's the one for the Ed25519 key:

pub fn ed25519_key_from_seed(salt: &str) -> Key<SecretParts, SubordinateRole> {
    let mut secret_phrase: String = get_secret_phrase();
    secret_phrase.push_str(salt);
    let key_from_seed = ed25519_private_key(&mut Yarrow::from_seed(&*Sha512::digest(
        secret_phrase.as_bytes(),
    )));
    Key::from(
        Key4::<SecretParts, SubordinateRole>::import_secret_ed25519(
            &*key_from_seed,
            get_key_creation_time(),
        )
        .unwrap(),
    )
}

On line 4, we set our SHA-hashed salted passphrase as the seed value for the CSPRNG, which results in a reproducible key. Then we wrap the resulting bytes up into a key, sign it, and attach it to our PGP certificate.

And that's all that there is to it. 

The keys are really interesting and are well-suited for corporate use or with cryptocurrency wallets. It was also a great opportunity to continue working with Rust, which is a delight to program with! 

Sample Output

PGP private certificate:

-----BEGIN PGP PRIVATE KEY BLOCK-----
Comment: C8D2 D5C6 D7FE 7FC4 1001  49DA 369E 3B28 10AB 798A
Comment: Alice <alice@example.com>

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
4SI0NzbZxwgHL18CmwICHgG+oAQZFgoAbwWCYGtocwkQYehOHReizqtHFAAAAAAA
HgAgc2FsdEBub3RhdGlvbnMuc2VxdW9pYS1wZ3Aub3Jn29q9F/w9eekkDNRWCOOL
oD+p4fNA66BIibmoxfj4q6kWIQSmlieAbT6NEM3a3GNh6E4dF6LOqwAAjFQA/iAn
5rONCJ+zviRC4mhVC8xJsvw7ctLUdAg68FGJQ54/APwNP4yVVUrmoaKHMLjDdPD8
ywwFAyjYpvCOm0ZM0kD2BBYhBMjS1cbX/n/EEAFJ2jaeOygQq3mKAAAkDQEAv+3b
CI1mGIbOwJGNBkgnZc3AOqqxUmi4dID0QjAUY1oBAONDDS3qeJHBweD3AxP2RoEY
WL6FzQp6/O1IUWJGgwIGx1gEAAAAABYJKwYBBAHaRw8BAQdAgxxaPSWsVTYPJn0U
g5mCc2hv+gG6OjUdHfisYOWUFxMAAP92AA01sopsxey+4musFbrLC+dGBubLHfG2
Zcyt6EIeJRFfwsAJBBgWCgB7BYJga2hzBYliS0pzCRA2njsoEKt5ikcUAAAAAAAe
ACBzYWx0QG5vdGF0aW9ucy5zZXF1b2lhLXBncC5vcmfYVBF5LsL6W9zVZqJ8yI6c
5IYVhTlHB8oTmV0tv/6jOgKbIAIeARYhBMjS1cbX/n/EEAFJ2jaeOygQq3mKAACr
uQEA+XtF9kboaX40BUASoHfP2zQmRapj/Xra9DLFVKeUE5UBAOkBHJErEq2Ucv10
slwmTOz49ZnJU4r4gM0Zc2ojwCoAx10EAAAAABIKKwYBBAGXVQEFAQEHQHF4Cesr
Bng/n2wmAh+50kDuRxB+HzhhSw8XB6a9zmUnAwEKCQAA/3xBvH2D5BM+L6b16VEn
MovQVZy9Pk743LILnDi7n7cwEUXCwAkEGBYKAHsFgmBraHMFiWJLSnMJEDaeOygQ
q3mKRxQAAAAAAB4AIHNhbHRAbm90YXRpb25zLnNlcXVvaWEtcGdwLm9yZ+U2I+ke
dxEwvZpS/GeSkCgOpHUEzx7MhUJiKjHEn/iLApsMAh4BFiEEyNLVxtf+f8QQAUna
Np47KBCreYoAAA51AP0XG+9OBhYm1PgKLZHFXe9/3xyCzQiYiRhEZOQ9itUcJQEA
ko+ZOYbuLgRUjFi6gsMWRztafZdwQZU1m3e2yfzCbQs=
=Gc7q
-----END PGP PRIVATE KEY BLOCK-----

PGP public certificate:

-----BEGIN PGP PUBLIC KEY BLOCK-----
Comment: C8D2 D5C6 D7FE 7FC4 1001  49DA 369E 3B28 10AB 798A
Comment: Alice <alice@example.com>

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
=twPs
-----END PGP PUBLIC KEY BLOCK-----

PGP certificate revocation signature:

-----BEGIN PGP SIGNATURE-----

BCAWCgB9BYJga2hzCRA2njsoEKt5ikcUAAAAAAAeACBzYWx0QG5vdGF0aW9ucy5z
ZXF1b2lhLXBncC5vcme9lZ+FBRS/JqYDhEoa6h9dNvClmx/O+/HQY5xCtvfkdQ0d
AFVuc3BlY2lmaWVkFiEEyNLVxtf+f8QQAUnaNp47KBCreYoAAOAJAQCxAgMlrHdp
xKgXmz9EB7GGjJXph4RqsNsC3BgCLdOswQD9FNlNJC9aw85sFSfeBydKXxBKuWFq
POt6TmHLlwKyzAc=
=1oNh
-----END PGP SIGNATURE-----

Keys:

Key ID C8D2D5C6D7FE7FC4100149DA369E3B2810AB798A (EdDSA Edwards-curve Digital Signature Algorithm): 

-----BEGIN PGP PRIVATE KEY BLOCK-----

x1gEAAAAABYJKwYBBAHaRw8BAQdAieNzsJ+6BApVuk4m/Z9G44MlhdaAXd4DsONp
Y7BWRIcAAQDU2Blrm8eeDIGB4NAfhqIejnRP1CRQnnZw3BstGHy3Bw7n
=xvtm
-----END PGP PRIVATE KEY BLOCK-----



Key ID F09EC7A545C9FC238B594ECD67A479A637224275 (RSA (Encrypt or Sign)): 

-----BEGIN PGP PRIVATE KEY BLOCK-----

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
=x44D
-----END PGP PRIVATE KEY BLOCK-----



Key ID A69627806D3E8D10CDDADC6361E84E1D17A2CEAB (EdDSA Edwards-curve Digital Signature Algorithm): 

-----BEGIN PGP PRIVATE KEY BLOCK-----

x1gEAAAAABYJKwYBBAHaRw8BAQdABk9JqizKg6XrvFCnWBNzyXTgGnbuRkJ3x83D
3a+iLWoAAP9mGNqIDE/Wcs1XHIKQcFTw/AjgZK3RONJqAi5LawKRuw/2
=maQR
-----END PGP PRIVATE KEY BLOCK-----



Key ID 07E13CD52E40EAB51576290F0745B7ABDE0413AA (EdDSA Edwards-curve Digital Signature Algorithm): 

-----BEGIN PGP PRIVATE KEY BLOCK-----

x1gEAAAAABYJKwYBBAHaRw8BAQdAgxxaPSWsVTYPJn0Ug5mCc2hv+gG6OjUdHfis
YOWUFxMAAP92AA01sopsxey+4musFbrLC+dGBubLHfG2Zcyt6EIeJRFf
=vI+g
-----END PGP PRIVATE KEY BLOCK-----



Key ID 2EB11593B2A67320199D163F464746CC47D3CD67 (ECDH public key algorithm): 

-----BEGIN PGP PRIVATE KEY BLOCK-----

x10EAAAAABIKKwYBBAGXVQEFAQEHQHF4CesrBng/n2wmAh+50kDuRxB+HzhhSw8X
B6a9zmUnAwEKCQAA/3xBvH2D5BM+L6b16VEnMovQVZy9Pk743LILnDi7n7cwEUU=
=BJrx
-----END PGP PRIVATE KEY BLOCK-----