shape_runtime/crypto/
signing.rs1use ed25519_dalek::{Signature, Signer, SigningKey, Verifier, VerifyingKey};
7use serde::{Deserialize, Serialize};
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct ModuleSignatureData {
15 pub author_key: [u8; 32],
17 pub signature: Vec<u8>,
20 pub signed_at: u64,
22}
23
24impl ModuleSignatureData {
25 pub fn sign(manifest_hash: &[u8; 32], signing_key: &SigningKey) -> Self {
30 let signature = signing_key.sign(manifest_hash);
31 let author_key = signing_key.verifying_key().to_bytes();
32 Self {
33 author_key,
34 signature: signature.to_bytes().to_vec(),
35 signed_at: std::time::SystemTime::now()
36 .duration_since(std::time::UNIX_EPOCH)
37 .unwrap_or_default()
38 .as_secs(),
39 }
40 }
41
42 pub fn verify(&self, manifest_hash: &[u8; 32]) -> bool {
47 let Ok(verifying_key) = VerifyingKey::from_bytes(&self.author_key) else {
48 return false;
49 };
50 let Ok(sig_bytes): Result<[u8; 64], _> = self.signature.as_slice().try_into() else {
51 return false;
52 };
53 let signature = Signature::from_bytes(&sig_bytes);
54 verifying_key.verify(manifest_hash, &signature).is_ok()
55 }
56}
57
58pub fn sign_manifest_hash(
63 manifest_hash: &[u8; 32],
64 secret_key_bytes: &[u8; 32],
65) -> ModuleSignatureData {
66 let signing_key = SigningKey::from_bytes(secret_key_bytes);
67 ModuleSignatureData::sign(manifest_hash, &signing_key)
68}
69
70pub fn public_key_from_secret(secret_key_bytes: &[u8; 32]) -> [u8; 32] {
72 let signing_key = SigningKey::from_bytes(secret_key_bytes);
73 signing_key.verifying_key().to_bytes()
74}
75
76pub fn generate_keypair() -> (SigningKey, VerifyingKey) {
78 let mut secret = [0u8; 32];
79 use rand::RngCore;
80 rand::thread_rng().fill_bytes(&mut secret);
81 let signing_key = SigningKey::from_bytes(&secret);
82 let verifying_key = signing_key.verifying_key();
83 (signing_key, verifying_key)
84}
85
86pub fn generate_keypair_bytes() -> ([u8; 32], [u8; 32]) {
91 let (signing, verifying) = generate_keypair();
92 (signing.to_bytes(), verifying.to_bytes())
93}
94
95#[cfg(test)]
96mod tests {
97 use super::*;
98
99 #[test]
100 fn test_sign_and_verify() {
101 let (signing_key, _) = generate_keypair();
102 let manifest_hash = [42u8; 32];
103 let sig = ModuleSignatureData::sign(&manifest_hash, &signing_key);
104 assert!(sig.verify(&manifest_hash));
105 }
106
107 #[test]
108 fn test_verify_fails_with_wrong_hash() {
109 let (signing_key, _) = generate_keypair();
110 let manifest_hash = [42u8; 32];
111 let sig = ModuleSignatureData::sign(&manifest_hash, &signing_key);
112 let wrong_hash = [99u8; 32];
113 assert!(!sig.verify(&wrong_hash));
114 }
115
116 #[test]
117 fn test_verify_fails_with_corrupt_signature() {
118 let (signing_key, _) = generate_keypair();
119 let manifest_hash = [42u8; 32];
120 let mut sig = ModuleSignatureData::sign(&manifest_hash, &signing_key);
121 sig.signature[0] ^= 0xFF;
122 assert!(!sig.verify(&manifest_hash));
123 }
124
125 #[test]
126 fn test_verify_fails_with_wrong_key() {
127 let (signing_key, _) = generate_keypair();
128 let (other_key, _) = generate_keypair();
129 let manifest_hash = [42u8; 32];
130 let mut sig = ModuleSignatureData::sign(&manifest_hash, &signing_key);
131 sig.author_key = other_key.verifying_key().to_bytes();
132 assert!(!sig.verify(&manifest_hash));
133 }
134
135 #[test]
136 fn test_signed_at_is_nonzero() {
137 let (signing_key, _) = generate_keypair();
138 let sig = ModuleSignatureData::sign(&[0u8; 32], &signing_key);
139 assert!(sig.signed_at > 0);
140 }
141
142 #[test]
143 fn test_serde_roundtrip() {
144 let (signing_key, _) = generate_keypair();
145 let manifest_hash = [7u8; 32];
146 let sig = ModuleSignatureData::sign(&manifest_hash, &signing_key);
147
148 let json = serde_json::to_string(&sig).expect("serialize");
149 let restored: ModuleSignatureData = serde_json::from_str(&json).expect("deserialize");
150
151 assert_eq!(restored.author_key, sig.author_key);
152 assert_eq!(restored.signature, sig.signature);
153 assert_eq!(restored.signed_at, sig.signed_at);
154 assert!(restored.verify(&manifest_hash));
155 }
156}