rjw | 1f88458 | 2022-01-06 17:20:42 +0800 | [diff] [blame^] | 1 | """ |
| 2 | This module is used to delegate signature generation to HSM(Hardware Security Module) |
| 3 | If public key is given for signing instead of private key, we'll know that |
| 4 | we're trying to delegate signature to HSM. Then we look up key table created |
| 5 | here to find HSM parameters. Here public key is used only as id for HSM |
| 6 | parameters and won't act as a public key. |
| 7 | """ |
| 8 | import filecmp |
| 9 | import os |
| 10 | import lib.cert |
| 11 | |
| 12 | class HsmParam(object): |
| 13 | """ |
| 14 | Parameter for HSM |
| 15 | """ |
| 16 | def __init__(self): |
| 17 | # you can add parameter required by your HSM here |
| 18 | self.m_prvk = None |
| 19 | |
| 20 | def create_key_table(): |
| 21 | """ |
| 22 | create key table for public key to private key mapping |
| 23 | """ |
| 24 | prvk_list = [] |
| 25 | pubk_list = [] |
| 26 | key_database_path = os.path.join(os.path.dirname(__file__), 'hsm_test_keys') |
| 27 | keys = os.listdir(key_database_path) |
| 28 | key_table = {} |
| 29 | |
| 30 | for key in keys: |
| 31 | key_path = os.path.join(key_database_path, key) |
| 32 | if lib.cert.is_prvk(key_path): |
| 33 | prvk_list.append(key_path) |
| 34 | elif lib.cert.is_pubk(key_path): |
| 35 | pubk_list.append(key_path) |
| 36 | |
| 37 | for pubk in pubk_list: |
| 38 | for prvk in prvk_list: |
| 39 | tmp_pubk = os.path.join(os.path.dirname(__file__), 'tmp_pubk.pem') |
| 40 | lib.cert.prvk_to_pubk(prvk, tmp_pubk) |
| 41 | if filecmp.cmp(pubk, tmp_pubk, False) is True: |
| 42 | key_table[pubk] = os.path.join(key_database_path, prvk) |
| 43 | os.remove(tmp_pubk) |
| 44 | break |
| 45 | os.remove(tmp_pubk) |
| 46 | |
| 47 | return key_table |
| 48 | |
| 49 | def query_key_table(key_table, key): |
| 50 | """ |
| 51 | get private key from public key. |
| 52 | In your implementation, you should convert input public |
| 53 | key to parameter passed to HSM, so HSM knows how to sign |
| 54 | message. Here as an example, we search public keys in a folder |
| 55 | as public key data base, and use corresponding private key |
| 56 | to sign message. |
| 57 | """ |
| 58 | for pubk in key_table.keys(): |
| 59 | if filecmp.cmp(key, pubk, False) is True: |
| 60 | return key_table[pubk] |
| 61 | |
| 62 | return None |
| 63 | |
| 64 | |
| 65 | def hsm_rsa_sign(data, key, padding, sig): |
| 66 | """ |
| 67 | sign data with HSM |
| 68 | """ |
| 69 | # note that key is pubk actually, use it as index for |
| 70 | # HSM parameters such as key selection |
| 71 | hsm_param_obj = HsmParam() |
| 72 | key_table = create_key_table() |
| 73 | hsm_param_obj.m_prvk = query_key_table(key_table, key) |
| 74 | if hsm_param_obj.m_prvk is None: |
| 75 | print 'not valid HSM parameter' |
| 76 | return -1 |
| 77 | |
| 78 | print "========================" |
| 79 | print "HSM parameter:" |
| 80 | print " m_prvk = " + hsm_param_obj.m_prvk |
| 81 | print "========================" |
| 82 | |
| 83 | # place hsm request here -- start |
| 84 | # we re-direct it to signing with private key to mimic HSM |
| 85 | # data is not hashed here, you can hash data here to reduce |
| 86 | # network usage |
| 87 | lib.cert.sig_gen(data, hsm_param_obj.m_prvk, padding, sig) |
| 88 | # place hsm request here -- end |
| 89 | return 0 |