Using WebCrypto API to generate a KeyPair

The other day, I was using my chromebook and I needed to generate a keypair to get access to a new ssh server. I googled for a solution, but surprisingly I couldn't find one. Though I was pretty sure that the WebCrypto API would allow me to do easily, it turned out it's not as easy as I thought and it took me a couple days to actually figure out how to use the webcrypto API to achieve this specific goal, though this was mostly due to my blissful ignorance of ASN.1 encoding, JWK, base64url and openssh weird public key format.

Of course the first point of reference should be the the actual W3C spec. But this document is a bit too abstract and I found it hard to actually use the API from the spec.

Then I found a WebCrypto live table that tells me if my current browser actually support the API. Since some of those use native libraries, the Chrome on ChromeOS would have different support as the Chrome on other OSes.

We also need to keep in mind that the WebCrypto api is only available from secure locations. Luckily the file url is counted as a secure location, so it makes it easy to experiment from there. And surge.sh does host under https so that will be my provider of choice to host the end result.

On an OS with support for openssh we have the nifty utility ssh-keygen which allows to generate a keypair that can be used with ssh - which is exactly what we need.

So we have to figure out which algorithm to use, then use it with the appropriate parameters, then find a way to expose the public key and the private key. Ideally save the private key to a file and copy the public key.

The WebCrypto api is based on promises for the async work, so you will need to be vaguely familiar with promises to be able to read the code.

I am forever grateful to Converting OpenSSH public Keys for explaining the format used by OpenSSH public keys.

I also had to use a lot of google-fu to find out how to ASN.1 encode the JWK produced for the private key by the WebCrypto API in format that will be accepted by openSSH. Thanks to Lapo Luchini for putting together the awesome ASN.1 online decoder that allowed me debug my code and find out that ASN.1 doesn't like integer that starts with the high bit set (you have to prefix them with 0x00 in this case).

Please note that it is usually a very bad idea to put private keys in a browser, as most thing that are displayed on a web page can be stolen and a private key is probably the worst thing you could think putting on a web page.

But now, equipped with those two string representation of my key pair, I can setup my ssh connection straight from my Chromebook without having to use another OS. I am using the ssh chrome extension.

Live demo at https://js-keygen.surge.sh
Code at https://github.com/PatrickRoumanoff/js-keygen


My Weekend

At my previous job, we used to have an informal Monday morning catchup where everyone would talk about their week-end activities before going on about their planned work activities for the week.
When I left, quite a few people told they were always looking for my updates to spin their heads about how many km I had to do to drop how many kids where...
So here is an account on my week-end.

It started on Friday afternoon, when we got ready to go to Friday night races organised by Carlisle Swimming center, as four of the kids are in the right groups to register for the races, it's only $12 per family so it's a great deal for us. And it's a lot of fun, you can win medals and get special cards if you get into the first three or achieve a personal best. J2 likes to do the long distance races, 100m freestyle or breathstroke, but all the other contestants are twice her size and finish in half the time, but she still manages to enjoy herself, and everyone clap when she get to the end.

Saturday starts pretty early as my wife is teaching the french horn from 7:30 to 12:30. Beside the usual breakfast, J1 made pancake for everyone which was nice. We left at 8:30 to head to choir which starts at 9:00 in the city. While J1 & J2 went to choir, we took a walk in the new Barangaroo park with E2, V and C, which was very nice, but E2 was wearing his brand new choir rehearsal outfit and had a difficult time stopping himself from rolling in the dirt, going down stair ramps and climbing rocks close to the water. The park is very nice and the weather was awesome.
J1 & J2 didn't like me going to the park as I usually do parent supervision at choir instead and they were pretty horrible all the way to the swimming pool.
Swimming was good with 5 of them in the water it's pretty relaxing time for me - which means no one cried to get into the water. It was a big day for E2 because he got evaluated and he managed to up a level - which is a big issue for me because there is no class for "SuperFish" at 10:30 and this breaks all my Saturday schedule. We manage to find a spot at 9:00 but I can only drop him at 8:30 on my way to choir - we will test  that next week.

After swimming it was time to go register for next Friday night races - and J2 decided for the 100m again - she is certainly persistant. Whereas I have to encourage Violette to do more than 25m (since the figured out she can get as many points out of 25m, 50m or 100m she opted for the less tiring option).
Once home  have to remember everyone to hang up their towel & costume - minor drama here as C lost her goggles and swimming cap - we will probably find them next week. You couldn't believe how many goggles we lost  in the 10 years we have been going to swimming lessons - that's why I only get the "3 for $10" deal from Big W, because at $25 a pop for a pair of swimming googles, I would already be ruined.
We also got a phone call V's birthday party was cancelled because the host was sick - which was a relief because there was no one to drive her or pick her up and we didn't get a present...

Lunch was alright - then it was time to go to French class for C - which means doing the homework first, for once J2 helped C which was a nice change. But this time I had to bring E1 and E2 because they have a special choir rehearsal this afternoon, so after dropping off C at french class, it's back to the city for me. Of course, E1 being 13 she has a go at me by not getting out of the car when I told her I was a hurry to get back to French class to pick up C. I know they were tired, because they both dozed off in the car, but still, I got angry at her - I should know better.
Back to French class, C is super happy - which is a nice change - and she can't stop speaking French to me which I love so much. She's actually the only who will voluntarily speak French to me. We go to Aldi for the weekly shopping - we only have one hour because I have to go back to the city at 5:30 to pick up the E1&E2 form Choir. C was super helpful at Aldi and even helped me with the bags at the cashier. Back home to drop the shopping and C and it's off to the city for me (third time in a day).
I arrive 10m late because of traffic, but apparently they finished early so they have been waiting 30m outside - though Steph was here to supervise them.

Saturday adventures finish here.
Then it's Sunday... J1 wants to do crepes for breakfast which is great but 7am is a bit early for a Sunday. We start off with a bassoon lesson at 9:30 for V, but for once my wife is driving, she enjoys that because she can talk a walk on the beach during the lesson, so it's not too bad. At Noon my wife is off to perform in a concert for most of the afternoon so I will be with the kids by myself. Not much planned today, but kids insist on going to Warringah Aquatic Center, which is always fun because I get to argue with the cashier lady on the merit of a family entry when you have 6 kids. Before we get to leave we have to fold the laundry which has been accumulating on the couch for the pat two days, it's always a struggle to get them to fold the laundry, but going swimming is a good motivator. Cashier lady is very strict, and I have to pay for a family ticket + two kids to gain entry. We have lots of fun, and I manage to convince E2 to dive properly, starting from the sitting position, then crouching position, then standing position. I think we managed to overcome his fear of belly flop - at least he now can dive. V found $4 at the bottom of the pool and she buys some hot chips she shares with everyone.
Back home, we have to get ready for cello lesson, luckily the teacher comes home for this one, and she brings her daughter with her. We have a big afternoon tea - cello start for E1 her exam is next Saturday so she has an extra long lesson, then it's J2 and C's turn. During the lesson I start dinner, I bought some prawn and they need to be peeled, no kids want to try, "it's too disgusting" only the cello teacher daughter manages to peel a couple prawns. I cook them with garlic to go with pasta. Kids won't touch them, they can have cheese & tomato sauce. For dessert I make apple crumble, but in the rush I leave the oven on grill instead of fan forced, and it ends up with slightly burned top - still alright to eat but I had done better. Wife is back from concert to share dinner with us, and we even have the cello daughter who is having pasta & apple crumble.

Then it's time for bed - at least for the kids


Give me a diagram!

It happens so often.

I read some blog post or a book or a github repository or I talk with someone, and the discussion is veering towards describing a process. Immediately I feel the need for a diagram. I didn't think I was a visual guy, but the more it goes, the more it drives me mad.

Look at gulp, or any of it's plugin, they are all describing a workflow process and there isn't a single diagram in any of the docs or books I am reading on the topic.


Static Site Hosting

Everyday I found out about a new service provider for static site hosting, it seems that everyone and their dog is providing the service, the latest one, surge.sh seems to be doing everything I have been looking for in such a service. So it's probably time to actually list what features I am looking for in a static site hosting service:

  • command line update
  • Documented CDN
  • No constraints on file types
  • SSL subdomain
  • SSL custom domain
  • Some kind of source control system (integration with a git provider is ok)
  • Online editing (for chromebooks)
  • drag and drop updates (not required, but nice to have)
  • minimal monthly price (free is fine)
Another I looked at recently is cloud9, which originally was only a web IDE, but seems to have evolved to be a full blown vm provider as well where you can run any command you like (a la runnable.com) probably a bit toomuch for what I am after, but interesting none the less.


2 more static site hosting solutions which are not

Today I realised that using Google Drive or Dropbox for static site hosting is probably no the best idea, as they don't support relative path and needs to hardcode each file dependencies in the html + there is not way to provide a custom a domain - so this should be reserved for the ad-hoc single-page site.


10, 100 days challenge

I challenged my kids to a 10 and 100 days challenge of blog post, after 5 days, we are all still there... very exciting to see them post stuff everyday.
check out their blogs at


3 static web site hosting solutions - Day 3

My three pick for the day are:

  • https://getforge.com/
  • https://neocities.org/
    Very cute UI, super simple, online editor, though the restriction to avoid abuse stopped me form uploading my website which contained sccs files, once deleted, the upload worked with a single drag&drop. After the free tier, there is only one tier at $5 a month, which gives you CNAME (custom domains), generic SSL and remove the restrictions, definitely chromebook friendly - would recommend for 1st time users and kids. But the lack of versioning or automation (beside the webdav mount on the payment tier) is a no-go for developers.
  • https://www.dropbox.com/
    There is a lot of documentation on how to host a website as a shared dropbox folder, but no matter how hard I tried, that feature doesn't seem to be available through the free account setup.


3 static web site hosting solutions - Day 2

Today I explored:

  • https://www.netlify.com/
    I couldn't get the git integration to work, but drag& drop was great, though they have both github and bitbucket integration
  • https://www.paperplane.io/
    You can login with twitter, facebook of github. The first one to support dropbox, great integration, simple, no docs but it just works! This is my favorite for the day, not because of feature, but because of its simplicity.
  • https://divshot.com/
    Very complete offering, drag&drop of zip files, or custom npm module, it supports environments and promotions between them. I couldn't find a way to restore previous version, but you can download them and redeploy. Though it is missing deploy form git. This is probably the most advanced offering I have explored so far.
URL https://www.netlify.com/ https://www.paperplane.io/ https://divshot.com/
Name netlify Paper Plane DivShot
Tag Line Because static sites are safer, faster, cheaper & simpler Radically simple static hosting. Blazing fast CDN, simple CLI deployment, hassle-free test environments. And much more.
Login GitHub, Bitbucket,email facebook, twitter, github gitHub, email
setup npm install netlify-cli -g dropbox npm install -g divshot-cli
create d&d or push or netlify deploy dropbox or github d&d or client
upload d&d or push or netlify deploy dropbox or push d&d or client
update d&d or push or netlify deploy dropbox or push d&d or client
Free Plan forever but logo forever
1st tier $9/month SSL
dynamic tracking no
url scheme http://*.netlify.com http://*.paperplane.io http://*.divshot.io/
http yes yes yes
https 1st Tier no 1st tier
CNAME yes 1st Tier 1st tier
CNAME https yes no 1st tier
notes can't make git work, but nice featureset, forms, proxy, redirect, oauth simple, just works, but no docs environment promotion
Chrome book compatible no no
deployed http://generators.netlify.com/#/ http://generators.paperplane.io/#/ http://generators.divshot.io/#/
Domain http://gen.roumanoff.com/


3 static web site hosting solutions - Day 1

Today I explored three of the provider I listed yesterday:

  • Aerobatic
    This one is actually not free, only in public beta, the publishing is bit complicated, requires a npm package (so nodes and command line) and a special directory structure, but it provides an api gateway, and supports oauth with popular services, and has a simulator mode, so it provides some extra services, but it is cumbersome to setup and your require a GitHub account to sign up.
  • Bitballoon
    This is the simplest one of the lot, just drag and drop your folder and BAM, it's published. I am pretty sure they worked very hard to build this one feature. Sign up with GitHub or Persona (the Mozilla id) - you can automate through a ruby gem or a REST API published at https://github.com/BitBalloon/bitballoon-api. It has some very nice versioning feature (you can restore previous version) and provides some password protection for private site, and collect form data for you.
  • GitHub Pages
    This is by far the most complete solution, but entirely based on git, Though it compatible with Chromebook because you can do all the editing online, in their basic but working editor, using markdown, or just HTML. They have an option to generate a site with templates (using markdown). You can also setup your own domain by editing a CNAME file in the repository.
Comparing those three, I would say BitBalloon wins for it's simplicity, but GitHub wins for it's completeness, I wasn't overwhelmed by Aerobatic if it wasn't for integration with bitbucket which could redeem them - but I have yet to explore more this integration build on the new Atlassian Connect API for BitBucket.

Stay for another three providers review tomorrow!
URL Login setup upload Free Plan 1st tier deployed
http://www.aerobatic.com/ github, then userid and secret key npm install -g yoke-cli yoke deploy free beta for 45 days $30 per month – not public yet http://generator.aerobaticapp.com/#/2
https://www.bitballoon.com/ Persona + GitHub none drag&drop forever $7/month http://generators.bitballoon.com/#/6
https://pages.github.com/ custom online, site generators,git git push forever


Static hosting of web site

Recently I discovered there was a plethora of services providing free (or nearly free) hosting for static web sites.

Here is the initial list I came up with:

My plan is to explore those services in more details, figuring out to which one is the most free, what feature they provide, how easy is it to get started, to update content, if there is integration with source control system (such as the github one), if they support SSL and custom domain (and both, eg SSL on custom domain)


My baguette recipe

Having a large number of children, it is always a challenge to find time for recurring activities such as a worm farm, a compost pile, looking after the chicken or making bread everyday. The trick I sue is that anything I do on a regular basis must take no energy for getting ready and no time (ie less than 5 minutes) to complete otherwise I know it's not going to happen. So here is my 5 minutes recipe for fresh baguettes.

Step 0 - Ingredient supply.

Making bread everyday involves having an infinite supply of flour, this means I always need to check that I will have enough flour for the next couple of days. We buy organic flour by bags of 5kg and I use a container I keep on my bench top. Actually I use two container, one for plain flour and on efor wholemeal which allows me to vary the recipe from day to day. I also keep extra 1kg bag of flour in the freezer just in case I run out. You can use any type of flour but a strong flour yield better results (eg > 14KJ , high protein or high gluten)
For the raising agent I use dry yeast, the packet I keep in fridge last a very long time and I always have a spare.
Water is unlimited since I use tap water.
I like to use iodised salt, but really any table salt will do.

Step 1 - Recipe

I use an electronic scale so I can reset the tare at each step. In a large bowl add in order

  • 7g of salt, any baby spoon will hold 7 g so I don't need to weight it
  • 550 to 570g of water depending on my mood or how much fall in the bowl
  • 700g of flour (I use a mix of 200g wholemeal and 500g plain, but anything will do, you can even mix other types of grain as well, the more the wholemeal, the more water you need)
  • 7g yeast
  • optional: 20g of SLA (Sunflower Linseed Almond meal) for taste and color. You can get fancy here eg: raisin, muesli, etc.

Mix until you have a big homogenous blob, cover with a wet towel, wait a few hours (overnight is fine on the kitchen counter)

Step 2 - Cooking

  • preheat oven to maximum temp
  • put flour on workbench, empty dough on flour, cut in 4, shape the dough in baguette, put on baking tray, put a bit of oil on baking tray first if you think it's sticky
  • spray baguettes with water to wet extra flour
  • cut bread with knife/scissors to make pretty marking on bread and avoiding it to crack while cooking
  • put tray in oven, lower temp to 220C (fan forced), throw half a glass of water at the bottom of the oven (this help with the crust)
  • wait 14 minutes (might be longer, depending on the oven)

It happens form time to time that I forget something, if it's the yeast, we get flat bread, which taste like a brick, but the kids love it. If I forget the salt, the bread is tasteless, but you can butter it up.

And sometimes the flour just drops on the floor...

mvnvm available on brew

Thanks to a few people, I managed to push the awesome mvnvm to the homebrew repository. It is now available as part of the standard distribution, all you have to do is:

brew install mvnvm

If you feel like following current development of this tool, you can even use the HEAD feature of brew packages and go for

brew install --HEAD mvnvm

In any case, I strongly recommend mvnvm to manage all you maven versions.

All my code is now on GitHub

For a long time I wasn't very consistent with my open source code hosting. But the past couple years, all the rage is happening on github.com. That's where I put all my open source contribution past and present.

The most active one (ie the one I get the most support request) is the crowd nexus plugin which is a fork form the sonatype plugin they stopped supporting with nexus 1.8 for commercial reasons. And that's fair enough, if you pay for your authentication provider you should pay for the tools using it as well. In my case I got interested in this project to allow my colleagues to keep using Nexus OSS while using crowd. Nexus OSS usage was well established, but management was not yet ready to pay for the commercial version with a weird pricing model.

see nexus-crowd-plugin