1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
use ed25519_dalek::{Signer, Verifier};
use serde::{Deserialize, Serialize};
/// Public key wrapper
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct PublicKey(pub [u8; 32]);
/// Secret key wrapper
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SecretKey(pub [u8; 32]);
/// Key pair for signing
#[derive(Debug, Clone)]
pub struct KeyPair {
pub public: PublicKey,
pub secret: SecretKey,
signing_key: ed25519_dalek::SigningKey,
}
impl KeyPair {
/// Generate new random keypair
pub fn generate() -> Self {
use rand::RngCore;
let mut rng = rand::thread_rng();
let mut secret_bytes = [0u8; 32];
rng.fill_bytes(&mut secret_bytes);
let signing_key = ed25519_dalek::SigningKey::from_bytes(&secret_bytes);
let verifying_key = signing_key.verifying_key();
Self {
public: PublicKey(verifying_key.to_bytes()),
secret: SecretKey(signing_key.to_bytes()),
signing_key,
}
}
/// Sign a message
pub fn sign(&self, message: &[u8]) -> [u8; 64] {
self.signing_key.sign(message).to_bytes()
}
/// Verify a signature
pub fn verify(public_key: &PublicKey, message: &[u8], signature: &[u8; 64]) -> bool {
let verifying_key = match ed25519_dalek::VerifyingKey::from_bytes(&public_key.0) {
Ok(key) => key,
Err(_) => return false,
};
let sig = ed25519_dalek::Signature::from_bytes(signature);
verifying_key.verify(message, &sig).is_ok()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_keypair_generation() {
let keypair = KeyPair::generate();
assert_ne!(keypair.public.0, [0u8; 32]);
assert_ne!(keypair.secret.0, [0u8; 32]);
}
#[test]
fn test_sign_verify() {
let keypair = KeyPair::generate();
let message = b"Hello, OnionCoin!";
let signature = keypair.sign(message);
assert!(KeyPair::verify(&keypair.public, message, &signature));
}
#[test]
fn test_verify_invalid_signature() {
let keypair = KeyPair::generate();
let message = b"Hello, OnionCoin!";
let wrong_sig = [0u8; 64];
assert!(!KeyPair::verify(&keypair.public, message, &wrong_sig));
}
}
|