从Firefox签署客户端证书以进行身份​​验证

问题描述:

我的组织正在寻求在我们的内部网站上使用客户端证书进行身份验证。这是一个在整个组织中使用Firefox的中型企业。从Firefox签署客户端证书以进行身份​​验证

我最初着眼于使用Firefox的window.crypto.generateCRMFRequest()window.crypto.importUserCertificates() javascript函数来生成和注册证书请求,但是它们的使用似乎完全没有记录。

要使window.crypto.importUserCertificates()正常工作,MDN's documentation声称任何证书都必须具有相应的请求ID(假设通过generateCRMFRequest()生成)才能成功导入。我能够用window.crypto.generateCRMFRequest()成功生成CRMF请求,但无法弄清楚如何生成CMMF认证响应。

OpenSSL的似乎有CRMF请求没有支持,但它可以读取ASN.1要求:

$ cat example.crmf 
MIIBiDCCAYQwgesCBF7ts6IwgcmAAQKlEDAOMQwwCgYDVQQDEwN2dnamgZ8wDQYJ 
KoZIhvcNAQEBBQADgY0AMIGJAoGBAME59JllBjW38By5ECaTatTd1hHY3Mrmzd+Z 
pm3XrLbS8u0A4kkFozm/Yrrwzzl4w/mdJwNxuOv+5CMr3u9VFDHj5SPOgSBUlR/v 
f9x9kqPVUeD21Rkv6YkS0flg8LpU22PMZgw1PtnbVXDGrkUvXr0ygF2En5ZvaL47 
hhZEZn3DAgMBAAGpEDAOBgNVHQ8BAf8EBAMCBeAwFzAVBgkrBgEFBQcFAQEMCHJl 
Z1Rva2VuoYGTMA0GCSqGSIb3DQEBBQUAA4GBAHx/KinpGg0+kjmF9ThduXDMuv9c 
d2qE4xiCqsrEbLScCtrk+4RNnthRnQ7UXGSSwTYh/gJs0LAr4EFSvWJEnNeKNY2V 
RqUD1LERr1pnTcGzZR5SCbQ6ASKqi99BgvoidAyYtAhrgLbttLIdsgHBldV8vOlL 
MUi5Ya1etnfZHsTt 

$ base64 -d example.crmf > example.der 
$ openssl asn1parse -in example.der -inform der 
0:d=0 hl=4 l= 392 cons: SEQUENCE   
4:d=1 hl=4 l= 388 cons: SEQUENCE   
8:d=2 hl=3 l= 235 cons: SEQUENCE   
11:d=3 hl=2 l= 4 prim: INTEGER   :5EEDB3A2 
17:d=3 hl=3 l= 201 cons: SEQUENCE   
20:d=4 hl=2 l= 1 prim: cont [ 0 ]   
23:d=4 hl=2 l= 16 cons: cont [ 5 ]   
25:d=5 hl=2 l= 14 cons: SEQUENCE   
27:d=6 hl=2 l= 12 cons: SET    
29:d=7 hl=2 l= 10 cons: SEQUENCE   
31:d=8 hl=2 l= 3 prim: OBJECT   :commonName 
36:d=8 hl=2 l= 3 prim: PRINTABLESTRING :vvv 
41:d=4 hl=3 l= 159 cons: cont [ 6 ]   
44:d=5 hl=2 l= 13 cons: SEQUENCE   
46:d=6 hl=2 l= 9 prim: OBJECT   :rsaEncryption 
57:d=6 hl=2 l= 0 prim: NULL    
59:d=5 hl=3 l= 141 prim: BIT STRING   
203:d=4 hl=2 l= 16 cons: cont [ 9 ]   
205:d=5 hl=2 l= 14 cons: SEQUENCE   
207:d=6 hl=2 l= 3 prim: OBJECT   :X509v3 Key Usage 
212:d=6 hl=2 l= 1 prim: BOOLEAN   :255 
215:d=6 hl=2 l= 4 prim: OCTET STRING  [HEX DUMP]:030205E0 
221:d=3 hl=2 l= 23 cons: SEQUENCE   
223:d=4 hl=2 l= 21 cons: SEQUENCE   
225:d=5 hl=2 l= 9 prim: OBJECT   :id-regCtrl-regToken 
236:d=5 hl=2 l= 8 prim: UTF8STRING  :regToken 
246:d=2 hl=3 l= 147 cons: cont [ 1 ]   
249:d=3 hl=2 l= 13 cons: SEQUENCE   
251:d=4 hl=2 l= 9 prim: OBJECT   :sha1WithRSAEncryption 
262:d=4 hl=2 l= 0 prim: NULL    
264:d=3 hl=3 l= 129 prim: BIT STRING   

这是令人沮丧的,因为startssl如果的网站有没有与他们的问题。

所以,我的问题是:服务器端处理CRMF请求和颁发证书可以导入window.cypto.importUserCertificates()什么魔术必须发生?

注意:这个问题纯粹是出于好奇,现在我已经通过使用OpenSSL自己生成每个证书来解决我的身份验证问题。我身上的安全意识型工程师并不是我完成任务的方式(特别是,我产生了每个人的私钥),但没有足够的时间去鼓捣这个。 :(

如果你能在服务器端使用Java,这里是一个要点,演示如何使用BouncyCastle的读取CRMF请求的内容:https://gist.github.com/503932

然后,您应该或多或少像对待它从CA的角度来看CSR(即获取公钥材料,将其绑定到您已验证出带外的身份并将其作为证书签名。)

MiniCaCertGen类中有一些示例可颁发证书。它需要从这个script的代码,它可以工作(对于XP和Vista/7上的IE,它们具有不同的API),以及使用<keygen/>。使用该代码来处理CRMF请求也不是太困难。另外,据我所知,Firefox仍然支持旧的<keygen/>(并且它现在回到了HTML 5的现场)。

您可能还对现有解决方案感兴趣,例如OpenCA