Well, I am working on a project to sell virtualization instances, a.k.a. vps, in http://bitcoin.org/.
Anyway, that has nothing to do with this. The thing is that I decided to go for http://cacert.org/ certificates. Why?
- They're free
- They do the work; which is encrypting the connection with the browser AND verifying that I am me.
- They're cause is cool
So, that said, there is a big problem. You need to check if your clients; more appropriately, their browsers, have CACert as an authority; which, most probably, they don't.
This makes me furious. Why don't they? Well:
- Mozilla:
- https://bugzilla.mozilla.org/show_bug.cgi?id=215243
- Chromium:
- http://code.google.com/p/chromium/issues/detail?id=78272
- Opera:
- http://my.opera.com/community/forums/topic.dml?id=71660
- The rest:
- http://wiki.cacert.org/InclusionStatus
So, as you can see, some are interested; some aren't; which is ridiculous!
If you have the time, the nerve, the words, the persuasive power, please, help us bump/solve these issues in the various fronts.
Anyway, I'll just let you know how to do it.
The technique
Through Javascript <yuck !>, we will require a link that is in the https realm. The link should offer nothing special. In my case, it's just your IP.
If it works; without complaints, your client will have CACert as an authority and you don't need to worry.
If it doesn't work, you will show an overlay with the links to the certs and revocation lists.
Also, in the case of chromium/Google Chrome; which use the system's store, we will offer a link to the wiki; where they can find out how to solve it.
The code
So, now, I'll show you my... code:
// main.js
// this function changes the display of the overlay section/div to block
function showOverlay() {
document.getElementById( 'overlay' ).style.display = 'block';
}
// this function changes the display of the overlay section/div to none; it will make it disappear.
function removeOverlay() {
document.getElementById( 'overlay' ).style.display = 'none';
}
// this one checks for the url and it will fail if you don't have the certs installed.
function detectCACert() {
try {
var xhr = new XMLHttpRequest();
xhr.open("GET", "https://btcsrv.com/ip", false);
xhr.send();
} catch( err ) {
console.log( 'There was an error: ' + err )
console.log( 'CACert root certificate not installed.' );
showOverlay();
}
if ( xhr.readyState == 4 && xhr.status == 200 ) {
console.log( 'CACert root certificate installed.' );
}
}
Now, it's important to have some CSS, right? I'd like that section/div to have "display: none" in the first place; so:
# CSS
/* Overlay */
section#overlay {
background: rgba( 0, 0, 0, .7 );
display: none;
position: absolute; top: 0; left: 0;
width: 100%; height: 100%;
z-index: 10;
}
section.overlayContent {
background: rgba( 255, 255, 255, 1 );
border-radius: 20px;
box-shadow: 10px 10px 5px #222;
display: block;
height: 420px;
margin: auto;
padding: 2em;
position: relative;
top: 10em;
width: 50%;
z-index: 10;
}
section.overlayContent button { position: relative; top: -1.5em; left: 98%; }
section.overlayContent h1 { text-align: center; }
section.overlayContent ul.links a { text-decoration: none; font-weight: bold; }
Now, I will use the detection function on the body tag of every page:
<body onload='detectCACert()'>
Now, there is one very important thing: https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS
Yep, you need to allow it. And, the way to do that in Sinatra is:
class MyApp < Sinatra::Application
get "/ip/?" do
cross_origin :allow_origin => [ 'http://btcsrv.com', 'https://btcsrv.com' ], :allow_methods => [:get]
request.ip
end
end
This will allow your website; in my case, http://btcsrv.com WITHOUT A FINAL SLASH to access https://btcsrv.com/ip with a GET method.
Well, that done, you can just try it out. Check out my http://btcsrv.com/ website without the certs and try installing them. Use Firefox, Opera or anything that isn't Chromium because, the example, is not gonna work just like that in chromium; a script is needed; which I will include right about now:
#!/usr/bin/env bash
# installCACertOnChrome: installs CACert on Google Chrome or Chromium; using the user's Store.
curl -O 'http://www.cacert.org/certs/root.crt'
curl -O 'http://www.cacert.org/certs/class3.crt'
certutil -d sql:$HOME/.pki/nssdb -A -t TC -n "CAcert.org" -i root.crt
certutil -d sql:$HOME/.pki/nssdb -A -t TC -n "CAcert.org Class 3" -i class3.crt
rm -f root.crt class3.crt
It is no secret that I am no Javascript wiz so, if you have any suggestions, they're welcome!