Created
October 24, 2019 22:08
-
-
Save ovnicraft/f1ed9c42b79ce7c724d24b761e678ee5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
from abc import ABC, abstractmethod | |
from base64 import b64encode, b64decode | |
from secrets import randbelow | |
from enum import Enum | |
from datetime import datetime | |
from OpenSSL.crypto import X509Name, load_pkcs12, FILETYPE_PEM, FILETYPE_ASN1 | |
from cryptography.hazmat.primitives.asymmetric import rsa, dsa, ec | |
from cryptography.hazmat.primitives.asymmetric.padding import PKCS1v15 | |
from cryptography.hazmat.primitives.hashes import ( | |
Hash, | |
SHA1, | |
SHA224, | |
SHA256, | |
SHA384, | |
SHA512, | |
) | |
from cryptography.hazmat.backends import default_backend | |
# from .util import ( | |
# bytes_to_long, | |
# long_to_bytes, | |
# strip_pem_header, | |
# add_pem_header, | |
# ensure_bytes, | |
# ensure_str, | |
# Namespace, | |
# XMLProcessor, | |
# iterate_pem, | |
# verify_x509_cert_chain, | |
# ) | |
# namespaces = Namespace( | |
# ds="http://www.w3.org/2000/09/xmldsig#", | |
# dsig11="http://www.w3.org/2009/xmldsig11#", | |
# dsig2="http://www.w3.org/2010/xmldsig2#", | |
# ec="http://www.w3.org/2001/10/xml-exc-c14n#", | |
# dsig_more="http://www.w3.org/2001/04/xmldsig-more#", | |
# xenc="http://www.w3.org/2001/04/xmlenc#", | |
# xenc11="http://www.w3.org/2009/xmlenc11#", | |
# ) | |
# methods = Enum("Methods", "enveloped enveloping detached") | |
def check_cert_not_after(cert): | |
cert_not_after = datetime.strptime( | |
cert.get_notAfter().decode("ascii"), "%Y%m%d%H%M%SZ" | |
) | |
if cert_not_after < datetime.utcnow(): | |
raise ValueError( | |
"Client certificate expired: Not After: {cert_not_after:%Y-%m-%d %H:%M:%SZ}".format( | |
**locals() | |
) | |
) | |
class Xades(ABC): | |
def __init__(self): | |
self._template_name = False | |
@property | |
@abstractmethod | |
def template(self): | |
raise NotImplementedError | |
def sign(self, data, cert=None, passphrase=None): | |
raise NotImplementedError | |
def verify(self): | |
return None | |
def generate_random_id(self): | |
return randbelow(100000) | |
class X509NamePKCS12(X509Name): | |
def slug_pkcs12(self): | |
x509name = self.get_components() | |
x509name.reverse() | |
return ",".join([f"{var.decode()}={alias.decode()}" for var, alias in x509name]) | |
class XadesBES(Xades): | |
def __init__(self): | |
""" | |
""" | |
self._template_name = "xades_bes.xml" | |
self._X509_issuername = False | |
self.data = {} | |
def read_issuer_slug(self, certificate): | |
return X509NamePKCS12(certificate.get_issuer()).slug_pkcs12() | |
@property | |
def template(self): | |
return self._template_name | |
def load_certificate(self, cert_path, password): | |
cert_data = open(cert_path, "+rb").read() | |
bpass = password.encode() | |
p12 = load_pkcs12(cert_data, bpass) | |
cert = p12.get_certificate() | |
check_cert_not_after(cert) | |
private_key = p12.get_privatekey() | |
self.data.update( | |
{ | |
"X509IssuerName": self.read_issuer_slug(cert), | |
"X509SerialNumber": cert.get_serial_number(), | |
} | |
) | |
def generate_data_ids(self): | |
self.data.update( | |
{ | |
"SignatureID": self.generate_random_id(), | |
"SignedInfoID": self.generate_random_id(), | |
"SignedPropertiesID": self.generate_random_id(), | |
"SignedProperties": self.generate_random_id(), | |
"CertificateID": self.generate_random_id(), | |
"ReferenceID": self.generate_random_id(), | |
"SignatureValueID": self.generate_random_id(), | |
"ObjectID": self.generate_random_id(), | |
} | |
) | |
@property | |
def signing_time(self): | |
return datetime.now().replace(microsecond=0).isoformat() | |
if __name__ == "__main__": | |
xades = XadesBES() | |
xades.render() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment