def verify_ca_cert_validity(self, nickname): certdb = cert = None if nss.nss_is_initialized(): nss.nss_shutdown() nss.nss_init(self.secdir) try: certdb = nss.get_default_certdb() cert = nss.find_cert_from_nickname(nickname) if not cert.subject: raise ValueError("has empty subject") try: bc = cert.get_extension(nss.SEC_OID_X509_BASIC_CONSTRAINTS) except KeyError: raise ValueError("missing basic constraints") bc = nss.BasicConstraints(bc.value) if not bc.is_ca: raise ValueError("not a CA certificate") intended_usage = nss.certificateUsageSSLCA try: approved_usage = cert.verify_now(certdb, True, intended_usage) except NSPRError as e: if e.errno != -8102: # SEC_ERROR_INADEQUATE_KEY_USAGE raise ValueError(e.strerror) approved_usage = 0 if approved_usage & intended_usage != intended_usage: raise ValueError('invalid for a CA') finally: del certdb, cert nss.nss_shutdown()
def test_csr_parse(self): csr = self.csr # Validate basic CSR information self.assertEqual(str(csr.subject), 'CN=localhost') self.assertEqual(csr.version, 0) # Validate the CSR Subject Public Key pub_key = csr.subject_public_key_info pub_key_algorithm = pub_key.algorithm self.assertEqual(pub_key_algorithm.id_tag, nss.SEC_OID_PKCS1_RSA_ENCRYPTION) self.assertEqual(pub_key.public_key.rsa.exponent.get_integer(), 65537) # Validate the extensions, the number of extensions should # match, the order of extensions should match, and the # contents of each extension should match. # # Note, extensions are contained in an attribute, in essence # the extensions are a special case of one attribute. extensions = csr.extensions self.assertEqual(len(extensions), 2) extension = extensions[0] self.assertIsInstance(extension, nss.CertificateExtension) self.assertEqual(extension.oid_tag, nss.SEC_OID_X509_BASIC_CONSTRAINTS) bc = nss.BasicConstraints(extension.value) self.assertEqual(bc.is_ca, False) self.assertEqual(bc.path_len, 0) extension = extensions[1] self.assertIsInstance(extension, nss.CertificateExtension) self.assertEqual(extension.oid_tag, nss.SEC_OID_X509_SUBJECT_KEY_ID) self.assertEqual( extension.value.der_to_hex().upper(), '8B:84:44:E2:3B:21:CD:54:37:95:2D:B7:E8:D1:B1:D8:0E:96:56:10', ) # Validate the attributes, the number of attributes should # match and the order of the attributes should match. Each # attribute has a type and a set of values. Confirm each # attribute has the correct number of values and each value is # what we expect. # # Note, one of the attributes is a set of extension requests, # this should be identical to CertificateRequest.extensions # property. The extenions property is just a shorthand for # accessing the attribute containing extensions. # # NSS has an odd behavior with attributes that is heavily # weighted toward extensions. If the attribute contains # extensions then the attribute values are # CertificateExtension's, otherwise they are SecItem's # and need to be interpreted according to the attribute.type. attributes = csr.attributes self.assertEqual(len(attributes), 2) attribute = attributes[0] self.assertIsInstance(attribute, nss.CertAttribute) self.assertEqual(attribute.type_tag, nss.SEC_OID_PKCS9_FRIENDLY_NAME) attribute_values = attribute.values self.assertEqual(len(attribute_values), 1) attribute_value = attribute.values[0] self.assertIsInstance(attribute_value, nss.SecItem) self.assertEqual(str(attribute_value), 'Test') attribute = attributes[1] self.assertIsInstance(attribute, nss.CertAttribute) self.assertEqual(attribute.type_tag, nss.SEC_OID_PKCS9_EXTENSION_REQUEST) attribute_values = attribute.values self.assertEqual(len(attribute_values), 2) attribute_value = attribute.values[0] self.assertIsInstance(attribute_value, nss.CertificateExtension) self.assertEqual(attribute_value.oid_tag, nss.SEC_OID_X509_BASIC_CONSTRAINTS) attribute_value = attribute.values[1] self.assertIsInstance(attribute_value, nss.CertificateExtension) self.assertEqual(attribute_value.oid_tag, nss.SEC_OID_X509_SUBJECT_KEY_ID)
def print_extension(level, extension): print( nss.indented_format([(level, 'Name: %s' % extension.name), (level, 'Critical: %s' % extension.critical)])) oid_tag = extension.oid_tag if oid_tag == nss.SEC_OID_PKCS12_KEY_USAGE: print(nss.indented_format([(level, 'Usages:')])) print( nss.indented_format( nss.make_line_fmt_tuples(level + 1, nss.x509_key_usage(extension.value)))) elif oid_tag == nss.SEC_OID_NS_CERT_EXT_CERT_TYPE: print(nss.indented_format([(level, 'Types:')])) print( nss.indented_format( nss.make_line_fmt_tuples(level + 1, nss.x509_cert_type(extension.value)))) elif oid_tag == nss.SEC_OID_X509_SUBJECT_KEY_ID: print(nss.indented_format([(level, 'Data:')])) print( nss.indented_format( nss.make_line_fmt_tuples( level + 1, extension.value.der_to_hex(nss.OCTETS_PER_LINE_DEFAULT)))) elif oid_tag == nss.SEC_OID_X509_CRL_DIST_POINTS: pts = nss.CRLDistributionPts(extension.value) print( nss.indented_format([ (level, 'CRL Distribution Points: [%d total]' % len(pts)) ])) for i, pt in enumerate(pts): print(nss.indented_format([(level + 1, 'Point[%d]:' % i)])) names = pt.get_general_names() print( nss.indented_format([ (level + 2, 'General Names: [%d total]' % len(names)) ])) for name in names: print(nss.indented_format([(level + 3, '%s:' % name)])) print( nss.indented_format([(level + 2, 'Reasons: %s' % (pt.get_reasons(), ))])) print(nss.indented_format([(level + 2, 'Issuer: %s' % pt.issuer)])) elif oid_tag == nss.SEC_OID_X509_AUTH_INFO_ACCESS: aias = nss.AuthorityInfoAccesses(extension.value) print( nss.indented_format([ (level, 'Authority Information Access: [%d total]' % len(aias)) ])) for i, aia in enumerate(aias): print(nss.indented_format([(level + 1, 'Info[%d]:' % i)])) print( nss.indented_format([(level + 2, 'Method: %s' % (aia.method_str, ))])) print( nss.indented_format([ (level + 2, 'Location: (%s) %s' % (aia.location.type_string, aia.location.name)) ])) elif oid_tag == nss.SEC_OID_X509_AUTH_KEY_ID: auth_key_id = nss.AuthKeyID(extension.value) print(nss.indented_format([(level + 1, 'Key ID:')])) print( nss.indented_format( nss.make_line_fmt_tuples( level + 2, auth_key_id.key_id.to_hex(nss.OCTETS_PER_LINE_DEFAULT)))) print( nss.indented_format([ (level + 1, 'Serial Number: %s' % (auth_key_id.serial_number)) ])) print( nss.indented_format([ (level + 1, 'Issuer:' % auth_key_id.get_general_names()) ])) elif oid_tag == nss.SEC_OID_X509_BASIC_CONSTRAINTS: bc = nss.BasicConstraints(extension.value) print(nss.indented_format([(level, '%s' % str(bc))])) elif oid_tag == nss.SEC_OID_X509_EXT_KEY_USAGE: print(nss.indented_format([(level, 'Usages:')])) print( nss.indented_format( nss.make_line_fmt_tuples( level + 1, nss.x509_ext_key_usage(extension.value)))) elif oid_tag in (nss.SEC_OID_X509_SUBJECT_ALT_NAME, nss.SEC_OID_X509_ISSUER_ALT_NAME): names = nss.x509_alt_name(extension.value) print( nss.indented_format([ (level + 2, 'Alternate Names: [%d total]' % len(names)) ])) for name in names: print(nss.indented_format([(level + 3, '%s:' % name)])) print()
def print_extension(level, extension): print nss.indented_format([(level, 'Name: %s' % extension.name), (level, 'Critical: %s' % extension.critical)]) oid_tag = extension.oid_tag if oid_tag == nss.SEC_OID_PKCS12_KEY_USAGE: print nss.indented_format([(level, 'Usages:')]) print nss.indented_format( nss.make_line_fmt_tuples(level + 1, nss.x509_key_usage(extension.value))) elif oid_tag == nss.SEC_OID_X509_SUBJECT_KEY_ID: print nss.indented_format([(level, 'Data:')]) print nss.indented_format( nss.make_line_fmt_tuples( level + 1, extension.value.der_to_hex(nss.OCTETS_PER_LINE_DEFAULT))) elif oid_tag == nss.SEC_OID_X509_CRL_DIST_POINTS: pts = nss.CRLDistributionPts(extension.value) i = 1 print nss.indented_format([ (level, 'CRL Distribution Points: [%d total]' % len(pts)) ]) for pt in pts: print nss.indented_format([(level + 1, 'Point[%d]:' % i)]) names = pt.get_general_names() print nss.indented_format([ (level + 2, 'General Names: [%d total]' % len(names)) ]) for name in names: print nss.indented_format([(level + 3, '%s:' % name)]) print nss.indented_format([(level + 2, 'Reasons: %s' % (pt.get_reasons(), ))]) print nss.indented_format([(level + 2, 'Issuer: %s' % pt.issuer)]) elif oid_tag == nss.SEC_OID_X509_AUTH_KEY_ID: auth_key_id = nss.AuthKeyID(extension.value) print nss.indented_format([(level + 1, 'Key ID:')]) print nss.indented_format( nss.make_line_fmt_tuples( level + 2, auth_key_id.key_id.to_hex(nss.OCTETS_PER_LINE_DEFAULT))) print nss.indented_format([ (level + 1, 'Serial Number: %s' % (auth_key_id.serial_number)) ]) print nss.indented_format([ (level + 1, 'Issuer:' % auth_key_id.get_general_names()) ]) elif oid_tag == nss.SEC_OID_X509_BASIC_CONSTRAINTS: bc = nss.BasicConstraints(extension.value) print nss.indented_format([(level, '%s' % str(bc))]) elif oid_tag == nss.SEC_OID_X509_EXT_KEY_USAGE: print nss.indented_format([(level, 'Usages:')]) print nss.indented_format( nss.make_line_fmt_tuples(level + 1, nss.x509_ext_key_usage(extension.value))) elif oid_tag in (nss.SEC_OID_X509_SUBJECT_ALT_NAME, nss.SEC_OID_X509_ISSUER_ALT_NAME): names = nss.x509_alt_name(extension.value) print nss.indented_format([ (level + 2, 'Alternate Names: [%d total]' % len(names)) ]) for name in names: print nss.indented_format([(level + 3, '%s:' % name)]) print