Browse Source

bip39.py: add `generate_seed(mnemonic,passwd)` method

The MMGen Project 11 months ago
parent
commit
cbe952a774
4 changed files with 40 additions and 2 deletions
  1. 13 0
      mmgen/bip39.py
  2. 1 1
      mmgen/data/release_date
  3. 1 1
      mmgen/data/version
  4. 25 0
      test/unit_tests_d/ut_bip39.py

+ 13 - 0
mmgen/bip39.py

@@ -128,3 +128,16 @@ class bip39(baseconv):
 		res = seed_bin + chk_bin
 		res = seed_bin + chk_bin
 
 
 		return tuple(wl[int(res[i*11:(i+1)*11],2)] for i in range(c.mn_len))
 		return tuple(wl[int(res[i*11:(i+1)*11],2)] for i in range(c.mn_len))
+
+	def generate_seed(self,words_arg,passwd=''):
+
+		self.tohex(words_arg) # validate
+
+		from cryptography.hazmat.primitives import hashes
+		from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
+		return PBKDF2HMAC(
+			algorithm  = hashes.SHA512(),
+			length     = 64,
+			salt       = b'mnemonic' + passwd.encode(),
+			iterations = 2048
+		).derive(' '.join(words_arg).encode())

+ 1 - 1
mmgen/data/release_date

@@ -1 +1 @@
-November 2023
+December 2023

+ 1 - 1
mmgen/data/version

@@ -1 +1 @@
-14.1.dev0
+14.1.dev1

+ 25 - 0
test/unit_tests_d/ut_bip39.py

@@ -149,3 +149,28 @@ class unit_tests:
 		vmsg('')
 		vmsg('')
 
 
 		return True
 		return True
+
+	def genseed(self,name,ut):
+
+		vmsg('')
+		qmsg(blue('Testing seed generation with password'))
+		fn = 'test/ref/98831F3A.bip39'
+
+		vmsg(f'Seed source: {purple(fn)}')
+		vmsg('KDF: PBKDF2-SHA512, 2048 rounds')
+		with open(fn) as fh:
+			mnemonic = fh.read().strip()
+
+		seed_hex = bip39().generate_seed(mnemonic.split()).hex()
+		vmsg(f'  Password: {orange("(null)")}\n    {seed_hex}')
+		assert seed_hex == '3c30b98d3d9a713cf5a7a42f5dd27b3bf7f4d792d2b9225f6f519a0da978e13c6f36989ef2123b12a96d6ad5a443a95d61022ffaa9fbce8f946da7b67f75d339'
+
+		passwd = 'passw0rd'
+		seed_hex = bip39().generate_seed(mnemonic.split(),passwd).hex()
+		vmsg(f'  Password: {orange(passwd)}\n    {seed_hex}')
+		assert seed_hex == '7eb773bf60f1a5071f96736b6ddbe5c544a7b7740182a80493e29577e58b7cde011d4e38d26f65dab6c9fdebe5594e523447a1427ffd60746e6d04b4daa42eb1'
+
+		qmsg('OK')
+		vmsg('')
+
+		return True