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