From b3c0e13ca840da5e4837ba8dfc4fb2c4d1b2bc28 Mon Sep 17 00:00:00 2001
From: Nicolas80 <nicolas.pmail@protonmail.com>
Date: Wed, 1 Jan 2025 18:36:53 +0100
Subject: [PATCH] * Added a test to verify we don't need the
 nacl::sign::Keypair to handle cesium v1 (we can keep using scrypt to retrieve
 the seed and then sp_core::ed25519::Pair) ** This means we could remove some
 code linked to that and possibly the `nacl` dependency.

---
 src/keys.rs | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 67 insertions(+), 3 deletions(-)

diff --git a/src/keys.rs b/src/keys.rs
index e71dc79..bdcd1ee 100644
--- a/src/keys.rs
+++ b/src/keys.rs
@@ -183,10 +183,16 @@ pub fn pair_from_predefined(deriv: &str) -> Result<Sr25519Pair, GcliError> {
 
 /// get keypair from Cesium id/pwd
 pub fn pair_from_cesium(id: String, pwd: String) -> nacl::sign::Keypair {
+	let seed = seed_from_cesium(&id, &pwd);
+	nacl::sign::generate_keypair(&seed)
+}
+
+/// get seed from Cesium id/pwd
+fn seed_from_cesium(id: &str, pwd: &str) -> [u8; 32] {
 	let params = scrypt::Params::new(12u8, 16u32, 1u32, 32).unwrap();
-	let seed = &mut [0u8; 32];
-	scrypt::scrypt(&pwd.into_bytes(), &id.into_bytes(), &params, seed).unwrap();
-	nacl::sign::generate_keypair(seed)
+	let mut seed = [0u8; 32];
+	scrypt::scrypt(&pwd.as_bytes(), &id.as_bytes(), &params, &mut seed).unwrap();
+	seed
 }
 
 /// ask user to input a secret
@@ -576,6 +582,8 @@ mod tests {
 			let cesium_id = "test_cesium_id".to_string();
 			let cesium_pwd = "test_cesium_pwd".to_string();
 
+			let expected_cesium_v1_ss58_address: String = "5ET2jhgJFoNQUpgfdSkdwftK8DKWdqZ1FKm5GKWdPfMWhPr4".to_string();
+
 			let cesium_keypair = pair_from_cesium(cesium_id, cesium_pwd);
 
 			println!(
@@ -589,6 +597,8 @@ mod tests {
 			let cesium_v1_address: AccountId = cesium_keypair.pkey.into();
 			println!("SS58 Address: '{}'", cesium_v1_address);
 
+			assert_eq!(expected_cesium_v1_ss58_address, cesium_v1_address.to_string());
+
 			//ed25519 seed **seems** to be the first 32 bytes of the secret key from nacl keypair
 			let mut seed: [u8; 32] = [0; 32];
 			seed.copy_from_slice(&cesium_keypair.skey[0..32]);
@@ -660,5 +670,59 @@ mod tests {
 				derived_ed25519_address_from_suri.to_string()
 			);
 		}
+
+		/// Test which verifies that it's possible to directly use a cesium v1 seed retrieved using scryt
+		/// as seed or suri to instantiate an ed25519 keypair - keeping the same resulting SS58 Address as when using nacl::sign::Keypair
+		///
+		/// Using subkey command with **ed25519** scheme to show the seed/suri and associated SS58 Address
+		///
+		/// ```
+		/// subkey inspect --scheme ed25519
+		/// URI:
+		/// Secret Key URI `0x2101d2bc68de9ad149c06293bfe489c8608de576c88927aa5439a81be17aae84` is account:
+		///   Network ID:        substrate
+		///   Secret seed:       0x2101d2bc68de9ad149c06293bfe489c8608de576c88927aa5439a81be17aae84
+		///   Public key (hex):  0x697f6bd16ddebf142384e503fd3f3efc39fe5c7be7c693bd98d982403bb6eb74
+		///   Account ID:        0x697f6bd16ddebf142384e503fd3f3efc39fe5c7be7c693bd98d982403bb6eb74
+		///   Public key (SS58): 5ET2jhgJFoNQUpgfdSkdwftK8DKWdqZ1FKm5GKWdPfMWhPr4
+		///   SS58 Address:      5ET2jhgJFoNQUpgfdSkdwftK8DKWdqZ1FKm5GKWdPfMWhPr4
+		/// ```
+		#[test]
+		fn test_cesium_v1_seed_using_scrypt() {
+			let cesium_id = "test_cesium_id".to_string();
+			let cesium_pwd = "test_cesium_pwd".to_string();
+
+			let expected_cesium_v1_ss58_address: String = "5ET2jhgJFoNQUpgfdSkdwftK8DKWdqZ1FKm5GKWdPfMWhPr4".to_string();
+
+			// retrieving seed using scrypt
+			let seed = seed_from_cesium(&cesium_id, &cesium_pwd);
+
+			println!("seed value from scrypt: '0x{}'", hex::encode(&seed));
+
+			let ed25519_pair_from_seed = sp_core::ed25519::Pair::from_seed(&seed);
+
+			println!();
+			println!(
+				"ed25519 keypair from seed : public:'0x{}' raw_vec:'0x{}'",
+				hex::encode(ed25519_pair_from_seed.public().0),
+				hex::encode(ed25519_pair_from_seed.to_raw_vec().as_slice())
+			);
+			let ed25519_address_from_seed: AccountId = ed25519_pair_from_seed.public().into();
+			println!(
+				"ed25519 keypair from seed : public SS58 Address:'{}'",
+				ed25519_address_from_seed
+			);
+			assert_eq!(expected_cesium_v1_ss58_address, ed25519_address_from_seed.to_string());
+
+			let root_suri = "0x".to_string() + &hex::encode(seed);
+			let ed25519_pair_from_suri =
+				sp_core::ed25519::Pair::from_string(&root_suri, None).unwrap();
+			let ed25519_address_from_suri: AccountId = ed25519_pair_from_suri.public().into();
+			println!(
+				"ed25519 keypair from suri : public SS58 Address:'{}'",
+				ed25519_address_from_suri
+			);
+			assert_eq!(expected_cesium_v1_ss58_address, ed25519_address_from_suri.to_string());
+		}
 	}
 }
-- 
GitLab