om_crypto_types/bls12381/
pop.rs1use std::{
7 fmt,
8 io::{Read, Write},
9};
10
11use blst::BLST_ERROR;
12use serde::{Deserialize, Deserializer, Serialize, Serializer};
13
14use crate::{
15 bls12381::{DST_BLS_POP_IN_G1, PrivateKey, PublicKey},
16 error::{CryptoError, CryptoResult},
17 io::{Export, Import},
18};
19
20#[derive(Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord)]
26pub struct ProofOfPossession {
27 pub(crate) pop: [u8; Self::LENGTH],
28}
29
30impl Serialize for ProofOfPossession {
31 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
32 where
33 S: Serializer,
34 {
35 if serializer.is_human_readable() {
36 serializer.serialize_str(&hex::encode(self.pop))
37 } else {
38 serializer.serialize_bytes(&self.pop)
39 }
40 }
41}
42
43impl<'de> Deserialize<'de> for ProofOfPossession {
44 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
45 where
46 D: Deserializer<'de>,
47 {
48 if deserializer.is_human_readable() {
49 let s: String = String::deserialize(deserializer)?;
50 let bytes = hex::decode(s.trim_start_matches("0x")).map_err(serde::de::Error::custom)?;
51 Self::from_bytes(&bytes).map_err(serde::de::Error::custom)
52 } else {
53 let bytes: Vec<u8> = Vec::deserialize(deserializer)?;
54 Self::from_bytes(&bytes).map_err(serde::de::Error::custom)
55 }
56 }
57}
58
59impl ProofOfPossession {
60 pub const LENGTH: usize = 48;
62
63 pub fn create(private_key: &PrivateKey, public_key: &PublicKey) -> Self {
68 let pk_bytes = public_key.to_bytes();
69 let pop = private_key.key.sign(&pk_bytes, DST_BLS_POP_IN_G1, &[]);
70 Self { pop: pop.to_bytes() }
71 }
72
73 pub fn verify(&self, public_key: &PublicKey) -> CryptoResult<()> {
78 let pop = blst::min_sig::Signature::from_bytes(&self.pop)
79 .map_err(|_| CryptoError::ProofOfPossessionError("invalid PoP bytes".to_string()))?;
80
81 let pk = blst::min_sig::PublicKey::from_bytes(&public_key.key)
82 .map_err(|_| CryptoError::InvalidPublicKey("invalid BLS public key bytes".to_string()))?;
83
84 let pk_bytes = public_key.to_bytes();
85
86 let result = pop.verify(true, &pk_bytes, DST_BLS_POP_IN_G1, &[], &pk, true);
88
89 if result == BLST_ERROR::BLST_SUCCESS {
90 Ok(())
91 } else {
92 Err(CryptoError::ProofOfPossessionError(format!(
93 "verification failed: {:?}",
94 result
95 )))
96 }
97 }
98
99 pub fn to_bytes(&self) -> [u8; Self::LENGTH] {
101 self.pop
102 }
103
104 pub fn from_bytes(bytes: &[u8]) -> CryptoResult<Self> {
109 if bytes.len() != Self::LENGTH {
110 return Err(CryptoError::ProofOfPossessionError("invalid PoP length".to_string()));
111 }
112 let pop = <[u8; Self::LENGTH]>::try_from(bytes)
113 .map_err(|_| CryptoError::ProofOfPossessionError("invalid PoP".to_string()))?;
114 Ok(Self { pop })
115 }
116
117 pub fn subgroup_check(&self) -> CryptoResult<()> {
122 let pop = blst::min_sig::Signature::from_bytes(&self.pop)
123 .map_err(|_| CryptoError::ProofOfPossessionError("invalid PoP bytes".to_string()))?;
124 pop.validate(true)
125 .map_err(|e| CryptoError::ProofOfPossessionError(format!("subgroup check failed: {:?}", e)))
126 }
127}
128
129impl fmt::Display for ProofOfPossession {
130 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131 write!(f, "0x{}", hex::encode(self.pop))
132 }
133}
134
135impl Export<true> for ProofOfPossession {
136 fn export<W: Write>(&self, writer: &mut W) -> crate::io::Result<()> {
137 self.to_bytes().as_slice().export(writer)
138 }
139}
140
141impl Import<true> for ProofOfPossession {
142 fn import<R: Read>(reader: &mut R) -> crate::io::Result<Self> {
143 let bytes = Vec::<u8>::import(reader)?;
144 Self::from_bytes(&bytes)
145 .map_err(|e| crate::io::IoError::Other(format!("Failed to import BLS proof of possession: {}", e)))
146 }
147}
148
149#[cfg(test)]
150mod tests {
151 use rand::rngs::OsRng;
152
153 use super::*;
154
155 #[test]
156 fn test_pop_create_and_verify() {
157 let mut rng = OsRng;
158 let sk = PrivateKey::generate(&mut rng);
159 let pk = PublicKey::from(&sk);
160
161 let pop = ProofOfPossession::create(&sk, &pk);
162 assert!(pop.verify(&pk).is_ok());
163 }
164
165 #[test]
166 fn test_pop_verify_wrong_key() {
167 let mut rng = OsRng;
168 let sk1 = PrivateKey::generate(&mut rng);
169 let sk2 = PrivateKey::generate(&mut rng);
170 let pk1 = PublicKey::from(&sk1);
171 let pk2 = PublicKey::from(&sk2);
172
173 let pop1 = ProofOfPossession::create(&sk1, &pk1);
174
175 assert!(pop1.verify(&pk2).is_err());
177 }
178
179 #[test]
180 fn test_pop_serialization() {
181 let mut rng = OsRng;
182 let sk = PrivateKey::generate(&mut rng);
183 let pk = PublicKey::from(&sk);
184
185 let pop1 = ProofOfPossession::create(&sk, &pk);
186 let pop_bytes = pop1.to_bytes();
187 let pop2 = ProofOfPossession::from_bytes(&pop_bytes).unwrap();
188
189 assert_eq!(pop1, pop2);
190 assert!(pop2.verify(&pk).is_ok());
191 }
192
193 #[test]
194 fn test_pop_multiple_validators() {
195 let mut rng = OsRng;
196 let num_validators = 10;
197
198 for _ in 0..num_validators {
199 let sk = PrivateKey::generate(&mut rng);
200 let pk = PublicKey::from(&sk);
201 let pop = ProofOfPossession::create(&sk, &pk);
202
203 assert!(pop.verify(&pk).is_ok());
204 }
205 }
206}