Пример #1
0
    def post(self):

        if not self.app.config['AUTHORITY_CERTIFICATE']:
            return 'The server lacks an authority certificate. Unable to sign the certificate request.', 403

        if not self.app.config['AUTHORITY_PRIVATE_KEY']:
            return 'The server lacks a private key. Unable to sign the certificate request.', 403

        certificate_request_der = base64.b64decode(
            request.json.get('certificate_request'))

        certificate_request = X509.load_request_der_string(
            certificate_request_der)

        if not (certificate_request.get_subject().CN == current_user.username):
            return 'I will not a sign certificate request for a different user ! (Got "%s" while "%s" was expected)' % (
                certificate_request.get_subject().CN,
                current_user.username), 403

        # Create a new certificate
        certificate = X509.X509()

        # Set the certificate version
        certificate.set_version(2)

        # Copy the certificate public key from the certificate request
        certificate.set_pubkey(certificate_request.get_pubkey())

        # Set the certificate issuer
        certificate.set_issuer(
            self.app.config['AUTHORITY_CERTIFICATE'].get_subject())

        # Set the certificate subject
        subject_name = X509.X509_Name()
        subject_name.CN = certificate_request.get_subject().CN or ''
        subject_name.OU = self.app.config['AUTHORITY_CERTIFICATE'].get_subject(
        ).OU or ''
        subject_name.O = self.app.config['AUTHORITY_CERTIFICATE'].get_subject(
        ).O or ''
        subject_name.L = self.app.config['AUTHORITY_CERTIFICATE'].get_subject(
        ).L or ''
        subject_name.ST = self.app.config['AUTHORITY_CERTIFICATE'].get_subject(
        ).ST or ''
        subject_name.C = self.app.config['AUTHORITY_CERTIFICATE'].get_subject(
        ).C or ''

        certificate.set_subject(subject_name)

        # Set the certificate "not before" timestamp
        not_before = ASN1.ASN1_UTCTIME()
        not_before.set_datetime(datetime.today() + timedelta(days=-1))

        certificate.set_not_before(not_before)

        # Set the certificate "not after" timestamp
        not_after = ASN1.ASN1_UTCTIME()
        not_after.set_datetime(
            datetime.today() +
            self.app.config['CERTIFICATE_VALIDITY_DURATION'])

        certificate.set_not_after(not_after)

        # The issued certificate shall not be used as a certificate authority
        certificate.add_ext(X509.new_extension('basicConstraints', 'CA:FALSE'))

        # Sign the certificate
        pkey = EVP.PKey()
        pkey.assign_rsa(self.app.config['AUTHORITY_PRIVATE_KEY'],
                        capture=False)

        certificate.sign(pkey, 'sha1')

        current_user.certificate = certificate

        DATABASE.session.commit()

        result = {
            'certificate': current_user.certificate_string,
        }

        return jsonify(result)
Пример #2
0
        def verify(context, certificate, error, depth, result):
            if not result:
                certificate = X509.X509(certificate)

            return result
Пример #3
0
 def test_set_long_serial(self):
     cert = X509.X509()
     cert.set_serial_number(127614157056681299805556476275995414779)
     self.assertEqual(cert.get_serial_number(),
                      127614157056681299805556476275995414779)
Пример #4
0
    def test_mkcert(self):
        for utc in (True, False):
            req, pk = self.mkreq(1024)
            pkey = req.get_pubkey()
            self.assertTrue(req.verify(pkey))
            sub = req.get_subject()
            self.assertEqual(len(sub), 2,
                             'Subject should be long 2 items not %d' % len(sub))

            cert = X509.X509()
            cert.set_serial_number(1)
            cert.set_version(2)
            cert.set_subject(sub)
            t = int(time.time()) + time.timezone
            if utc:
                now = ASN1.ASN1_UTCTIME()
            else:
                now = ASN1.ASN1_TIME()
            now.set_time(t)
            now_plus_year = ASN1.ASN1_TIME()
            now_plus_year.set_time(t + 60 * 60 * 24 * 365)
            cert.set_not_before(now)
            cert.set_not_after(now_plus_year)
            self.assertEqual(str(cert.get_not_before()), str(now))
            self.assertEqual(str(cert.get_not_after()), str(now_plus_year))

            issuer = X509.X509_Name()
            issuer.CN = 'The Issuer Monkey'
            issuer.O = 'The Organization Otherwise Known as My CA, Inc.'
            cert.set_issuer(issuer)
            cert.set_pubkey(pkey)
            cert.set_pubkey(cert.get_pubkey())  # Make sure get/set work

            ext = X509.new_extension('subjectAltName', 'DNS:foobar.example.com')
            ext.set_critical(0)
            self.assertEqual(ext.get_critical(), 0)
            cert.add_ext(ext)

            cert.sign(pk, 'sha1')
            with self.assertRaises(ValueError):
                cert.sign(pk, 'nosuchalgo')

            self.assertTrue(cert.get_ext('subjectAltName').get_name(),
                            'subjectAltName')
            self.assertTrue(cert.get_ext_at(0).get_name(),
                            'subjectAltName')
            self.assertTrue(cert.get_ext_at(0).get_value(),
                            'DNS:foobar.example.com')
            self.assertEqual(cert.get_ext_count(), 1,
                             'Certificate should have now 1 extension not %d' %
                             cert.get_ext_count())
            with self.assertRaises(IndexError):
                cert.get_ext_at(1)
            self.assertTrue(cert.verify())
            self.assertTrue(cert.verify(pkey))
            self.assertTrue(cert.verify(cert.get_pubkey()))
            self.assertEqual(cert.get_version(), 2)
            self.assertEqual(cert.get_serial_number(), 1)
            self.assertEqual(cert.get_issuer().CN, 'The Issuer Monkey')

            if m2.OPENSSL_VERSION_NUMBER >= 0x90800f:
                self.assertFalse(cert.check_ca())
                self.assertFalse(cert.check_purpose(m2.X509_PURPOSE_SSL_SERVER, 1))
                self.assertFalse(cert.check_purpose(m2.X509_PURPOSE_NS_SSL_SERVER,
                                                    1))
                self.assertTrue(cert.check_purpose(m2.X509_PURPOSE_SSL_SERVER, 0))
                self.assertTrue(cert.check_purpose(m2.X509_PURPOSE_NS_SSL_SERVER,
                                                   0))
                self.assertTrue(cert.check_purpose(m2.X509_PURPOSE_ANY, 0))
            else:
                with self.assertRaises(AttributeError):
                    cert.check_ca()
Пример #5
0
def genCertificate(privkey, signature, certificate):
    #首先读取证书请求文件。
    # signature=file("req.pem", "rb").read()
    #返回一个X509.Request类型代表证书请求文件
    req=X509.load_request_string(signature)

    #首先验证一下,是不是真的是使用它本身的私钥签名的。
    #如果是,返回非0值。如果不是,说明这是一个非法的证书请求文件。
    is_verify = req.verify(req.get_pubkey())
    if not is_verify:
        return False, False, None

    #接下来载入CA的电子证书。与CA的密钥不一样,CA的电子证书包含了CA的身份信息。
    #CA的电子证书会分发给各个通信节点。
    # certificate=file("ca.pem", "rb").read()
    ca=X509.load_cert_string(certificate)

    #可以使用check_ca()方法判断这个证书文件是不是CA。
    #本质是判断它是不是自签名。如果是的话,就返回非0值。如果不是的话就返回0。
    is_ca = ca.check_ca()
    # if not is_ca:
    #     return True, False, None

    #接下来载入CA的密钥
    # cakey_str=file("cakey.pem", "rb").read()
    #一般CA的密钥要加密保存。回调函数返回密码
    # cakey=EVP.load_key_string(privkey, lambda *args: "1234")
    cakey=EVP.load_key_string(privkey, util.no_passphrase_callback)

    #接下来开始生成电子证书
    cert=X509.X509()

    #首先,设定开始生效时间与结束生效时间
    t = long(time.time()) + time.timezone #当前时间,单位是秒

    #开始生效时间。证书的时间类型不是普通的Python datetime类型。
    now = ASN1.ASN1_UTCTIME()
    now.set_time(t)
    nowPlusYear = ASN1.ASN1_UTCTIME() #结束生效时间
    nowPlusYear.set_time(t + 60 * 60 * 24 * 365) #一年以后。
    cert.set_not_before(now)
    cert.set_not_after(nowPlusYear)

    # 把证书请求附带的身份信息复制过来
    cert.set_subject(req.get_subject())

    #设置颁发者的身份信息,把CA电子证书内身份信息复制过来
    cert.set_issuer(ca.get_subject())

    #序列号是指,CA颁发的第几个电子证书文件
    cert.set_serial_number(2)

    #把证书请求内的公钥复制过来
    cert.set_pubkey(req.get_pubkey())

    #使用CA的秘钥进行签名。
    cert.sign(cakey, "sha1")

    certificateT = cert.as_pem()
    return True, True, certificateT
    #保存文件。
    file("cert.pem", "wb").write(cert.as_pem())
Пример #6
0
def new_cert(keySize,
             subject,
             expiry,
             issuer=None,
             issuer_evp=None,
             isCA=None,
             serial=None,
             extensions=None,
             e_value=E_VALUE,
             timestamp_offset=0):
    """
    Generate a new X509 certificate and RSA key.

    Returns the new RSA and X509 objects.

    @param keySize: Number of bits for the new RSA key
    @param subject: X509 subject for new certificate
    @param expiry: Number of days after which the new certificate
                   will expire
    @param issuer: X509 name of the CA to which the new certificate will be a
                    client
    @param issuer_evp: EVP matching the issuer CA, for signing the new
                    certificate
    @param isCA: If C{True}, the new certificate will be a CA. If
                 C{False}, it will explicitly be a non-CA. If C{None},
                 no C{basicConstraints} extension will be attached.
    @param serial: Serial number of the new certificate.
    @param extensions: List of X509 extensions to add
    @param e_value: Value of C{e} to use when generating the new key.
    @param timestamp_offset: Add this many seconds to the 'not before' and
                'not after' attributes.
    """

    # Generate RSA key and a matching EVP (signing helper).
    rsa = RSA.gen_key(keySize, e_value, lambda *_: None)
    evp = EVP.PKey()
    evp.assign_rsa(rsa, capture=False)

    # Create X509 object and assign parameters.
    now = long(time.time() + timestamp_offset)
    not_before = ASN1.ASN1_UTCTIME()
    not_before.set_time(now)
    not_after = ASN1.ASN1_UTCTIME()
    not_after.set_time(now + expiry * 86400)

    if issuer is None:
        issuer = subject
        issuer_evp = evp

    if serial is None:
        serial = random.randint(1, (2**15) - 1)

    x509 = X509.X509()
    x509.set_pubkey(evp)
    x509.set_subject(subject)
    x509.set_issuer(issuer)
    x509.set_not_before(not_before)
    x509.set_not_after(not_after)
    x509.set_version(0x2)
    x509.set_serial_number(serial)

    # Add extensions to X509.
    if isCA is not None:
        constraints = X509.new_extension('basicConstraints',
                                         'CA:%s' %
                                         (isCA and 'TRUE' or 'FALSE'),
                                         critical=1)
        x509.add_ext(constraints)
    if extensions:
        for extension in extensions:
            x509.add_ext(extension)

    # Sign the certificate with the authority's EVP, or ours if this is
    # a self-sign certificate.
    x509.sign(issuer_evp, 'sha1')

    return rsa, x509
Пример #7
0
def generate_proxycert(new_pkey, cert, key, **kwargs):
    """Generate a proxy certificate.

     * new_pkey: EVP.PKey for the proxy certificate
     * cert: Issuer certificate
     * key: Issuer private key

    Optional arguments:

     * lifetime: proxy certificate lifetime, in seconds. Default: is 12 hours.
     * full: proxy type, full or limited. Default is False (limited proxy).
     * hash_algorithm: hash algorithm to use for certificate signing. Default: sha1.
     * globus_bug: do not use basicConstraints extension and do not allow Key Agreement. Default: true
    """
    args = kwargs.copy()
    if 'args' in args:
        args.update(args.pop('args'))

    legacy = args.get('legacy', is_legacy_proxy(cert))
    full = args.get('full', False)
    globus_bug = args.get('globus_bug', True)

    proxy = X509.X509()
    proxy.set_pubkey(new_pkey)
    proxy.set_version(2)

    now = int(time.time())
    not_before = ASN1.ASN1_UTCTIME()
    not_before.set_time(now - CLOCK_SKEW)
    proxy.set_not_before(not_before)
    not_after = ASN1.ASN1_UTCTIME()
    not_after.set_time(now + args.get('lifetime', 12 * 60 * 60) + CLOCK_SKEW)
    proxy.set_not_after(not_after)

    proxy.set_issuer_name(cert.get_subject())
    digest = EVP.MessageDigest('sha1')
    digest.update(new_pkey.as_der())
    serial = struct.unpack("<L", digest.final()[:4])[0]
    proxy.set_serial_number(int(serial & 0x7fffffff))

    # Не совсем понятно, что и как с памятью в следующих операциях,
    # поэтому по завершению всего действа будет перезагрузка
    # сертификата через der
    proxy_subject = X509.X509_Name()
    subject = cert.get_subject()
    for idx in xrange(subject.entry_count()):
        entry = subject[idx].x509_name_entry
        m2.x509_name_add_entry(proxy_subject._ptr(), entry, -1, 0)
    if legacy:
        if full:
            proxy_subject.add_entry_by_txt('CN', ASN1.MBSTRING_ASC, "proxy",
                                           -1, -1, 0)
        else:
            proxy_subject.add_entry_by_txt('CN', ASN1.MBSTRING_ASC,
                                           "limited proxy", -1, -1, 0)
    else:
        proxy_subject.add_entry_by_txt('CN', ASN1.MBSTRING_ASC, str(serial),
                                       -1, -1, 0)
    proxy.set_subject(proxy_subject)
    if legacy:
        if globus_bug:
            proxy.add_ext(
                X509.new_extension(
                    "keyUsage",
                    "Digital Signature, Key Encipherment, Data Encipherment",
                    1))
        else:
            proxy.add_ext(
                X509.new_extension(
                    "keyUsage",
                    "Digital Signature, Key Encipherment, Data Encipherment, Key Agreement",
                    1))
            proxy.add_ext(X509.new_extension("basicConstraints", "CA:FALSE",
                                             1))

            # does not work (?) seems like need to add authorityCertIssuer
            # and authorityCertSerialNumber somehow, see rfc 3280 for more
            # details

            # try:
            #     subjkey = cert.get_ext('subjectKeyIdentifier')
            #     keyid = "keyid:%s" % subjkey.get_value()
            #     ext = X509.new_extension("authorityKeyIdentifier", keyid, 0)
            #     proxy.add_ext(ext)
            # except LookupError:
            #     pass
    else:
        if globus_bug:
            proxy.add_ext(
                X509.new_extension(
                    "keyUsage",
                    "Digital Signature, Key Encipherment, Data Encipherment",
                    1))
        else:
            proxy.add_ext(X509.new_extension("basicConstraints", "CA:FALSE",
                                             1))
            proxy.add_ext(
                X509.new_extension(
                    "keyUsage",
                    "Digital Signature, Key Encipherment, Data Encipherment, Key Agreement",
                    1))
    if not legacy:
        if full:
            proxy.add_ext(
                X509.new_extension("proxyCertInfo",
                                   "critical, language:Inherit all", 1))
        else:
            proxy.add_ext(
                X509.new_extension(
                    "proxyCertInfo",
                    "critical, language:1.3.6.1.4.1.3536.1.1.1.9", 1))

    sign_pkey = EVP.PKey()
    sign_pkey.assign_rsa(key, 0)
    proxy.sign(sign_pkey, args.get('hash_algorithm', 'sha1'))

    return X509.load_cert_string(proxy.as_pem())
Пример #8
0
    def _sign_request(self, x509_request, lifetime):
        not_before = ASN1.ASN1_UTCTIME()
        not_before.set_datetime(datetime.now(UTC))
        not_after = ASN1.ASN1_UTCTIME()
        not_after.set_datetime(datetime.now(UTC) + lifetime)

        proxy_subject = X509.X509_Name()
        for entry in self.context.x509.get_subject():
            ret = m2.x509_name_add_entry(proxy_subject._ptr(), entry._ptr(), -1, 0)
            if ret == 0:
                raise Exception(
                    "%s: '%s'" % (m2.err_reason_error_string(m2.err_get_error()), entry)
                )

        proxy = X509.X509()
        proxy.set_serial_number(self.context.x509.get_serial_number())
        proxy.set_version(x509_request.get_version())
        proxy.set_issuer(self.context.x509.get_subject())
        proxy.set_pubkey(x509_request.get_pubkey())

        # Extensions are broken in SL5!!
        if _m2crypto_extensions_broken():
            log.warning("X509v3 extensions disabled!")
        else:
            # X509v3 Basic Constraints
            proxy.add_ext(X509.new_extension('basicConstraints', 'CA:FALSE', critical=True))
            # X509v3 Key Usage
            proxy.add_ext(X509.new_extension('keyUsage', 'Digital Signature, Key Encipherment', critical=True))
            #X509v3 Authority Key Identifier
            identifier_ext = _workaround_new_extension(
                'authorityKeyIdentifier', 'keyid', critical=False, issuer=self.context.x509
            )
            proxy.add_ext(identifier_ext)

        any_rfc_proxies = False
        # FTS-1217 Ignore the user input and select the min proxy lifetime available on the list
        min_cert_lifetime = self.context.x509_list[0].get_not_after()
        for cert in self.context.x509_list:
            if cert.get_not_after().get_datetime() < min_cert_lifetime.get_datetime():
                not_after = cert.get_not_after()
                min_cert_lifetime = cert.get_not_after()
            try:
                cert.get_ext('proxyCertInfo')
                any_rfc_proxies = True
            except:
                pass

        proxy.set_not_after(not_after)
        proxy.set_not_before(not_before)

        if any_rfc_proxies:
            if _m2crypto_extensions_broken():
                raise NotImplementedError("X509v3 extensions are disabled, so RFC proxies can not be generated!")
            else:
                _add_rfc3820_extensions(proxy)

        if any_rfc_proxies:
            m2.x509_name_set_by_nid(proxy_subject._ptr(), X509.X509_Name.nid['commonName'], str(int(time.time())))
        else:
            m2.x509_name_set_by_nid(proxy_subject._ptr(), X509.X509_Name.nid['commonName'], 'proxy')

        proxy.set_subject(proxy_subject)
        proxy.set_version(2)
        proxy.sign(self.context.evp_key, 'sha1')

        return proxy
Пример #9
0
def create_proxy(issuer_cred, public_key, lifetime_hours):
    old_proxy = False

    # Standard order is cert, private key, then the chain.
    _begin_idx = issuer_cred.index(_begin_private_key)
    _end_idx = issuer_cred.index(_end_private_key) + len(_end_private_key)
    issuer_key = issuer_cred[_begin_idx:_end_idx]
    issuer_cert = issuer_cred[:_begin_idx]
    issuer_chain = issuer_cert + issuer_cred[_end_idx:]

    proxy = X509.X509()
    proxy.set_version(2)
    serial = get_random_serial()
    proxy.set_serial_number(serial)

    now = long(time.time())
    not_before = ASN1.ASN1_UTCTIME()
    not_before.set_time(now)
    proxy.set_not_before(not_before)

    not_after = ASN1.ASN1_UTCTIME()
    not_after.set_time(now + lifetime_hours * 3600)
    proxy.set_not_after(not_after)

    pkey = EVP.PKey()
    tmp_bio = BIO.MemoryBuffer(str(public_key))
    rsa = RSA.load_pub_key_bio(tmp_bio)
    pkey.assign_rsa(rsa)
    del rsa
    del tmp_bio
    proxy.set_pubkey(pkey)

    issuer = X509.load_cert_string(issuer_cert)

    # Examine the last CN to see if it looks like and old proxy.
    cn_entries = issuer.get_subject().get_entries_by_nid(
        X509.X509_Name.nid["CN"])
    if cn_entries:
        last_cn = cn_entries[-1].get_data()
        old_proxy = (str(last_cn) in ("proxy", "limited proxy"))

    # If the issuer has keyUsage extension, make sure it contains all
    # the values we require.
    try:
        keyUsageExt = issuer.get_ext("keyUsage")
        if keyUsageExt:
            values = keyUsageExt.get_value().split(", ")
            for required in REQUIRED_KEY_USAGE:
                if required not in values:
                    raise InterfaceError(
                        "issuer contains keyUsage without required usage '%s'"
                        % required)
    except LookupError:
        keyUsageExt = None

    # hack to get a copy of the X509 name that we can append to.
    issuer_copy = X509.load_cert_string(issuer_cert)
    proxy_subject = issuer_copy.get_subject()
    if old_proxy:
        proxy_subject.add_entry_by_txt(field="CN",
                                       type=ASN1.MBSTRING_ASC,
                                       entry="proxy",
                                       len=-1,
                                       loc=-1,
                                       set=0)
    else:
        proxy_subject.add_entry_by_txt(field="CN",
                                       type=ASN1.MBSTRING_ASC,
                                       entry=str(serial),
                                       len=-1,
                                       loc=-1,
                                       set=0)
    proxy.set_subject(proxy_subject)
    proxy.set_issuer(issuer.get_subject())

    # create a full proxy (legacy/old or rfc, draft is not supported)
    # For old proxies, there is no spec that defines the interpretation,
    # so the keyUsage extension is more important.
    # TODO: copy extended key usage also?
    if keyUsageExt:
        # Copy from the issuer if it had a keyUsage extension.
        ku_ext = X509.new_extension("keyUsage", keyUsageExt.get_value(), 1)
    else:
        # Otherwise default to this set of usages.
        ku_ext = X509.new_extension(
            "keyUsage",
            "Digital Signature, Key Encipherment, Data Encipherment", 1)
    proxy.add_ext(ku_ext)
    if not old_proxy:
        # For RFC proxies the effictive usage is defined as the intersection
        # of the usage of each cert in the chain. See section 4.2 of RFC 3820.
        # We opt not to add keyUsage.
        pci_ext = X509.new_extension("proxyCertInfo",
                                     "critical,language:Inherit all", 1)
        proxy.add_ext(pci_ext)

    issuer_rsa = RSA.load_key_string(issuer_key)
    sign_pkey = EVP.PKey()
    sign_pkey.assign_rsa(issuer_rsa)
    proxy.sign(pkey=sign_pkey, md="sha1")
    return proxy.as_pem() + issuer_chain