cardano_sdk/cardano/crypto/ed25519/
signature.rs

1//  This Source Code Form is subject to the terms of the Mozilla Public
2//  License, v. 2.0. If a copy of the MPL was not distributed with this
3//  file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5use crate::{PlutusData, pallas::ed25519};
6use std::{cmp, fmt, str::FromStr};
7
8/// An EdDSA signature on Curve25519.
9#[derive(Debug, PartialEq, Eq, Clone, Copy)]
10#[repr(transparent)]
11pub struct Signature(ed25519::Signature);
12
13impl fmt::Display for Signature {
14    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
15        self.0.fmt(f)
16    }
17}
18
19impl PartialOrd for Signature {
20    fn partial_cmp(&self, rhs: &Self) -> Option<cmp::Ordering> {
21        Some(self.cmp(rhs))
22    }
23}
24
25impl Ord for Signature {
26    fn cmp(&self, rhs: &Self) -> cmp::Ordering {
27        let lhs = self.as_ref();
28        let rhs = rhs.as_ref();
29        lhs.cmp(rhs)
30    }
31}
32// ------------------------------------------------------------------ Inspecting
33
34impl Signature {
35    pub const SIZE: usize = ed25519::Signature::SIZE;
36}
37
38// ----------------------------------------------------------- Converting (from)
39
40impl From<[u8; 64]> for Signature {
41    fn from(value: [u8; 64]) -> Self {
42        Self(ed25519::Signature::from(value))
43    }
44}
45
46impl TryFrom<Vec<u8>> for Signature {
47    type Error = Vec<u8>;
48
49    fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
50        Ok(Self::from(<[u8; 64]>::try_from(value)?))
51    }
52}
53
54impl FromStr for Signature {
55    type Err = anyhow::Error;
56
57    fn from_str(s: &str) -> anyhow::Result<Self> {
58        Ok(Signature(ed25519::Signature::from_str(s)?))
59    }
60}
61
62impl From<ed25519::Signature> for Signature {
63    fn from(sig: ed25519::Signature) -> Self {
64        Self(sig)
65    }
66}
67
68impl<'a> TryFrom<&PlutusData<'a>> for Signature {
69    type Error = anyhow::Error;
70
71    fn try_from(data: &PlutusData<'a>) -> anyhow::Result<Self> {
72        let array =
73            <&'_ [u8; 64]>::try_from(data).map_err(|e| e.context("invalid verification key"))?;
74        Ok(Self(ed25519::Signature::from(*array)))
75    }
76}
77
78impl<'a> TryFrom<PlutusData<'a>> for Signature {
79    type Error = anyhow::Error;
80
81    fn try_from(data: PlutusData<'a>) -> anyhow::Result<Self> {
82        Self::try_from(&data)
83    }
84}
85
86// ------------------------------------------------------------- Converting (to)
87
88impl AsRef<[u8]> for Signature {
89    fn as_ref(&self) -> &[u8] {
90        self.0.as_ref()
91    }
92}
93
94impl From<Signature> for [u8; 64] {
95    fn from(sig: Signature) -> Self {
96        // Only way to 'leak' bytes is via slice?!
97        <[u8; 64]>::try_from(sig.0.as_ref())
98            .unwrap_or_else(|e| unreachable!("couldn't convert signature; not 64 bytes: {e:?}"))
99    }
100}
101
102impl From<Signature> for ed25519::Signature {
103    fn from(sig: Signature) -> Self {
104        sig.0
105    }
106}
107
108impl<'a> From<&'a Signature> for &'a ed25519::Signature {
109    fn from(sig: &'a Signature) -> Self {
110        &sig.0
111    }
112}
113
114impl<'a> From<Signature> for PlutusData<'a> {
115    fn from(key: Signature) -> Self {
116        Self::bytes(key.0)
117    }
118}
119
120#[cfg(test)]
121mod tests {
122    use super::*;
123
124    #[test]
125    fn test_roundtrip_fixed_array() {
126        let inner = [0; 64];
127        let sig = Signature::from(inner);
128        let re_inner = <[u8; 64]>::from(sig);
129        assert_eq!(inner, re_inner, "Failed roundtrip");
130    }
131}