Skip to content
Snippets Groups Projects
Commit b0f4a8da authored by Vincent Texier's avatar Vincent Texier
Browse files

[feat] #150 Add DUBP Mnemonic SigningKey feature

See the RFC0014 of the Duniter Project
parent 60fa96f6
No related branches found
No related tags found
No related merge requests found
Pipeline #11675 passed
...@@ -22,7 +22,7 @@ from typing import Optional, Union, TypeVar, Type ...@@ -22,7 +22,7 @@ from typing import Optional, Union, TypeVar, Type
import libnacl.sign import libnacl.sign
import pyaes import pyaes
from libnacl.utils import load_key from libnacl.utils import load_key
from hashlib import scrypt from hashlib import scrypt, sha256
from .scrypt_params import ScryptParams from .scrypt_params import ScryptParams
from .base58 import Base58Encoder from .base58 import Base58Encoder
...@@ -33,6 +33,18 @@ from ..tools import ( ...@@ -33,6 +33,18 @@ from ..tools import (
convert_seed_to_seedhex, convert_seed_to_seedhex,
) )
def chunkstring(data: bytes, length: int):
"""
Return a tuple of chunks sized at length from the data bytes
:param data: Data to split
:param length: Size of chunks
:return:
"""
return (data[0 + i : length + i] for i in range(0, len(data), length))
# required to type hint cls in classmethod # required to type hint cls in classmethod
SigningKeyType = TypeVar("SigningKeyType", bound="SigningKey") SigningKeyType = TypeVar("SigningKeyType", bound="SigningKey")
...@@ -509,3 +521,27 @@ Data: {data}""".format( ...@@ -509,3 +521,27 @@ Data: {data}""".format(
seed = bytes(base64.b64decode(secret)[0:32]) seed = bytes(base64.b64decode(secret)[0:32])
return cls(seed) return cls(seed)
@classmethod
def from_dubp_mnemonic(cls, mnemonic: str, scrypt_params: ScryptParams = None):
"""
Generate key pair instance from a DUBP mnemonic passphrase
:param mnemonic: Passphrase generated from a mnemonic algorithm
:param scrypt_params: ScryptParams instance (default=None)
:return:
"""
if scrypt_params is None:
scrypt_params = ScryptParams()
_password = mnemonic.encode("utf-8") # type: bytes
_salt = sha256(b"dubp" + _password).digest() # type: bytes
_seed = scrypt(
password=_password,
salt=_salt,
n=scrypt_params.N, # 4096
r=scrypt_params.r, # 16
p=scrypt_params.p, # 1
dklen=scrypt_params.seed_length, # 32
) # type: bytes
return cls(_seed)
...@@ -14,7 +14,7 @@ GNU General Public License for more details. ...@@ -14,7 +14,7 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
import base64
import os import os
from duniterpy.key import VerifyingKey, SigningKey, PublicKey from duniterpy.key import VerifyingKey, SigningKey, PublicKey
...@@ -144,3 +144,16 @@ class TestSigningKey(unittest.TestCase): ...@@ -144,3 +144,16 @@ class TestSigningKey(unittest.TestCase):
sign_key_load.vk.hex(), sign_key_load.vk.hex(),
"d27f4cb2bfadbaf45b61714b896d4639ab90db035aee746611cdd342bdaa8996", "d27f4cb2bfadbaf45b61714b896d4639ab90db035aee746611cdd342bdaa8996",
) )
def test_dubp_mnemonic(self):
mnemonic = (
"tongue cute mail fossil great frozen same social weasel impact brush kind"
)
keypair = SigningKey.from_dubp_mnemonic(mnemonic)
self.assertEqual(
base64.b64encode(keypair.seed).decode("utf-8"),
"qGdvpbP9lJe7ZG4ZUSyu33KFeAEs/KkshAp9gEI4ReY=",
)
self.assertEqual(keypair.pubkey, "732SSfuwjB7jkt9th1zerGhphs6nknaCBCTozxUcPWPU")
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment