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
316impl Account for Ed25519SingleKeyAccount {
317 fn address(&self) -> AccountAddress {
318 self.address
319 }
320
321 fn authentication_key(&self) -> AuthenticationKey {
322 let bcs_bytes = self.bcs_public_key_bytes();
323 let key = derive_authentication_key(&bcs_bytes, SINGLE_KEY_SCHEME);
324 AuthenticationKey::new(key)
325 }
326
327 fn sign(&self, message: &[u8]) -> AptosResult<Vec<u8>> {
328 Ok(self.private_key.sign(message).to_bytes().to_vec())
329 }
330
331 fn public_key_bytes(&self) -> Vec<u8> {
332 self.bcs_public_key_bytes()
334 }
335
336 fn signature_scheme(&self) -> u8 {
337 SINGLE_KEY_SCHEME
338 }
339}
340
341impl fmt::Debug for Ed25519SingleKeyAccount {
342 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
343 f.debug_struct("Ed25519SingleKeyAccount")
344 .field("address", &self.address)
345 .field("public_key", &self.public_key)
346 .finish_non_exhaustive()
347 }
348}
349
350#[cfg(test)]
351mod tests {
352 use super::*;
353
354 #[test]
355 fn test_generate() {
356 let account = Ed25519Account::generate();
357 assert!(!account.address().is_zero());
358 }
359
360 #[test]
361 #[cfg(feature = "mnemonic")]
362 fn test_from_mnemonic() {
363 let mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
365 let account = Ed25519Account::from_mnemonic(mnemonic, 0).unwrap();
366
367 let account2 = Ed25519Account::from_mnemonic(mnemonic, 0).unwrap();
369 assert_eq!(account.address(), account2.address());
370
371 let account3 = Ed25519Account::from_mnemonic(mnemonic, 1).unwrap();
373 assert_ne!(account.address(), account3.address());
374 }
375
376 #[test]
377 fn test_sign_and_verify() {
378 let account = Ed25519Account::generate();
379 let message = b"hello world";
380
381 let signature = account.sign_message(message);
382 assert!(account.public_key().verify(message, &signature).is_ok());
383 }
384
385 #[test]
386 #[cfg(feature = "mnemonic")]
387 fn test_generate_with_mnemonic() {
388 let (account, mnemonic) = Ed25519Account::generate_with_mnemonic().unwrap();
389
390 let restored = Ed25519Account::from_mnemonic(&mnemonic, 0).unwrap();
392 assert_eq!(account.address(), restored.address());
393 }
394
395 #[test]
396 fn test_from_private_key() {
397 let original = Ed25519Account::generate();
398 let private_key = original.private_key().clone();
399 let restored = Ed25519Account::from_private_key(private_key);
400 assert_eq!(original.address(), restored.address());
401 }
402
403 #[test]
404 fn test_from_private_key_bytes() {
405 let original = Ed25519Account::generate();
406 let bytes = original.private_key().to_bytes();
407 let restored = Ed25519Account::from_private_key_bytes(&bytes).unwrap();
408 assert_eq!(original.address(), restored.address());
409 }
410
411 #[test]
412 fn test_from_private_key_hex() {
413 let original = Ed25519Account::generate();
414 let hex = original.private_key().to_hex();
415 let restored = Ed25519Account::from_private_key_hex(&hex).unwrap();
416 assert_eq!(original.address(), restored.address());
417 }
418
419 #[test]
420 fn test_authentication_key() {
421 let account = Ed25519Account::generate();
422 let auth_key = account.authentication_key();
423 assert_eq!(auth_key.as_bytes().len(), 32);
424 }
425
426 #[test]
427 fn test_public_key_bytes() {
428 let account = Ed25519Account::generate();
429 let bytes = account.public_key_bytes();
430 assert_eq!(bytes.len(), 32);
431 }
432
433 #[test]
434 fn test_signature_scheme() {
435 let account = Ed25519Account::generate();
436 assert_eq!(account.signature_scheme(), ED25519_SCHEME);
437 }
438
439 #[test]
440 fn test_sign_trait() {
441 let account = Ed25519Account::generate();
442 let message = b"test message";
443 let sig_bytes = account.sign(message).unwrap();
444 assert_eq!(sig_bytes.len(), 64);
445 }
446
447 #[test]
448 fn test_debug_output() {
449 let account = Ed25519Account::generate();
450 let debug = format!("{account:?}");
451 assert!(debug.contains("Ed25519Account"));
452 assert!(debug.contains("address"));
453 }
454
455 #[test]
456 fn test_invalid_private_key_bytes() {
457 let result = Ed25519Account::from_private_key_bytes(&[0u8; 16]);
458 assert!(result.is_err());
459 }
460
461 #[test]
462 fn test_invalid_private_key_hex() {
463 let result = Ed25519Account::from_private_key_hex("invalid");
464 assert!(result.is_err());
465 }
466
467 #[test]
468 #[cfg(feature = "mnemonic")]
469 fn test_invalid_mnemonic() {
470 let result = Ed25519Account::from_mnemonic("invalid mnemonic phrase", 0);
471 assert!(result.is_err());
472 }
473
474 #[test]
477 fn test_single_key_generate() {
478 let account = Ed25519SingleKeyAccount::generate();
479 assert!(!account.address().is_zero());
480 }
481
482 #[test]
483 fn test_single_key_different_address() {
484 let legacy_account = Ed25519Account::generate();
486 let private_key = legacy_account.private_key().clone();
487
488 let single_key_account = Ed25519SingleKeyAccount::from_private_key(private_key);
489
490 assert_ne!(legacy_account.address(), single_key_account.address());
492 }
493
494 #[test]
495 fn test_single_key_sign_and_verify() {
496 let account = Ed25519SingleKeyAccount::generate();
497 let message = b"hello world";
498
499 let signature = account.sign_message(message);
500 assert!(account.public_key().verify(message, &signature).is_ok());
501 }
502
503 #[test]
504 fn test_single_key_from_private_key() {
505 let original = Ed25519SingleKeyAccount::generate();
506 let private_key = original.private_key().clone();
507 let restored = Ed25519SingleKeyAccount::from_private_key(private_key);
508 assert_eq!(original.address(), restored.address());
509 }
510
511 #[test]
512 fn test_single_key_from_private_key_bytes() {
513 let original = Ed25519SingleKeyAccount::generate();
514 let bytes = original.private_key().to_bytes();
515 let restored = Ed25519SingleKeyAccount::from_private_key_bytes(&bytes).unwrap();
516 assert_eq!(original.address(), restored.address());
517 }
518
519 #[test]
520 fn test_single_key_from_private_key_hex() {
521 let original = Ed25519SingleKeyAccount::generate();
522 let hex = original.private_key().to_hex();
523 let restored = Ed25519SingleKeyAccount::from_private_key_hex(&hex).unwrap();
524 assert_eq!(original.address(), restored.address());
525 }
526
527 #[test]
528 fn test_single_key_authentication_key() {
529 let account = Ed25519SingleKeyAccount::generate();
530 let auth_key = account.authentication_key();
531 assert_eq!(auth_key.as_bytes().len(), 32);
532 }
533
534 #[test]
535 fn test_single_key_public_key_bytes() {
536 let account = Ed25519SingleKeyAccount::generate();
537 let bytes = account.public_key_bytes();
538 assert_eq!(bytes.len(), 34);
540 assert_eq!(bytes[0], 0x00); assert_eq!(bytes[1], 32); }
543
544 #[test]
545 fn test_single_key_signature_scheme() {
546 let account = Ed25519SingleKeyAccount::generate();
547 assert_eq!(account.signature_scheme(), SINGLE_KEY_SCHEME);
548 }
549
550 #[test]
551 fn test_single_key_sign_trait() {
552 let account = Ed25519SingleKeyAccount::generate();
553 let message = b"test message";
554 let sig_bytes = account.sign(message).unwrap();
555 assert_eq!(sig_bytes.len(), 64);
556 }
557
558 #[test]
559 fn test_single_key_debug_output() {
560 let account = Ed25519SingleKeyAccount::generate();
561 let debug = format!("{account:?}");
562 assert!(debug.contains("Ed25519SingleKeyAccount"));
563 assert!(debug.contains("address"));
564 }
565
566 #[test]
567 #[cfg(feature = "mnemonic")]
568 fn test_single_key_from_mnemonic() {
569 let mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
570 let account = Ed25519SingleKeyAccount::from_mnemonic(mnemonic, 0).unwrap();
571
572 let account2 = Ed25519SingleKeyAccount::from_mnemonic(mnemonic, 0).unwrap();
574 assert_eq!(account.address(), account2.address());
575
576 let account3 = Ed25519SingleKeyAccount::from_mnemonic(mnemonic, 1).unwrap();
578 assert_ne!(account.address(), account3.address());
579 }
580
581 #[test]
582 #[cfg(feature = "mnemonic")]
583 fn test_single_key_vs_legacy_mnemonic() {
584 let mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
585
586 let legacy = Ed25519Account::from_mnemonic(mnemonic, 0).unwrap();
587 let single_key = Ed25519SingleKeyAccount::from_mnemonic(mnemonic, 0).unwrap();
588
589 assert_eq!(
591 legacy.private_key().to_bytes(),
592 single_key.private_key().to_bytes()
593 );
594 assert_ne!(legacy.address(), single_key.address());
595 }
596}