Python RSA, ECDSA384签名/验证

工作中用到了RSA和ECDSA的签名,整理一下脚本代码,分享给有需要的人。RSA支持多种bit位数, ECDSA暂时只支持ECDSA384。RSA的脚本用的python2,ECDSA用python3写的。

RSA

#!/usr/bin/python
from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.serialization import load_pem_private_key, \
    load_pem_public_key
import os
import sys

from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
import binascii


def 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_ok


if __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/python3
import os
import sys
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import ec, rsa
from cryptography.hazmat.primitives import hashes
import codecs
from cryptography.hazmat.primitives.serialization import load_pem_private_key
from cryptography.hazmat.primitives.asymmetric.utils import decode_dss_signature, encode_dss_signature
from cryptography.x509 import load_pem_x509_certificate

from cryptography.exceptions import InvalidSignature
import binascii
from cryptography.hazmat.primitives.asymmetric import padding

def bit_to_bytes(a):
    return (a + 7) // 8

def 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 ECDSA384
def 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 ECDSA384
def 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)

猜你喜欢

转载自blog.csdn.net/u011280717/article/details/78508677