commonware_cryptography/bls12381/
scheme.rs1use super::primitives::{
29 group::{self, Private},
30 ops,
31 variant::{MinPk, Variant},
32};
33use crate::{BatchVerifier, Secret, Signer as _};
34#[cfg(not(feature = "std"))]
35use alloc::vec::Vec;
36use bytes::{Buf, BufMut};
37use commonware_codec::{
38 DecodeExt, EncodeFixed, Error as CodecError, FixedSize, Read, ReadExt, Write,
39};
40use commonware_math::algebra::Random;
41use commonware_parallel::Sequential;
42use commonware_utils::{hex, Array, Span};
43use core::{
44 fmt::{Debug, Display, Formatter},
45 hash::{Hash, Hasher},
46 ops::Deref,
47};
48use rand_core::CryptoRngCore;
49use zeroize::Zeroizing;
50
51const CURVE_NAME: &str = "bls12381";
52
53#[derive(Clone, Debug)]
55pub struct PrivateKey {
56 raw: Secret<[u8; group::PRIVATE_KEY_LENGTH]>,
57 key: Private,
58}
59
60impl PartialEq for PrivateKey {
61 fn eq(&self, other: &Self) -> bool {
62 self.raw == other.raw
63 }
64}
65
66impl Eq for PrivateKey {}
67
68impl Write for PrivateKey {
69 fn write(&self, buf: &mut impl BufMut) {
70 self.raw.expose(|raw| raw.write(buf));
71 }
72}
73
74impl Read for PrivateKey {
75 type Cfg = ();
76
77 fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, CodecError> {
78 let raw = Zeroizing::new(<[u8; Self::SIZE]>::read(buf)?);
79 let key =
80 Private::decode(raw.as_ref()).map_err(|e| CodecError::Wrapped(CURVE_NAME, e.into()))?;
81 Ok(Self {
82 raw: Secret::new(*raw),
83 key,
84 })
85 }
86}
87
88impl FixedSize for PrivateKey {
89 const SIZE: usize = group::PRIVATE_KEY_LENGTH;
90}
91
92impl From<Private> for PrivateKey {
93 fn from(key: Private) -> Self {
94 let raw = Zeroizing::new(key.expose(|s| s.encode_fixed()));
95 Self {
96 raw: Secret::new(*raw),
97 key,
98 }
99 }
100}
101
102impl Display for PrivateKey {
103 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
104 write!(f, "{:?}", self)
105 }
106}
107
108impl crate::PrivateKey for PrivateKey {}
109
110impl crate::Signer for PrivateKey {
111 type Signature = Signature;
112 type PublicKey = PublicKey;
113
114 fn public_key(&self) -> Self::PublicKey {
115 PublicKey::from(ops::compute_public::<MinPk>(&self.key))
116 }
117
118 fn sign(&self, namespace: &[u8], msg: &[u8]) -> Self::Signature {
119 ops::sign_message::<MinPk>(&self.key, namespace, msg).into()
120 }
121}
122
123impl Random for PrivateKey {
124 fn random(mut rng: impl CryptoRngCore) -> Self {
125 let (private, _) = ops::keypair::<_, MinPk>(&mut rng);
126 private.into()
127 }
128}
129
130#[cfg(feature = "arbitrary")]
131impl arbitrary::Arbitrary<'_> for PrivateKey {
132 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
133 use rand::{rngs::StdRng, SeedableRng};
134
135 let mut rand = StdRng::from_seed(u.arbitrary::<[u8; 32]>()?);
136 Ok(Self::random(&mut rand))
137 }
138}
139
140impl crate::PublicKey for PublicKey {}
141
142impl crate::Verifier for PublicKey {
143 type Signature = Signature;
144
145 fn verify(&self, namespace: &[u8], msg: &[u8], sig: &Self::Signature) -> bool {
146 ops::verify_message::<MinPk>(&self.key, namespace, msg, &sig.signature).is_ok()
147 }
148}
149
150#[derive(Clone, Eq, PartialEq)]
152pub struct PublicKey {
153 raw: [u8; <MinPk as Variant>::Public::SIZE],
154 key: <MinPk as Variant>::Public,
155}
156
157impl From<PrivateKey> for PublicKey {
158 fn from(private_key: PrivateKey) -> Self {
159 private_key.public_key()
160 }
161}
162
163impl AsRef<<MinPk as Variant>::Public> for PublicKey {
164 fn as_ref(&self) -> &<MinPk as Variant>::Public {
165 &self.key
166 }
167}
168
169impl Write for PublicKey {
170 fn write(&self, buf: &mut impl BufMut) {
171 self.raw.write(buf);
172 }
173}
174
175impl Read for PublicKey {
176 type Cfg = ();
177
178 fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, CodecError> {
179 let raw = <[u8; Self::SIZE]>::read(buf)?;
180 let key = <MinPk as Variant>::Public::decode(raw.as_ref())
181 .map_err(|e| CodecError::Wrapped(CURVE_NAME, e.into()))?;
182 Ok(Self { raw, key })
183 }
184}
185
186impl FixedSize for PublicKey {
187 const SIZE: usize = <MinPk as Variant>::Public::SIZE;
188}
189
190impl Span for PublicKey {}
191
192impl Array for PublicKey {}
193
194impl Hash for PublicKey {
195 fn hash<H: Hasher>(&self, state: &mut H) {
196 self.raw.hash(state);
197 }
198}
199
200impl Ord for PublicKey {
201 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
202 self.raw.cmp(&other.raw)
203 }
204}
205
206impl PartialOrd for PublicKey {
207 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
208 Some(self.cmp(other))
209 }
210}
211
212impl AsRef<[u8]> for PublicKey {
213 fn as_ref(&self) -> &[u8] {
214 &self.raw
215 }
216}
217
218impl Deref for PublicKey {
219 type Target = [u8];
220 fn deref(&self) -> &[u8] {
221 &self.raw
222 }
223}
224
225impl From<<MinPk as Variant>::Public> for PublicKey {
226 fn from(key: <MinPk as Variant>::Public) -> Self {
227 let raw = key.encode_fixed();
228 Self { raw, key }
229 }
230}
231
232impl Debug for PublicKey {
233 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
234 write!(f, "{}", hex(&self.raw))
235 }
236}
237
238impl Display for PublicKey {
239 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
240 write!(f, "{}", hex(&self.raw))
241 }
242}
243
244#[cfg(feature = "arbitrary")]
245impl arbitrary::Arbitrary<'_> for PublicKey {
246 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
247 use crate::Signer;
248 use rand::{rngs::StdRng, SeedableRng};
249
250 let mut rand = StdRng::from_seed(u.arbitrary::<[u8; 32]>()?);
251 let private_key = PrivateKey::random(&mut rand);
252 Ok(private_key.public_key())
253 }
254}
255
256#[derive(Clone, Eq, PartialEq)]
258pub struct Signature {
259 raw: [u8; <MinPk as Variant>::Signature::SIZE],
260 signature: <MinPk as Variant>::Signature,
261}
262
263impl crate::Signature for Signature {}
264
265impl AsRef<<MinPk as Variant>::Signature> for Signature {
266 fn as_ref(&self) -> &<MinPk as Variant>::Signature {
267 &self.signature
268 }
269}
270
271impl Write for Signature {
272 fn write(&self, buf: &mut impl BufMut) {
273 self.raw.write(buf);
274 }
275}
276
277impl Read for Signature {
278 type Cfg = ();
279
280 fn read_cfg(buf: &mut impl Buf, _: &()) -> Result<Self, CodecError> {
281 let raw = <[u8; Self::SIZE]>::read(buf)?;
282 let signature = <MinPk as Variant>::Signature::decode(raw.as_ref())
283 .map_err(|e| CodecError::Wrapped(CURVE_NAME, e.into()))?;
284 Ok(Self { raw, signature })
285 }
286}
287
288impl FixedSize for Signature {
289 const SIZE: usize = <MinPk as Variant>::Signature::SIZE;
290}
291
292impl Span for Signature {}
293
294impl Array for Signature {}
295
296impl Hash for Signature {
297 fn hash<H: Hasher>(&self, state: &mut H) {
298 self.raw.hash(state);
299 }
300}
301
302impl Ord for Signature {
303 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
304 self.raw.cmp(&other.raw)
305 }
306}
307
308impl PartialOrd for Signature {
309 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
310 Some(self.cmp(other))
311 }
312}
313
314impl AsRef<[u8]> for Signature {
315 fn as_ref(&self) -> &[u8] {
316 &self.raw
317 }
318}
319
320impl Deref for Signature {
321 type Target = [u8];
322 fn deref(&self) -> &[u8] {
323 &self.raw
324 }
325}
326
327impl From<<MinPk as Variant>::Signature> for Signature {
328 fn from(signature: <MinPk as Variant>::Signature) -> Self {
329 let raw = signature.encode_fixed();
330 Self { raw, signature }
331 }
332}
333
334impl Debug for Signature {
335 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
336 write!(f, "{}", hex(&self.raw))
337 }
338}
339
340impl Display for Signature {
341 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
342 write!(f, "{}", hex(&self.raw))
343 }
344}
345
346#[cfg(feature = "arbitrary")]
347impl arbitrary::Arbitrary<'_> for Signature {
348 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
349 use crate::Signer;
350 use rand::{rngs::StdRng, SeedableRng};
351
352 let mut rand = StdRng::from_seed(u.arbitrary::<[u8; 32]>()?);
353 let private_key = PrivateKey::random(&mut rand);
354 let len = u.arbitrary::<usize>()? % 256;
355 let message = u
356 .arbitrary_iter()?
357 .take(len)
358 .collect::<Result<Vec<_>, _>>()?;
359
360 Ok(private_key.sign(b"_COMMONWARE_CRYPTOGRAPHY_BLS12381_TEST", &message))
361 }
362}
363
364pub struct Batch {
366 publics: Vec<<MinPk as Variant>::Public>,
367 hms: Vec<<MinPk as Variant>::Signature>,
368 signatures: Vec<<MinPk as Variant>::Signature>,
369}
370
371impl BatchVerifier<PublicKey> for Batch {
372 fn new() -> Self {
373 Self {
374 publics: Vec::new(),
375 hms: Vec::new(),
376 signatures: Vec::new(),
377 }
378 }
379
380 fn add(
381 &mut self,
382 namespace: &[u8],
383 message: &[u8],
384 public_key: &PublicKey,
385 signature: &Signature,
386 ) -> bool {
387 self.publics.push(public_key.key);
388 let hm = ops::hash_with_namespace::<MinPk>(MinPk::MESSAGE, namespace, message);
389 self.hms.push(hm);
390 self.signatures.push(signature.signature);
391 true
392 }
393
394 fn verify<R: CryptoRngCore>(self, rng: &mut R) -> bool {
395 MinPk::batch_verify(rng, &self.publics, &self.hms, &self.signatures, &Sequential).is_ok()
396 }
397}
398
399#[cfg(test)]
400mod tests {
401 use super::*;
402 use crate::{bls12381, Verifier as _};
403 use commonware_codec::{DecodeExt, Encode};
404 use commonware_math::algebra::Random;
405 use commonware_utils::test_rng;
406
407 #[test]
408 fn test_codec_private_key() {
409 let original =
410 parse_private_key("0x263dbd792f5b1be47ed85f8938c0f29586af0d3ac7b977f21c278fe1462040e3")
411 .unwrap();
412 let encoded = original.encode();
413 assert_eq!(encoded.len(), bls12381::PrivateKey::SIZE);
414 let decoded = bls12381::PrivateKey::decode(encoded).unwrap();
415 assert_eq!(original, decoded);
416 }
417
418 #[test]
419 fn test_codec_public_key() {
420 let original =
421 parse_public_key("0xa491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a")
422 .unwrap();
423 let encoded = original.encode();
424 assert_eq!(encoded.len(), PublicKey::SIZE);
425 let decoded = PublicKey::decode(encoded).unwrap();
426 assert_eq!(original, decoded);
427 }
428
429 #[test]
430 fn test_codec_signature() {
431 let original =
432 parse_signature("0x882730e5d03f6b42c3abc26d3372625034e1d871b65a8a6b900a56dae22da98abbe1b68f85e49fe7652a55ec3d0591c20767677e33e5cbb1207315c41a9ac03be39c2e7668edc043d6cb1d9fd93033caa8a1c5b0e84bedaeb6c64972503a43eb")
433 .unwrap();
434 let encoded = original.encode();
435 assert_eq!(encoded.len(), Signature::SIZE);
436 let decoded = Signature::decode(encoded).unwrap();
437 assert_eq!(original, decoded);
438 }
439
440 fn parse_private_key(private_key: &str) -> Result<PrivateKey, CodecError> {
441 PrivateKey::decode(
442 commonware_utils::from_hex_formatted(private_key)
443 .unwrap()
444 .as_ref(),
445 )
446 }
447
448 fn parse_public_key(public_key: &str) -> Result<PublicKey, CodecError> {
449 PublicKey::decode(
450 commonware_utils::from_hex_formatted(public_key)
451 .unwrap()
452 .as_ref(),
453 )
454 }
455
456 fn parse_signature(signature: &str) -> Result<Signature, CodecError> {
457 Signature::decode(
458 commonware_utils::from_hex_formatted(signature)
459 .unwrap()
460 .as_ref(),
461 )
462 }
463
464 #[test]
465 fn test_from_private() {
466 let mut rng = test_rng();
467 let private = Private::random(&mut rng);
468 let private_key = PrivateKey::from(private);
469 let msg = b"test message";
471 let sig = private_key.sign(b"ns", msg);
472 assert!(private_key.public_key().verify(b"ns", msg, &sig));
473 }
474
475 #[test]
476 fn test_private_key_redacted() {
477 let mut rng = test_rng();
478 let private_key = PrivateKey::random(&mut rng);
479 let debug = format!("{:?}", private_key);
480 let display = format!("{}", private_key);
481 assert!(debug.contains("REDACTED"));
482 assert!(display.contains("REDACTED"));
483 }
484
485 #[cfg(feature = "arbitrary")]
486 mod conformance {
487 use super::*;
488 use commonware_codec::conformance::CodecConformance;
489
490 commonware_conformance::conformance_tests! {
491 CodecConformance<PublicKey>,
492 CodecConformance<PrivateKey>,
493 CodecConformance<Signature>,
494 }
495 }
496}