コード例 #1
0
ファイル: iap.py プロジェクト: fantasyx2/python-iap
def decode_obj(data, expected_type):
    der = asn1.DerObject()
    der.decode(data)
    if der.typeTag != expected_type:
        raise InvalidReceipt('Expected tag type {}; got {}'.format(
            expected_type, der.typeTag))
    return der.payload
コード例 #2
0
def verifyCertificateSignature(certificate, ca_certificate):

    # Get the signature algorithm
    algorithm = certificate.get_signature_algorithm()
    cert_asn1 = crypto.dump_certificate(crypto.FILETYPE_ASN1, certificate)

    # Decode the certificate
    der = asn1.DerSequence()
    der.decode(cert_asn1)

    # Der is [certificate, signature algorithm, signature]
    der_cert = der[0]
    der_algo = der[1]
    der_sig = der[2]

    # Decode signature
    der_sigTemp = asn1.DerObject()
    der_sigTemp.decode(der_sig)

    # Get the signature
    sig = der_sigTemp.payload[1:]

    # Verify the certificate
    try:
        crypto.verify(ca_certificate, sig, der_cert, bytesToString(algorithm))
        return True
    except crypto.Error as e:
        return False
コード例 #3
0
ファイル: X509.py プロジェクト: ajwerner/safe
    def validate_cert(self, cacert_pem):
        #print cacert_pem
        # Create an X509 object for cacert_pem (CA Certificate).
        cacert = X509.load_certificate_from_PEM(
            cacert_pem).get_certificate()[0]
        # Get the X509 object of this certifcate.
        cert = self.get_certificate()[0]
        sig_algo = cert.get_signature_algorithm()

        # Let's start with the ASN1 format of this certificate
        ASN1_cert = crypto.dump_certificate(crypto.FILETYPE_ASN1, cert)
        # We need everything in DER format
        der_seq = asn1.DerSequence()
        der_seq.decode(ASN1_cert)
        der_cert = der_seq[0]
        der_algo = der_seq[1]
        der_sig = asn1.DerObject()
        der_sig.decode(der_seq[2])
        cert_sig_payload = der_sig.payload
        if cert_sig_payload[0] != '\x00':
            raise Exception('Unused bits found!')
        cert_sig = cert_sig_payload[1:]
        # Verify this cert with cacert
        try:
            crypto.verify(cacert, cert_sig, der_cert, sig_algo)
            #print "Certifcate Valid!"
            return True
        except crypto.Error as e:
            #print "Certrifcate Invalid: \n"+str(e)
            return False
コード例 #4
0
 def verify_sig(self, encoded_cert):
     der = asn1.DerSequence()
     der.decode(encoded_cert)
     der_sig = asn1.DerObject()
     der_sig.decode(der[2])
     sig = der_sig.payload
     self.assertEqual(b'\x00', sig[:1])
     crypto.verify(self.ca.cert, sig[1:], der[0], 'sha256')
コード例 #5
0
def crl_dates(crl_der):
    crl_seq = asn1.DerSequence()
    crl_seq.decode(crl_der)
    if len(crl_seq) != 3: raise ValueError("unknown crl format")
    tbsCertList = asn1.DerSequence()
    tbsCertList.decode(crl_seq[0])
    thisUpdate = asn1.DerObject()
    nextUpdate = asn1.DerObject()
    if isinstance(tbsCertList[0], types.StringTypes):  # CRL v1
        thisUpdate.decode(tbsCertList[2])
        nextUpdate.decode(tbsCertList[3])
    else:
        if tbsCertList[0] > 1:
            raise ValueError("unsupported CRL profile version: %d" %
                             tbsCertList[0])
        thisUpdate.decode(tbsCertList[3])
        nextUpdate.decode(tbsCertList[4])
    if thisUpdate.typeTag not in time_formats or \
       nextUpdate.typeTag not in time_formats:
        raise ValueError("invalid CRL date/time fields")
    return time_formats[nextUpdate.typeTag](nextUpdate)
コード例 #6
0
    def getURLSFromCertificate(self, certificate):
        urls = []

        for i in range(0, certificate.get_extension_count()):
            # Get the crl lists
            if (certificate.get_extension(i).get_short_name() ==
                    b'crlDistributionPoints'):
                data = asn1.DerObject()
                data.decode(certificate.get_extension(i).get_data())
                if len(data.payload.split(b'http://')) > 1:
                    content = data.payload.split(b'http://')[-1]
                    urls += ["http://" + bytesToString(content)]

            # Get the delta crl lists
            if (certificate.get_extension(i).get_short_name() == b'freshestCRL'
                ):
                data = asn1.DerObject()
                data.decode(certificate.get_extension(i).get_data())
                if len(data.payload.split(b'http://')) > 1:
                    content = data.payload.split(b'http://')[-1]
                    urls += ["http://" + bytesToString(content)]

        return urls
コード例 #7
0
    def extract_cert_signature(self, cert):
        # TODO: Can this be done from M2Crypto's certificate object?
        der_cert = cert.as_der()
        der = asn1.DerSequence()
        der.decode(der_cert)

        der_sig_raw = der[2]

        der_sig_dec = asn1.DerObject()
        der_sig_dec.decode(der_sig_raw)

        sig0 = der_sig_dec.payload

        sig = sig0[1:]

        return sig
コード例 #8
0
    def __init__(self, crt_fname, ca_fname):
        self.crt_fname = crt_fname
        self.ca_fname = ca_fname
        with open(ca_fname, 'r') as fh:
            self.ca_raw = fh.read()
        with open(crt_fname, 'r') as fh:
            self.crt_raw = fh.read()

        self.ca = ossl.load_certificate(ossl.FILETYPE_PEM, self.ca_raw)

        ossl_crt = ossl.load_certificate(ossl.FILETYPE_PEM, self.crt_raw)
        self.pdat = self.PEMData(*PEM.decode(self.crt_raw))
        self.cdat = self.CrtData(*asn1.DerSequence().decode(self.pdat.cert))
        _sig = asn1.DerObject().decode(self.cdat.sig).payload
        self.sig = self.SigData(_sig[0], _sig[1:],
                                ossl_crt.get_signature_algorithm().decode())
        self.crt = RSA.importKey(self.pdat.cert)
        self.verifier = PKCS1_v1_5.new(self.crt)
コード例 #9
0
    def _extract_plain_cert(nvhttp, text):
        cert_text = nvhttp.get_xml_string(text, "plaincert")

        cert = X509.load_cert_string(cert_text.decode('hex'))

        der_cert = cert.as_der()
        der = asn1.DerSequence()
        der.decode(der_cert)
        der_sig_raw = der[2]

        der_sig_dec = asn1.DerObject()
        der_sig_dec.decode(der_sig_raw)

        sig0 = der_sig_dec.payload

        sig = sig0[1:]

        return cert, sig.encode('hex')
コード例 #10
0
def verifyCertSig(id_cert, cert_to_verify, algo='sha1'):
    '''Verify that the SSL certificate *id_cert* has signed the TLS cert
    *cert_to_verify*.

    :param id_cert: Identification Certificate
    :type id_cert: OpenSSL.crypto.X509
    :param cert_to_verify: certificate to verify signature on
    :type cert_to_verify: OpenSSL.crypto.X509
    :param algo: algorithm to use for certificate verification
    :type algo: str

    :returns: **bool** **True** if the signature of *cert_to_verify* can be
        verified from *id_cert*, **False** otherwise
    '''
    cert_to_verify_ASN1 = OpenSSL.crypto.dump_certificate(
        OpenSSL.crypto.FILETYPE_ASN1, cert_to_verify)

    der = asn1.DerSequence()
    der.decode(cert_to_verify_ASN1)
    cert_to_verify_DER = der[0]
    cert_to_verify_ALGO = der[1]
    cert_to_verify_SIG = der[2]

    sig_DER = asn1.DerObject()
    sig_DER.decode(cert_to_verify_SIG)

    sig = sig_DER.payload

    # first byte is number of unused bytes. should be zero
    if sig[0] != '\x00':
        return False

    sig = sig[1:]

    try:
        OpenSSL.crypto.verify(id_cert, sig, cert_to_verify_DER, algo)
        return True
    except OpenSSL.crypto.Error:
        return False
コード例 #11
0
ファイル: x509_util.py プロジェクト: jtwaleson/certinator
 def is_signed_by(self, other):
     if self.get_issuer().hash() != other.get_subject().hash():
         return False
     signature_algorithm = self.get_signature_algorithm()
     self_asn1 = crypto.dump_certificate(
         crypto.FILETYPE_ASN1, self
     )
     self_der = asn1.DerSequence()
     self_der.decode(self_asn1)
     der_cert, der_algo, der_sig = self_der
     der_sig_in = asn1.DerObject()
     der_sig_in.decode(der_sig)
     sig0 = der_sig_in.payload
     if sig0[0] != '\x00':
         raise Exception('Number of unused bits is strange')
     sig = sig0[1:]
     try:
         crypto.verify(other, sig, der_cert, signature_algorithm)
         return True
     except crypto.Error:
         return False
     return False
コード例 #12
0
ファイル: cert.py プロジェクト: 571451370/devstack_mitaka
    def verify(self, signing_cert_str, cert_str):
        """
        Verifies if a certificate is valid and signed by a given certificate.

        :param signing_cert_str: This certificate will be used to verify the
                                  signature. Must be a string representation
                                 of the certificate. If you only have a file
                                 use the method read_str_from_file to
                                 get a string representation.
        :param cert_str:         This certificate will be verified if it is
                                  correct. Must be a string representation
                                 of the certificate. If you only have a file
                                 use the method read_str_from_file to
                                 get a string representation.
        :return:                 Valid, Message
                                 Valid = True if the certificate is valid,
                                 otherwise false.
                                 Message = Why the validation failed.
        """
        try:
            ca_cert = crypto.load_certificate(crypto.FILETYPE_PEM,
                                              signing_cert_str)
            cert = crypto.load_certificate(crypto.FILETYPE_PEM, cert_str)

            if self.certificate_not_valid_yet(ca_cert):
                return False, "CA certificate is not valid yet."

            if ca_cert.has_expired() == 1:
                return False, "CA certificate is expired."

            if cert.has_expired() == 1:
                return False, "The signed certificate is expired."

            if self.certificate_not_valid_yet(cert):
                return False, "The signed certificate is not valid yet."

            if ca_cert.get_subject().CN == cert.get_subject().CN:
                return False, (
                    "CN may not be equal for CA certificate and the "
                    "signed certificate.")

            cert_algorithm = cert.get_signature_algorithm()
            if six.PY3:
                cert_algorithm = cert_algorithm.decode('ascii')

            cert_asn1 = crypto.dump_certificate(crypto.FILETYPE_ASN1, cert)

            der_seq = asn1.DerSequence()
            der_seq.decode(cert_asn1)

            cert_certificate = der_seq[0]
            #cert_signature_algorithm=der_seq[1]
            cert_signature = der_seq[2]

            cert_signature_decoded = asn1.DerObject()
            cert_signature_decoded.decode(cert_signature)

            signature_payload = cert_signature_decoded.payload

            sig_pay0 = signature_payload[0]
            if ((isinstance(sig_pay0, int) and sig_pay0 != 0)
                    or (isinstance(sig_pay0, str) and sig_pay0 != '\x00')):
                return (False,
                        "The certificate should not contain any unused bits.")

            signature = signature_payload[1:]

            try:
                crypto.verify(ca_cert, signature, cert_certificate,
                              cert_algorithm)
                return True, "Signed certificate is valid and correctly signed by CA certificate."
            except crypto.Error as e:
                return False, "Certificate is incorrectly signed."
        except Exception as e:
            return False, "Certificate is not valid for an unknown reason. %s" % str(
                e)
コード例 #13
0
def parse_certs_from_connecs(dir_path, L, top):
	# Open database connection
	db = MySQLdb.connect("localhost","root","","CRL", charset='utf8' )
	# prepare a cursor object using cursor() method
	cursor = db.cursor()
	for index, file_name in enumerate(L):
		if (index % 1000) == 0:
			print ("(%d) connection blobs have been processed" % (index))
		matchObj = re.search( r'^(.*).txt$', file_name, re.I|re.M)
		if matchObj:
			uri = matchObj.group(1)
		file = open(os.path.join(dir_path,file_name), "r")
		ssl_session = 0
		protocol = ""
		cipher = ""
		verify_code = -1
		verify_msg = ""
		certFound = 0
		certs = list()
		for line in file.readlines():
			if (certFound == 1):
					cert += line
			matchObj = re.search( r'BEGIN CERTIFICATE', line, re.I|re.M)
			if matchObj:
				certFound = 1
				cert = line;
			matchObj = re.search( r'END CERTIFICATE', line, re.I|re.M)
			if matchObj:
				certFound = 0;
				certs.append(cert)
			matchObj = re.search( r'^.*SSL-Session:.*$', line, re.I|re.M)
			if matchObj:
				ssl_session = 1
			matchObj = re.search( r'^.*[Pp]rotocol\s*:\s*(.*)$', line, re.I|re.M)
			if ssl_session == 1 and matchObj:
				protocol = matchObj.group(1)
			matchObj = re.search( r'^.*[Cc]ipher\s*:\s*(.*)$', line, re.I|re.M)
			if ssl_session == 1 and matchObj:
				cipher = matchObj.group(1)
			matchObj = re.search( r'^.*[Vv]erify return code\s*:\s*(\d+)\s*\((.*)\).*$', line, re.I|re.M)
			if matchObj:
				verify_code = matchObj.group(1)
				verify_code = int(verify_code)
				verify_msg = matchObj.group(2)
		file.close()
		certs.reverse()
		num_of_certs = len(certs)
		prev_cert_id = -1
		iden_cert_id = -1
		for j, cert in enumerate(certs):
			cert_name = "%s_%d.pem" % (uri, (num_of_certs - j))
			x509 = ""
			try:
				x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert)
			except:
				continue
			
			#########################################
			##### Insert the issuer information #####
			issuer = x509.get_issuer()
			if issuer.organizationName is not None:
				matchObj = re.search( r'^.*"(.*)".*$', issuer.organizationName, re.I|re.M)
				if matchObj:
					issuer.organizationName = matchObj.group(1)
			if issuer.organizationalUnitName is not None:
				matchObj = re.search( r'^.*"(.*)".*$', issuer.organizationalUnitName, re.I|re.M)
				if matchObj:
					issuer.organizationalUnitName = matchObj.group(1)
			if issuer.commonName is not None:
				matchObj = re.search( r'^.*"(.*)".*$', issuer.commonName, re.I|re.M)
				if matchObj:
					issuer.commonName = matchObj.group(1)
			if issuer.countryName is not None:
				matchObj = re.search( r'^.*"(.*)".*$', issuer.countryName, re.I|re.M)
				if matchObj:
					issuer.countryName = matchObj.group(1)
				else:
					matchObj  = re.search( r'^(.*)".*$', issuer.countryName, re.I|re.M)
					if matchObj:
						issuer.countryName = matchObj.group(1)
			sql = '''INSERT INTO names(country, org, org_unit, com_name, top) VALUES ("%s", "%s", "%s", "%s", %d) ON DUPLICATE KEY UPDATE name_id=LAST_INSERT_ID(name_id);''' % (issuer.countryName, issuer.organizationName, issuer.organizationalUnitName, issuer.commonName, top)
			Issuer_id = -1
			try:
				cursor.execute(sql)
				issuer_id = db.insert_id()
			except MySQLdb.Error, e:
				print ("\tError2 %d: %s SQL STMT [%s]" % (e.args[0], e.args[1], sql))
				print ("\tError2 saving the issuer information in the DB in [%s]" % file_name)
				sys.exit()
	
	
			##########################################	
			##### Insert the subject information #####
			subject = x509.get_subject()
			if subject.organizationName is not None:
				matchObj = re.search( r'^.*"(.*)".*$', subject.organizationName, re.I|re.M)
				if matchObj:
					subject.organizationName = matchObj.group(1)
			if subject.organizationalUnitName is not None:
				matchObj = re.search( r'^.*"(.*)".*$', subject.organizationalUnitName, re.I|re.M)
				if matchObj:
					subject.organizationalUnitName = matchObj.group(1)
			if subject.commonName is not None:
				matchObj = re.search( r'^.*"(.*)".*$', subject.commonName, re.I|re.M)
				if matchObj:
					subject.commonName = matchObj.group(1)
			if subject.countryName is not None:
				matchObj = re.search( r'^.*"(.*)".*$', subject.countryName, re.I|re.M)
				if matchObj:
					subject.countryName = matchObj.group(1)
				else:
					matchObj  = re.search( r'^(.*)".*$', subject.countryName, re.I|re.M)
					if matchObj:
						subject.countryName = matchObj.group(1)
			sql = '''INSERT INTO names(country, org, org_unit, com_name, top) VALUES ("%s", "%s", "%s", "%s", %d) ON DUPLICATE KEY UPDATE name_id=LAST_INSERT_ID(name_id);''' % (subject.countryName, subject.organizationName, subject.organizationalUnitName, subject.commonName, top)
			subject_id = -1
			try:
				cursor.execute(sql)
				subject_id = db.insert_id()
			except MySQLdb.Error, e:
				print ("\tError3 %d: %s" % (e.args[0], e.args[1]))
				print ("\tError3 saving the subject information in the DB in [%s] with SQL [%s]" % (file_name, sql))
				sys.exit()
	
			################################
			##### Check if self signed #####
			is_self_signed = 0
			if (subject.get_components()) == (issuer.get_components()):
				is_self_signed = 1
	
			##############################
			##### Get the Extensions #####
			crl_points = list()
			auth_points = list()
			ext_count = x509.get_extension_count()
			for i in range (0, ext_count):
				x509_ext = x509.get_extension(i)
				ext_name = x509_ext.get_short_name()
				matchObj = re.search( r'^.*crlDistributionPoints.*$', ext_name, re.I|re.M)
				if matchObj:
					ext_data_der = x509_ext.get_data()
					der_seq = asn1.DerSequence()
					der_seq.decode(ext_data_der)
					for u in range(len(der_seq)):
						der_obj = asn1.DerObject()
						der_obj.decode(der_seq[u])
						matchObj = re.search( r'^.*(http[s]?:[\w\d=/\.%-_!]+).*$', der_obj.payload, re.I|re.M)
						if matchObj:
							try:
								crl_uri = matchObj.group(1)
								crl_points.append(crl_uri)
							except:
								print ("\tError3_1 error getting the CRL URI [%s] when connecting to [%s]" % (ext_data, file_name))
								sys.exit()
						else:
							if (re.search( r'^.*(http.*).*$', der_obj.payload, re.I|re.M)):
								print ("\tError3_3 extracting the URI from [%s]" % der_obj.payload)
							else:
								pass
				matchObj = re.search( r'^.*authorityInfoAccess.*$', ext_name, re.I|re.M)
				if matchObj:
					ext_data_der = x509_ext.get_data()
					der_seq = asn1.DerSequence()
					der_seq.decode(ext_data_der)
					for u in range(len(der_seq)):
						der_obj = asn1.DerObject()
						der_obj.decode(der_seq[u])
						matchObj = re.search( r'^.*(http:.*)$', der_obj.payload, re.I|re.M)
						if matchObj:
							try:
								auth_uri = matchObj.group(1)
								auth_points.append(auth_uri)
							except:
								print ("\tError3_2 error getting the Auth URI [%s] when connecting to [%s]" % (ext_data, file_name))
								sys.exit()
					
			
			##############################################
			##### Insert the Authority URI in the DB #####
			
			auth_ids = list()
			if len(auth_points) > 0:
				for auth_uri in auth_points:
					sql = '''INSERT INTO authority(auth_uri, top) VALUES ("%s", %d) ON DUPLICATE KEY UPDATE auth_id=LAST_INSERT_ID(auth_id);''' % (auth_uri, top)
					try:
						cursor.execute(sql)
						auth_id = db.insert_id()
						auth_ids.append(auth_id)
					except MySQLdb.Error, e:
						print ("\tError4 %d: %s" % (e.args[0], e.args[1]))
						print ("\tError4 saving the Authority information in the DB in [%s]", file_name)
						sys.exit()	
コード例 #14
0
		##############################
		##### Get the Extensions #####
		
		crl_points = list()
		auth_points = list()
		ext_count = x509.get_extension_count()
		for i in range (0, ext_count):
			x509_ext = x509.get_extension(i)
			ext_name = x509_ext.get_short_name()
			matchObj = re.search( r'^.*crlDistributionPoints.*$', ext_name, re.I|re.M)
			if matchObj:
				ext_data_der = x509_ext.get_data()
				der_seq = asn1.DerSequence()
				der_seq.decode(ext_data_der)
				for u in range(len(der_seq)):
					der_obj = asn1.DerObject()
					der_obj.decode(der_seq[u])
					matchObj = re.search( r'^.*(http[s]?:[\w\d=/\.%-_!]+).*$', der_obj.payload, re.I|re.M)
					if matchObj:
						try:
							crl_uri = matchObj.group(1)
							crl_points.append(crl_uri)
						except:
							print ("\tError3_1 error getting the CRL URI [%s] when connecting to [%s]" % (ext_data, file_name))
							sys.exit()
					else:
						if (re.search( r'^.*(http.*).*$', der_obj.payload, re.I|re.M)):
							print ("\tError3_3 extracting the URI from [%s]" % der_obj.payload)
						else:
							pass
			matchObj = re.search( r'^.*authorityInfoAccess.*$', ext_name, re.I|re.M)
コード例 #15
0
ファイル: pki.py プロジェクト: cldeluna/salt
def auth(username, password, **kwargs):
    '''
    Returns True if the given user cert (password is the cert contents)
    was issued by the CA and if cert's Common Name is equal to username.

    Returns False otherwise.

    ``username``: we need it to run the auth function from CLI/API;
                  it should be in master config auth/acl
    ``password``: contents of user certificate (pem-encoded user public key);
                  why "password"? For CLI, it's the only available name

    Configure the CA cert in the master config file:

    .. code-block:: yaml

        external_auth:
          pki:
            ca_file: /etc/pki/tls/ca_certs/trusted-ca.crt
            your_user:
              - .*
    '''
    c = OpenSSL.crypto
    pem = password
    cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, pem)

    cacert_file = __salt__['config.get']('external_auth:pki:ca_file')
    with salt.utils.fopen(cacert_file) as f:
        cacert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM,
                                                 f.read())

    log.debug('Attempting to authenticate via pki.')
    log.debug('Using CA file: {0}'.format(cacert_file))
    log.debug('Certificate contents: {0}'.format(pem))

    # Get the signing algorithm
    algo = cert.get_signature_algorithm()

    # Get the ASN1 format of the certificate
    cert_asn1 = c.dump_certificate(c.FILETYPE_ASN1, cert)

    # Decode the certificate
    der = asn1.DerSequence()
    der.decode(cert_asn1)

    # The certificate has three parts:
    # - certificate
    # - signature algorithm
    # - signature
    # http://usefulfor.com/nothing/2009/06/10/x509-certificate-basics/
    der_cert = der[0]
    #der_algo = der[1]
    der_sig = der[2]

    # The signature is a BIT STRING (Type 3)
    # Decode that as well
    der_sig_in = asn1.DerObject()
    der_sig_in.decode(der_sig)

    # Get the payload
    sig0 = der_sig_in.payload

    # Do the following to see a validation error for tests
    # der_cert=der_cert[:20]+'1'+der_cert[21:]

    # First byte is the number of unused bits. This should be 0
    # http://msdn.microsoft.com/en-us/library/windows/desktop/bb540792(v=vs.85).aspx
    if sig0[0] != '\x00':
        raise Exception('Number of unused bits is strange')
    # Now get the signature itself
    sig = sig0[1:]

    # And verify the certificate
    try:
        c.verify(cacert, sig, der_cert, algo)
        assert dict(cert.get_subject().get_components(
        ))['CN'] == username, "Certificate's CN should match the username"
        log.info('Successfully authenticated certificate: {0}'.format(pem))
        return True
    except (OpenSSL.crypto.Error, AssertionError):
        log.info('Failed to authenticate certificate: {0}'.format(pem))
    return False
コード例 #16
0
# Decode the certificate
der = asn1.DerSequence()
der.decode(cert_asn1)

# The certificate has three parts:
# - certificate
# - signature algorithm
# - signature
# http://usefulfor.com/nothing/2009/06/10/x509-certificate-basics/
der_cert = der[0]
der_algo = der[1]
der_sig = der[2]

# The signature is a BIT STRING (Type 3)
# Decode that as well
der_sig_in = asn1.DerObject()
der_sig_in.decode(der_sig)

# Get the payload
sig0 = der_sig_in.payload

# Do the following to see a validation error for tests
# der_cert=der_cert[:20]+'1'+der_cert[21:]

# First byte is the number of unused bits. This should be 0
# http://msdn.microsoft.com/en-us/library/windows/desktop/bb540792(v=vs.85).aspx
if sig0[0] != '\x00':
    raise Exception('Number of unused bits is strange')

# Now get the signature itself
sig = sig0[1:]