aptos_sdk/account/
ed25519.rs1#[cfg(feature = "mnemonic")]
15use crate::account::Mnemonic;
16use crate::account::account::{Account, AuthenticationKey};
17use crate::crypto::{
18 ED25519_SCHEME, Ed25519PrivateKey, Ed25519PublicKey, SINGLE_KEY_SCHEME,
19 derive_authentication_key,
20};
21use crate::error::AptosResult;
22use crate::types::AccountAddress;
23use std::fmt;
24
25#[derive(Clone)]
39pub struct Ed25519Account {
40 private_key: Ed25519PrivateKey,
41 public_key: Ed25519PublicKey,
42 address: AccountAddress,
43}
44
45impl Ed25519Account {
46 pub fn generate() -> Self {
48 let private_key = Ed25519PrivateKey::generate();
49 Self::from_private_key(private_key)
50 }
51
52 pub fn from_private_key(private_key: Ed25519PrivateKey) -> Self {
54 let public_key = private_key.public_key();
55 let address = public_key.to_address();
56 Self {
57 private_key,
58 public_key,
59 address,
60 }
61 }
62
63 pub fn from_private_key_bytes(bytes: &[u8]) -> AptosResult<Self> {
69 let private_key = Ed25519PrivateKey::from_bytes(bytes)?;
70 Ok(Self::from_private_key(private_key))
71 }
72
73 pub fn from_private_key_hex(hex_str: &str) -> AptosResult<Self> {
81 let private_key = Ed25519PrivateKey::from_hex(hex_str)?;
82 Ok(Self::from_private_key(private_key))
83 }
84
85 #[cfg(feature = "mnemonic")]
107 #[cfg_attr(docsrs, doc(cfg(feature = "mnemonic")))]
108 pub fn from_mnemonic(mnemonic: &str, index: u32) -> AptosResult<Self> {
109 let mnemonic = Mnemonic::from_phrase(mnemonic)?;
110 let private_key = mnemonic.derive_ed25519_key(index)?;
111 Ok(Self::from_private_key(private_key))
112 }
113
114 #[cfg(feature = "mnemonic")]
122 #[cfg_attr(docsrs, doc(cfg(feature = "mnemonic")))]
123 pub fn generate_with_mnemonic() -> AptosResult<(Self, String)> {
124 let mnemonic = Mnemonic::generate(24)?;
125 let phrase = mnemonic.phrase().to_string();
126 let private_key = mnemonic.derive_ed25519_key(0)?;
127 let account = Self::from_private_key(private_key);
128 Ok((account, phrase))
129 }
130
131 pub fn address(&self) -> AccountAddress {
133 self.address
134 }
135
136 pub fn public_key(&self) -> &Ed25519PublicKey {
138 &self.public_key
139 }
140
141 pub fn private_key(&self) -> &Ed25519PrivateKey {
145 &self.private_key
146 }
147
148 pub fn sign_message(&self, message: &[u8]) -> crate::crypto::Ed25519Signature {
150 self.private_key.sign(message)
151 }
152}
153
154impl Account for Ed25519Account {
155 fn address(&self) -> AccountAddress {
156 self.address
157 }
158
159 fn authentication_key(&self) -> AuthenticationKey {
160 AuthenticationKey::new(self.public_key.to_authentication_key())
161 }
162
163 fn sign(&self, message: &[u8]) -> AptosResult<Vec<u8>> {
164 Ok(self.private_key.sign(message).to_bytes().to_vec())
165 }
166
167 fn public_key_bytes(&self) -> Vec<u8> {
168 self.public_key.to_bytes().to_vec()
169 }
170
171 fn signature_scheme(&self) -> u8 {
172 ED25519_SCHEME
173 }
174}
175
176impl fmt::Debug for Ed25519Account {
177 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
178 f.debug_struct("Ed25519Account")
179 .field("address", &self.address)
180 .field("public_key", &self.public_key)
181 .finish_non_exhaustive()
182 }
183}
184
185#[derive(Clone)]
213pub struct Ed25519SingleKeyAccount {
214 private_key: Ed25519PrivateKey,
215 public_key: Ed25519PublicKey,
216 address: AccountAddress,
217}
218
219impl Ed25519SingleKeyAccount {
220 pub fn generate() -> Self {
222 let private_key = Ed25519PrivateKey::generate();
223 Self::from_private_key(private_key)
224 }
225
226 pub fn from_private_key(private_key: Ed25519PrivateKey) -> Self {
228 let public_key = private_key.public_key();
229 let address = Self::derive_address(&public_key);
230 Self {
231 private_key,
232 public_key,
233 address,
234 }
235 }
236
237 pub fn from_private_key_bytes(bytes: &[u8]) -> AptosResult<Self> {
243 let private_key = Ed25519PrivateKey::from_bytes(bytes)?;
244 Ok(Self::from_private_key(private_key))
245 }
246
247 pub fn from_private_key_hex(hex_str: &str) -> AptosResult<Self> {
255 let private_key = Ed25519PrivateKey::from_hex(hex_str)?;
256 Ok(Self::from_private_key(private_key))
257 }
258
259 #[cfg(feature = "mnemonic")]
267 #[cfg_attr(docsrs, doc(cfg(feature = "mnemonic")))]
268 pub fn from_mnemonic(mnemonic: &str, index: u32) -> AptosResult<Self> {
269 let mnemonic = Mnemonic::from_phrase(mnemonic)?;
270 let private_key = mnemonic.derive_ed25519_key(index)?;
271 Ok(Self::from_private_key(private_key))
272 }
273
274 pub fn address(&self) -> AccountAddress {
276 self.address
277 }
278
279 pub fn public_key(&self) -> &Ed25519PublicKey {
281 &self.public_key
282 }
283
284 pub fn private_key(&self) -> &Ed25519PrivateKey {
286 &self.private_key
287 }
288
289 pub fn sign_message(&self, message: &[u8]) -> crate::crypto::Ed25519Signature {
291 self.private_key.sign(message)
292 }
293
294 fn derive_address(public_key: &Ed25519PublicKey) -> AccountAddress {
296 let pk_bytes = public_key.to_bytes();
298 let mut bcs_bytes = Vec::with_capacity(1 + 1 + pk_bytes.len());
299 bcs_bytes.push(0x00); bcs_bytes.push(32); bcs_bytes.extend_from_slice(&pk_bytes);
302 let auth_key = derive_authentication_key(&bcs_bytes, SINGLE_KEY_SCHEME);
303 AccountAddress::new(auth_key)
304 }
305
306 fn bcs_public_key_bytes(&self) -> Vec<u8> {
310 let pk_bytes = self.public_key.to_bytes();
311 let mut bcs_bytes = Vec::with_capacity(1 + 1 + pk_bytes.len());
312 bcs_bytes.push(0x00); bcs_bytes.push(32); bcs_bytes.extend_from_slice(&pk_bytes);
315 bcs_bytes
316 }
317}
318
319impl Account for Ed25519SingleKeyAccount {
320 fn address(&self) -> AccountAddress {
321 self.address
322 }
323
324 fn authentication_key(&self) -> AuthenticationKey {
325 let bcs_bytes = self.bcs_public_key_bytes();
326 let key = derive_authentication_key(&bcs_bytes, SINGLE_KEY_SCHEME);
327 AuthenticationKey::new(key)
328 }
329
330 fn sign(&self, message: &[u8]) -> AptosResult<Vec<u8>> {
331 Ok(self.private_key.sign(message).to_bytes().to_vec())
332 }
333
334 fn public_key_bytes(&self) -> Vec<u8> {
335 self.bcs_public_key_bytes()
337 }
338
339 fn signature_scheme(&self) -> u8 {
340 SINGLE_KEY_SCHEME
341 }
342}
343
344impl fmt::Debug for Ed25519SingleKeyAccount {
345 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
346 f.debug_struct("Ed25519SingleKeyAccount")
347 .field("address", &self.address)
348 .field("public_key", &self.public_key)
349 .finish_non_exhaustive()
350 }
351}
352
353#[cfg(test)]
354mod tests {
355 use super::*;
356
357 #[test]
358 fn test_generate() {
359 let account = Ed25519Account::generate();
360 assert!(!account.address().is_zero());
361 }
362
363 #[test]
364 #[cfg(feature = "mnemonic")]
365 fn test_from_mnemonic() {
366 let mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
368 let account = Ed25519Account::from_mnemonic(mnemonic, 0).unwrap();
369
370 let account2 = Ed25519Account::from_mnemonic(mnemonic, 0).unwrap();
372 assert_eq!(account.address(), account2.address());
373
374 let account3 = Ed25519Account::from_mnemonic(mnemonic, 1).unwrap();
376 assert_ne!(account.address(), account3.address());
377 }
378
379 #[test]
380 fn test_sign_and_verify() {
381 let account = Ed25519Account::generate();
382 let message = b"hello world";
383
384 let signature = account.sign_message(message);
385 assert!(account.public_key().verify(message, &signature).is_ok());
386 }
387
388 #[test]
389 #[cfg(feature = "mnemonic")]
390 fn test_generate_with_mnemonic() {
391 let (account, mnemonic) = Ed25519Account::generate_with_mnemonic().unwrap();
392
393 let restored = Ed25519Account::from_mnemonic(&mnemonic, 0).unwrap();
395 assert_eq!(account.address(), restored.address());
396 }
397
398 #[test]
399 fn test_from_private_key() {
400 let original = Ed25519Account::generate();
401 let private_key = original.private_key().clone();
402 let restored = Ed25519Account::from_private_key(private_key);
403 assert_eq!(original.address(), restored.address());
404 }
405
406 #[test]
407 fn test_from_private_key_bytes() {
408 let original = Ed25519Account::generate();
409 let bytes = original.private_key().to_bytes();
410 let restored = Ed25519Account::from_private_key_bytes(&bytes).unwrap();
411 assert_eq!(original.address(), restored.address());
412 }
413
414 #[test]
415 fn test_from_private_key_hex() {
416 let original = Ed25519Account::generate();
417 let hex = original.private_key().to_hex();
418 let restored = Ed25519Account::from_private_key_hex(&hex).unwrap();
419 assert_eq!(original.address(), restored.address());
420 }
421
422 #[test]
423 fn test_authentication_key() {
424 let account = Ed25519Account::generate();
425 let auth_key = account.authentication_key();
426 assert_eq!(auth_key.as_bytes().len(), 32);
427 }
428
429 #[test]
430 fn test_public_key_bytes() {
431 let account = Ed25519Account::generate();
432 let bytes = account.public_key_bytes();
433 assert_eq!(bytes.len(), 32);
434 }
435
436 #[test]
437 fn test_signature_scheme() {
438 let account = Ed25519Account::generate();
439 assert_eq!(account.signature_scheme(), ED25519_SCHEME);
440 }
441
442 #[test]
443 fn test_sign_trait() {
444 let account = Ed25519Account::generate();
445 let message = b"test message";
446 let sig_bytes = account.sign(message).unwrap();
447 assert_eq!(sig_bytes.len(), 64);
448 }
449
450 #[test]
451 fn test_debug_output() {
452 let account = Ed25519Account::generate();
453 let debug = format!("{account:?}");
454 assert!(debug.contains("Ed25519Account"));
455 assert!(debug.contains("address"));
456 }
457
458 #[test]
459 fn test_invalid_private_key_bytes() {
460 let result = Ed25519Account::from_private_key_bytes(&[0u8; 16]);
461 assert!(result.is_err());
462 }
463
464 #[test]
465 fn test_invalid_private_key_hex() {
466 let result = Ed25519Account::from_private_key_hex("invalid");
467 assert!(result.is_err());
468 }
469
470 #[test]
471 #[cfg(feature = "mnemonic")]
472 fn test_invalid_mnemonic() {
473 let result = Ed25519Account::from_mnemonic("invalid mnemonic phrase", 0);
474 assert!(result.is_err());
475 }
476
477 #[test]
480 fn test_single_key_generate() {
481 let account = Ed25519SingleKeyAccount::generate();
482 assert!(!account.address().is_zero());
483 }
484
485 #[test]
486 fn test_single_key_different_address() {
487 let legacy_account = Ed25519Account::generate();
489 let private_key = legacy_account.private_key().clone();
490
491 let single_key_account = Ed25519SingleKeyAccount::from_private_key(private_key);
492
493 assert_ne!(legacy_account.address(), single_key_account.address());
495 }
496
497 #[test]
498 fn test_single_key_sign_and_verify() {
499 let account = Ed25519SingleKeyAccount::generate();
500 let message = b"hello world";
501
502 let signature = account.sign_message(message);
503 assert!(account.public_key().verify(message, &signature).is_ok());
504 }
505
506 #[test]
507 fn test_single_key_from_private_key() {
508 let original = Ed25519SingleKeyAccount::generate();
509 let private_key = original.private_key().clone();
510 let restored = Ed25519SingleKeyAccount::from_private_key(private_key);
511 assert_eq!(original.address(), restored.address());
512 }
513
514 #[test]
515 fn test_single_key_from_private_key_bytes() {
516 let original = Ed25519SingleKeyAccount::generate();
517 let bytes = original.private_key().to_bytes();
518 let restored = Ed25519SingleKeyAccount::from_private_key_bytes(&bytes).unwrap();
519 assert_eq!(original.address(), restored.address());
520 }
521
522 #[test]
523 fn test_single_key_from_private_key_hex() {
524 let original = Ed25519SingleKeyAccount::generate();
525 let hex = original.private_key().to_hex();
526 let restored = Ed25519SingleKeyAccount::from_private_key_hex(&hex).unwrap();
527 assert_eq!(original.address(), restored.address());
528 }
529
530 #[test]
531 fn test_single_key_authentication_key() {
532 let account = Ed25519SingleKeyAccount::generate();
533 let auth_key = account.authentication_key();
534 assert_eq!(auth_key.as_bytes().len(), 32);
535 }
536
537 #[test]
538 fn test_single_key_public_key_bytes() {
539 let account = Ed25519SingleKeyAccount::generate();
540 let bytes = account.public_key_bytes();
541 assert_eq!(bytes.len(), 34);
543 assert_eq!(bytes[0], 0x00); assert_eq!(bytes[1], 32); }
546
547 #[test]
548 fn test_single_key_signature_scheme() {
549 let account = Ed25519SingleKeyAccount::generate();
550 assert_eq!(account.signature_scheme(), SINGLE_KEY_SCHEME);
551 }
552
553 #[test]
554 fn test_single_key_sign_trait() {
555 let account = Ed25519SingleKeyAccount::generate();
556 let message = b"test message";
557 let sig_bytes = account.sign(message).unwrap();
558 assert_eq!(sig_bytes.len(), 64);
559 }
560
561 #[test]
562 fn test_single_key_debug_output() {
563 let account = Ed25519SingleKeyAccount::generate();
564 let debug = format!("{account:?}");
565 assert!(debug.contains("Ed25519SingleKeyAccount"));
566 assert!(debug.contains("address"));
567 }
568
569 #[test]
570 #[cfg(feature = "mnemonic")]
571 fn test_single_key_from_mnemonic() {
572 let mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
573 let account = Ed25519SingleKeyAccount::from_mnemonic(mnemonic, 0).unwrap();
574
575 let account2 = Ed25519SingleKeyAccount::from_mnemonic(mnemonic, 0).unwrap();
577 assert_eq!(account.address(), account2.address());
578
579 let account3 = Ed25519SingleKeyAccount::from_mnemonic(mnemonic, 1).unwrap();
581 assert_ne!(account.address(), account3.address());
582 }
583
584 #[test]
585 #[cfg(feature = "mnemonic")]
586 fn test_single_key_vs_legacy_mnemonic() {
587 let mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
588
589 let legacy = Ed25519Account::from_mnemonic(mnemonic, 0).unwrap();
590 let single_key = Ed25519SingleKeyAccount::from_mnemonic(mnemonic, 0).unwrap();
591
592 assert_eq!(
594 legacy.private_key().to_bytes(),
595 single_key.private_key().to_bytes()
596 );
597 assert_ne!(legacy.address(), single_key.address());
598 }
599}