Skip to main content

cml_crypto/chain_crypto/
byron_proxy_key.rs

1use cbor_event::{
2    self,
3    de::Deserializer,
4    se::{self, Serializer},
5};
6use std::io::{BufRead, Write};
7
8use cml_core::network::ProtocolMagic;
9
10use super::{byron_tags, Ed25519Bip32, Signature};
11
12type SignData = ();
13
14type ProxyCert = Signature<(), Ed25519Bip32>;
15
16#[derive(Debug, Clone)]
17pub struct ByronProxySecretKey {
18    pub omega: u64,
19    pub issuer_pk: super::PublicKey<Ed25519Bip32>,
20    pub delegate_pk: super::PublicKey<Ed25519Bip32>,
21    pub cert: ProxyCert,
22}
23
24impl cbor_event::se::Serialize for ByronProxySecretKey {
25    fn serialize<'se, W: Write>(
26        &self,
27        serializer: &'se mut Serializer<W>,
28    ) -> cbor_event::Result<&'se mut Serializer<W>> {
29        serializer
30            .write_array(cbor_event::Len::Len(4))?
31            .serialize(&self.omega)?
32            .serialize(&self.issuer_pk)?
33            .serialize(&self.delegate_pk)?
34            .serialize(&self.cert)
35    }
36}
37
38impl cbor_event::de::Deserialize for ByronProxySecretKey {
39    fn deserialize<R: BufRead>(raw: &mut Deserializer<R>) -> cbor_event::Result<Self> {
40        raw.tuple(4, "ByronProxySecretKey")?;
41
42        let omega = cbor_event::de::Deserialize::deserialize(raw)?;
43        let issuer_pk = cbor_event::de::Deserialize::deserialize(raw)?;
44        let delegate_pk = cbor_event::de::Deserialize::deserialize(raw)?;
45        let cert = cbor_event::de::Deserialize::deserialize(raw)?;
46
47        Ok(ByronProxySecretKey {
48            omega,
49            issuer_pk,
50            delegate_pk,
51            cert,
52        })
53    }
54}
55
56impl ByronProxySecretKey {
57    /// Verify that 'cert' is a signature from 'issuer_pk' over
58    /// 'delegate_pk' and 'omega'.
59    pub fn verify(&self, protocol_magic: ProtocolMagic) -> bool {
60        let buf = Self::data_to_sign(&self.delegate_pk, self.omega, protocol_magic);
61        // signature.0.verify_slice(&self.0, data) == crypto::Verification::Success
62        self.cert.verify_slice(&self.issuer_pk, &buf) == super::sign::Verification::Success
63    }
64
65    /// Use 'issuer_prv' to sign 'delegate_pk' and 'omega' to create a
66    /// ByronProxySecretKey.
67    pub fn sign(
68        issuer_prv: &super::SecretKey<Ed25519Bip32>,
69        delegate_pk: super::PublicKey<Ed25519Bip32>,
70        omega: u64,
71        protocol_magic: ProtocolMagic,
72    ) -> Self {
73        let buf = Self::data_to_sign(&delegate_pk, omega, protocol_magic);
74
75        Self {
76            omega,
77            issuer_pk: issuer_prv.to_public(),
78            delegate_pk,
79            cert: issuer_prv.sign_slice(&buf),
80        }
81    }
82
83    fn data_to_sign(
84        delegate_pk: &super::PublicKey<Ed25519Bip32>,
85        omega: u64,
86        protocol_magic: ProtocolMagic,
87    ) -> Vec<u8> {
88        // Yes, this really is
89        // CBOR-in-byte-vector-in-CBOR-in-byte-vector...
90        let mut buf2 = vec![b'0', b'0'];
91        buf2.extend(delegate_pk.as_ref());
92        se::Serializer::new(&mut buf2).serialize(&omega).unwrap();
93
94        let mut buf = vec![];
95        buf.push(byron_tags::SigningTag::ProxySK as u8);
96        se::Serializer::new(&mut buf)
97            .serialize(&protocol_magic)
98            .unwrap()
99            .write_bytes(buf2)
100            .unwrap();
101
102        buf
103    }
104}
105
106#[derive(Debug, Clone)]
107pub struct ProxySignature {
108    pub psk: ByronProxySecretKey,
109    pub sig: Signature<(), Ed25519Bip32>,
110}
111
112impl cbor_event::se::Serialize for ProxySignature {
113    fn serialize<'se, W: Write>(
114        &self,
115        serializer: &'se mut Serializer<W>,
116    ) -> cbor_event::Result<&'se mut Serializer<W>> {
117        serializer
118            .write_array(cbor_event::Len::Len(2))?
119            .serialize(&self.psk)?
120            .serialize(&self.sig)
121    }
122}
123
124impl cbor_event::de::Deserialize for ProxySignature {
125    fn deserialize<R: BufRead>(raw: &mut Deserializer<R>) -> cbor_event::Result<Self> {
126        raw.tuple(2, "ProxySignature")?;
127
128        let psk = cbor_event::de::Deserialize::deserialize(raw)?;
129        let sig = cbor_event::de::Deserialize::deserialize(raw)?;
130
131        Ok(ProxySignature { psk, sig })
132    }
133}
134
135#[derive(Debug, Clone)]
136pub enum BlockSignature {
137    Signature(Signature<SignData, Ed25519Bip32>),
138    ProxyLight(Vec<cbor_event::Value>), // TODO: decode
139    ProxyHeavy(ProxySignature),
140}
141impl BlockSignature {
142    pub fn to_bytes(&self) -> Option<&[u8; ed25519_bip32::SIGNATURE_SIZE]> {
143        match self {
144            BlockSignature::Signature(s) => Some(s.signdata.to_bytes()),
145            _ => None,
146        }
147    }
148}
149impl cbor_event::se::Serialize for BlockSignature {
150    fn serialize<'se, W: Write>(
151        &self,
152        serializer: &'se mut Serializer<W>,
153    ) -> cbor_event::Result<&'se mut Serializer<W>> {
154        match self {
155            BlockSignature::Signature(ref sig) => serializer
156                .write_array(cbor_event::Len::Len(2))?
157                .write_unsigned_integer(0)?
158                .serialize(sig),
159            BlockSignature::ProxyLight(ref v) => {
160                let serializer = serializer
161                    .write_array(cbor_event::Len::Len(2))?
162                    .write_unsigned_integer(1)?;
163                cbor_event::se::serialize_fixed_array(v.iter(), serializer)
164            }
165            BlockSignature::ProxyHeavy(ref v) => serializer
166                .write_array(cbor_event::Len::Len(2))?
167                .write_unsigned_integer(2)?
168                .serialize(v),
169        }
170    }
171}
172impl cbor_event::de::Deserialize for BlockSignature {
173    fn deserialize<R: BufRead>(raw: &mut Deserializer<R>) -> cbor_event::Result<Self> {
174        raw.tuple(2, "BlockSignature")?;
175        let sum_type_idx = raw.unsigned_integer()?;
176        match sum_type_idx {
177            0 => Ok(BlockSignature::Signature(raw.deserialize()?)),
178            1 => Ok(BlockSignature::ProxyLight(raw.deserialize()?)),
179            2 => Ok(BlockSignature::ProxyHeavy(
180                cbor_event::de::Deserialize::deserialize(raw)?,
181            )),
182            _ => Err(cbor_event::Error::CustomError(format!(
183                "Unsupported BlockSignature: {}",
184                sum_type_idx
185            ))),
186        }
187    }
188}
189
190#[cfg(test)]
191mod tests {
192    use base64::{engine::general_purpose::STANDARD, Engine};
193
194    use std::str::FromStr;
195
196    use crate::chain_crypto::{
197        byron_proxy_key::ByronProxySecretKey, Ed25519Bip32, PublicKey, SecretKey, Signature,
198    };
199
200    #[test]
201    fn test_psk_verify() {
202        let mut psk = ByronProxySecretKey {
203            omega: 0,
204            issuer_pk: PublicKey::<Ed25519Bip32>::from_binary(&STANDARD.decode("nFhj99RbuDjG5jU3XjRXlUbP+4LStPeiMh7E7l3oWWfwRqjxXg10jUFt+4pKRlnZTrmI4weBWMGpchDJA9MKnA==").unwrap()).unwrap(),
205            delegate_pk: PublicKey::<Ed25519Bip32>::from_binary(&STANDARD.decode("mLujHvc/6KIvUEt2IdnjmVRENEHx9ifl45ZmhZZ8e39+C4fe/HgnKjFtT1M5LjeeSn1Bp8tSAM4WZwL+ECWgsw==").unwrap()).unwrap(),
206            cert: Signature::<(), Ed25519Bip32>::from_str("fd30c5ac3f77df733eabe48de391ad6727b6ecd7ee72cc85207075a9bba90365f10455b80f3dbf5cc821f71075f00ebdfcffd30b264b5262c1473fd70125ee05").unwrap()
207        };
208
209        let pm = 1097911063.into();
210
211        assert!(psk.verify(pm));
212
213        psk.omega = 1;
214
215        assert!(!psk.verify(pm));
216    }
217
218    #[test]
219    fn test_psk_sign() {
220        let pm = 328429219.into();
221
222        let issuer_prv = SecretKey::<Ed25519Bip32>::from_str("b8b054ec1b92dd4542db35e2f813f013a8d7ee9f53255b26f3ef3dafb74e11462545bd9c85aa0a6f6719a933eba16909c1a2fa0bbb58e9cd98bf9ddbb79f7d50fcfc22db8155f8d6ca0e3a975cb1b6aa5d6e7609b30c99877e469db06b5d5016").unwrap();
223        let delegate_pk = PublicKey::<Ed25519Bip32>::from_str("695b380fc72ae7d830d46f902a7c9d4057a4b9a7a0be235b87fdf51e698619e033aac8d93fd4cb82785973bb943f2047ddd1e664d4e185e7be634722e108389a").unwrap();
224        let expected_cert = Signature::<(), Ed25519Bip32>::from_str("a72bf0119afd1ba5bed56b6521544105b6077c884609666296dbc59275477149a1b8230ce5b6c0fa81e1ec61c717164be57422e86a8f2f5773cdc66da99fcc0e").unwrap();
225
226        let psk = ByronProxySecretKey::sign(&issuer_prv, delegate_pk, 0, pm);
227
228        assert_eq!(psk.cert, expected_cert);
229
230        assert!(psk.verify(pm));
231    }
232}