使用相同的自签名CA编写多个证书?

时间:2014-06-30 09:33:46

标签: firefox ssl proxy openssl self-signed

我正在编写一个拦截代理来监控从我的浏览器发送的请求。使用https,我正在做的是:  当浏览器发出CONNECT请求时,代理连接到该主机并获取其证书。 然后,此证书的subject和subjectAltName用于动态生成新证书,该证书将呈现给浏览器以建立与代理的SSL连接。

所有这些新证书都具有root自签名证书作为颁发者。 根证书已在Firefox中作为受信任导入。

然而,当我尝试连接时,我仍然收到不受信任的连接警告以及以下详细信息:

www.google.com uses an invalid security certificate. 
The certificate is not trusted because the issuer certificate is not trusted. 
(Error code: sec_error_untrusted_issuer)

我使用的浏览器是Firefox 28.0。我还没有完全理解为什么连接结果不可信,因为我已经安装了根证书。现在我必须为我访问的每个网站添加一个例外,这很坦率地说非常烦人并且减慢了一切。

我使用pyOpenSSL制作证书。 我用来制作根证书的代码是:

    from OpenSSL import crypto
    CERT_FILE = 'myapp.pem'
    KEY_FILE = 'myapp.key'
    k = crypto.PKey()
    k.generate_key(crypto.TYPE_RSA, 1024)

    cert = crypto.X509()
    cert.get_subject().O = "Myapp"
    cert.get_subject().OU = 'MyApp Root CA'
    cert.get_subject().CN = 'MyApp Root CA'
    cert.set_serial_number(888)
    cert.gmtime_adj_notBefore(0)
    cert.gmtime_adj_notAfter(10*365*24*60*60)
    cert.set_issuer(cert.get_subject())
    cert.set_pubkey(k)
    cert.sign(k, 'sha1')

    with open(CERT_FILE, "wt") as cf: cf.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert))
    with open(KEY_FILE, "wt") as kf: kf.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, k))

然后,我使用类似的代码生成特定于域的证书。现在我只使用谷歌的一个例子,虽然我会在解决这个问题后立即使用一些缓存系统。

root_cert = crypto.load_certificate(crypto.FILETYPE_PEM, 'myapp.pem') 
root_key = crypto.load_privatekey(crypto.FILETYPE_PEM, 'myapp.key') 
root_issuer = root_cert.get_issuer()

def make_example_cert(pem_data):
    if os.path.exists('google.pem'): return #ugly hack to avoid remaking file
    #load the certificate received from google 
    old_cert = crypto.load_certificate(crypto.FILETYPE_PEM, pem_data) 
    #generate new key and certificate
    pkey = crypto.PKey()
    pkey.generate_key(crypto.TYPE_RSA, 1024)
    new_cert = crypto.X509()
    new_cert.gmtime_adj_notBefore(0)
    new_cert.gmtime_adj_notAfter(10*365*24*60*60)
    #set same subject of old cert
    new_cert.set_subject(old_cert.get_subject())
    #look for and set SNA of old cert
    for i in range(old_cert.get_extension_count()):
            ext = old_cert.get_extension(i)
            if ext.get_short_name() == 'subjectAltName':
                new_cert.add_extensions([ext])
    #set root certificate as issuer
    new_cert.set_issuer(root_issuer)
    new_cert.set_pubkey(pkey)
    new_cert.sign(root_key, 'sha1')
    certfile = 'google.pem'
    keyfile = 'google.key'
    with open(certfile, "wt") as cf:
        cf.write(crypto.dump_certificate(crypto.FILETYPE_PEM, new_cert))
    with open(keyfile, "wt") as kf:
        kf.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey))
    #append root certificate to chain
    with open(certfile, "at") as cf2:
        cf2.write(crypto.dump_certificate(crypto.FILETYPE_PEM, root_cert))

    return certfile, keyfile

我似乎没有在这里发现重大错误,当我查看创建的证书时,它正确地拥有我自己的证书根作为发行者。尽管如此,浏览器还是说它不受信任。如果我将其添加为例外,它可以工作,但对于某些网站,我甚至没有这个选项,我唯一能做的就是查看详细信息并点击“#34;让我离开这里"”。

问题可能在代码中吗?或者是配置浏览器的问题?

1 个答案:

答案 0 :(得分:3)

如果您的CA证书已作为受信任的CA导入Firefox,则应该可以正常运行。

证书不受信任,因为它是自签名的。”和“证书仅对MyApp CA Root 有效”表示您明显没有提供您认为自己的服务器证书。

要么是代码中的一个简单的错误,你发送错误的证书,或者你可能以错误的顺序发送链:首先是CA证书,而最终实体证书应该是第一个(其次是CA,按签约顺序)。