Henry, I would rather you attempt to address Ryan's point 5, namely: 5) <keygen> just generates keys, and relies on application/x-x509-*-cert to install certificates. This MIME handling, unspecified but implemented by major browsers, represents yet-another-way for a website to make persistent modifications to the user system.
The key generation capability exists today with webcrypto. I'm actually more interested in the consequences of the MIME-type handling and it's interaction with key stores on the browser. That is the more relevant piece of this whole issue. I know that it is at the core of the argument. I honestly think that the best thing here - given the current state - is to treat this as an opportunity to ask for new work in the W3C. We can examine these needs on their own merits and determine if investing in new technology based on TLS client certificates is the right thing for the web. On Fri, Sep 4, 2015 at 12:44 PM, <henry.st...@gmail.com> wrote: > On Thursday, 30 July 2015 01:35:52 UTC+2, David Keeler wrote: >> [cc'd to dev-security for visibility. This discussion is intended to >> happen on dev-platform; please reply to that list.] >> >> Ryan Sleevi recently announced the pre-intention to deprecate and >> eventually remove support for the <keygen> element and special-case >> handling of the application/x-x509-*-cert MIME types from the blink >> platform (i.e. Chrome). >> >> Rather than reiterate his detailed analysis, I'll refer to the post here: >> >> https://groups.google.com/a/chromium.org/d/msg/blink-dev/pX5NbX0Xack/kmHsyMGJZAMJ >> > > One of the elements of his detailed analysis is under fire, namely that the > reliance of keygen on PEM is a key security hole. I made this case in more > detail here: > https://github.com/whatwg/html/issues/102 > > But to avoid your needing to click on the link here it is in full: > > <keygen> has been deprecated a few days ago, and the issue has been taken up > by @timbl on the Technical Architecture Group as it removes a useful tool in > the asymmetric public key cryptography available in browsers. > > One reason given for deprecating that recurs often is that keygen uses MD5 > which opens an attack vector presented in a very good paper "MD5 considered > harmful today" at the Chaos Communication Congress in Berlin in 2008 by a > number of researchers of which Jacob Appelbaum ( aka. @ioerror ) . ( That was > the time when Julian Assange was working freely on Wikileaks, so you can even > hear him ask a question at the end ) > > The slides are here: > https://www.trailofbits.com/resources/creating_a_rogue_ca_cert_slides.pdf > The video is here: > http://chaosradio.ccc.de/25c3_m4v_3023.html > > In short they were able to create a fake Certificate Authority (CA) because > the CA signed its certificates with MD5 and they were able to create hash > collisions, to use the certificate signed by the CA > and change some information in it to produce their own top level certificate, > with which > they could create a certificate for any site they wished to! ( Pretty > awesomely bad - though they did this carefully to avoid misuse ). This is why > projects such as IETFs DANE, DNSSEC, and many other improvements to the > internet infrastructure are vital. > > This was 7 years ago, so all of this should be fixed by now. There should be > no CA signing > Server Certificates with MD5 anymore. > > Great. But that has nothing to do with what is going on with <keygen>. The > problem > may well be that the documentation of <keygen> is misleading here. The WHATWG > documentation on keygen currently states: > > If the keytype attribute is in the RSA state: Generate an RSA key pair using > the settings given by the user, if appropriate, using the > md5WithRSAEncryption RSA signature algorithm (the signature algorithm with > MD5 and the RSA encryption algorithm) referenced in section 2.2.1 ("RSA > Signature Algorithm") of RFC 3279, and defined in RFC 3447. [RFC3279] > [RFC3447] > By whether or not keygen wraps the key and signs it with MD5 is of not much > importance, since this is the keyrequest we are speaking of here, not the > generated certificate! > > To summarise how the keygen is actually used: > 1. The browser creates a public/private key, saves the private key in the > secure keychain > 2. and sends the public key in an spkac request to the server which > 3. which on receipt of the certificate request and verification of the data, > uses that to create a Client Certificate using any signature algorithm it > wants for the creation of the certificate ( And so it SHOULD NOT USE MD5: see > CCC talk above ) > 4. which it returns using one of the x509 mime types available to it, > > Here is an illustration of the flow that we use in the WebID-TLS spec to > illustrate this: > Certificate Creation Flow > > http://www.w3.org/2005/Incubator/webid/spec/tls/#certificate-creation > > To see some real code implementing this I point you to my > ClientCertificateApp.scala code that receives a certificate Request, and > either returns an error or a certificate. > The key parts of the code are extracted below > https://github.com/read-write-web/rww-play/blob/f587382935c85e9f8916d5065434f7525c328ab9/app/controllers/ClientCertificateApp.scala > > def generate = Action { implicit request => > certForm.bindFromRequest.fold( > errors => BadRequest(html.webid.cert.genericCertCreator(errors)), > certreq => { > Result( > > //https://developer.mozilla.org/en-US/docs/NSS_Certificate_Download_Specification > header = ResponseHeader(200, Map("Content-Type" -> > "application/x-x509-user-cert")), > body = Enumerator(certreq.certificate.getEncoded) > ) > } > ) > } > > CertForm just takes the data from the html form (verifies all fields are ok) > and generates a CertReq object. ( or it can also take a CertReq object and > generate a form, so that errors can be shown to the user ) > > val certForm = Form( > mapping( > "CN" -> email, > "webids" -> list(of[Option[URI]]). > transform[List[URI]](_.flatten,_.map(e=>Some(e))). > verifying("require at least one WebID", _.size > 0), > "spkac" -> of(spkacFormatter), > "years" -> number(min=1,max=20) > )((CN, webids, pubkey,years) => > CertReq(CN,webids,pubkey,tenMinutesAgo,yearsFromNow(years))) > ((req: CertReq) => Some(req.cn,req.webids,null,2)) > ) > > The spkacFormatter just returns a public key. ( It plays around with testing > the challenge, but I am not sure what that is for - would like to know ). > > Anyway as I wrote above: if successful the generate method returns an encoded > certificate with the right mime type. And as you can see we create a > certificate with SHA1withRSA > > val sigAlgId = new > DefaultSignatureAlgorithmIdentifierFinder().find("SHA1withRSA") > val digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId) > val rsaParams = CertReq.issuerKey.getPrivate match { > case k: RSAPrivateCrtKey => > new RSAPrivateCrtKeyParameters( > k.getModulus(), k.getPublicExponent(), k.getPrivateExponent(), > k.getPrimeP(), k.getPrimeQ(), k.getPrimeExponentP(), > k.getPrimeExponentQ(), > k.getCrtCoefficient()); > case k: RSAPrivateKey => > new RSAKeyParameters(true, k.getModulus(), k.getPrivateExponent()); > } > > > val sigGen = new BcRSAContentSignerBuilder(sigAlgId, > digAlgId).build(rsaParams); > x509Builder.build(sigGen) > So the MD5 plays no serious role in all this. > > This should not be a big surprise. The only thing of value sent to the server > is the public key. It sends back a certificate based on that public key ( and > other information it may have on the user ). But the only one to be able to > use that certificate is the person owning the private key. > > Now my code could presumably be improved in many places I doubt not. But this > should show how > <keygen> is actually used. After all remember that <keygen> was added 10 > years after it appeared in browsers, and that there was not that much > discussion about the documentation when it was added. > > I then posted a certificate I created using keygen and the server code > described above. As you can see from the openssl command there is no MD5 in > the resulting certificate. > > $ openssl pkcs12 -clcerts -nokeys -in ~/Certificates.p12 | openssl x509 > -noout -text > Enter Import Password: > MAC verified OK > Certificate: > Data: > Version: 3 (0x2) > Serial Number: > 01:4c:19:67:ea:05 > Signature Algorithm: sha1WithRSAEncryption > Issuer: CN=WebID, O={} > Validity > Not Before: Mar 14 17:39:42 2015 GMT > Not After : Mar 13 17:49:42 2019 GMT > Subject: dnQualifier=he...@bblfish.net > Subject Public Key Info: > Public Key Algorithm: rsaEncryption > RSA Public Key: (2048 bit) > Modulus (2048 bit): > 00:da:b9:d1:e9:41:f6:f8:5a:08:63:16:9d:0d:b6: > 32:8d:1d:4a:15:a7:1d:ff:e3:d4:f4:d0:87:52:a5: > 2f:b1:45:4d:73:58:e4:a5:ec:f3:50:1e:39:24:bc: > 02:52:f3:00:4b:0b:b2:1a:0d:6b:64:ca:05:3f:0f: > bc:b5:a5:4e:c9:3e:be:2d:c9:b9:1e:4c:43:2b:82: > 78:84:c4:cc:2a:d8:a1:02:b4:6d:2a:20:17:bf:45: > d9:d4:c8:8a:56:4d:42:02:34:48:4a:1b:2e:44:6d: > bb:4c:d4:38:e7:9c:24:66:ce:31:0f:32:77:73:a7: > 79:d2:4e:d7:b6:0a:05:a6:18:b9:84:75:7b:94:6d: > 67:ba:79:f2:e0:64:e6:ae:d3:8b:d6:55:9c:e7:fc: > 95:02:72:08:23:d5:6d:b1:c0:34:09:93:67:d7:db: > 27:b6:bd:af:da:8c:c4:83:47:13:3f:4a:14:67:5f: > 67:5f:b4:84:ce:32:df:66:c1:1a:36:38:fa:84:d5: > be:69:b1:a6:f2:38:11:5d:ef:9b:0f:79:bb:25:c0: > cb:7e:4a:39:45:9a:08:29:b1:fd:35:c0:d1:db:dd: > 60:f9:c6:79:d8:94:15:ed:7e:a4:1e:b0:2f:bc:01: > 6f:c0:e7:92:cb:96:98:c9:f4:db:84:2c:da:d5:b5: > f5:c9 > Exponent: 65537 (0x10001) > X509v3 extensions: > X509v3 Subject Alternative Name: critical > URI:http://bblfish.net/people/henry/card#me > X509v3 Key Usage: critical > Digital Signature, Non Repudiation, Key Encipherment, Key > Agreement, Certificate Sign > X509v3 Basic Constraints: critical > CA:FALSE > Netscape Cert Type: > SSL Client, S/MIME > Signature Algorithm: sha1WithRSAEncryption > 03:25:38:47:76:34:ba:da:0b:40:ea:75:63:98:6b:b0:0b:b6: > 11:85:c7:b1:c4:91:cc:5c:99:a5:b5:01:24:6f:1f:8c:03:39: > 80:03:e7:50:59:9f:b0:48:6e:e7:16:b8:b7:92:6f:31:cd:cc: > ba:60:40:08:9e:3c:38:5d:19:94:fd:2c:be:6d:84:57:d4:ea: > 7f:54:a7:69:73:aa:37:a4:b8:81:21:0c:65:dc:f1:f6:a3:40: > d1:18:cf:04:a4:d6:8b:9a:1f:43:c2:67:4a:0e:8d:00:b7:e8: > 49:e3:b7:d5:f9:00:0f:98:32:b2:09:5e:ca:c0:44:37:dc:df: > 3b:57:e0:c2:5a:8a:79:0d:55:7a:4a:73:4a:24:64:27:e5:16: > 78:d4:c9:35:5e:f8:67:9c:e9:41:bd:c6:25:6b:1b:d7:03:c1: > af:64:d0:e3:0a:ea:58:a4:bc:3a:a4:8f:51:8d:33:58:ed:ba: > af:3d:b7:75:28:32:33:76:65:80:56:ae:ec:43:db:9e:7e:4b: > 74:f5:88:07:9f:2d:e8:74:f1:89:d1:af:52:34:07:52:f3:54: > 2f:60:fd:de:96:f6:00:67:2e:8f:10:23:e6:af:95:bf:a6:3c: > 61:0d:8c:24:47:cf:52:45:0f:96:ee:ca:3a:69:82:69:3b:20: > 87:06:5c:58 > > Watch out that if you look at this certificate with viewers such as OSX > keychain they will nevertheless show an MD5 signature - but that is not in > the certificate itself. I checked with the openssl folks. > > _______________________________________________ > dev-platform mailing list > dev-platform@lists.mozilla.org > https://lists.mozilla.org/listinfo/dev-platform _______________________________________________ dev-platform mailing list dev-platform@lists.mozilla.org https://lists.mozilla.org/listinfo/dev-platform