Add sign with key pem
This commit is contained in:
parent
b06a2c0ffb
commit
c44df24629
|
@ -6,7 +6,6 @@ import datetime
|
||||||
import getpass
|
import getpass
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import xmlsec
|
|
||||||
from cryptography.hazmat.backends import default_backend
|
from cryptography.hazmat.backends import default_backend
|
||||||
from cryptography.hazmat.primitives import serialization
|
from cryptography.hazmat.primitives import serialization
|
||||||
from cryptography import x509
|
from cryptography import x509
|
||||||
|
@ -20,15 +19,17 @@ from conf import TOKEN
|
||||||
|
|
||||||
class SATCertificate(object):
|
class SATCertificate(object):
|
||||||
|
|
||||||
def __init__(self, cer=b'', key=b'', password=''):
|
def __init__(self, cer=b'', key=b'', pem=b'', password=''):
|
||||||
self._error = ''
|
self._error = ''
|
||||||
self._init_values()
|
self._init_values()
|
||||||
self._get_data_cer(cer)
|
self._get_data_cer(cer)
|
||||||
self._get_data_key(key, password)
|
self._get_data_key(key, password)
|
||||||
|
self._get_data_pem(pem)
|
||||||
|
|
||||||
def _init_values(self):
|
def _init_values(self):
|
||||||
self._rfc = ''
|
self._rfc = ''
|
||||||
self._serial_number = ''
|
self._serial_number = ''
|
||||||
|
self._serial_number2 = ''
|
||||||
self._not_before = None
|
self._not_before = None
|
||||||
self._not_after = None
|
self._not_after = None
|
||||||
self._is_fiel = False
|
self._is_fiel = False
|
||||||
|
@ -37,9 +38,11 @@ class SATCertificate(object):
|
||||||
self._cer_pem = ''
|
self._cer_pem = ''
|
||||||
self._cer_txt = ''
|
self._cer_txt = ''
|
||||||
self._key_enc = b''
|
self._key_enc = b''
|
||||||
|
self._key_pem = b''
|
||||||
self._p12 = b''
|
self._p12 = b''
|
||||||
self._cer_modulus = 0
|
self._cer_modulus = 0
|
||||||
self._key_modulus = 0
|
self._key_modulus = 0
|
||||||
|
self._issuer = ''
|
||||||
return
|
return
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -66,9 +69,12 @@ class SATCertificate(object):
|
||||||
obj = x509.load_der_x509_certificate(cer, default_backend())
|
obj = x509.load_der_x509_certificate(cer, default_backend())
|
||||||
self._rfc = obj.subject.get_attributes_for_oid(
|
self._rfc = obj.subject.get_attributes_for_oid(
|
||||||
NameOID.X500_UNIQUE_IDENTIFIER)[0].value.split(' ')[0]
|
NameOID.X500_UNIQUE_IDENTIFIER)[0].value.split(' ')[0]
|
||||||
|
self._serial_number2 = obj.serial_number
|
||||||
self._serial_number = '{0:x}'.format(obj.serial_number)[1::2]
|
self._serial_number = '{0:x}'.format(obj.serial_number)[1::2]
|
||||||
self._not_before = obj.not_valid_before
|
self._not_before = obj.not_valid_before
|
||||||
self._not_after = obj.not_valid_after
|
self._not_after = obj.not_valid_after
|
||||||
|
self._issuer = ','.join([i.rfc4514_string() for i in obj.issuer])
|
||||||
|
|
||||||
now = datetime.datetime.utcnow()
|
now = datetime.datetime.utcnow()
|
||||||
self._is_valid_time = (now > self.not_before) and (now < self.not_after)
|
self._is_valid_time = (now > self.not_before) and (now < self.not_after)
|
||||||
if not self._is_valid_time:
|
if not self._is_valid_time:
|
||||||
|
@ -81,6 +87,7 @@ class SATCertificate(object):
|
||||||
self._cer_pem = obj.public_bytes(serialization.Encoding.PEM).decode()
|
self._cer_pem = obj.public_bytes(serialization.Encoding.PEM).decode()
|
||||||
self._cer_txt = ''.join(self._cer_pem.split('\n')[1:-2])
|
self._cer_txt = ''.join(self._cer_pem.split('\n')[1:-2])
|
||||||
self._cer_modulus = obj.public_key().public_numbers().n
|
self._cer_modulus = obj.public_key().public_numbers().n
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def _get_data_key(self, key, password):
|
def _get_data_key(self, key, password):
|
||||||
|
@ -126,6 +133,14 @@ class SATCertificate(object):
|
||||||
)
|
)
|
||||||
return key_pem
|
return key_pem
|
||||||
|
|
||||||
|
def _get_data_pem(self, pem):
|
||||||
|
if not pem:
|
||||||
|
return
|
||||||
|
|
||||||
|
self._key_pem = serialization.load_pem_private_key(
|
||||||
|
pem, None, backend=default_backend())
|
||||||
|
return
|
||||||
|
|
||||||
# Not work
|
# Not work
|
||||||
def _get_p12(self):
|
def _get_p12(self):
|
||||||
obj = serialization.pkcs12.serialize_key_and_certificates('test',
|
obj = serialization.pkcs12.serialize_key_and_certificates('test',
|
||||||
|
@ -139,7 +154,26 @@ class SATCertificate(object):
|
||||||
firma = private_key.sign(data, padding.PKCS1v15(), hashes.SHA256())
|
firma = private_key.sign(data, padding.PKCS1v15(), hashes.SHA256())
|
||||||
return base64.b64encode(firma).decode()
|
return base64.b64encode(firma).decode()
|
||||||
|
|
||||||
|
def _sign_with_pem(self, data, name_hash):
|
||||||
|
if name_hash == 'sha256':
|
||||||
|
type_hash = hashes.SHA256()
|
||||||
|
elif name_hash == 'sha1':
|
||||||
|
type_hash = hashes.SHA1()
|
||||||
|
|
||||||
|
firma = self._key_pem.sign(data, padding.PKCS1v15(), type_hash)
|
||||||
|
return base64.b64encode(firma).decode()
|
||||||
|
|
||||||
|
def sign_sha1(self, data, password=''):
|
||||||
|
if self._key_pem:
|
||||||
|
return self._sign_with_pem(data, 'sha1')
|
||||||
|
|
||||||
|
private_key = self._get_key(password)
|
||||||
|
firma = private_key.sign(data, padding.PKCS1v15(), hashes.SHA1())
|
||||||
|
return base64.b64encode(firma).decode()
|
||||||
|
|
||||||
def sign_xml(self, tree):
|
def sign_xml(self, tree):
|
||||||
|
import xmlsec
|
||||||
|
|
||||||
node = xmlsec.tree.find_node(tree, xmlsec.constants.NodeSignature)
|
node = xmlsec.tree.find_node(tree, xmlsec.constants.NodeSignature)
|
||||||
ctx = xmlsec.SignatureContext()
|
ctx = xmlsec.SignatureContext()
|
||||||
key = xmlsec.Key.from_memory(self.key_pem, xmlsec.constants.KeyDataFormatPem)
|
key = xmlsec.Key.from_memory(self.key_pem, xmlsec.constants.KeyDataFormatPem)
|
||||||
|
@ -157,6 +191,10 @@ class SATCertificate(object):
|
||||||
def serial_number(self):
|
def serial_number(self):
|
||||||
return self._serial_number
|
return self._serial_number
|
||||||
|
|
||||||
|
@property
|
||||||
|
def serial_number2(self):
|
||||||
|
return self._serial_number2
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def not_before(self):
|
def not_before(self):
|
||||||
return self._not_before
|
return self._not_before
|
||||||
|
@ -197,6 +235,10 @@ class SATCertificate(object):
|
||||||
def key_enc(self):
|
def key_enc(self):
|
||||||
return self._key_enc
|
return self._key_enc
|
||||||
|
|
||||||
|
@property
|
||||||
|
def issuer(self):
|
||||||
|
return self._issuer
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def p12(self):
|
def p12(self):
|
||||||
return self._get_p12()
|
return self._get_p12()
|
||||||
|
@ -204,52 +246,3 @@ class SATCertificate(object):
|
||||||
@property
|
@property
|
||||||
def error(self):
|
def error(self):
|
||||||
return self._error
|
return self._error
|
||||||
|
|
||||||
|
|
||||||
def main(args):
|
|
||||||
# ~ contra = getpass.getpass('Introduce la contraseña del archivo KEY: ')
|
|
||||||
contra = '12345678a'
|
|
||||||
if not contra.strip():
|
|
||||||
msg = 'La contraseña es requerida'
|
|
||||||
print(msg)
|
|
||||||
return
|
|
||||||
|
|
||||||
path_cer = Path(args.cer)
|
|
||||||
path_key = Path(args.key)
|
|
||||||
|
|
||||||
if not path_cer.is_file():
|
|
||||||
msg = 'El archivo CER es necesario'
|
|
||||||
print(msg)
|
|
||||||
return
|
|
||||||
|
|
||||||
if not path_key.is_file():
|
|
||||||
msg = 'El archivo KEY es necesario'
|
|
||||||
print(msg)
|
|
||||||
return
|
|
||||||
|
|
||||||
cer = path_cer.read_bytes()
|
|
||||||
key = path_key.read_bytes()
|
|
||||||
cert = SATCertificate(cer, key, contra)
|
|
||||||
|
|
||||||
if cert.error:
|
|
||||||
print(cert.error)
|
|
||||||
else:
|
|
||||||
print(cert)
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
def _process_command_line_arguments():
|
|
||||||
parser = argparse.ArgumentParser(description='CFDI Certificados')
|
|
||||||
|
|
||||||
help = 'Archivo CER'
|
|
||||||
parser.add_argument('-c', '--cer', help=help, default='')
|
|
||||||
help = 'Archivo KEY'
|
|
||||||
parser.add_argument('-k', '--key', help=help, default='')
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
|
||||||
return args
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
args = _process_command_line_arguments()
|
|
||||||
main(args)
|
|
Loading…
Reference in New Issue