Add sign with key pem

This commit is contained in:
Mauricio Baeza 2021-07-19 15:24:42 -05:00
parent b06a2c0ffb
commit c44df24629
1 changed files with 44 additions and 51 deletions

View File

@ -6,7 +6,6 @@ import datetime
import getpass
from pathlib import Path
import xmlsec
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography import x509
@ -20,15 +19,17 @@ from conf import TOKEN
class SATCertificate(object):
def __init__(self, cer=b'', key=b'', password=''):
def __init__(self, cer=b'', key=b'', pem=b'', password=''):
self._error = ''
self._init_values()
self._get_data_cer(cer)
self._get_data_key(key, password)
self._get_data_pem(pem)
def _init_values(self):
self._rfc = ''
self._serial_number = ''
self._serial_number2 = ''
self._not_before = None
self._not_after = None
self._is_fiel = False
@ -37,9 +38,11 @@ class SATCertificate(object):
self._cer_pem = ''
self._cer_txt = ''
self._key_enc = b''
self._key_pem = b''
self._p12 = b''
self._cer_modulus = 0
self._key_modulus = 0
self._issuer = ''
return
def __str__(self):
@ -66,9 +69,12 @@ class SATCertificate(object):
obj = x509.load_der_x509_certificate(cer, default_backend())
self._rfc = obj.subject.get_attributes_for_oid(
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._not_before = obj.not_valid_before
self._not_after = obj.not_valid_after
self._issuer = ','.join([i.rfc4514_string() for i in obj.issuer])
now = datetime.datetime.utcnow()
self._is_valid_time = (now > self.not_before) and (now < self.not_after)
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_txt = ''.join(self._cer_pem.split('\n')[1:-2])
self._cer_modulus = obj.public_key().public_numbers().n
return
def _get_data_key(self, key, password):
@ -126,6 +133,14 @@ 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
# Not work
def _get_p12(self):
obj = serialization.pkcs12.serialize_key_and_certificates('test',
@ -139,7 +154,26 @@ class SATCertificate(object):
firma = private_key.sign(data, padding.PKCS1v15(), hashes.SHA256())
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):
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)
@ -157,6 +191,10 @@ class SATCertificate(object):
def serial_number(self):
return self._serial_number
@property
def serial_number2(self):
return self._serial_number2
@property
def not_before(self):
return self._not_before
@ -197,6 +235,10 @@ class SATCertificate(object):
def key_enc(self):
return self._key_enc
@property
def issuer(self):
return self._issuer
@property
def p12(self):
return self._get_p12()
@ -204,52 +246,3 @@ class SATCertificate(object):
@property
def error(self):
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)