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

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. 

4 

5""" 

6 

7from .key import Key 

8from typing import abstractmethod 

9from hashlib import blake2b 

10 

11 

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. 

16 

17 """ 

18 

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). 

24 

25 Parameters: 

26 public_point: the public point generated by the other party in compressed format 

27 

28 Returns: 

29 The resulting point in compressed format (32 bytes). 

30 

31 """ 

32 ... 

33 

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. 

39 

40 Parameters: 

41 reader_public_key: the reader public key (point) in compressed format 

42 

43 Returns: 

44 The writer symmetric key as raw 32 bytes. 

45 

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] 

53 

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. 

59 

60 Parameters: 

61 writer_public_key: the writer public key (point) in compressed format 

62 

63 Returns: 

64 The reader symmetric key as raw 32 bytes. 

65 

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] 

73 

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. 

78 

79 Returns: 

80 Always True. 

81 

82 """ 

83 return True