ironfish_reddsa/
signing_key.rs1use core::{
12 convert::{TryFrom, TryInto},
13 marker::PhantomData,
14};
15
16use crate::{
17 private::SealedScalar, Error, Randomizer, SigType, Signature, SpendAuth, VerificationKey,
18};
19
20use group::{ff::PrimeField, GroupEncoding};
21use rand_core::{CryptoRng, RngCore};
22
23#[derive(Copy, Clone, Debug)]
25#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
26#[cfg_attr(feature = "serde", serde(try_from = "SerdeHelper"))]
27#[cfg_attr(feature = "serde", serde(into = "SerdeHelper"))]
28#[cfg_attr(feature = "serde", serde(bound = "T: SigType"))]
29pub struct SigningKey<T: SigType> {
30 sk: T::Scalar,
31 pk: VerificationKey<T>,
32}
33
34impl<T: SigType> From<&SigningKey<T>> for VerificationKey<T> {
35 fn from(sk: &SigningKey<T>) -> VerificationKey<T> {
36 sk.pk
37 }
38}
39
40impl<T: SigType> From<SigningKey<T>> for [u8; 32] {
41 fn from(sk: SigningKey<T>) -> [u8; 32] {
42 sk.sk.to_repr().as_ref().try_into().unwrap()
43 }
44}
45
46impl<T: SigType> TryFrom<[u8; 32]> for SigningKey<T> {
47 type Error = Error;
48
49 fn try_from(bytes: [u8; 32]) -> Result<Self, Self::Error> {
50 let mut repr = <T::Scalar as PrimeField>::Repr::default();
52 repr.as_mut().copy_from_slice(&bytes);
53 let maybe_sk = T::Scalar::from_repr(repr);
54 if maybe_sk.is_some().into() {
55 let sk = maybe_sk.unwrap();
56 let pk = VerificationKey::from(&sk);
57 Ok(SigningKey { sk, pk })
58 } else {
59 Err(Error::MalformedSigningKey)
60 }
61 }
62}
63
64#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
65struct SerdeHelper([u8; 32]);
66
67impl<T: SigType> TryFrom<SerdeHelper> for SigningKey<T> {
68 type Error = Error;
69
70 fn try_from(helper: SerdeHelper) -> Result<Self, Self::Error> {
71 helper.0.try_into()
72 }
73}
74
75impl<T: SigType> From<SigningKey<T>> for SerdeHelper {
76 fn from(sk: SigningKey<T>) -> Self {
77 Self(sk.into())
78 }
79}
80
81impl<T: SpendAuth> SigningKey<T> {
82 pub fn randomize(&self, randomizer: &Randomizer<T>) -> SigningKey<T> {
84 let sk = self.sk + randomizer;
85 let pk = VerificationKey::from(&sk);
86 SigningKey { sk, pk }
87 }
88}
89
90impl<T: SigType> SigningKey<T> {
91 pub fn new<R: RngCore + CryptoRng>(mut rng: R) -> SigningKey<T> {
93 let sk = {
94 let mut bytes = [0; 64];
95 rng.fill_bytes(&mut bytes);
96 T::Scalar::from_bytes_wide(&bytes)
97 };
98 let pk = VerificationKey::from(&sk);
99 SigningKey { sk, pk }
100 }
101
102 pub fn sign<R: RngCore + CryptoRng>(&self, mut rng: R, msg: &[u8]) -> Signature<T> {
105 use crate::HStar;
106
107 let random_bytes = {
111 let mut bytes = [0; 80];
112 rng.fill_bytes(&mut bytes);
113 bytes
114 };
115
116 let nonce = HStar::<T>::default()
117 .update(&random_bytes[..])
118 .update(&self.pk.bytes.bytes[..]) .update(msg)
120 .finalize();
121
122 let r: T::Point = T::basepoint() * nonce;
123 let r_bytes: [u8; 32] = r.to_bytes().as_ref().try_into().unwrap();
124
125 let c = HStar::<T>::default()
126 .update(&r_bytes[..])
127 .update(&self.pk.bytes.bytes[..]) .update(msg)
129 .finalize();
130
131 let s = nonce + (c * self.sk);
132 let s_bytes = s.to_repr().as_ref().try_into().unwrap();
133
134 Signature {
135 r_bytes,
136 s_bytes,
137 _marker: PhantomData,
138 }
139 }
140}