forked from openwallet-foundation/acapy
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feature multikey management (openwallet-foundation#3246)
* load key plugin Signed-off-by: Patrick <[email protected]> * simplify functions Signed-off-by: Patrick <[email protected]> * added option kid field to KeyInfo Signed-off-by: PatStLouis <[email protected]> * improving linting and unit tests Signed-off-by: PatStLouis <[email protected]> * add empty kid value for bbs tests Signed-off-by: PatStLouis <[email protected]> * linting fix Signed-off-by: PatStLouis <[email protected]> * more linting Signed-off-by: PatStLouis <[email protected]> * add 2 more tests Signed-off-by: PatStLouis <[email protected]> * linting Signed-off-by: PatStLouis <[email protected]> * await function in tests Signed-off-by: PatStLouis <[email protected]> * askar support Signed-off-by: PatStLouis <[email protected]> * implement askar Signed-off-by: PatStLouis <[email protected]> * spelling mistake Signed-off-by: PatStLouis <[email protected]> * use a constant for default algorithm Signed-off-by: PatStLouis <[email protected]> * linting Signed-off-by: PatStLouis <[email protected]> * remove unused code Signed-off-by: PatStLouis <[email protected]> * formatting Signed-off-by: PatStLouis <[email protected]> * linting Signed-off-by: PatStLouis <[email protected]> * fix key by kid Signed-off-by: PatStLouis <[email protected]> * fix unit tests Signed-off-by: PatStLouis <[email protected]> * add type hints and pass session to call functions instead of profile Signed-off-by: PatStLouis <[email protected]> * remove manager from test function instanciation Signed-off-by: PatStLouis <[email protected]> * replace inject_or with inject for providing wallet interface Signed-off-by: PatStLouis <[email protected]> * move wallet injection to class initialization step Signed-off-by: PatStLouis <[email protected]> --------- Signed-off-by: Patrick <[email protected]> Signed-off-by: PatStLouis <[email protected]>
- Loading branch information
1 parent
620ca2a
commit 89120be
Showing
9 changed files
with
403 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
"""Multikey class.""" | ||
|
||
from ...core.profile import ProfileSession | ||
from ..base import BaseWallet | ||
from ..key_type import ED25519 | ||
from ..util import b58_to_bytes, bytes_to_b58 | ||
from ...utils.multiformats import multibase | ||
from ...wallet.error import WalletNotFoundError | ||
|
||
DEFAULT_ALG = "ed25519" | ||
ALG_MAPPINGS = { | ||
"ed25519": {"key_type": ED25519, "prefix_hex": "ed01", "prefix_length": 2} | ||
} | ||
|
||
|
||
class MultikeyManagerError(Exception): | ||
"""Generic MultikeyManager Error.""" | ||
|
||
|
||
class MultikeyManager: | ||
"""Class for managing wallet keys.""" | ||
|
||
def __init__(self, session: ProfileSession): | ||
"""Initialize the MultikeyManager.""" | ||
|
||
self.wallet: BaseWallet = session.inject(BaseWallet) | ||
|
||
def _multikey_to_verkey(self, multikey: str, alg: str = DEFAULT_ALG): | ||
"""Transform multikey to verkey.""" | ||
|
||
prefix_length = ALG_MAPPINGS[alg]["prefix_length"] | ||
public_bytes = bytes(bytearray(multibase.decode(multikey))[prefix_length:]) | ||
|
||
return bytes_to_b58(public_bytes) | ||
|
||
def _verkey_to_multikey(self, verkey: str, alg: str = DEFAULT_ALG): | ||
"""Transform verkey to multikey.""" | ||
|
||
prefix_hex = ALG_MAPPINGS[alg]["prefix_hex"] | ||
prefixed_key_hex = f"{prefix_hex}{b58_to_bytes(verkey).hex()}" | ||
|
||
return multibase.encode(bytes.fromhex(prefixed_key_hex), "base58btc") | ||
|
||
async def kid_exists(self, kid: str): | ||
"""Check if kid exists.""" | ||
|
||
try: | ||
key = await self.wallet.get_key_by_kid(kid=kid) | ||
|
||
if key: | ||
return True | ||
|
||
except (WalletNotFoundError, AttributeError): | ||
return False | ||
|
||
async def from_kid(self, kid: str): | ||
"""Fetch a single key.""" | ||
|
||
key_info = await self.wallet.get_key_by_kid(kid=kid) | ||
|
||
return { | ||
"kid": key_info.kid, | ||
"multikey": self._verkey_to_multikey(key_info.verkey), | ||
} | ||
|
||
async def from_multikey(self, multikey: str): | ||
"""Fetch a single key.""" | ||
|
||
key_info = await self.wallet.get_signing_key( | ||
verkey=self._multikey_to_verkey(multikey) | ||
) | ||
|
||
return { | ||
"kid": key_info.kid, | ||
"multikey": self._verkey_to_multikey(key_info.verkey), | ||
} | ||
|
||
async def create(self, seed: str = None, kid: str = None, alg: str = DEFAULT_ALG): | ||
"""Create a new key pair.""" | ||
|
||
if alg not in ALG_MAPPINGS: | ||
raise MultikeyManagerError( | ||
f"Unknown key algorithm, use one of {list(ALG_MAPPINGS.keys())}." | ||
) | ||
|
||
if kid and await self.kid_exists(kid=kid): | ||
raise MultikeyManagerError(f"kid '{kid}' already exists in wallet.") | ||
|
||
key_type = ALG_MAPPINGS[alg]["key_type"] | ||
key_info = await self.wallet.create_key(key_type=key_type, seed=seed, kid=kid) | ||
|
||
return { | ||
"kid": key_info.kid, | ||
"multikey": self._verkey_to_multikey(key_info.verkey), | ||
} | ||
|
||
async def update(self, multikey: str, kid: str): | ||
"""Assign a new kid to a key pair.""" | ||
|
||
if kid and await self.kid_exists(kid=kid): | ||
raise MultikeyManagerError(f"kid '{kid}' already exists in wallet.") | ||
|
||
key_info = await self.wallet.assign_kid_to_key( | ||
verkey=self._multikey_to_verkey(multikey), kid=kid | ||
) | ||
|
||
return { | ||
"kid": key_info.kid, | ||
"multikey": self._verkey_to_multikey(key_info.verkey), | ||
} |
Oops, something went wrong.