mithril_stm/bls_multi_signature/
proof_of_possession.rs

1use blst::{blst_p1, min_sig::Signature as BlstSig};
2
3use crate::bls_multi_signature::{
4    BlsSigningKey, POP,
5    helper::unsafe_helpers::{compress_p1, scalar_to_pk_in_g1, uncompress_p1},
6};
7use crate::error::{MultiSignatureError, blst_err_to_mithril};
8
9/// MultiSig proof of possession, which contains two elements from G1. However,
10/// the two elements have different types: `k1` is represented as a BlstSig
11/// as it has the same structure, and this facilitates its verification. On
12/// the other hand, `k2` is a G1 point, as it does not share structure with
13/// the BLS signature, and we need to have an ad-hoc verification mechanism.
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub struct BlsProofOfPossession {
16    k1: BlstSig,
17    k2: blst_p1,
18}
19
20impl BlsProofOfPossession {
21    /// Convert to a 96 byte string.
22    ///
23    /// # Layout
24    /// The layout of a `MspPoP` encoding is
25    /// * K1 (G1 point)
26    /// * K2 (G1 point)
27    pub fn to_bytes(self) -> [u8; 96] {
28        let mut pop_bytes = [0u8; 96];
29        pop_bytes[..48].copy_from_slice(&self.k1.to_bytes());
30
31        pop_bytes[48..].copy_from_slice(&compress_p1(&self.k2)[..]);
32        pop_bytes
33    }
34
35    /// Deserialize a byte string to a `PublicKeyPoP`.
36    pub fn from_bytes(bytes: &[u8]) -> Result<Self, MultiSignatureError> {
37        let k1 = match BlstSig::from_bytes(
38            bytes.get(..48).ok_or(MultiSignatureError::SerializationError)?,
39        ) {
40            Ok(key) => key,
41            Err(e) => {
42                return Err(blst_err_to_mithril(e, None, None)
43                    .expect_err("If it passed, blst returns and error different to SUCCESS."));
44            }
45        };
46
47        let k2 = uncompress_p1(bytes.get(48..96).ok_or(MultiSignatureError::SerializationError)?)?;
48
49        Ok(Self { k1, k2 })
50    }
51
52    pub(crate) fn get_k1(self) -> BlstSig {
53        self.k1
54    }
55
56    pub(crate) fn get_k2(self) -> blst_p1 {
57        self.k2
58    }
59}
60
61impl From<&BlsSigningKey> for BlsProofOfPossession {
62    /// Convert a secret key into an `MspPoP`. This is performed by computing
63    /// `k1 =  H_G1(b"PoP" || mvk)` and `k2 = g1 * sk` where `H_G1` hashes into
64    /// `G1` and `g1` is the generator in `G1`.
65    fn from(sk: &BlsSigningKey) -> Self {
66        let k1 = sk.to_blst_secret_key().sign(POP, &[], &[]);
67        let k2 = scalar_to_pk_in_g1(&sk.to_blst_secret_key());
68        Self { k1, k2 }
69    }
70}