forked from LBRYCommunity/lbry-sdk
57 lines
1.5 KiB
Python
57 lines
1.5 KiB
Python
import hashlib
|
|
import asyncio
|
|
import unicodedata
|
|
from binascii import hexlify
|
|
from secrets import randbits
|
|
|
|
from lbry.crypto.hash import hmac_sha512
|
|
from . import words
|
|
|
|
|
|
def get_languages():
|
|
return words.languages
|
|
|
|
|
|
def normalize(phrase: str) -> str:
|
|
return ' '.join(unicodedata.normalize('NFKD', phrase).lower().split())
|
|
|
|
|
|
def is_phrase_valid(language, phrase):
|
|
local_words = getattr(words, language)
|
|
for word in normalize(phrase).split():
|
|
if word not in local_words:
|
|
return False
|
|
return bool(phrase)
|
|
|
|
|
|
def sync_generate_phrase(language: str) -> str:
|
|
local_words = getattr(words, language)
|
|
entropy = randbits(132)
|
|
nonce = 0
|
|
while True:
|
|
nonce += 1
|
|
i = entropy + nonce
|
|
word_buffer = []
|
|
while i:
|
|
word_buffer.append(local_words[i % 2048])
|
|
i //= 2048
|
|
seed = ' '.join(word_buffer)
|
|
if hexlify(hmac_sha512(b"Seed version", seed.encode())).startswith(b"01"):
|
|
break
|
|
return seed
|
|
|
|
|
|
def sync_derive_key_from_phrase(phrase: str) -> bytes:
|
|
return hashlib.pbkdf2_hmac('sha512', normalize(phrase).encode(), b'lbryum', 2048)
|
|
|
|
|
|
async def generate_phrase(language: str) -> str:
|
|
return await asyncio.get_running_loop().run_in_executor(
|
|
None, sync_generate_phrase, language
|
|
)
|
|
|
|
|
|
async def derive_key_from_phrase(phrase: str) -> bytes:
|
|
return await asyncio.get_running_loop().run_in_executor(
|
|
None, sync_derive_key_from_phrase, phrase
|
|
)
|