工作中用到了RSA和ECDSA的簽名,整理一下指令碼代碼,分享給有需要的人。RSA支援多種bit位元, ECDSA暫時只支援ECDSA384。RSA的指令碼用的python2,ECDSA用python3寫的。 RSA
#!/usr/bin/pythonfrom cryptography.exceptions import InvalidSignaturefrom cryptography.hazmat.backends import default_backendfrom cryptography.hazmat.primitives.serialization import load_pem_private_key, \ load_pem_public_keyimport osimport sysfrom cryptography.hazmat.primitives import hashesfrom cryptography.hazmat.primitives.asymmetric import paddingimport binasciidef gen_rsa_key(bit_nr, pri_key, pub_key): #Pub key and pri key are generated by openssl. gen_skey = "openssl genrsa -out {} {}".format(pri_key, bit_nr) print(gen_skey) os.system(gen_skey) gen_pkey = "openssl rsa -in {} -pubout -out {}".format(pri_key, pub_key) print(gen_pkey) os.system(gen_pkey)def rsa_sign(data_file_name, private_key_file_name, signautre_file_name = None, hash_type = "SHA256"): #Read the raw data data_file = open(data_file_name, "rb") data = data_file.read() data_file.close() #Read privtate key data key_file = open(private_key_file_name, "rb") key_data = key_file.read() key_file.close() private_key = load_pem_private_key( key_data, password=None, backend=default_backend() ) if hash_type == "SHA256": hash_t = hashes.SHA256() elif hash_type == "SHA384": hash_t = hashes.SHA384() else: hash_t = hashes.SHA512() signature = private_key.sign( data, padding.PKCS1v15(), hash_t ) if signautre_file_name != None: #Write the signature data signautre_file = open(signautre_file_name, "wb") signautre_file.write(signature) signautre_file.close(); print("Signautre data:") print(binascii.b2a_hex(signature))def rsa_verify(data_file_name, signature_bin, public_key_file, is_file = True, hash_type = "SHA256"): #Read the data file data_file = open(data_file_name, "rb") data = data_file.read() data_file.close() #Read the signature file signature_file = open(signature_bin, "rb") signature = signature_file.read() signature_file.close() key_file = open(public_key_file, "rb") key_data = key_file.read() key_file.close() public_key = load_pem_public_key( key_data, backend=default_backend() ) if hash_type == "SHA256": hash_t = hashes.SHA256() elif hash_type == "SHA384": hash_t = hashes.SHA384() else: hash_t = hashes.SHA512() verify_ok = False try: public_key.verify( signature, data, padding.PKCS1v15(), hash_t ) print("RSA correct signature :)") except InvalidSignature: print("Invalid signature! :(") else: verify_ok = True return verify_okif __name__ == '__main__': if len(sys.argv) <= 1: print("paramter not correct") exit() if sys.argv[1] == "gen": if len(sys.argv) <= 4: print("my_rsa gen pri_key_file pub_key_file bit_nr") exit() pri_key = sys.argv[2] pub_key = sys.argv[3] bit_nr = sys.argv[4] gen_rsa_key(bit_nr, pri_key, pub_key) if sys.argv[1] == "sign": if len(sys.argv) <= 3: print("my_rsa sign data pri_key_file sig_file") print("or my_rsa sign data pri_key_file") print("or my_rsa sign data pri_key_file sig_file hash") exit() data_file = sys.argv[2] pri_key_file = sys.argv[3] if len(sys.argv)== 5: sig_file = sys.argv[4] rsa_sign(data_file, pri_key_file, sig_file) elif len(sys.argv) == 6: sig_file = sys.argv[4] hash_type = sys.argv[5] rsa_sign(data_file, pri_key_file, sig_file, hash_type) else: rsa_sign(data_file, pri_key_file) if sys.argv[1] == "verify": if len(sys.argv) <= 4: print("my_rsa verify data sig_file pub_key_file") exit() data_file = sys.argv[2] sig_data = sys.argv[3] pub_key_file = sys.argv[4] if len(sys.argv) == 6: hash_type = sys.argv[5] rsa_verify(data_file, sig_data, pub_key_file, True, hash_type) else: rsa_verify(data_file, sig_data, pub_key_file)
ECDSA384
#!/usr/bin/python3import osimport sysfrom cryptography.hazmat.backends import default_backendfrom cryptography.hazmat.primitives.asymmetric import ec, rsafrom cryptography.hazmat.primitives import hashesimport codecsfrom cryptography.hazmat.primitives.serialization import load_pem_private_keyfrom cryptography.hazmat.primitives.asymmetric.utils import decode_dss_signature, encode_dss_signaturefrom cryptography.x509 import load_pem_x509_certificatefrom cryptography.exceptions import InvalidSignatureimport binasciifrom cryptography.hazmat.primitives.asymmetric import paddingdef bit_to_bytes(a): return (a + 7) // 8def gen_ecdsa_key(pri_key, cert_file, ecdsa_type = "SECP384"): #Only support ECDSA384 so far, using openssl gen_ecdsa_pri_key_cmd = "openssl ecparam -genkey -text -out {} -name secp384r1".format(pri_key) print(gen_ecdsa_pri_key_cmd) os.system(gen_ecdsa_pri_key_cmd) gen_ecdsa_cert_key_cmd = "openssl req -new -verbose -pubkey -inform PEM -key {} -x509 -nodes -days 10" \ " -out {}".format(pri_key, cert_file) print(gen_ecdsa_cert_key_cmd) os.system(gen_ecdsa_cert_key_cmd)#Only support ECDSA384def ecdsa_sign(data_file_name, pri_key_file_name, sig_file_name): #Read the raw data data_file = open(data_file_name, "rb") data = data_file.read() data_file.close() #Read the pri_key_file pri_key_file = open(pri_key_file_name, "rb") key_data = pri_key_file.read() pri_key_file.close() digest = hashes.Hash( hashes.SHA384(), default_backend() ) digest.update(data) dgst = digest.finalize() print("Data digest to sign: {:s}".format(dgst.hex())) skey = load_pem_private_key( key_data, password=None, backend=default_backend()) sig_data = skey.sign( data, ec.ECDSA(hashes.SHA384()) ) sig_r, sig_s = decode_dss_signature(sig_data) sig_bytes = b'' key_size_in_bytes = bit_to_bytes(skey.public_key().key_size) sig_r_bytes = sig_r.to_bytes(key_size_in_bytes, "big") sig_bytes += sig_r_bytes print("ECDSA signature R: {:s}".format(sig_r_bytes.hex())) sig_s_bytes = sig_s.to_bytes(key_size_in_bytes, "big") sig_bytes += sig_s_bytes print("ECDSA signature S: {:s}".format(sig_s_bytes.hex())) print("ECDSA signautre: {:s}".format(sig_bytes.hex())) #Write sig to sig_file sig_file = open(sig_file_name, "wb") sig_file.write(sig_bytes) sig_file.close()#Only support ECDSA384def ecdsa_verify(data_file, sig_data, pub_key_file): data_f = open(data_file, "rb") pay_load = data_f.read() data_f.close() sig_f = open(sig_data, "rb") r_s = sig_f.read() sig_f.close() with open(pub_key_file, 'rb') as fpkey: pem_data = fpkey.read() cert = load_pem_x509_certificate(pem_data, default_backend()) public_key = cert.public_key() if isinstance(public_key, ec.EllipticCurvePublicKey): sig_r = int.from_bytes(r_s[:int(len(r_s) / 2)], byteorder='big') sig_s = int.from_bytes(r_s[-int(len(r_s) / 2):], byteorder='big') signature = encode_dss_signature(sig_r, sig_s) try: public_key.verify( signature, pay_load, ec.ECDSA(hashes.SHA384()) ) print("ECDSA Correct signature detected.. :)\n") except InvalidSignature: print("ECDSA Invalid signature detected.. :(\n") else: print("RSA not yet supported") exit()if __name__ == '__main__': if len(sys.argv) <= 1: print("paramter not correct") exit() if sys.argv[1] == "gen": if len(sys.argv) <= 3: print("my_ecdsa gen pri_key_file pub_key_file") exit() pri_key = sys.argv[2] pub_key = sys.argv[3] gen_ecdsa_key(pri_key, pub_key) if sys.argv[1] == "sign": if len(sys.argv) <= 3: print("my_ecdsa sign data pri_key_file sig_file") print("or my_rsa sign data pri_key_file") print("or my_rsa sign data pri_key_file sig_file hash") exit() data_file = sys.argv[2] pri_key_file = sys.argv[3] if len(sys.argv)== 5: sig_file = sys.argv[4] ecdsa_sign(data_file, pri_key_file, sig_file) else: ecdsa_sign(data_file, pri_key_file) if sys.argv[1] == "verify": if len(sys.argv) <= 4: print("my_rsa verify data sig_file cert_file") exit() data_file = sys.argv[2] sig_data = sys.argv[3] pub_key_file = sys.argv[4] ecdsa_verify(data_file, sig_data, pub_key_file)