Coverage for signonetime.py: 91%

35 statements  

« prev     ^ index     » next       coverage.py v7.5.3, created at 2025-07-10 13:43 +0000

1# The MIT License (MIT) 

2# 

3# Copyright (c) 2021 RSK Labs Ltd 

4# 

5# Permission is hereby granted, free of charge, to any person obtaining a copy of 

6# this software and associated documentation files (the "Software"), to deal in 

7# the Software without restriction, including without limitation the rights to 

8# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 

9# of the Software, and to permit persons to whom the Software is furnished to do 

10# so, subject to the following conditions: 

11# 

12# The above copyright notice and this permission notice shall be included in all 

13# copies or substantial portions of the Software. 

14# 

15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 

16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 

17# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 

18# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 

19# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 

20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 

21# SOFTWARE. 

22 

23import sys 

24from argparse import ArgumentParser 

25import logging 

26import ecdsa 

27from admin.misc import info 

28from admin.ledger_utils import compute_app_hash 

29 

30 

31def main(): 

32 logging.disable(logging.CRITICAL) 

33 

34 parser = ArgumentParser(description="powHSM OneTime Key App Signer") 

35 parser.add_argument( 

36 "-a", 

37 "--app", 

38 dest="app_path", 

39 help="Path to the app(s) to be signed (comma-separated).", 

40 required=True, 

41 ) 

42 parser.add_argument( 

43 "-p", 

44 "--publickey", 

45 dest="publickey_path", 

46 help="Destination file for the public key.", 

47 required=True, 

48 ) 

49 parser.add_argument( 

50 "-v", 

51 "--verbose", 

52 dest="verbose", 

53 action="store_const", 

54 help="Enable verbose mode", 

55 default=False, 

56 const=True, 

57 ) 

58 options = parser.parse_args() 

59 

60 try: 

61 # Generate the signing key 

62 sk = ecdsa.SigningKey.generate(curve=ecdsa.SECP256k1) 

63 

64 # Save the public key to disk 

65 with open(options.publickey_path.strip(), "wb") as file: 

66 file.write(sk.get_verifying_key().to_string("uncompressed").hex().encode()) 

67 info(f"Public key saved to {options.publickey_path}") 

68 

69 # Sign apps 

70 for app_path in options.app_path.split(","): 

71 app_path = app_path.strip() 

72 info(f"Computing hash for '{app_path}'...") 

73 app_hash = compute_app_hash(app_path) 

74 info(f"App hash: {app_hash.hex()}") 

75 

76 # Sign the app hash with a random key 

77 info("Signing with key...") 

78 signature = sk.sign_digest(app_hash, sigencode=ecdsa.util.sigencode_der) 

79 

80 # Save the signature to disk 

81 signature_path = f"{app_path}.sig" 

82 with open(signature_path, "wb") as file: 

83 file.write(signature.hex().encode()) 

84 info(f"Signature saved to {signature_path}") 

85 

86 sys.exit(0) 

87 except Exception as e: 

88 info(str(e)) 

89 sys.exit(1) 

90 

91 

92if __name__ == "__main__": 

93 main()