1use super::types::{
2 DilithiumPair, DilithiumPublic, DilithiumSignatureScheme, DilithiumSigner, Error,
3 WrappedPublicBytes, WrappedSignatureBytes,
4};
5
6use crate::{DilithiumSignature, DilithiumSignatureWithPublic};
7use alloc::vec::Vec;
8use qp_poseidon_core::hash_bytes;
9use sp_core::{
10 crypto::{Derive, Public, PublicBytes, Signature, SignatureBytes},
11 ByteArray, H256,
12};
13use sp_runtime::{
14 traits::{IdentifyAccount, Verify},
15 AccountId32, CryptoType,
16};
17
18pub fn verify(pub_key: &[u8], msg: &[u8], sig: &[u8]) -> bool {
42 use qp_rusty_crystals_dilithium::ml_dsa_87::PublicKey;
43 match PublicKey::from_bytes(pub_key) {
44 Ok(pk) => pk.verify(msg, sig, None),
45 Err(e) => {
46 log::warn!("public key failed to deserialize {:?}", e);
47 false
48 },
49 }
50}
51
52impl<const N: usize, SubTag> Derive for WrappedPublicBytes<N, SubTag> {}
57impl<const N: usize, SubTag> AsMut<[u8]> for WrappedPublicBytes<N, SubTag> {
58 fn as_mut(&mut self) -> &mut [u8] {
59 self.0.as_mut()
60 }
61}
62impl<const N: usize, SubTag> AsRef<[u8]> for WrappedPublicBytes<N, SubTag> {
63 fn as_ref(&self) -> &[u8] {
64 self.0.as_slice()
65 }
66}
67impl<const N: usize, SubTag> TryFrom<&[u8]> for WrappedPublicBytes<N, SubTag> {
68 type Error = ();
69 fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
70 PublicBytes::from_slice(data)
71 .map(|bytes| WrappedPublicBytes(bytes))
72 .map_err(|_| ())
73 }
74}
75impl<const N: usize, SubTag> ByteArray for WrappedPublicBytes<N, SubTag> {
76 fn as_slice(&self) -> &[u8] {
77 self.0.as_slice()
78 }
79 const LEN: usize = N;
80 fn from_slice(data: &[u8]) -> Result<Self, ()> {
81 PublicBytes::from_slice(data)
82 .map(|bytes| WrappedPublicBytes(bytes))
83 .map_err(|_| ())
84 }
85 fn to_raw_vec(&self) -> Vec<u8> {
86 self.0.as_slice().to_vec()
87 }
88}
89impl<const N: usize, SubTag> CryptoType for WrappedPublicBytes<N, SubTag> {
90 type Pair = DilithiumPair;
91}
92impl<const N: usize, SubTag: Clone + Eq> Public for WrappedPublicBytes<N, SubTag> {}
93
94impl<const N: usize, SubTag> Default for WrappedPublicBytes<N, SubTag> {
95 fn default() -> Self {
96 WrappedPublicBytes(PublicBytes::default())
97 }
98}
99impl<const N: usize, SubTag> alloc::fmt::Debug for WrappedPublicBytes<N, SubTag> {
100 #[cfg(feature = "std")]
101 fn fmt(&self, f: &mut alloc::fmt::Formatter) -> alloc::fmt::Result {
102 use sp_core::bytes::to_hex;
103
104 write!(f, "{}", to_hex(self.0.as_ref(), false))
105 }
106
107 #[cfg(not(feature = "std"))]
108 fn fmt(&self, _: &mut alloc::fmt::Formatter) -> alloc::fmt::Result {
109 Ok(())
110 }
111}
112
113impl IdentifyAccount for DilithiumPublic {
114 type AccountId = AccountId32;
115 fn into_account(self) -> Self::AccountId {
116 AccountId32::new(hash_bytes(self.0.as_slice()))
118 }
119}
120
121pub struct WormholeAddress(pub H256);
122
123impl IdentifyAccount for WormholeAddress {
125 type AccountId = AccountId32;
126 fn into_account(self) -> Self::AccountId {
127 AccountId32::new(self.0.as_bytes().try_into().unwrap())
128 }
129}
130
131impl<const N: usize, SubTag> Derive for WrappedSignatureBytes<N, SubTag> {}
135impl<const N: usize, SubTag> AsMut<[u8]> for WrappedSignatureBytes<N, SubTag> {
136 fn as_mut(&mut self) -> &mut [u8] {
137 self.0.as_mut()
138 }
139}
140impl<const N: usize, SubTag> AsRef<[u8]> for WrappedSignatureBytes<N, SubTag> {
141 fn as_ref(&self) -> &[u8] {
142 self.0.as_slice()
143 }
144}
145impl<const N: usize, SubTag> TryFrom<&[u8]> for WrappedSignatureBytes<N, SubTag> {
146 type Error = ();
147 fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
148 SignatureBytes::from_slice(data)
149 .map(|bytes| WrappedSignatureBytes(bytes))
150 .map_err(|_| ())
151 }
152}
153impl<const N: usize, SubTag> ByteArray for WrappedSignatureBytes<N, SubTag> {
154 fn as_slice(&self) -> &[u8] {
155 self.0.as_slice()
156 }
157 const LEN: usize = N;
158 fn from_slice(data: &[u8]) -> Result<Self, ()> {
159 SignatureBytes::from_slice(data)
160 .map(|bytes| WrappedSignatureBytes(bytes))
161 .map_err(|_| ())
162 }
163 fn to_raw_vec(&self) -> Vec<u8> {
164 self.0.as_slice().to_vec()
165 }
166}
167impl<const N: usize, SubTag> CryptoType for WrappedSignatureBytes<N, SubTag> {
168 type Pair = DilithiumPair;
169}
170impl<const N: usize, SubTag: Clone + Eq> Signature for WrappedSignatureBytes<N, SubTag> {}
171
172impl<const N: usize, SubTag> Default for WrappedSignatureBytes<N, SubTag> {
173 fn default() -> Self {
174 WrappedSignatureBytes(SignatureBytes::default())
175 }
176}
177
178impl<const N: usize, SubTag> alloc::fmt::Debug for WrappedSignatureBytes<N, SubTag> {
179 #[cfg(feature = "std")]
180 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
181 use sp_core::bytes::to_hex;
182
183 write!(f, "{}", to_hex(self.0.as_slice(), false))
184 }
185
186 #[cfg(not(feature = "std"))]
187 fn fmt(&self, _: &mut alloc::fmt::Formatter) -> alloc::fmt::Result {
188 Ok(())
189 }
190}
191
192impl CryptoType for DilithiumPair {
197 type Pair = Self;
198}
199
200impl Verify for DilithiumSignatureScheme {
205 type Signer = DilithiumSigner;
206
207 fn verify<L: sp_runtime::traits::Lazy<[u8]>>(
208 &self,
209 mut msg: L,
210 signer: &<Self::Signer as IdentifyAccount>::AccountId,
211 ) -> bool {
212 let Self::Dilithium(sig_public) = self;
213 let account = sig_public.public().clone().into_account();
214 if account != *signer {
215 return false;
216 }
217 verify(sig_public.public().as_ref(), msg.get(), sig_public.signature().as_ref())
218 }
219}
220
221impl From<DilithiumPublic> for DilithiumSigner {
225 fn from(x: DilithiumPublic) -> Self {
226 Self::Dilithium(x)
227 }
228}
229
230impl IdentifyAccount for DilithiumSigner {
231 type AccountId = AccountId32;
232
233 fn into_account(self) -> AccountId32 {
234 let Self::Dilithium(who) = self;
236 hash_bytes(who.as_ref()).into()
237 }
238}
239
240impl From<DilithiumPublic> for AccountId32 {
241 fn from(public: DilithiumPublic) -> Self {
242 public.into_account()
243 }
244}
245
246impl DilithiumPair {
251 pub fn from_seed(seed: &[u8]) -> Result<Self, Error> {
252 let keypair = crate::pair::generate(seed)?;
253 Ok(DilithiumPair { secret: keypair.secret.to_bytes(), public: keypair.public.to_bytes() })
254 }
255
256 pub fn from_keypair(keypair: qp_rusty_crystals_dilithium::ml_dsa_87::Keypair) -> Self {
257 DilithiumPair { secret: keypair.secret.to_bytes(), public: keypair.public.to_bytes() }
258 }
259
260 pub fn from_raw(public: &[u8], secret: &[u8]) -> Result<Self, Error> {
267 let keypair = crate::pair::create_keypair(public, secret)?;
268 const VALIDATION_MSG: &[u8] = b"qp_dilithium_crypto::from_raw_validation";
270 let sig = keypair.sign(VALIDATION_MSG, None, None).map_err(|_| Error::InvalidSecretKey)?;
271 if !keypair.verify(VALIDATION_MSG, sig.as_ref(), None) {
272 return Err(Error::InvalidPublicKey);
273 }
274 Ok(DilithiumPair { secret: keypair.secret.to_bytes(), public: keypair.public.to_bytes() })
275 }
276
277 pub fn secret_bytes(&self) -> &[u8] {
278 &self.secret
279 }
280
281 pub fn public_bytes(&self) -> &[u8] {
282 &self.public
283 }
284}
285
286impl alloc::fmt::Debug for DilithiumSignatureWithPublic {
287 #[cfg(feature = "std")]
288 fn fmt(&self, f: &mut alloc::fmt::Formatter) -> alloc::fmt::Result {
289 write!(
290 f,
291 "DilithiumSignatureWithPublic {{ signature: {:?}, public: {:?} }}",
292 self.signature(),
293 self.public()
294 )
295 }
296
297 #[cfg(not(feature = "std"))]
298 fn fmt(&self, f: &mut alloc::fmt::Formatter) -> alloc::fmt::Result {
299 write!(f, "DilithiumSignatureWithPublic")
300 }
301}
302
303impl From<DilithiumSignatureWithPublic> for DilithiumSignatureScheme {
304 fn from(x: DilithiumSignatureWithPublic) -> Self {
305 Self::Dilithium(x)
306 }
307}
308
309impl TryFrom<DilithiumSignatureScheme> for DilithiumSignatureWithPublic {
310 type Error = ();
311 fn try_from(m: DilithiumSignatureScheme) -> Result<Self, Self::Error> {
312 let DilithiumSignatureScheme::Dilithium(sig_with_public) = m;
313 Ok(sig_with_public)
314 }
315}
316
317impl AsMut<[u8]> for DilithiumSignatureWithPublic {
318 fn as_mut(&mut self) -> &mut [u8] {
319 self.bytes.as_mut()
320 }
321}
322impl TryFrom<&[u8]> for DilithiumSignatureWithPublic {
323 type Error = ();
324 fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
325 if data.len() != Self::TOTAL_LEN {
326 return Err(());
327 }
328 let (sig_bytes, pub_bytes) = data.split_at(<DilithiumSignature as ByteArray>::LEN);
329 let signature = DilithiumSignature::from_slice(sig_bytes).map_err(|_| ())?;
330 let public = DilithiumPublic::from_slice(pub_bytes).map_err(|_| ())?;
331 Ok(Self::new(signature, public))
332 }
333}
334
335impl ByteArray for DilithiumSignatureWithPublic {
336 const LEN: usize = Self::TOTAL_LEN;
337
338 fn to_raw_vec(&self) -> Vec<u8> {
339 self.to_bytes().to_vec()
340 }
341
342 fn from_slice(data: &[u8]) -> Result<Self, ()> {
343 if data.len() != Self::LEN {
344 return Err(());
345 }
346 let bytes = <[u8; Self::LEN]>::try_from(data).map_err(|_| ())?;
347 Self::from_bytes(&bytes).map_err(|_| ())
348 }
349
350 fn as_slice(&self) -> &[u8] {
351 self.bytes.as_slice()
352 }
353}
354impl AsRef<[u8; Self::LEN]> for DilithiumSignatureWithPublic {
355 fn as_ref(&self) -> &[u8; Self::LEN] {
356 &self.bytes
357 }
358}
359
360impl AsRef<[u8]> for DilithiumSignatureWithPublic {
361 fn as_ref(&self) -> &[u8] {
362 &self.bytes
363 }
364}
365impl Signature for DilithiumSignatureWithPublic {}
366
367impl CryptoType for DilithiumSignatureWithPublic {
368 type Pair = DilithiumPair;
369}