1use crate::SignatureError;
2use crate::Signer;
3use crate::Verifier;
4use sui_sdk_types::Ed25519PublicKey;
5use sui_sdk_types::Ed25519Signature;
6use sui_sdk_types::SignatureScheme;
7use sui_sdk_types::SimpleSignature;
8use sui_sdk_types::UserSignature;
9
10#[derive(Clone, Eq, PartialEq)]
11pub struct Ed25519PrivateKey(ed25519_dalek::SigningKey);
12
13impl std::fmt::Debug for Ed25519PrivateKey {
14 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
15 f.debug_tuple("Ed25519PrivateKey")
16 .field(&"__elided__")
17 .finish()
18 }
19}
20
21#[cfg(test)]
22impl proptest::arbitrary::Arbitrary for Ed25519PrivateKey {
23 type Parameters = ();
24 type Strategy = proptest::strategy::BoxedStrategy<Self>;
25 fn arbitrary_with(_: Self::Parameters) -> Self::Strategy {
26 use proptest::strategy::Strategy;
27
28 proptest::arbitrary::any::<[u8; Self::LENGTH]>()
29 .prop_map(Self::new)
30 .boxed()
31 }
32}
33
34impl Ed25519PrivateKey {
35 pub const LENGTH: usize = 32;
37
38 pub fn new(bytes: [u8; Self::LENGTH]) -> Self {
39 Self(bytes.into())
40 }
41
42 pub fn scheme(&self) -> SignatureScheme {
43 SignatureScheme::Ed25519
44 }
45
46 pub fn verifying_key(&self) -> Ed25519VerifyingKey {
47 let verifying_key = self.0.verifying_key();
48 Ed25519VerifyingKey(verifying_key)
49 }
50
51 pub fn public_key(&self) -> Ed25519PublicKey {
52 self.verifying_key().public_key()
53 }
54
55 pub fn generate<R>(mut rng: R) -> Self
56 where
57 R: rand_core::RngCore + rand_core::CryptoRng,
58 {
59 let mut buf: [u8; Self::LENGTH] = [0; Self::LENGTH];
60 rng.fill_bytes(&mut buf);
61 Self(buf.into())
62 }
63
64 #[cfg(feature = "pem")]
65 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
66 pub fn from_der(bytes: &[u8]) -> Result<Self, SignatureError> {
68 ed25519_dalek::pkcs8::DecodePrivateKey::from_pkcs8_der(bytes)
69 .map(Self)
70 .map_err(SignatureError::from_source)
71 }
72
73 #[cfg(feature = "pem")]
74 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
75 pub fn to_der(&self) -> Result<Vec<u8>, SignatureError> {
77 use ed25519_dalek::pkcs8::EncodePrivateKey;
78
79 self.0
80 .to_pkcs8_der()
81 .map_err(SignatureError::from_source)
82 .map(|der| der.as_bytes().to_owned())
83 }
84
85 #[cfg(feature = "pem")]
86 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
87 pub fn from_pem(s: &str) -> Result<Self, SignatureError> {
89 ed25519_dalek::pkcs8::DecodePrivateKey::from_pkcs8_pem(s)
90 .map(Self)
91 .map_err(SignatureError::from_source)
92 }
93
94 #[cfg(feature = "pem")]
95 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
96 pub fn to_pem(&self) -> Result<String, SignatureError> {
98 use pkcs8::EncodePrivateKey;
99
100 self.0
101 .to_pkcs8_pem(pkcs8::LineEnding::default())
102 .map_err(SignatureError::from_source)
103 .map(|pem| (*pem).to_owned())
104 }
105
106 #[cfg(feature = "pem")]
107 pub(crate) fn from_dalek(private_key: ed25519_dalek::SigningKey) -> Self {
108 Self(private_key)
109 }
110}
111
112impl Signer<Ed25519Signature> for Ed25519PrivateKey {
113 fn try_sign(&self, msg: &[u8]) -> Result<Ed25519Signature, SignatureError> {
114 self.0
115 .try_sign(msg)
116 .map(|signature| Ed25519Signature::new(signature.to_bytes()))
117 }
118}
119
120impl Signer<SimpleSignature> for Ed25519PrivateKey {
121 fn try_sign(&self, msg: &[u8]) -> Result<SimpleSignature, SignatureError> {
122 <Self as Signer<Ed25519Signature>>::try_sign(self, msg).map(|signature| {
123 SimpleSignature::Ed25519 {
124 signature,
125 public_key: self.public_key(),
126 }
127 })
128 }
129}
130
131impl Signer<UserSignature> for Ed25519PrivateKey {
132 fn try_sign(&self, msg: &[u8]) -> Result<UserSignature, SignatureError> {
133 <Self as Signer<SimpleSignature>>::try_sign(self, msg).map(UserSignature::Simple)
134 }
135}
136
137#[derive(Debug, Clone, Eq, PartialEq, Default)]
138pub struct Ed25519VerifyingKey(ed25519_dalek::VerifyingKey);
139
140impl Ed25519VerifyingKey {
141 pub fn new(public_key: &Ed25519PublicKey) -> Result<Self, SignatureError> {
142 ed25519_dalek::VerifyingKey::from_bytes(public_key.inner()).map(Self)
143 }
144
145 pub fn public_key(&self) -> Ed25519PublicKey {
146 Ed25519PublicKey::new(self.0.to_bytes())
147 }
148
149 #[cfg(feature = "pem")]
150 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
151 pub fn from_der(bytes: &[u8]) -> Result<Self, SignatureError> {
153 ed25519_dalek::pkcs8::DecodePublicKey::from_public_key_der(bytes)
154 .map(Self)
155 .map_err(SignatureError::from_source)
156 }
157
158 #[cfg(feature = "pem")]
159 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
160 pub fn to_der(&self) -> Result<Vec<u8>, SignatureError> {
162 use pkcs8::EncodePublicKey;
163
164 self.0
165 .to_public_key_der()
166 .map_err(SignatureError::from_source)
167 .map(|der| der.into_vec())
168 }
169
170 #[cfg(feature = "pem")]
171 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
172 pub fn from_pem(s: &str) -> Result<Self, SignatureError> {
174 ed25519_dalek::pkcs8::DecodePublicKey::from_public_key_pem(s)
175 .map(Self)
176 .map_err(SignatureError::from_source)
177 }
178
179 #[cfg(feature = "pem")]
180 #[cfg_attr(doc_cfg, doc(cfg(feature = "pem")))]
181 pub fn to_pem(&self) -> Result<String, SignatureError> {
183 use pkcs8::EncodePublicKey;
184
185 self.0
186 .to_public_key_pem(pkcs8::LineEnding::default())
187 .map_err(SignatureError::from_source)
188 }
189
190 #[cfg(feature = "pem")]
191 pub(crate) fn from_dalek(verifying_key: ed25519_dalek::VerifyingKey) -> Self {
192 Self(verifying_key)
193 }
194}
195
196impl Verifier<Ed25519Signature> for Ed25519VerifyingKey {
197 fn verify(&self, message: &[u8], signature: &Ed25519Signature) -> Result<(), SignatureError> {
198 let signature = ed25519_dalek::Signature::from_bytes(signature.inner());
199 self.0.verify_strict(message, &signature)
200 }
201}
202
203impl Verifier<SimpleSignature> for Ed25519VerifyingKey {
204 fn verify(&self, message: &[u8], signature: &SimpleSignature) -> Result<(), SignatureError> {
205 let SimpleSignature::Ed25519 {
206 signature,
207 public_key,
208 } = signature
209 else {
210 return Err(SignatureError::from_source("not an ed25519 signature"));
211 };
212
213 if public_key.inner() != self.0.as_bytes() {
214 return Err(SignatureError::from_source(
215 "public_key in signature does not match",
216 ));
217 }
218
219 <Self as Verifier<Ed25519Signature>>::verify(self, message, signature)
220 }
221}
222
223impl Verifier<UserSignature> for Ed25519VerifyingKey {
224 fn verify(&self, message: &[u8], signature: &UserSignature) -> Result<(), SignatureError> {
225 let UserSignature::Simple(signature) = signature else {
226 return Err(SignatureError::from_source("not an ed25519 signature"));
227 };
228
229 <Self as Verifier<SimpleSignature>>::verify(self, message, signature)
230 }
231}
232
233#[derive(Default, Clone, Debug)]
234pub struct Ed25519Verifier {}
235
236impl Ed25519Verifier {
237 pub fn new() -> Self {
238 Self {}
239 }
240}
241
242impl Verifier<SimpleSignature> for Ed25519Verifier {
243 fn verify(&self, message: &[u8], signature: &SimpleSignature) -> Result<(), SignatureError> {
244 let SimpleSignature::Ed25519 {
245 signature,
246 public_key,
247 } = signature
248 else {
249 return Err(SignatureError::from_source("not an ed25519 signature"));
250 };
251
252 let verifying_key = Ed25519VerifyingKey::new(public_key)?;
253
254 verifying_key.verify(message, signature)
255 }
256}
257
258impl Verifier<UserSignature> for Ed25519Verifier {
259 fn verify(&self, message: &[u8], signature: &UserSignature) -> Result<(), SignatureError> {
260 let UserSignature::Simple(signature) = signature else {
261 return Err(SignatureError::from_source("not an ed25519 signature"));
262 };
263
264 <Self as Verifier<SimpleSignature>>::verify(self, message, signature)
265 }
266}
267
268#[cfg(test)]
269mod test {
270 use super::*;
271 use crate::SuiSigner;
272 use crate::SuiVerifier;
273 use sui_sdk_types::PersonalMessage;
274 use test_strategy::proptest;
275
276 #[cfg(target_arch = "wasm32")]
277 use wasm_bindgen_test::wasm_bindgen_test as test;
278
279 #[proptest]
290 fn personal_message_signing(signer: Ed25519PrivateKey, message: Vec<u8>) {
291 let message = PersonalMessage(message.into());
292 let signature = signer.sign_personal_message(&message).unwrap();
293 let verifying_key = signer.verifying_key();
294 verifying_key
295 .verify_personal_message(&message, &signature)
296 .unwrap();
297
298 let verifier = Ed25519Verifier::default();
299 verifier
300 .verify_personal_message(&message, &signature)
301 .unwrap();
302 }
303}