Coverage for oarepo_c4gh/key/external.py: 100%
23 statements
« prev ^ index » next coverage.py v7.10.2, created at 2025-08-07 12:05 +0000
« prev ^ index » next coverage.py v7.10.2, created at 2025-08-07 12:05 +0000
1"""This module provides partial implementation of external (hardware
2or network) private keys that allow for computing symmetric keys. It
3assumes a derived class will implement the actual ECDH finalization.
5"""
7from .key import Key
8from typing import abstractmethod
9from hashlib import blake2b
12class ExternalKey(Key):
13 """This class implements the Crypt4GH symmetric key derivation
14 from ECDH result. The actual ECDH computation must be implemented
15 by derived class.
17 """
19 @abstractmethod
20 def compute_ecdh(self, public_point: bytes) -> bytes:
21 """Given a public point on the curve, this function must
22 multiply it by the private key and return the resulting point
23 in compressed format (32 bytes).
25 Parameters:
26 public_point: the public point generated by the other party in compressed format
28 Returns:
29 The resulting point in compressed format (32 bytes).
31 """
32 ...
34 def compute_write_key(self, reader_public_key: bytes) -> bytes:
35 """Computes the write key using this instance's private key
36 and the provided reader public key. See
37 [`Software.compute_write_key`][oarepo_c4gh.key.software.SoftwareKey.compute_write_key]
38 for details.
40 Parameters:
41 reader_public_key: the reader public key (point) in compressed format
43 Returns:
44 The writer symmetric key as raw 32 bytes.
46 """
47 shared_secret = self.compute_ecdh(reader_public_key)
48 hash_source = shared_secret + reader_public_key + self.public_key
49 the_hash = blake2b(digest_size=64)
50 the_hash.update(hash_source)
51 digest = the_hash.digest()
52 return digest[:32]
54 def compute_read_key(self, writer_public_key: bytes) -> bytes:
55 """Computes the reader key using this instance's private key
56 and provided writer public key. See
57 [`Software.compute_read_key`][oarepo_c4gh.key.software.SoftwareKey.compute_read_key]
58 for details.
60 Parameters:
61 writer_public_key: the writer public key (point) in compressed format
63 Returns:
64 The reader symmetric key as raw 32 bytes.
66 """
67 shared_secret = self.compute_ecdh(writer_public_key)
68 hash_source = shared_secret + self.public_key + writer_public_key
69 the_hash = blake2b(digest_size=64)
70 the_hash.update(hash_source)
71 digest = the_hash.digest()
72 return digest[:32]
74 @property
75 def can_compute_symmetric_keys(self) -> bool:
76 """External keys always have private key and therefore can
77 always compute the symmetric keys.
79 Returns:
80 Always True.
82 """
83 return True