ed448_goldilocks/sign/
expanded.rs1use crate::{
2 EdwardsPoint, EdwardsScalar, EdwardsScalarBytes, SECRET_KEY_LENGTH, SecretKey, SigningError,
3 VerifyingKey, WideEdwardsScalarBytes,
4 sign::{HASH_HEAD, InnerSignature},
5};
6use elliptic_curve::{
7 group::GroupEncoding,
8 zeroize::{Zeroize, ZeroizeOnDrop},
9};
10use shake::{
11 Shake256,
12 digest::{ExtendableOutput, ExtendableOutputReset, Update, XofReader},
13};
14
15#[derive(Clone)]
16pub struct ExpandedSecretKey {
17 pub(crate) seed: SecretKey,
18 pub(crate) scalar: EdwardsScalar,
19 pub(crate) public_key: VerifyingKey,
20 pub(crate) hash_prefix: EdwardsScalarBytes,
21}
22
23impl Zeroize for ExpandedSecretKey {
24 fn zeroize(&mut self) {
25 self.seed.zeroize();
26 self.scalar.zeroize();
27 self.hash_prefix.zeroize();
28 }
29}
30
31impl Drop for ExpandedSecretKey {
32 fn drop(&mut self) {
33 self.zeroize();
34 }
35}
36
37impl From<&SecretKey> for ExpandedSecretKey {
38 fn from(secret_key: &SecretKey) -> Self {
39 Self::from_seed(secret_key)
40 }
41}
42
43impl ZeroizeOnDrop for ExpandedSecretKey {}
44
45impl ExpandedSecretKey {
46 pub fn from_seed(seed: &SecretKey) -> Self {
47 let mut reader = Shake256::default().chain(seed).finalize_xof();
48 let mut bytes = WideEdwardsScalarBytes::default();
49 reader.read(&mut bytes);
50 let mut scalar_bytes = EdwardsScalarBytes::default();
51 scalar_bytes.copy_from_slice(&bytes[..SECRET_KEY_LENGTH]);
52
53 scalar_bytes[0] &= 0xFC;
57 scalar_bytes[56] = 0;
58 scalar_bytes[55] |= 0x80;
59
60 let scalar = EdwardsScalar::from_bytes_mod_order(&scalar_bytes);
61
62 let mut hash_prefix = EdwardsScalarBytes::default();
63 hash_prefix.copy_from_slice(&bytes[SECRET_KEY_LENGTH..]);
64
65 let point = EdwardsPoint::GENERATOR * scalar;
66 let public_key = VerifyingKey {
67 compressed: point.to_affine().compress(),
68 point,
69 };
70
71 Self {
72 seed: *seed,
73 scalar,
74 public_key,
75 hash_prefix,
76 }
77 }
78
79 pub fn sign_raw(&self, m: &[u8]) -> Result<InnerSignature, SigningError> {
86 self.sign_inner(0, &[], m)
87 }
88
89 pub fn sign_ctx(&self, ctx: &[u8], m: &[u8]) -> Result<InnerSignature, SigningError> {
95 self.sign_inner(0, ctx, m)
96 }
97
98 pub fn sign_prehashed(&self, ctx: &[u8], m: &[u8]) -> Result<InnerSignature, SigningError> {
107 self.sign_inner(1, ctx, m)
108 }
109
110 fn sign_inner(&self, phflag: u8, ctx: &[u8], m: &[u8]) -> Result<InnerSignature, SigningError> {
111 if ctx.len() > 255 {
112 return Err(SigningError::PrehashedContextLength);
113 }
114 let ctx_len = ctx.len() as u8;
116 let mut reader = Shake256::default()
117 .chain(HASH_HEAD)
118 .chain([phflag])
119 .chain([ctx_len])
120 .chain(ctx)
121 .chain(self.hash_prefix)
122 .chain(m)
123 .finalize_xof_reset();
124 let mut bytes = WideEdwardsScalarBytes::default();
125 reader.read(&mut bytes);
126 let r = EdwardsScalar::from_bytes_mod_order_wide(&bytes);
127
128 let big_r = EdwardsPoint::GENERATOR * r;
130 let compressed_r = big_r.to_bytes();
131
132 reader = Shake256::default()
134 .chain(HASH_HEAD)
135 .chain([phflag])
136 .chain([ctx_len])
137 .chain(ctx)
138 .chain(compressed_r)
139 .chain(self.public_key.compressed.as_bytes())
140 .chain(m)
141 .finalize_xof();
142 reader.read(&mut bytes);
143 let k = EdwardsScalar::from_bytes_mod_order_wide(&bytes);
144 Ok(InnerSignature {
145 r: big_r,
146 s: r + k * self.scalar,
147 })
148 }
149}