[−][src]Crate keynesis
Keynesis: key management for signing and e2e communication
Keynesis leverage the curve25519 and ed25519 to provide some keys and APIs to use for different purpose
Identity
The identity is the pivot component of the scheme. It is the root keys
from which everything can be derived. There is a PrivateIdentity
and a
PublicIdentity
. The PrivateIdentity
key needs to be kept private while the
PublicIdentity
can be safely shared... "Publicly".
Conveniently, the PrivateIdentity
exposes the shield
method to safely
password protect the content of the PrivateIdentity
. The scheme uses
(HMAC PBKDF2 with 10_000 iteration to derive the password into the key of
32 bytes long and a salt of 16 bytes long; for the encryption we use
ChaCha20Poly1305 with a nonce of 12 bytes).
use keynesis::PrivateIdentity; let private_id = PrivateIdentity::new(&mut secure_rng()); let public_id = private_id.public_id(); println!("Public Identity: {}", public_id); let shielded_private_id = private_id.shield(&mut secure_rng(), PASSWORD); println!("Shielded Private Identity: {}", shielded_private_id);
Signing Keys
From the PrivateIdentity
it is possible to "derive" the PrivateSigningKey
.
This key can then be used to sign messages that can be verified with the
associated VerifyPublicKey
. This key can be retrieved from the PrivateSigningKey
or it can be derived from the PublicIdentity
.
let signing_key = private_id.signing_key(); let verify_key = public_id.verify_key(); let signature = signing_key.sign(MESSAGE); assert!(verify_key.verify(&signature, MESSAGE));
Establishing secure stream
Now it is possible to generate a SharedSecret
between 2 PrivateIdentity
owners
so long they have each other's PublicIdentity
. To do so we will can generate keys
from the identity keys using an arbitrarily defined scheme to generate a
derivation path.
Alice's and Bob's generating each other's key
First alice will generate her key and send the PublicIdentity
to Bob.
use keynesis::PrivateIdentity; let alice_private_id = PrivateIdentity::new(&mut secure_rng()); let alice_public_id = alice_private_id.public_id(); // send `alice_public_id` to Bob
Then Bob does the same and send the PublicIdentity
to Alice.
use keynesis::PrivateIdentity; let bob_private_id = PrivateIdentity::new(&mut secure_rng()); let bob_public_id = bob_private_id.public_id(); // send `bob_public_id` to Alice
Generating the keys to establish a shared secret
Now that they both have each other's PublicIdentity
they can
generate each other's public key. Let say Alice is the initiator
of the channel and tells Bob to generate a SharedSecret
to
establish an encrypted connection with the nonce.
Alice will have generate the secret key as follow:
let alice_path = format!("/keynesis/alice/bob/{}", NONCE); let bob_path = format!("/keynesis/bob/alice/{}", NONCE); let alice_private_key = alice_private_id.derive(&alice_path); let bob_public_key = bob_public_id.derive(&bob_path); let alice_shared_secret = alice_private_key.exchange(&bob_public_key);
Once the request received by Bob (the nonce), bob can derived the appropriate key on her side:
let alice_path = format!("/keynesis/alice/bob/{}", NONCE); let bob_path = format!("/keynesis/bob/alice/{}", NONCE); let bob_private_key = bob_private_id.derive(&bob_path); let alice_public_key = alice_public_id.derive(&alice_path); let bob_shared_secret = bob_private_key.exchange(&alice_public_key);
Now these 2 shared secrets (alice's and bob's) are both the same.
assert_eq!(alice_shared_secret, bob_shared_secret);
The SharedSecret
can now be used to seed a symmetric cipher, ChaCha20
for example (don't forget an extra random nonce to make the cipher more
secure).
Understanding the link between Identity and the other keys
We use the PrivateIdentity
and PublicIdentity
as root keys. From
there we derive the other keys. It's much like with BIP32 and HD Wallet
for cryptocurrencies except that instead of using 32bits integer as
derivation index, we accept any array as derivation index. Allowing
512bits of derivation possibilities per derivation levels.
+--------+ +--------+
|Private +- - - - - - - - - - - - - - - - - - - - - - ->+Public |
|Identity| |Identity|
++-----+-+ +-+---+--+
| | | |
| | | |
| | +----------+ +---------+ | |
| | |Private | |Public | | |
| +---->+SigningKey+- - - - - - ->+VerifyKey+<-------+ |
| +----------+ +---------+ |
| |
| |
| |
| |
| +-------+ +-------+ |
| |Private| |Public | |
+---->+Key +- - - - - - - - - - - - - -->+Key +<-------+
| +-------+ +-------+ |
| |
| +-------+ +-------+ |
| |Private| |Public | |
+---->+Key +- - - - - - - - - - - - - -->+Key +<-------+
| +-------+ +-------+ |
| |
| +-------+ +-------+ |
| |Private| |Public | |
+---->+Key +- - - - - - - - - - - - - -->+Key <--------+
+-------+ +-------+
+---------------------+
| +-----> Derivation |
| |
| - - --> To Public |
| |
+---------------------+
Re-exports
pub use self::key::ed25519_extended::Signature; |
Modules
key | Keynesis's Keys |
memsec |
Structs
PrivateIdentity | private identity, to keep close to you, privately and securely |
PrivateSigningKey | The Signing Key associated to your |
PublicIdentity | Public identity |
PublicKey | Public key to use for key exchange |
PublicVerifyKey | The Verify Key associated to the |
SecretKey | Secret key to use for key exchange |
SharedSecret | A Shared Secret that can be used to generate a symmetric key |
Shielded |