diff --git a/source/cfdi-descarga.py b/source/cfdi-descarga.py index 9cbd48f..c19ee2c 100644 --- a/source/cfdi-descarga.py +++ b/source/cfdi-descarga.py @@ -5,10 +5,14 @@ from sat import util def main(args): - print(args) + print(args, '\n') if args.fiel_validar: util.fiel_validate(args) + return + + util.download(args) + return @@ -17,11 +21,14 @@ def _process_command_line_arguments(): description='Descarga SAT') parser.add_argument('-fv', '--fiel-validar', default=False, action='store_true') - help = "Directorio de ubicaciĆ³n de la FIEL" + help = 'Directorio de ubicaciĆ³n de la FIEL' parser.add_argument('-fd', '--fiel-dir', help=help, default='') help = "Nombre de la Fiel, el predeterminado es 'fiel'" parser.add_argument('-fn', '--fiel-nombre', help=help, default='fiel') + help = 'Directorio de descarga' + parser.add_argument('-dd', '--dir-descarga', help=help, default='') + return parser.parse_args() diff --git a/source/sat/cfdi_cert.py b/source/sat/cfdi_cert.py index 03712cd..3310cea 100644 --- a/source/sat/cfdi_cert.py +++ b/source/sat/cfdi_cert.py @@ -1,10 +1,7 @@ #!/usr/bin/env python3 -import argparse import base64 import datetime -import getpass -from pathlib import Path from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization @@ -20,11 +17,9 @@ from conf import TOKEN class SATCertificate(object): def __init__(self, cer): - # ~ def __init__(self, cer=b'', key=b'', pem=b'', password=''): self._error = '' self._init_values() self._get_data_cer(cer) - # ~ self._get_data_pem(pem) def _init_values(self): self._rfc = '' @@ -37,6 +32,7 @@ class SATCertificate(object): self._is_valid_time = False self._cer_pem = '' self._cer_txt = '' + self._key = b'' self._key_enc = b'' self._key_pem = b'' self._cer_modulus = 0 @@ -89,13 +85,6 @@ class SATCertificate(object): digest.update(TOKEN.encode()) return digest.finalize() - # ~ def _get_key(self, password): - # ~ if not password: - # ~ password = self._get_hash() - # ~ private_key = serialization.load_pem_private_key( - # ~ self._key_enc, password=password, backend=default_backend()) - # ~ return private_key - # ~ def _get_key_pem(self): # ~ obj = self._get_key('') # ~ key_pem = obj.private_bytes( @@ -105,14 +94,6 @@ class SATCertificate(object): # ~ ) # ~ 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 - # ~ def _sign_with_pem(self, data, name_hash): # ~ if name_hash == 'sha256': # ~ type_hash = hashes.SHA256() @@ -122,26 +103,6 @@ class SATCertificate(object): # ~ 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): - # ~ import xmlsec - - # ~ node = xmlsec.tree.find_node(tree, xmlsec.constants.NodeSignature) - # ~ ctx = xmlsec.SignatureContext() - # ~ key = xmlsec.Key.from_memory(self.key_pem, xmlsec.constants.KeyDataFormatPem) - # ~ ctx.key = key - # ~ ctx.sign(node) - # ~ node = xmlsec.tree.find_node(tree, 'X509Certificate') - # ~ node.text = self.cer_txt - # ~ return tree - @property def rfc(self): return self._rfc @@ -189,6 +150,9 @@ class SATCertificate(object): @property def key_pem(self): return self._key_pem + @key_pem.setter + def key_pem(self, value): + self._key_pem = value @property def key_enc(self): @@ -202,6 +166,13 @@ class SATCertificate(object): def error(self): return self._error + @property + def key(self): + return self._key + @key.setter + def key(self, value): + self._key = value + def validate_key(self, key, password): try: obj = serialization.load_der_private_key( @@ -232,7 +203,16 @@ class SATCertificate(object): return - def sign(self, data, password=''): - private_key = self._get_key(password) - firma = private_key.sign(data, padding.PKCS1v15(), hashes.SHA256()) - return base64.b64encode(firma).decode() + def sign(self, data, name_hash='sha256'): + if name_hash == 'sha256': + type_hash = hashes.SHA256() + elif name_hash == 'sha1': + type_hash = hashes.SHA1() + + password = self._get_hash() + private_key = serialization.load_pem_private_key( + self._key, password=password, backend=default_backend()) + sign = private_key.sign(data.encode(), padding.PKCS1v15(), type_hash) + del password + del private_key + return base64.b64encode(sign).decode() diff --git a/source/sat/util.py b/source/sat/util.py index 6495361..d4154b0 100644 --- a/source/sat/util.py +++ b/source/sat/util.py @@ -71,3 +71,54 @@ def fiel_validate(args): log.info(msg) return + + +def _get_certificate(path_fiel, name_fiel): + if not path_fiel: + msg = 'El argumento -fd (fiel-dir) es requerido' + log.error(msg) + return + + path_fiel = Path(path_fiel) + path_fiel_cer = path_fiel / f'{name_fiel}.cer' + path_fiel_key = path_fiel / f'{name_fiel}.enc' + path_fiel_pem = path_fiel / f'{name_fiel}.pem' + + cer = path_fiel_cer.read_bytes() + + certificate = SATCertificate(cer) + if not certificate.is_valid: + log.error(certificate.error) + return + + if path_fiel_key.exists(): + certificate.key = path_fiel_key.read_bytes() + if path_fiel_pem.exists(): + certificate.key_pem = path_fiel_pem.read_bytes() + + return certificate + + +def _validate_arguments(args): + path_download = args.dir_descarga + if not path_download: + msg = 'El argumento -dd (dir-descarga) es requerido' + log.error(msg) + return {}, None + + cert = _get_certificate(args.fiel_dir, args.fiel_nombre) + if cert is None: + return {}, None + + data = {'path_dowload': path_download} + + return data, cert + +def download(args): + data, cert = _validate_arguments(args) + if not data: + return + + print(data) + + return