ruvector_dag/qudag/crypto/
identity.rs1use super::{
4 MlDsa65, MlDsa65PublicKey, MlDsa65SecretKey, MlKem768, MlKem768PublicKey, MlKem768SecretKey,
5};
6
7pub struct QuDagIdentity {
8 pub node_id: String,
9 pub kem_public: MlKem768PublicKey,
10 pub kem_secret: MlKem768SecretKey,
11 pub dsa_public: MlDsa65PublicKey,
12 pub dsa_secret: MlDsa65SecretKey,
13}
14
15impl QuDagIdentity {
16 pub fn generate() -> Result<Self, IdentityError> {
17 let (kem_public, kem_secret) =
18 MlKem768::generate_keypair().map_err(|_| IdentityError::KeyGenerationFailed)?;
19
20 let (dsa_public, dsa_secret) =
21 MlDsa65::generate_keypair().map_err(|_| IdentityError::KeyGenerationFailed)?;
22
23 let node_id = Self::hash_to_id(&kem_public.0[..32]);
25
26 Ok(Self {
27 node_id,
28 kem_public,
29 kem_secret,
30 dsa_public,
31 dsa_secret,
32 })
33 }
34
35 pub fn sign(&self, message: &[u8]) -> Result<Vec<u8>, IdentityError> {
36 let sig =
37 MlDsa65::sign(&self.dsa_secret, message).map_err(|_| IdentityError::SigningFailed)?;
38 Ok(sig.0.to_vec())
39 }
40
41 pub fn verify(&self, message: &[u8], signature: &[u8]) -> Result<bool, IdentityError> {
42 if signature.len() != super::ml_dsa::ML_DSA_65_SIGNATURE_SIZE {
43 return Err(IdentityError::InvalidSignature);
44 }
45
46 let mut sig_array = [0u8; super::ml_dsa::ML_DSA_65_SIGNATURE_SIZE];
47 sig_array.copy_from_slice(signature);
48
49 MlDsa65::verify(
50 &self.dsa_public,
51 message,
52 &super::ml_dsa::Signature(sig_array),
53 )
54 .map_err(|_| IdentityError::VerificationFailed)
55 }
56
57 pub fn encrypt_for(
58 &self,
59 recipient_pk: &[u8],
60 plaintext: &[u8],
61 ) -> Result<Vec<u8>, IdentityError> {
62 if recipient_pk.len() != super::ml_kem::ML_KEM_768_PUBLIC_KEY_SIZE {
63 return Err(IdentityError::InvalidPublicKey);
64 }
65
66 let mut pk_array = [0u8; super::ml_kem::ML_KEM_768_PUBLIC_KEY_SIZE];
67 pk_array.copy_from_slice(recipient_pk);
68
69 let encap = MlKem768::encapsulate(&MlKem768PublicKey(pk_array))
70 .map_err(|_| IdentityError::EncryptionFailed)?;
71
72 let mut ciphertext = encap.ciphertext.to_vec();
74 for (i, byte) in plaintext.iter().enumerate() {
75 ciphertext.push(*byte ^ encap.shared_secret[i % 32]);
76 }
77
78 Ok(ciphertext)
79 }
80
81 pub fn decrypt(&self, ciphertext: &[u8]) -> Result<Vec<u8>, IdentityError> {
82 if ciphertext.len() < super::ml_kem::ML_KEM_768_CIPHERTEXT_SIZE {
83 return Err(IdentityError::InvalidCiphertext);
84 }
85
86 let mut ct_array = [0u8; super::ml_kem::ML_KEM_768_CIPHERTEXT_SIZE];
87 ct_array.copy_from_slice(&ciphertext[..super::ml_kem::ML_KEM_768_CIPHERTEXT_SIZE]);
88
89 let shared_secret = MlKem768::decapsulate(&self.kem_secret, &ct_array)
90 .map_err(|_| IdentityError::DecryptionFailed)?;
91
92 let encrypted_data = &ciphertext[super::ml_kem::ML_KEM_768_CIPHERTEXT_SIZE..];
94 let plaintext: Vec<u8> = encrypted_data
95 .iter()
96 .enumerate()
97 .map(|(i, &b)| b ^ shared_secret[i % 32])
98 .collect();
99
100 Ok(plaintext)
101 }
102
103 fn hash_to_id(data: &[u8]) -> String {
104 let hash: u64 = data
105 .iter()
106 .fold(0u64, |acc, &b| acc.wrapping_mul(31).wrapping_add(b as u64));
107 format!("qudag_{:016x}", hash)
108 }
109}
110
111#[derive(Debug, thiserror::Error)]
112pub enum IdentityError {
113 #[error("Key generation failed")]
114 KeyGenerationFailed,
115 #[error("Signing failed")]
116 SigningFailed,
117 #[error("Verification failed")]
118 VerificationFailed,
119 #[error("Invalid signature")]
120 InvalidSignature,
121 #[error("Invalid public key")]
122 InvalidPublicKey,
123 #[error("Encryption failed")]
124 EncryptionFailed,
125 #[error("Decryption failed")]
126 DecryptionFailed,
127 #[error("Invalid ciphertext")]
128 InvalidCiphertext,
129}