Esempio n. 1
0
 def load_gnames(self, gname_list):
     """Converts list of prefixed strings to GeneralName list.
     """
     gnames = []
     for alt in gname_list:
         if ':' not in alt:
             die("Invalid gname: %s", alt)
         t, val = alt.split(':', 1)
         t = t.lower().strip()
         val = val.strip()
         if t == 'dn':
             gn = x509.DirectoryName(self.load_name(parse_dn(val)))
         elif t == 'dns':
             gn = x509.DNSName(val)
         elif t == 'email':
             gn = x509.RFC822Name(val)
         elif t == 'uri':
             gn = x509.UniformResourceIdentifier(val)
         elif t == 'ip':
             if val.find(':') >= 0:
                 gn = x509.IPAddress(ipaddress.IPv6Address(val))
             else:
                 gn = x509.IPAddress(ipaddress.IPv4Address(val))
         elif t == 'dn':
             gn = x509.DirectoryName(self.load_name(parse_dn(val)))
         elif t == 'net':
             if val.find(':') >= 0:
                 gn = x509.IPAddress(ipaddress.IPv6Network(val))
             else:
                 gn = x509.IPAddress(ipaddress.IPv4Network(val))
         else:
             raise Exception('Invalid GeneralName: ' + alt)
         gnames.append(gn)
     return gnames
Esempio n. 2
0
def make_cert(cacert: Cert):
    private_key = make_key()

    builder = (
        x509.CertificateSigningRequestBuilder().subject_name(
            x509.Name([x509.NameAttribute(
                NameOID.COMMON_NAME, "localhost")])).add_extension(
                    x509.SubjectAlternativeName([
                        # Describe what sites we want this certificate for.
                        x509.DNSName("localhost"),
                        x509.IPAddress(ipaddress.IPv4Address("127.0.0.1")),
                        x509.IPAddress(ipaddress.IPv6Address("::1")),
                    ]),
                    critical=False,
                ))
    csr = builder.sign(private_key, hashes.SHA256(), default_backend())

    assert csr.is_signature_valid

    cert_builder = (x509.CertificateBuilder().subject_name(
        csr.subject).issuer_name(cacert.cert.subject).not_valid_before(
            datetime.today() -
            one_day).not_valid_after(datetime.today() + one_day).serial_number(
                int(uuid.uuid4())).public_key(csr.public_key()))
    for extension in csr.extensions:
        cert_builder = cert_builder.add_extension(extension.value,
                                                  critical=extension.critical)
    certificate = cert_builder.sign(private_key=cacert.key,
                                    algorithm=hashes.SHA256(),
                                    backend=default_backend())
    return Cert(certificate, private_key)
Esempio n. 3
0
def generate_selfsigned_cert(
        name,
        key,
        valid_until,
        other_ips: Optional[List] = None) -> x509.Certificate:
    subject = issuer = x509.Name(
        [x509.NameAttribute(NameOID.COMMON_NAME, name)])
    # Add common SAN for localhost
    san_names = [
        x509.DNSName("localhost"),
        x509.DNSName("localhost.localdomain"),
        x509.IPAddress(IPv4Address("127.0.0.1")),
        x509.IPAddress(IPv6Address("::1")),
    ]
    if other_ips:
        for ip in other_ips:
            san_names.append(x509.IPAddress(ip_address(ip)))
    cert = (x509.CertificateBuilder().subject_name(subject).add_extension(
        x509.SubjectAlternativeName(san_names),
        critical=False).issuer_name(issuer).public_key(
            key.public_key()).serial_number(
                x509.random_serial_number()).not_valid_before(
                    datetime.datetime.utcnow()).not_valid_after(
                        valid_until).sign(key,
                                          hashes.SHA256(),
                                          backend=default_backend()))
    return cert
Esempio n. 4
0
def cryptography_get_name(name, what='Subject Alternative Name'):
    '''
    Given a name string, returns a cryptography x509.GeneralName object.
    Raises an OpenSSLObjectError if the name is unknown or cannot be parsed.
    '''
    try:
        if name.startswith('DNS:'):
            return x509.DNSName(to_text(name[4:]))
        if name.startswith('IP:'):
            address = to_text(name[3:])
            if '/' in address:
                return x509.IPAddress(ipaddress.ip_network(address))
            return x509.IPAddress(ipaddress.ip_address(address))
        if name.startswith('email:'):
            return x509.RFC822Name(to_text(name[6:]))
        if name.startswith('URI:'):
            return x509.UniformResourceIdentifier(to_text(name[4:]))
        if name.startswith('RID:'):
            m = re.match(r'^([0-9]+(?:\.[0-9]+)*)$', to_text(name[4:]))
            if not m:
                raise OpenSSLObjectError('Cannot parse {what} "{name}"'.format(
                    name=name, what=what))
            return x509.RegisteredID(x509.oid.ObjectIdentifier(m.group(1)))
        if name.startswith('otherName:'):
            # otherName can either be a raw ASN.1 hex string or in the format that OpenSSL works with.
            m = re.match(
                r'^([0-9]+(?:\.[0-9]+)*);([0-9a-fA-F]{1,2}(?::[0-9a-fA-F]{1,2})*)$',
                to_text(name[10:]))
            if m:
                return x509.OtherName(x509.oid.ObjectIdentifier(m.group(1)),
                                      _parse_hex(m.group(2)))

            # See https://www.openssl.org/docs/man1.0.2/man5/x509v3_config.html - Subject Alternative Name for more
            # defailts on the format expected.
            name = to_text(name[10:], errors='surrogate_or_strict')
            if ';' not in name:
                raise OpenSSLObjectError(
                    'Cannot parse {what} otherName "{name}", must be in the '
                    'format "otherName:<OID>;<ASN.1 OpenSSL Encoded String>" or '
                    '"otherName:<OID>;<hex string>"'.format(name=name,
                                                            what=what))

            oid, value = name.split(';', 1)
            b_value = serialize_asn1_string_as_der(value)
            return x509.OtherName(x509.ObjectIdentifier(oid), b_value)
        if name.startswith('dirName:'):
            return x509.DirectoryName(x509.Name(_parse_dn(to_text(name[8:]))))
    except Exception as e:
        raise OpenSSLObjectError(
            'Cannot parse {what} "{name}": {error}'.format(name=name,
                                                           what=what,
                                                           error=e))
    if ':' not in name:
        raise OpenSSLObjectError(
            'Cannot parse {what} "{name}" (forgot "DNS:" prefix?)'.format(
                name=name, what=what))
    raise OpenSSLObjectError(
        'Cannot parse {what} "{name}" (potentially unsupported by cryptography backend)'
        .format(name=name, what=what))
Esempio n. 5
0
    def generate_cert(self, addr: str = '') -> Tuple[str, str]:
        have_ip = True
        if addr:
            try:
                ip = x509.IPAddress(ipaddress.IPv4Address(addr))
            except Exception:
                try:
                    ip = x509.IPAddress(ipaddress.IPv6Address(addr))
                except Exception:
                    have_ip = False
                    pass
        else:
            ip = x509.IPAddress(ipaddress.IPv4Address(self.mgr.get_mgr_ip()))

        private_key = rsa.generate_private_key(public_exponent=65537,
                                               key_size=4096,
                                               backend=default_backend())
        public_key = private_key.public_key()

        builder = x509.CertificateBuilder()

        builder = builder.subject_name(
            x509.Name([
                x509.NameAttribute(
                    NameOID.COMMON_NAME,
                    addr if addr else str(self.mgr.get_mgr_ip())),
            ]))

        builder = builder.issuer_name(
            x509.Name([
                x509.NameAttribute(NameOID.COMMON_NAME, u'cephadm-root'),
            ]))

        builder = builder.not_valid_before(datetime.now())
        builder = builder.not_valid_after(datetime.now() +
                                          timedelta(days=(365 * 10 + 3)))
        builder = builder.serial_number(x509.random_serial_number())
        builder = builder.public_key(public_key)
        if have_ip:
            builder = builder.add_extension(x509.SubjectAlternativeName([ip]),
                                            critical=False)
        builder = builder.add_extension(
            x509.BasicConstraints(ca=False, path_length=None),
            critical=True,
        )

        cert = builder.sign(private_key=self.root_key,
                            algorithm=hashes.SHA256(),
                            backend=default_backend())

        cert_str = crypto.dump_certificate(crypto.FILETYPE_PEM,
                                           cert).decode('utf-8')
        key_str = private_key.private_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PrivateFormat.TraditionalOpenSSL,
            encryption_algorithm=serialization.NoEncryption()).decode('utf-8')

        return (cert_str, key_str)
Esempio n. 6
0
    def _deserialize(self, value, attr, data):
        general_names = []
        for name in value:
            if name['nameType'] == 'DNSName':
                validators.sensitive_domain(name['value'])
                general_names.append(x509.DNSName(name['value']))

            elif name['nameType'] == 'IPAddress':
                general_names.append(x509.IPAddress(ipaddress.ip_address(name['value'])))

            elif name['nameType'] == 'IPNetwork':
                general_names.append(x509.IPAddress(ipaddress.ip_network(name['value'])))

            elif name['nameType'] == 'uniformResourceIdentifier':
                general_names.append(x509.UniformResourceIdentifier(name['value']))

            elif name['nameType'] == 'directoryName':
                # TODO: Need to parse a string in name['value'] like:
                # 'CN=Common Name, O=Org Name, OU=OrgUnit Name, C=US, ST=ST, L=City/[email protected]'
                # or
                # 'CN=Common Name/O=Org Name/OU=OrgUnit Name/C=US/ST=NH/L=City/[email protected]'
                # and turn it into something like:
                # x509.Name([
                #     x509.NameAttribute(x509.OID_COMMON_NAME, "Common Name"),
                #     x509.NameAttribute(x509.OID_ORGANIZATION_NAME, "Org Name"),
                #     x509.NameAttribute(x509.OID_ORGANIZATIONAL_UNIT_NAME, "OrgUnit Name"),
                #     x509.NameAttribute(x509.OID_COUNTRY_NAME, "US"),
                #     x509.NameAttribute(x509.OID_STATE_OR_PROVINCE_NAME, "NH"),
                #     x509.NameAttribute(x509.OID_LOCALITY_NAME, "City"),
                #     x509.NameAttribute(x509.OID_EMAIL_ADDRESS, "*****@*****.**")
                # ]
                # general_names.append(x509.DirectoryName(x509.Name(BLAH))))
                pass

            elif name['nameType'] == 'rfc822Name':
                general_names.append(x509.RFC822Name(name['value']))

            elif name['nameType'] == 'registeredID':
                general_names.append(x509.RegisteredID(x509.ObjectIdentifier(name['value'])))

            elif name['nameType'] == 'otherName':
                # This has two inputs (type and value), so it doesn't fit the mold of the rest of these GeneralName entities.
                # general_names.append(x509.OtherName(name['type'], bytes(name['value']), 'utf-8'))
                pass

            elif name['nameType'] == 'x400Address':
                # The Python Cryptography library doesn't support x400Address types (yet?)
                pass

            elif name['nameType'] == 'EDIPartyName':
                # The Python Cryptography library doesn't support EDIPartyName types (yet?)
                pass

            else:
                current_app.logger.warning('Unable to deserialize SubAltName with type: {name_type}'.format(name_type=name['nameType']))

        return x509.SubjectAlternativeName(general_names)
Esempio n. 7
0
def generate_local_cert(private_key,
                        days_valid=3650,
                        output_file='server.crt',
                        loc_name=None,
                        org_name=None):

    def_name = u'SickGear'

    # Various details about who we are. For a self-signed certificate the
    # subject and issuer are always the same.
    subject = issuer = x509.Name([
        x509.NameAttribute(NameOID.LOCALITY_NAME, loc_name or def_name),
        x509.NameAttribute(NameOID.ORGANIZATION_NAME, org_name or def_name)
    ])

    # build Subject Alternate Names (aka SAN) list
    # First the host names, add with x509.DNSName():
    san_list = [x509.DNSName(u'localhost')]
    try:
        thishostname = text_type(socket.gethostname())
        san_list.append(x509.DNSName(thishostname))
    except (BaseException, Exception):
        pass

    # Then the host IP addresses, add with x509.IPAddress()
    # Inside a try-except, just to be sure
    try:
        # noinspection PyCompatibility
        from ipaddress import IPv4Address, IPv6Address
        san_list.append(x509.IPAddress(IPv4Address(u'127.0.0.1')))
        san_list.append(x509.IPAddress(IPv6Address(u'::1')))

        # append local v4 ip
        mylocalipv4 = localipv4()
        if mylocalipv4:
            san_list.append(x509.IPAddress(IPv4Address(u'' + mylocalipv4)))
    except (ImportError, Exception):
        pass

    cert = x509.CertificateBuilder() \
        .subject_name(subject) \
        .issuer_name(issuer) \
        .public_key(private_key.public_key()) \
        .not_valid_before(datetime.datetime.utcnow()) \
        .not_valid_after(datetime.datetime.utcnow() + datetime.timedelta(days=days_valid)) \
        .serial_number(random_serial_number()) \
        .add_extension(x509.SubjectAlternativeName(san_list), critical=True) \
        .sign(private_key, hashes.SHA256(), default_backend())

    # Write the certificate out to disk.
    with open(output_file, 'wb') as f:
        f.write(cert.public_bytes(serialization.Encoding.PEM))

    return cert
Esempio n. 8
0
def generate_local_cert(private_key,
                        days_valid=3560,
                        output_file="cert.cert",
                        LN="SABnzbd",
                        ON="SABnzbd"):
    """Generate a certificate, using basic information.
    Ported from cryptography docs/x509/tutorial.rst
    """
    # Various details about who we are. For a self-signed certificate the
    # subject and issuer are always the same.
    subject = issuer = x509.Name([
        x509.NameAttribute(NameOID.LOCALITY_NAME, LN),
        x509.NameAttribute(NameOID.ORGANIZATION_NAME, ON),
        # x509.NameAttribute(NameOID.COMMON_NAME, CN),
    ])

    # build Subject Alternate Names (aka SAN) list
    # First the host names, add with x509.DNSName():
    san_list = [
        x509.DNSName("localhost"),
        x509.DNSName(str(socket.gethostname()))
    ]

    # Then the host IP addresses, add with x509.IPAddress()
    # Inside a try-except, just to be sure
    try:
        import ipaddress

        san_list.append(x509.IPAddress(ipaddress.IPv4Address("127.0.0.1")))
        san_list.append(x509.IPAddress(ipaddress.IPv6Address("::1")))

        # append local v4 ip
        mylocalipv4 = localipv4()
        if mylocalipv4:
            san_list.append(
                x509.IPAddress(ipaddress.IPv4Address(str(mylocalipv4))))
    except:
        pass

    cert = (x509.CertificateBuilder().subject_name(subject).issuer_name(
        issuer).public_key(private_key.public_key()).not_valid_before(
            datetime.datetime.utcnow()).not_valid_after(
                datetime.datetime.utcnow() +
                datetime.timedelta(days=days_valid)).serial_number(
                    x509.random_serial_number()).add_extension(
                        x509.SubjectAlternativeName(san_list),
                        critical=True).sign(private_key, hashes.SHA256(),
                                            default_backend()))

    # Write our certificate out to disk.
    with open(output_file, "wb") as f:
        f.write(cert.public_bytes(serialization.Encoding.PEM))

    return cert
Esempio n. 9
0
def get_certificate():

    private_key = ec.generate_private_key(ec.SECP384R1, default_backend())
    public_key = private_key.public_key()
    host = '127.0.0.1'

    now = datetime.datetime.utcnow()

    fields = [
        x509.NameAttribute(NameOID.COMMON_NAME, host),
    ]

    subject = issuer = x509.Name(fields)
    cert = x509.CertificateBuilder().subject_name(subject)
    cert = cert.issuer_name(issuer)
    cert = cert.public_key(public_key)
    cert = cert.serial_number(x509.random_serial_number())
    cert = cert.not_valid_before(now)
    cert = cert.not_valid_after(now + datetime.timedelta(days=1))
    cert = cert.add_extension(x509.SubjectAlternativeName(
        [x509.IPAddress(IPv4Address(host))]),
                              critical=False)
    cert = cert.sign(private_key, hashes.SHA512(), default_backend())

    return cert, private_key
Esempio n. 10
0
def generate_server_cert(name, passphrase):
    """
    """
    key = rsa.generate_private_key(
        public_exponent=65537,
        key_size=2048,
    )

    cert = base_cert(name, key).add_extension(
        x509.SubjectAlternativeName([x509.IPAddress(IPv4Address("127.0.0.1"))
                                     ]),
        critical=False).add_extension(
            x509.ExtendedKeyUsage([
                ExtendedKeyUsageOID.SERVER_AUTH,
            ]),
            critical=True,
        ).sign(key, hashes.SHA256())

    return (
        cert.public_bytes(serialization.Encoding.PEM),
        key.private_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PrivateFormat.TraditionalOpenSSL,
            encryption_algorithm=serialization.BestAvailableEncryption(
                passphrase.encode('utf-8'))),
    )
Esempio n. 11
0
def server_certificate(ip, issuer, issuer_key):
    server_cert_filepath, server_key_filepath = get_filepaths(
        ip, SERVER_DIRNAME)

    server_key = get_persistent_key(server_key_filepath)

    subject = x509.Name([
        x509.NameAttribute(NameOID.COUNTRY_NAME, "AU"),
        x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "NSW"),
        x509.NameAttribute(NameOID.LOCALITY_NAME, "Wagga Wagga"),
        x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Quarc"),
        x509.NameAttribute(NameOID.COMMON_NAME, "quarc.internal")
    ])

    if not os.path.exists(server_cert_filepath):
        cert = x509.CertificateBuilder().subject_name(subject).issuer_name(
            issuer).public_key(server_key.public_key()).serial_number(
                x509.random_serial_number()).not_valid_before(
                    datetime.datetime.utcnow()).not_valid_after(
                        datetime.datetime.utcnow() +
                        datetime.timedelta(days=3650)).add_extension(
                            x509.SubjectAlternativeName(
                                [x509.IPAddress(ipaddress.ip_address(ip))]),
                            critical=True,
                        ).sign(issuer_key, hashes.SHA256(), default_backend())

        with open(server_cert_filepath, 'wb') as file:
            file.write(cert.public_bytes(serialization.Encoding.PEM))

    return server_cert_filepath, server_key_filepath
Esempio n. 12
0
        def _generate_pem_cert_and_key(cn='127.0.0.1', alt_ip='127.0.0.1'):
            import datetime
            import ipaddress
            from cryptography import x509
            from cryptography.x509.oid import NameOID
            from cryptography.hazmat.backends import default_backend
            from cryptography.hazmat.primitives import hashes, serialization
            from cryptography.hazmat.primitives.asymmetric import rsa

            key = rsa.generate_private_key(public_exponent=65537,
                                           key_size=2048,
                                           backend=default_backend())
            name = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, cn)])
            now = datetime.datetime.utcnow()
            cert_builder = (x509.CertificateBuilder().subject_name(
                name).issuer_name(name).public_key(
                    key.public_key()).serial_number(1000).not_valid_before(
                        now).not_valid_after(now + datetime.timedelta(days=1)))
            if alt_ip is not None:
                cert_builder = cert_builder.add_extension(
                    x509.SubjectAlternativeName([
                        x509.DNSName(cn),
                        x509.IPAddress(ipaddress.IPv4Address(alt_ip))
                    ]),
                    critical=False)
            cert = cert_builder.sign(key, hashes.SHA256(), default_backend())
            cert_pem = cert.public_bytes(encoding=serialization.Encoding.PEM)
            key_pem = key.private_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PrivateFormat.TraditionalOpenSSL,
                encryption_algorithm=serialization.NoEncryption())
            return cert_pem, key_pem
Esempio n. 13
0
    def _encode_host(name):
        """Encode a host principal as a DNS name or IP address"""

        try:
            return x509.IPAddress(ip_address(name))
        except ValueError:
            return x509.DNSName(name)
Esempio n. 14
0
def user_input_alt_name():
    data = []
    count = 0
    common_name = ""
    print(
        "Please enter the domain or ip address you want to create in the cert")
    print("Enter 1 domain or IP address each time, press ENTER to end")
    while True:
        input_data = input()
        if count == 0:
            common_name = input_data  # use first domain or ip address as cert CN
            count = count + 1
        if input_data == "":
            break
        if check_is_ip(input_data):
            try:
                data.append(x509.IPAddress(IPv4Address(input_data)))
            except ValueError:
                print("Illegal IP address! Please try again")
        else:
            try:
                data.append(x509.DNSName(input_data))
            except ValueError:
                print(
                    "IDN current not supported!, please convert to punycode first"
                )
        print("current domain or ipaddress:", end="")
        print(data)
    common_name = common_name.replace("*", "_")
    return common_name, data
Esempio n. 15
0
def selfSignedCert(ip: str) -> typing.Tuple[str, str, str]:
    key = rsa.generate_private_key(
        public_exponent=65537,
        key_size=2048,
        backend=default_backend(),
    )
    # Create a random password for private key
    password = secrets.token_urlsafe(32)

    name = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, ip)])
    san = x509.SubjectAlternativeName(
        [x509.IPAddress(ipaddress.ip_address(ip))])

    basic_contraints = x509.BasicConstraints(ca=True, path_length=0)
    now = datetime.utcnow()
    cert = (
        x509.CertificateBuilder().subject_name(name).issuer_name(
            name)  # self signed, its Issuer DN must match its Subject DN.
        .public_key(key.public_key()).serial_number(
            random.SystemRandom().randint(0, 1 << 64)).not_valid_before(now).
        not_valid_after(now + timedelta(days=10 * 365)).add_extension(
            basic_contraints,
            False).add_extension(san, False).sign(key, hashes.SHA256(),
                                                  default_backend()))

    return (key.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.TraditionalOpenSSL,
        encryption_algorithm=serialization.BestAvailableEncryption(
            password.encode())).decode(),
            cert.public_bytes(encoding=serialization.Encoding.PEM).decode(),
            password)
Esempio n. 16
0
    def build_name(key, value):
        key = key.lower()

        if key == "dns":
            return x509.DNSName(str(value))

        if key == "email":
            return x509.RFC822Name(str(value))

        if key == "uri":
            return x509.UniformResourceIdentifier(str(value))

        if key == "dirname":
            return x509.DirectoryName(str(value))

        if key in ("ip", "ip address"):
            import ipaddress

            try:
                value = ipaddress.ip_address(str(value))
            except ValueError:
                value = ipaddress.ip_network(str(value))

            return x509.IPAddress(value)

        raise ValueError(f"Unsupported alternative name: {key}")
Esempio n. 17
0
def generate_self_signed_certificate(
        host: str,
        checksum_address: str,
        curve: EllipticCurve,
        private_key: _EllipticCurvePrivateKey = None,
        days_valid: int = 365) -> Tuple[Certificate, _EllipticCurvePrivateKey]:
    if not private_key:
        private_key = ec.generate_private_key(curve, default_backend())

    public_key = private_key.public_key()

    now = datetime.datetime.utcnow()
    subject = issuer = x509.Name([
        x509.NameAttribute(NameOID.COMMON_NAME, host),
        x509.NameAttribute(NameOID.PSEUDONYM, checksum_address)
    ])
    cert = x509.CertificateBuilder().subject_name(subject)
    cert = cert.issuer_name(issuer)
    cert = cert.public_key(public_key)
    cert = cert.serial_number(x509.random_serial_number())
    cert = cert.not_valid_before(now)
    cert = cert.not_valid_after(now + datetime.timedelta(days=days_valid))
    cert = cert.add_extension(x509.SubjectAlternativeName(
        [x509.IPAddress(IPv4Address(host))]),
                              critical=False)
    cert = cert.sign(private_key, hashes.SHA512(), default_backend())

    return cert, private_key
Esempio n. 18
0
def generate_self_signed_certificate(
    host: str,
    private_key: SecretKey = None,
    days_valid: int = 365,
    curve: ClassVar[EllipticCurve] = _TLS_CURVE,
) -> Tuple[Certificate, _EllipticCurvePrivateKey]:

    if private_key:
        private_bn = int.from_bytes(private_key.to_secret_bytes(), 'big')
        private_key = ec.derive_private_key(private_value=private_bn,
                                            curve=curve())
    else:
        private_key = ec.generate_private_key(curve(), default_backend())
    public_key = private_key.public_key()

    now = datetime.datetime.utcnow()
    fields = [x509.NameAttribute(NameOID.COMMON_NAME, host)]

    subject = issuer = x509.Name(fields)
    cert = x509.CertificateBuilder().subject_name(subject)
    cert = cert.issuer_name(issuer)
    cert = cert.public_key(public_key)
    cert = cert.serial_number(x509.random_serial_number())
    cert = cert.not_valid_before(now)
    cert = cert.not_valid_after(now + datetime.timedelta(days=days_valid))
    cert = cert.add_extension(x509.SubjectAlternativeName(
        [x509.IPAddress(IPv4Address(host))]),
                              critical=False)
    cert = cert.sign(private_key, hashes.SHA512(), default_backend())

    return cert, private_key
Esempio n. 19
0
def generate_device_cert(hostname: str, ipv4_address: IPv4Address):
    apidata = get_apidata()
    try:
        if not os.path.isfile(apidata['cafile']):
            raise Exception("Specified cafile is not a file: {}".format(
                apidata['cafile']))
    except KeyError:
        raise Exception("No cafile specified in api.yml")

    try:
        if not os.path.isfile(apidata['cakeyfile']):
            raise Exception("Specified cakeyfile is not a file: {}".format(
                apidata['cakeyfile']))
    except KeyError:
        raise Exception("No cakeyfile specified in api.yml")

    try:
        if not os.path.isdir(apidata['certpath']):
            raise Exception("Specified certpath is not a directory")
    except KeyError:
        raise Exception("No certpath found in api.yml settings")

    with open(apidata['cakeyfile'], "rb") as cakeyfile:
        root_key = serialization.load_pem_private_key(
            cakeyfile.read(),
            password=None,
        )

    with open(apidata['cafile'], "rb") as cafile:
        root_cert = x509.load_pem_x509_certificate(cafile.read())

    cert_key = rsa.generate_private_key(public_exponent=65537,
                                        key_size=2048,
                                        backend=default_backend())
    new_subject = x509.Name([
        x509.NameAttribute(NameOID.COMMON_NAME, hostname),
    ])
    cert = (x509.CertificateBuilder().subject_name(new_subject).issuer_name(
        root_cert.issuer).public_key(cert_key.public_key()).serial_number(
            x509.random_serial_number()).not_valid_before(
                datetime.datetime.utcnow()).not_valid_after(
                    datetime.datetime.utcnow() +
                    datetime.timedelta(days=7300)).add_extension(
                        x509.SubjectAlternativeName(
                            [x509.IPAddress(ipv4_address)]),
                        critical=False,
                    ).sign(root_key, hashes.SHA256(), default_backend()))

    with open(os.path.join(apidata['certpath'], "{}.crt".format(hostname)),
              "wb") as f:
        f.write(cert.public_bytes(serialization.Encoding.PEM))

    with open(os.path.join(apidata['certpath'], "{}.key".format(hostname)),
              "wb") as f:
        f.write(
            cert_key.private_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PrivateFormat.TraditionalOpenSSL,
                encryption_algorithm=serialization.NoEncryption(),
            ))
Esempio n. 20
0
 def _get_alt_name(self, alt_name):
     """Get instances of X509 Names according to their type"""
     try:
         socket.inet_pton(socket.AF_INET, alt_name)
     except socket.error:
         return x509.DNSName(unicode(alt_name))
     else:
         return x509.IPAddress(ipaddress.IPv4Address(unicode(alt_name)))
Esempio n. 21
0
def generate_selfsigned_cert(hostname, public_ip, private_ip):
    import datetime
    import ipaddress
    from cryptography import x509
    from cryptography.x509.oid import NameOID
    from cryptography.hazmat.primitives import hashes
    from cryptography.hazmat.backends import default_backend
    from cryptography.hazmat.primitives import serialization
    from cryptography.hazmat.primitives.asymmetric import rsa

    # Generate our key
    key = rsa.generate_private_key(public_exponent=65537,
                                   key_size=1024,
                                   backend=default_backend())

    name = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, hostname)])
    alt_names = x509.SubjectAlternativeName([
        # best practice seem to be to include the hostname in the SAN, which *SHOULD* mean COMMON_NAME is ignored.
        x509.DNSName(hostname),
        # allow addressing by IP, for when you don't have real DNS (common in most testing scenarios)
        # openssl wants DNSnames for ips...
        x509.DNSName(public_ip),
        x509.DNSName(private_ip),
        # ... whereas golang's crypto/tls is stricter, and needs IPAddresses
        x509.IPAddress(ipaddress.ip_address(public_ip)),
        x509.IPAddress(ipaddress.ip_address(private_ip)),
    ])
    # path_len=0 means this cert can only sign itself, not other certs.
    basic_constraints = x509.BasicConstraints(ca=True, path_length=0)
    now = datetime.datetime.utcnow()
    cert = (x509.CertificateBuilder().subject_name(name).issuer_name(
        name).public_key(
            key.public_key()).serial_number(1000).not_valid_before(now).
            not_valid_after(now +
                            datetime.timedelta(days=100 * 365)).add_extension(
                                basic_constraints,
                                False).add_extension(alt_names, False).sign(
                                    key, hashes.SHA256(), default_backend()))
    cert_pem = cert.public_bytes(encoding=serialization.Encoding.PEM)
    key_pem = key.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.TraditionalOpenSSL,
        encryption_algorithm=serialization.NoEncryption(),
    )

    return cert_pem, key_pem
Esempio n. 22
0
 def test_basic(self):
     # duplication of doctests, but those are not run for every version
     self.assertEqual(format_general_name(x509.DNSName('example.com')),
                      'DNS:example.com')
     self.assertEqual(
         format_general_name(
             x509.IPAddress(ipaddress.IPv4Address('127.0.0.1'))),
         'IP:127.0.0.1')
Esempio n. 23
0
    def _create_server_certificate(self, cert: Certificate_model,
                                   private_key: Key,
                                   issuer_key: Key) -> x509.Certificate:
        # TODO implement checks
        # countryName = match
        # stateOrProvinceName = match
        # localityName = match
        # organizationName = match
        # organizationalUnitName = optional
        # commonName = supplied
        # emailAddress = optional
        if cert.parent.type != CertificateTypes.INTERMEDIATE and cert.parent.type != CertificateTypes.ROOT:
            raise RuntimeError("A root or intermediate parent is expected ")

        self._builder = x509.CertificateBuilder()
        self._set_basic(cert, private_key, issuer_key)

        self._builder = self._builder.add_extension(
            x509.KeyUsage(digital_signature=True,
                          content_commitment=False,
                          key_encipherment=True,
                          data_encipherment=False,
                          key_agreement=False,
                          key_cert_sign=False,
                          crl_sign=False,
                          encipher_only=False,
                          decipher_only=False),
            critical=True,
        )

        self._builder = self._builder.add_extension(
            x509.ExtendedKeyUsage([ExtendedKeyUsageOID.SERVER_AUTH]),
            critical=False,
        )

        if cert.dn.subjectAltNames:
            alts = []
            for altname in cert.dn.subjectAltNames:
                try:
                    alt = x509.IPAddress(ipaddress.ip_address(altname))
                    alts.append(alt)
                    continue
                except:
                    pass
                try:
                    alt = x509.DNSName(altname)
                    alts.append(alt)
                    continue
                except:
                    pass

            self._builder = self._builder.add_extension(
                x509.SubjectAlternativeName(alts),
                critical=False,
            )

        return self._sign_certificate(issuer_key)
Esempio n. 24
0
def create_cert(ca_crt, ca_key, common_name, subjectAltNames, filename):
    logger.info('Create certificate for %s with sans %s', common_name,
                ','.join(subjectAltNames))
    one_day = datetime.timedelta(1, 0, 0)
    issuer_name = ca_crt.issuer.get_attributes_for_oid(
        x509.name.NameOID.COMMON_NAME)[0].value
    private_key = rsa.generate_private_key(public_exponent=65537,
                                           key_size=2048,
                                           backend=default_backend())

    public_key = private_key.public_key()

    builder = x509.CertificateBuilder()
    builder = builder.subject_name(
        x509.Name([
            x509.NameAttribute(NameOID.COMMON_NAME, common_name),
        ]))
    builder = builder.issuer_name(
        x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, issuer_name)]))

    builder = builder.not_valid_before(datetime.datetime.today() - one_day)
    builder = builder.not_valid_after(datetime.datetime.today() +
                                      one_day * 365 * 1)
    builder = builder.serial_number(int(x509.random_serial_number()))
    builder = builder.public_key(public_key)
    builder = builder.add_extension(
        x509.BasicConstraints(ca=False, path_length=None),
        critical=True,
    )
    builder = builder.add_extension(x509.SubjectAlternativeName(
        [x509.DNSName(name) for name in subjectAltNames] +
        [x509.IPAddress(ipaddress.IPv4Address('127.0.0.1'))]),
                                    critical=True)
    builder = builder.add_extension(x509.ExtendedKeyUsage([
        x509.oid.ExtendedKeyUsageOID.CLIENT_AUTH,
        x509.oid.ExtendedKeyUsageOID.SERVER_AUTH,
    ]),
                                    critical=False)
    certificate = builder.sign(private_key=ca_key,
                               algorithm=hashes.SHA256(),
                               backend=default_backend())

    ca_key_filename = filename + '-key.pem'
    ca_crt_filename = filename + '-crt.pem'
    logger.info('Write %s certificate and key in %s %s', common_name,
                ca_crt_filename, ca_key_filename)

    with open(ca_key_filename, 'wb') as f:
        f.write(
            private_key.private_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PrivateFormat.TraditionalOpenSSL,
                encryption_algorithm=serialization.NoEncryption()))

    with open(ca_crt_filename, 'wb') as f:
        f.write(certificate.public_bytes(encoding=serialization.Encoding.PEM))
    return certificate, private_key
Esempio n. 25
0
    def build_csr(self):
        if not self.private_key:
            if self.key_type == KeyTypes.RSA:
                self.private_key = rsa.generate_private_key(
                    public_exponent=65537,
                    key_size=self.key_length,
                    backend=default_backend())
            elif self.key_type == KeyTypes.ECDSA:
                if self.key_curve == "P521":
                    curve = ec.SECP521R1()
                elif self.key_curve == "P384":
                    curve = ec.SECP384R1()
                elif self.key_curve == "P256":
                    curve = ec.SECP256R1()
                elif self.key_curve == "P224":
                    curve = ec.SECP224R1()
                else:
                    curve = ec.SECP521R1()
                self.private_key = ec.generate_private_key(
                    curve, default_backend())
            else:
                raise ClientBadData
            self.public_key_from_private()

        csr_builder = x509.CertificateSigningRequestBuilder()
        subject = [
            x509.NameAttribute(
                NameOID.COMMON_NAME,
                self.common_name,
            )
        ]
        csr_builder = csr_builder.subject_name(x509.Name(subject))

        alt_names = []
        if self.ip_addresses:
            for ip in self.ip_addresses:
                alt_names.append(x509.IPAddress(ipaddress.IPv4Address(ip)))

        if self.san_dns:
            for ns in self.san_dns:
                alt_names.append(x509.DNSName(ns))

        if self.email_addresses:
            for mail in self.email_addresses:
                alt_names.append(x509.RFC822Name(mail))

        csr_builder = csr_builder.add_extension(
            x509.SubjectAlternativeName(alt_names),
            critical=False,
        )

        csr_builder = csr_builder.sign(self.private_key, hashes.SHA256(),
                                       default_backend())
        self.csr = csr_builder.public_bytes(
            serialization.Encoding.PEM).decode()
        return
Esempio n. 26
0
def generate_selfsigned_cert(hostname, ip_addresses=None, key=None):
    """Generates self signed certificate for a hostname, and optional IP
    addresses."""
    from cryptography import x509
    from cryptography.x509.oid import NameOID
    from cryptography.hazmat.primitives import hashes
    from cryptography.hazmat.backends import default_backend
    from cryptography.hazmat.primitives import serialization
    from cryptography.hazmat.primitives.asymmetric import rsa

    # Generate our key
    if key is None:
        key = rsa.generate_private_key(
            public_exponent=65537,
            key_size=2048,
            backend=default_backend(),
        )

    name = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, hostname)])

    # best practice seem to be to include the hostname in the SAN, which
    # *SHOULD* mean COMMON_NAME is ignored.
    alt_names = [x509.DNSName(hostname)]

    # allow addressing by IP, for when you don't have real DNS (common in
    # most testing scenarios
    if ip_addresses:
        for addr in ip_addresses:
            # openssl wants DNSnames for ips...
            alt_names.append(x509.DNSName(addr))
            # whereas golang's crypto/tls is stricter, and needs IPAddresses
            # note: older versions of cryptography do not understand
            # ip_address objects
            alt_names.append(x509.IPAddress(ipaddress.ip_address(addr)))

    san = x509.SubjectAlternativeName(alt_names)

    # path_len=0 means this cert can only sign itself, not other certs.
    basic_contraints = x509.BasicConstraints(ca=True, path_length=0)
    now = datetime.utcnow()
    cert = (x509.CertificateBuilder().subject_name(name).issuer_name(
        name).public_key(key.public_key()).serial_number(
            x509.random_serial_number()).not_valid_before(now).not_valid_after(
                now + timedelta(days=2 * 365)).add_extension(
                    basic_contraints,
                    False).add_extension(san,
                                         False).sign(key, hashes.SHA256(),
                                                     default_backend()))
    cert_pem = cert.public_bytes(encoding=serialization.Encoding.PEM)
    key_pem = key.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.TraditionalOpenSSL,
        encryption_algorithm=serialization.NoEncryption(),
    )

    return key_pem, cert_pem
Esempio n. 27
0
def authority_certificate(ip):
    auth_cert_filepath, _ = get_filepaths(ip, AUTHORITY_DIRNAME)

    auth_key = make_key()

    issuer = subject = x509.Name([
        x509.NameAttribute(NameOID.COUNTRY_NAME, "AU"),
        x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "NSW"),
        x509.NameAttribute(NameOID.LOCALITY_NAME, "Wagga Wagga"),
        x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Quarc"),
        x509.NameAttribute(NameOID.COMMON_NAME, "quarc.services")
    ])

    if os.path.exists(auth_cert_filepath):
        # print(
        #     "\nTLS authority certificate:\n"
        #     "    {}\n".format(auth_cert_filepath))
        pass
    else:
        # Uses name constraints
        # https://nameconstraints.bettertls.com/

        cert = x509.CertificateBuilder().subject_name(subject).issuer_name(
            issuer).public_key(auth_key.public_key()).serial_number(
                x509.random_serial_number()).not_valid_before(
                    datetime.datetime.utcnow()).not_valid_after(
                        datetime.datetime.utcnow() +
                        datetime.timedelta(days=3650)).add_extension(
                            x509.NameConstraints(
                                [x509.IPAddress(ipaddress.ip_network(ip))],
                                None),
                            critical=True,
                        ).sign(auth_key, hashes.SHA256(), default_backend())

        with open(auth_cert_filepath, 'wb') as file:
            file.write(cert.public_bytes(serialization.Encoding.PEM))

        print(
            "\n"
            "================================================================="
            "==============="
            "\n\n"
            "  A TLS certificate for your current IP address has been created at:\n\n"
            "      {}\n\n"
            "  This certificate is to be installed as a certificate authority\n"
            "  on each client that needs access to this server. This certificate\n"
            "  will only allow authentication for servers hosted at the followng\n"
            "  address:\n\n"
            "      https://{}:PORT\n\n"
            "  This is achieved by implementing the Name Constraints extension\n"
            "  and by not storing the certificate authority private key to disk.\n\n"
            "================================================================="
            "==============="
            "\n".format(auth_cert_filepath, ip))

    return auth_cert_filepath, subject, auth_key
Esempio n. 28
0
def _build_general_name(backend, gn):
    if gn.type == backend._lib.GEN_DNS:
        data = backend._ffi.buffer(gn.d.dNSName.data, gn.d.dNSName.length)[:]
        return x509.DNSName(idna.decode(data))
    elif gn.type == backend._lib.GEN_URI:
        data = backend._ffi.buffer(
            gn.d.uniformResourceIdentifier.data,
            gn.d.uniformResourceIdentifier.length)[:].decode("ascii")
        parsed = urllib_parse.urlparse(data)
        hostname = idna.decode(parsed.hostname)
        if parsed.port:
            netloc = hostname + u":" + six.text_type(parsed.port)
        else:
            netloc = hostname

        # Note that building a URL in this fashion means it should be
        # semantically indistinguishable from the original but is not
        # guaranteed to be exactly the same.
        uri = urllib_parse.urlunparse(
            (parsed.scheme, netloc, parsed.path, parsed.params, parsed.query,
             parsed.fragment))
        return x509.UniformResourceIdentifier(uri)
    elif gn.type == backend._lib.GEN_RID:
        oid = _obj2txt(backend, gn.d.registeredID)
        return x509.RegisteredID(x509.ObjectIdentifier(oid))
    elif gn.type == backend._lib.GEN_IPADD:
        return x509.IPAddress(
            ipaddress.ip_address(
                backend._ffi.buffer(gn.d.iPAddress.data,
                                    gn.d.iPAddress.length)[:]))
    elif gn.type == backend._lib.GEN_DIRNAME:
        return x509.DirectoryName(_build_x509_name(backend,
                                                   gn.d.directoryName))
    elif gn.type == backend._lib.GEN_EMAIL:
        data = backend._ffi.buffer(gn.d.rfc822Name.data,
                                   gn.d.rfc822Name.length)[:].decode("ascii")
        name, address = parseaddr(data)
        parts = address.split(u"@")
        if name or len(parts) > 2 or not address:
            # parseaddr has found a name (e.g. Name <email>) or the split
            # has found more than 2 parts (which means more than one @ sign)
            # or the entire value is an empty string.
            raise ValueError("Invalid rfc822name value")
        elif len(parts) == 1:
            # Single label email name. This is valid for local delivery. No
            # IDNA decoding can be done since there is no domain component.
            return x509.RFC822Name(address)
        else:
            # A normal email of the form [email protected]. Let's attempt to
            # decode the domain component and return the entire address.
            return x509.RFC822Name(parts[0] + u"@" + idna.decode(parts[1]))
    else:
        # otherName, x400Address or ediPartyName
        raise x509.UnsupportedGeneralNameType(
            "{0} is not a supported type".format(
                x509._GENERAL_NAMES.get(gn.type, gn.type)), gn.type)
Esempio n. 29
0
def gen_alt_name(list):
  alt_name_objs = []
  for name in list:
    try:
      addr = IPv4Address(name)
      alt_name_objs.append(x509.IPAddress(addr))
      continue
    except AddressValueError:
      pass

    try:
      addr = IPv6Address(name)
      alt_name_objs.append(x509.IPAddress(addr))
      continue
    except AddressValueError:
      pass

    alt_name_objs.append(x509.DNSName(name))
  return x509.SubjectAlternativeName(alt_name_objs)
Esempio n. 30
0
def dummy_cert(
    privkey: rsa.RSAPrivateKey,
    cacert: x509.Certificate,
    commonname: Optional[str],
    sans: List[str],
    organization: Optional[str] = None,
) -> Cert:
    """
        Generates a dummy certificate.

        privkey: CA private key
        cacert: CA certificate
        commonname: Common name for the generated certificate.
        sans: A list of Subject Alternate Names.
        organization: Organization name for the generated certificate.

        Returns cert if operation succeeded, None if not.
    """
    builder = x509.CertificateBuilder()
    builder = builder.issuer_name(cacert.subject)
    builder = builder.add_extension(x509.ExtendedKeyUsage(
        [ExtendedKeyUsageOID.SERVER_AUTH]),
                                    critical=False)
    builder = builder.public_key(cacert.public_key())

    now = datetime.datetime.now()
    builder = builder.not_valid_before(now - datetime.timedelta(days=2))
    builder = builder.not_valid_after(now + CERT_EXPIRY)

    subject = []
    is_valid_commonname = (commonname is not None and len(commonname) < 64)
    if is_valid_commonname:
        assert commonname is not None
        subject.append(x509.NameAttribute(NameOID.COMMON_NAME, commonname))
    if organization is not None:
        assert organization is not None
        subject.append(
            x509.NameAttribute(NameOID.ORGANIZATION_NAME, organization))
    builder = builder.subject_name(x509.Name(subject))
    builder = builder.serial_number(x509.random_serial_number())

    ss: List[x509.GeneralName] = []
    for x in sans:
        try:
            ip = ipaddress.ip_address(x)
        except ValueError:
            ss.append(x509.DNSName(x))
        else:
            ss.append(x509.IPAddress(ip))
    # RFC 5280 §4.2.1.6: subjectAltName is critical if subject is empty.
    builder = builder.add_extension(x509.SubjectAlternativeName(ss),
                                    critical=not is_valid_commonname)
    cert = builder.sign(private_key=privkey,
                        algorithm=hashes.SHA256())  # type: ignore
    return Cert(cert)