hypercore/crypto/
key_pair.rs

1//! Generate an `Ed25519` keypair.
2
3use ed25519_dalek::{Signature, Signer, SigningKey, Verifier, VerifyingKey};
4use rand::rngs::OsRng;
5
6use crate::HypercoreError;
7
8/// Key pair where for read-only hypercores the secret key can also be missing.
9#[derive(Debug, Clone)]
10pub struct PartialKeypair {
11    /// Public key
12    pub public: VerifyingKey,
13    /// Secret key. If None, the hypercore is read-only.
14    pub secret: Option<SigningKey>,
15}
16
17/// Generate a new `Ed25519` key pair.
18pub fn generate() -> SigningKey {
19    let mut csprng = OsRng;
20    SigningKey::generate(&mut csprng)
21}
22
23/// Sign a byte slice using a keypair's private key.
24pub fn sign(signing_key: &SigningKey, msg: &[u8]) -> Signature {
25    signing_key.sign(msg)
26}
27
28/// Verify a signature on a message with a keypair's public key.
29pub fn verify(
30    public: &VerifyingKey,
31    msg: &[u8],
32    sig: Option<&Signature>,
33) -> Result<(), HypercoreError> {
34    match sig {
35        None => Err(HypercoreError::InvalidSignature {
36            context: "No signature provided.".to_string(),
37        }),
38        Some(sig) => {
39            if public.verify(msg, sig).is_ok() {
40                Ok(())
41            } else {
42                Err(HypercoreError::InvalidSignature {
43                    context: "Signature could not be verified.".to_string(),
44                })
45            }
46        }
47    }
48}
49
50#[test]
51fn can_verify_messages() {
52    let signing_key = generate();
53    let from = b"hello";
54    let sig = sign(&signing_key, from);
55    verify(&signing_key.verifying_key(), from, Some(&sig)).unwrap();
56    verify(&signing_key.verifying_key(), b"oops", Some(&sig)).unwrap_err();
57}