[Mint] Fix key derivation (#187)

* fix private key derivation

* add backwards compatilibity for old keysets

* bump version

* test pubkeys and private keys

* make format

* reset keys for tests

* fix cli tests
This commit is contained in:
calle
2023-05-01 22:43:51 +02:00
committed by GitHub
parent d201b89df2
commit 321fc733c8
9 changed files with 86 additions and 24 deletions

View File

@@ -3,9 +3,15 @@ import json
from sqlite3 import Row
from typing import Any, Dict, List, Optional, TypedDict, Union
from loguru import logger
from pydantic import BaseModel
from ..core.crypto import derive_keys, derive_keyset_id, derive_pubkeys
from ..core.crypto import (
derive_keys,
derive_keys_backwards_compatible_0_11_insecure,
derive_keyset_id,
derive_pubkeys,
)
from ..core.secp import PrivateKey, PublicKey
# ------- PROOFS -------
@@ -241,6 +247,8 @@ class WalletKeyset:
if public_keys:
self.public_keys = public_keys
self.id = derive_keyset_id(self.public_keys)
if id:
assert id == self.id, "id must match derived id from public keys"
class MintKeyset:
@@ -267,7 +275,7 @@ class MintKeyset:
active=None,
seed: str = "",
derivation_path: str = "",
version: str = "",
version: str = "1",
):
self.derivation_path = derivation_path
self.id = id
@@ -282,16 +290,26 @@ class MintKeyset:
def generate_keys(self, seed):
"""Generates keys of a keyset from a seed."""
self.private_keys = derive_keys(seed, self.derivation_path)
backwards_compatibility_pre_0_12 = False
if (
self.version
and len(self.version.split(".")) > 1
and int(self.version.split(".")[0]) == 0
and int(self.version.split(".")[1]) <= 11
):
backwards_compatibility_pre_0_12 = True
# WARNING: Broken key derivation for backwards compatibility with < 0.12
self.private_keys = derive_keys_backwards_compatible_0_11_insecure(
seed, self.derivation_path
)
else:
self.private_keys = derive_keys(seed, self.derivation_path)
self.public_keys = derive_pubkeys(self.private_keys) # type: ignore
self.id = derive_keyset_id(self.public_keys) # type: ignore
def get_keybase(self):
assert self.id is not None
return {
k: KeyBase(id=self.id, amount=k, pubkey=v.serialize().hex())
for k, v in self.public_keys.items() # type: ignore
}
if backwards_compatibility_pre_0_12:
logger.warning(
f"WARNING: Using weak key derivation for keyset {self.id} (backwards compatibility < 0.12)"
)
class MintKeysets:

View File

@@ -19,6 +19,24 @@ def derive_keys(master_key: str, derivation_path: str = ""):
Deterministic derivation of keys for 2^n values.
TODO: Implement BIP32.
"""
return {
2
** i: PrivateKey(
hashlib.sha256(
(master_key + derivation_path + str(i)).encode("utf-8")
).digest()[:32],
raw=True,
)
for i in range(settings.max_order)
}
def derive_keys_backwards_compatible_0_11_insecure(
master_key: str, derivation_path: str = ""
):
"""
WARNING: Broken key derivation for backwards compatibility with 0.11.
"""
return {
2
** i: PrivateKey(
@@ -33,7 +51,7 @@ def derive_keys(master_key: str, derivation_path: str = ""):
def derive_pubkey(master_key: str):
return PrivateKey(
hashlib.sha256((master_key).encode("utf-8")).hexdigest().encode("utf-8")[:32],
hashlib.sha256((master_key).encode("utf-8")).digest()[:32],
raw=True,
).pubkey

View File

@@ -8,7 +8,7 @@ from pydantic import BaseSettings, Extra, Field, validator
env = Env()
VERSION = "0.11.2"
VERSION = "0.12.0"
def find_env_file():

View File

@@ -116,7 +116,7 @@ class LedgerAPI:
"""Returns proofs of promise from promises. Wants secrets and blinding factors rs."""
proofs: List[Proof] = []
for promise, secret, r in zip(promises, secrets, rs):
logger.trace(f"Creating proof with keyset {self.keyset_id} =+ {promise.id}")
logger.trace(f"Creating proof with keyset {self.keyset_id} = {promise.id}")
assert (
self.keyset_id == promise.id
), "our keyset id does not match promise id."
@@ -278,7 +278,7 @@ class LedgerAPI:
int(amt): PublicKey(bytes.fromhex(val), raw=True)
for amt, val in keys.items()
}
keyset = WalletKeyset(public_keys=keyset_keys, mint_url=url)
keyset = WalletKeyset(id=keyset_id, public_keys=keyset_keys, mint_url=url)
return keyset
@async_set_requests