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 pub fn from_mnemonic(mnemonic: &str, index: u32) -> AptosResult<Self> {
108 let mnemonic = Mnemonic::from_phrase(mnemonic)?;
109 let private_key = mnemonic.derive_ed25519_key(index)?;
110 Ok(Self::from_private_key(private_key))
111 }
112
113 #[cfg(feature = "mnemonic")]
121 pub fn generate_with_mnemonic() -> AptosResult<(Self, String)> {
122 let mnemonic = Mnemonic::generate(24)?;
123 let phrase = mnemonic.phrase().to_string();
124 let private_key = mnemonic.derive_ed25519_key(0)?;
125 let account = Self::from_private_key(private_key);
126 Ok((account, phrase))
127 }
128
129 pub fn address(&self) -> AccountAddress {
131 self.address
132 }
133
134 pub fn public_key(&self) -> &Ed25519PublicKey {
136 &self.public_key
137 }
138
139 pub fn private_key(&self) -> &Ed25519PrivateKey {
143 &self.private_key
144 }
145
146 pub fn sign_message(&self, message: &[u8]) -> crate::crypto::Ed25519Signature {
148 self.private_key.sign(message)
149 }
150}
151
152impl Account for Ed25519Account {
153 fn address(&self) -> AccountAddress {
154 self.address
155 }
156
157 fn authentication_key(&self) -> AuthenticationKey {
158 AuthenticationKey::new(self.public_key.to_authentication_key())
159 }
160
161 fn sign(&self, message: &[u8]) -> AptosResult<Vec<u8>> {
162 Ok(self.private_key.sign(message).to_bytes().to_vec())
163 }
164
165 fn public_key_bytes(&self) -> Vec<u8> {
166 self.public_key.to_bytes().to_vec()
167 }
168
169 fn signature_scheme(&self) -> u8 {
170 ED25519_SCHEME
171 }
172}
173
174impl fmt::Debug for Ed25519Account {
175 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
176 f.debug_struct("Ed25519Account")
177 .field("address", &self.address)
178 .field("public_key", &self.public_key)
179 .finish_non_exhaustive()
180 }
181}
182
183#[derive(Clone)]
211pub struct Ed25519SingleKeyAccount {
212 private_key: Ed25519PrivateKey,
213 public_key: Ed25519PublicKey,
214 address: AccountAddress,
215}
216
217impl Ed25519SingleKeyAccount {
218 pub fn generate() -> Self {
220 let private_key = Ed25519PrivateKey::generate();
221 Self::from_private_key(private_key)
222 }
223
224 pub fn from_private_key(private_key: Ed25519PrivateKey) -> Self {
226 let public_key = private_key.public_key();
227 let address = Self::derive_address(&public_key);
228 Self {
229 private_key,
230 public_key,
231 address,
232 }
233 }
234
235 pub fn from_private_key_bytes(bytes: &[u8]) -> AptosResult<Self> {
241 let private_key = Ed25519PrivateKey::from_bytes(bytes)?;
242 Ok(Self::from_private_key(private_key))
243 }
244
245 pub fn from_private_key_hex(hex_str: &str) -> AptosResult<Self> {
253 let private_key = Ed25519PrivateKey::from_hex(hex_str)?;
254 Ok(Self::from_private_key(private_key))
255 }
256
257 #[cfg(feature = "mnemonic")]
265 pub fn from_mnemonic(mnemonic: &str, index: u32) -> AptosResult<Self> {
266 let mnemonic = Mnemonic::from_phrase(mnemonic)?;
267 let private_key = mnemonic.derive_ed25519_key(index)?;
268 Ok(Self::from_private_key(private_key))
269 }
270
271 pub fn address(&self) -> AccountAddress {
273 self.address
274 }
275
276 pub fn public_key(&self) -> &Ed25519PublicKey {
278 &self.public_key
279 }
280
281 pub fn private_key(&self) -> &Ed25519PrivateKey {
283 &self.private_key
284 }
285
286 pub fn sign_message(&self, message: &[u8]) -> crate::crypto::Ed25519Signature {
288 self.private_key.sign(message)
289 }
290
291 fn derive_address(public_key: &Ed25519PublicKey) -> AccountAddress {
293 let pk_bytes = public_key.to_bytes();
295 let mut bcs_bytes = Vec::with_capacity(1 + 1 + pk_bytes.len());
296 bcs_bytes.push(0x00); bcs_bytes.push(32); bcs_bytes.extend_from_slice(&pk_bytes);
299 let auth_key = derive_authentication_key(&bcs_bytes, SINGLE_KEY_SCHEME);
300 AccountAddress::new(auth_key)
301 }
302
303 fn bcs_public_key_bytes(&self) -> Vec<u8> {
307 let pk_bytes = self.public_key.to_bytes();
308 let mut bcs_bytes = Vec::with_capacity(1 + 1 + pk_bytes.len());
309 bcs_bytes.push(0x00); bcs_bytes.push(32); bcs_bytes.extend_from_slice(&pk_bytes);
312 bcs_bytes
313 }
314
315 fn bcs_signature_bytes(sig: &crate::crypto::Ed25519Signature) -> Vec<u8> {
319 let sig_bytes = sig.to_bytes();
320 let mut out = Vec::with_capacity(1 + 1 + sig_bytes.len());
321 out.push(0x00); out.push(64); out.extend_from_slice(&sig_bytes);
324 out
325 }
326}
327
328impl Account for Ed25519SingleKeyAccount {
329 fn address(&self) -> AccountAddress {
330 self.address
331 }
332
333 fn authentication_key(&self) -> AuthenticationKey {
334 let bcs_bytes = self.bcs_public_key_bytes();
335 let key = derive_authentication_key(&bcs_bytes, SINGLE_KEY_SCHEME);
336 AuthenticationKey::new(key)
337 }
338
339 fn sign(&self, message: &[u8]) -> AptosResult<Vec<u8>> {
340 let sig = self.private_key.sign(message);
344 Ok(Self::bcs_signature_bytes(&sig))
345 }
346
347 fn public_key_bytes(&self) -> Vec<u8> {
348 self.bcs_public_key_bytes()
350 }
351
352 fn signature_scheme(&self) -> u8 {
353 SINGLE_KEY_SCHEME
354 }
355}
356
357impl fmt::Debug for Ed25519SingleKeyAccount {
358 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
359 f.debug_struct("Ed25519SingleKeyAccount")
360 .field("address", &self.address)
361 .field("public_key", &self.public_key)
362 .finish_non_exhaustive()
363 }
364}
365
366#[cfg(test)]
367mod tests {
368 use super::*;
369
370 #[test]
371 fn test_generate() {
372 let account = Ed25519Account::generate();
373 assert!(!account.address().is_zero());
374 }
375
376 #[test]
377 #[cfg(feature = "mnemonic")]
378 fn test_from_mnemonic() {
379 let mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
381 let account = Ed25519Account::from_mnemonic(mnemonic, 0).unwrap();
382
383 let account2 = Ed25519Account::from_mnemonic(mnemonic, 0).unwrap();
385 assert_eq!(account.address(), account2.address());
386
387 let account3 = Ed25519Account::from_mnemonic(mnemonic, 1).unwrap();
389 assert_ne!(account.address(), account3.address());
390 }
391
392 #[test]
393 fn test_sign_and_verify() {
394 let account = Ed25519Account::generate();
395 let message = b"hello world";
396
397 let signature = account.sign_message(message);
398 assert!(account.public_key().verify(message, &signature).is_ok());
399 }
400
401 #[test]
402 #[cfg(feature = "mnemonic")]
403 fn test_generate_with_mnemonic() {
404 let (account, mnemonic) = Ed25519Account::generate_with_mnemonic().unwrap();
405
406 let restored = Ed25519Account::from_mnemonic(&mnemonic, 0).unwrap();
408 assert_eq!(account.address(), restored.address());
409 }
410
411 #[test]
412 fn test_from_private_key() {
413 let original = Ed25519Account::generate();
414 let private_key = original.private_key().clone();
415 let restored = Ed25519Account::from_private_key(private_key);
416 assert_eq!(original.address(), restored.address());
417 }
418
419 #[test]
420 fn test_from_private_key_bytes() {
421 let original = Ed25519Account::generate();
422 let bytes = original.private_key().to_bytes();
423 let restored = Ed25519Account::from_private_key_bytes(&bytes).unwrap();
424 assert_eq!(original.address(), restored.address());
425 }
426
427 #[test]
428 fn test_from_private_key_hex() {
429 let original = Ed25519Account::generate();
430 let hex = original.private_key().to_hex();
431 let restored = Ed25519Account::from_private_key_hex(&hex).unwrap();
432 assert_eq!(original.address(), restored.address());
433 }
434
435 #[test]
436 fn test_authentication_key() {
437 let account = Ed25519Account::generate();
438 let auth_key = account.authentication_key();
439 assert_eq!(auth_key.as_bytes().len(), 32);
440 }
441
442 #[test]
443 fn test_public_key_bytes() {
444 let account = Ed25519Account::generate();
445 let bytes = account.public_key_bytes();
446 assert_eq!(bytes.len(), 32);
447 }
448
449 #[test]
450 fn test_signature_scheme() {
451 let account = Ed25519Account::generate();
452 assert_eq!(account.signature_scheme(), ED25519_SCHEME);
453 }
454
455 #[test]
456 fn test_sign_trait() {
457 let account = Ed25519Account::generate();
458 let message = b"test message";
459 let sig_bytes = account.sign(message).unwrap();
460 assert_eq!(sig_bytes.len(), 64);
461 }
462
463 #[test]
464 fn test_debug_output() {
465 let account = Ed25519Account::generate();
466 let debug = format!("{account:?}");
467 assert!(debug.contains("Ed25519Account"));
468 assert!(debug.contains("address"));
469 }
470
471 #[test]
472 fn test_invalid_private_key_bytes() {
473 let result = Ed25519Account::from_private_key_bytes(&[0u8; 16]);
474 assert!(result.is_err());
475 }
476
477 #[test]
478 fn test_invalid_private_key_hex() {
479 let result = Ed25519Account::from_private_key_hex("invalid");
480 assert!(result.is_err());
481 }
482
483 #[test]
484 #[cfg(feature = "mnemonic")]
485 fn test_invalid_mnemonic() {
486 let result = Ed25519Account::from_mnemonic("invalid mnemonic phrase", 0);
487 assert!(result.is_err());
488 }
489
490 #[test]
493 fn test_single_key_generate() {
494 let account = Ed25519SingleKeyAccount::generate();
495 assert!(!account.address().is_zero());
496 }
497
498 #[test]
499 fn test_single_key_different_address() {
500 let legacy_account = Ed25519Account::generate();
502 let private_key = legacy_account.private_key().clone();
503
504 let single_key_account = Ed25519SingleKeyAccount::from_private_key(private_key);
505
506 assert_ne!(legacy_account.address(), single_key_account.address());
508 }
509
510 #[test]
511 fn test_single_key_sign_and_verify() {
512 let account = Ed25519SingleKeyAccount::generate();
513 let message = b"hello world";
514
515 let signature = account.sign_message(message);
516 assert!(account.public_key().verify(message, &signature).is_ok());
517 }
518
519 #[test]
520 fn test_single_key_from_private_key() {
521 let original = Ed25519SingleKeyAccount::generate();
522 let private_key = original.private_key().clone();
523 let restored = Ed25519SingleKeyAccount::from_private_key(private_key);
524 assert_eq!(original.address(), restored.address());
525 }
526
527 #[test]
528 fn test_single_key_from_private_key_bytes() {
529 let original = Ed25519SingleKeyAccount::generate();
530 let bytes = original.private_key().to_bytes();
531 let restored = Ed25519SingleKeyAccount::from_private_key_bytes(&bytes).unwrap();
532 assert_eq!(original.address(), restored.address());
533 }
534
535 #[test]
536 fn test_single_key_from_private_key_hex() {
537 let original = Ed25519SingleKeyAccount::generate();
538 let hex = original.private_key().to_hex();
539 let restored = Ed25519SingleKeyAccount::from_private_key_hex(&hex).unwrap();
540 assert_eq!(original.address(), restored.address());
541 }
542
543 #[test]
544 fn test_single_key_authentication_key() {
545 let account = Ed25519SingleKeyAccount::generate();
546 let auth_key = account.authentication_key();
547 assert_eq!(auth_key.as_bytes().len(), 32);
548 }
549
550 #[test]
551 fn test_single_key_public_key_bytes() {
552 let account = Ed25519SingleKeyAccount::generate();
553 let bytes = account.public_key_bytes();
554 assert_eq!(bytes.len(), 34);
556 assert_eq!(bytes[0], 0x00); assert_eq!(bytes[1], 32); }
559
560 #[test]
561 fn test_single_key_signature_scheme() {
562 let account = Ed25519SingleKeyAccount::generate();
563 assert_eq!(account.signature_scheme(), SINGLE_KEY_SCHEME);
564 }
565
566 #[test]
567 fn test_single_key_sign_trait() {
568 let account = Ed25519SingleKeyAccount::generate();
569 let message = b"test message";
570 let sig_bytes = account.sign(message).unwrap();
571 assert_eq!(sig_bytes.len(), 66);
573 assert_eq!(sig_bytes[0], 0x00, "AnySignature::Ed25519 variant tag");
574 assert_eq!(sig_bytes[1], 64, "ULEB128(64)");
575 }
576
577 #[test]
578 fn test_single_key_debug_output() {
579 let account = Ed25519SingleKeyAccount::generate();
580 let debug = format!("{account:?}");
581 assert!(debug.contains("Ed25519SingleKeyAccount"));
582 assert!(debug.contains("address"));
583 }
584
585 #[test]
586 #[cfg(feature = "mnemonic")]
587 fn test_single_key_from_mnemonic() {
588 let mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
589 let account = Ed25519SingleKeyAccount::from_mnemonic(mnemonic, 0).unwrap();
590
591 let account2 = Ed25519SingleKeyAccount::from_mnemonic(mnemonic, 0).unwrap();
593 assert_eq!(account.address(), account2.address());
594
595 let account3 = Ed25519SingleKeyAccount::from_mnemonic(mnemonic, 1).unwrap();
597 assert_ne!(account.address(), account3.address());
598 }
599
600 #[test]
601 #[cfg(feature = "mnemonic")]
602 fn test_single_key_vs_legacy_mnemonic() {
603 let mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
604
605 let legacy = Ed25519Account::from_mnemonic(mnemonic, 0).unwrap();
606 let single_key = Ed25519SingleKeyAccount::from_mnemonic(mnemonic, 0).unwrap();
607
608 assert_eq!(
610 legacy.private_key().to_bytes(),
611 single_key.private_key().to_bytes()
612 );
613 assert_ne!(legacy.address(), single_key.address());
614 }
615}