decaf377_rdsa/
signature.rs1use core::{cmp, convert::TryFrom, marker::PhantomData};
2
3use crate::{Domain, Error};
4
5#[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 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::*;