decaf377_rdsa/
signature.rs

1use core::{cmp, convert::TryFrom, marker::PhantomData};
2
3use crate::{Domain, Error};
4
5/// A `decaf377-rdsa` signature.
6#[derive(Copy, Clone)]
7#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8#[cfg_attr(feature = "serde", serde(try_from = "&[u8]", into = "Vec<u8>"))]
9pub struct Signature<D: Domain> {
10    bytes: [u8; 64],
11    _marker: PhantomData<D>,
12}
13
14impl<D: Domain> AsRef<[u8]> for Signature<D> {
15    fn as_ref(&self) -> &[u8] {
16        &self.bytes
17    }
18}
19
20impl<D: Domain> Signature<D> {
21    /// Returns the bytes of the signature.
22    ///
23    /// This is the same as `.into()`, but does not require type inference.
24    pub fn to_bytes(&self) -> [u8; 64] {
25        self.bytes
26    }
27
28    pub(crate) fn from_parts(r_bytes: [u8; 32], s_bytes: [u8; 32]) -> Self {
29        let mut bytes = [0; 64];
30        bytes[0..32].copy_from_slice(&r_bytes[..]);
31        bytes[32..64].copy_from_slice(&s_bytes[..]);
32        Self {
33            bytes,
34            _marker: PhantomData,
35        }
36    }
37
38    pub(crate) fn r_bytes(&self) -> [u8; 32] {
39        self.bytes[0..32].try_into().expect("32 byte array")
40    }
41
42    pub(crate) fn s_bytes(&self) -> [u8; 32] {
43        self.bytes[32..64].try_into().expect("32 byte array")
44    }
45}
46
47impl<D: Domain> From<[u8; 64]> for Signature<D> {
48    fn from(bytes: [u8; 64]) -> Signature<D> {
49        Signature {
50            bytes,
51            _marker: PhantomData,
52        }
53    }
54}
55
56impl<D: Domain> From<Signature<D>> for [u8; 64] {
57    fn from(sig: Signature<D>) -> [u8; 64] {
58        sig.to_bytes()
59    }
60}
61
62impl<D: Domain> TryFrom<&[u8]> for Signature<D> {
63    type Error = Error;
64
65    fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
66        if bytes.len() == 64 {
67            let mut bytes64 = [0u8; 64];
68            bytes64.copy_from_slice(bytes);
69            Ok(bytes64.into())
70        } else {
71            Err(Error::WrongSliceLength {
72                expected: 64,
73                found: bytes.len(),
74            })
75        }
76    }
77}
78
79impl<D: Domain> cmp::PartialEq for Signature<D> {
80    fn eq(&self, other: &Self) -> bool {
81        self.bytes == other.bytes
82    }
83}
84
85impl<D: Domain> cmp::Eq for Signature<D> {}
86
87#[cfg(feature = "std")]
88mod std_only {
89    use super::*;
90    use std::fmt;
91
92    use crate::{Binding, Signature, SpendAuth};
93
94    impl<D: Domain> TryFrom<Vec<u8>> for Signature<D> {
95        type Error = Error;
96
97        fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
98            value.as_slice().try_into()
99        }
100    }
101
102    impl<D: Domain> From<Signature<D>> for Vec<u8> {
103        fn from(sig: Signature<D>) -> Vec<u8> {
104            sig.to_bytes().into()
105        }
106    }
107
108    impl fmt::Debug for Signature<Binding> {
109        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
110            f.debug_tuple("Signature<Binding>")
111                .field(&hex::encode(&<[u8; 64]>::from(*self)))
112                .finish()
113        }
114    }
115
116    impl fmt::Debug for Signature<SpendAuth> {
117        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118            f.debug_tuple("Signature<SpendAuth>")
119                .field(&hex::encode(&<[u8; 64]>::from(*self)))
120                .finish()
121        }
122    }
123}
124
125#[cfg(feature = "std")]
126pub use std_only::*;