2015-06-13 48 views
0

我在导航混淆Ruby OpenSSL库的世界时遇到了一些问题。动态创建具有常见CA的SSL证书/密钥

期望的最终结果是动态创建SSL服务器证书和密钥,以便与WEBrick::HTTPProxyServer一起使用,每个密钥对应CN对应于请求的域,并且全部共享相同的CA.

其原因是允许HTTP代理拦截并监控启用了HSTS标头的网站的HTTPS流量,方法是首先将CACert加载到浏览器中,从而使我的自签名证书看起来合法给定的网站。

如果有人有这种事情的经验,代码示例将不胜感激。

在此先感谢。

PS。这里没有什么邪恶的,只是improving a featurepenetration testing software

+0

* “......每个对应于请求的域名CN的......” * - 浏览器会拒绝这样的证书。它们需要* Subject Alternate Name *(SAN)中的服务器名称,而不是* Common Name *(CN)。相关的,请参见[如何使用openssl创建自签名证书?](http://stackoverflow.com/a/27931596/608639)。它解释了使大多数用户代理感到满意的规则。 – jww

回答

1

想通了。 :)

ca  = OpenSSL::X509::Certificate.new(File.read(INTERCEPTOR_CA_CERTIFICATE)) 
ca_key = OpenSSL::PKey::RSA.new(File.read(INTERCEPTOR_CA_KEY)) 

keypair = OpenSSL::PKey::RSA.new(4096) 

req   = OpenSSL::X509::Request.new 
req.version = 0 
req.subject = OpenSSL::X509::Name.parse(
    "CN=www.origin-server.com/O=Arachni/OU=Proxy/L=Athens/ST=Attika/C=GR" 
) 
req.public_key = keypair.public_key 
req.sign(keypair, OpenSSL::Digest::SHA1.new) 

cert   = OpenSSL::X509::Certificate.new 
cert.version = 2 
cert.serial  = rand(999999) 
cert.not_before = Time.new 
cert.not_after = cert.not_before + (60 * 60 * 24 * 365) 
cert.public_key = req.public_key 
cert.subject = req.subject 
cert.issuer  = ca.subject 

ef = OpenSSL::X509::ExtensionFactory.new 
ef.subject_certificate = cert 
ef.issuer_certificate = ca 

cert.extensions = [ 
    ef.create_extension('basicConstraints', 'CA:FALSE', true), 
    ef.create_extension('extendedKeyUsage', 'serverAuth', false), 
    ef.create_extension('subjectKeyIdentifier', 'hash'), 
    ef.create_extension('authorityKeyIdentifier', 'keyid:always,issuer:always'), 
    ef.create_extension('keyUsage', 
     %w(nonRepudiation digitalSignature 
     keyEncipherment dataEncipherment).join(","), 
     true 
    ) 
] 
cert.sign(ca_key, OpenSSL::Digest::SHA1.new) 

有用的资源:

  1. http://users.nccs.gov/~fwang2/ruby/ruby_ssl.html
  2. http://acidx.net/wordpress/2012/09/creating-a-certification-authority-and-a-server-certificate-on-ubuntu/
+0

如果您将服务器名称放在*主题备用名称(SAN)*(而不是*常用名称(CN)*)中,那么我会对此答案满意。因为上面的代码依赖于IETF和CA/Browser论坛的弃用行为。它在现代浏览器中不起作用,但我不确定您的拦截代理是针对目标还是适应浏览器。 – jww

+0

@jww那么“CN =#{host}/subjectAltName =#{host}”应该让大多数UA高兴? –