In 2011, Mozilla introduced Persona which created an authentication system for web systems and which used the BrowserID protocol. It uses an email addresses as an identifiers, and creates a signed JSON Web object. Unfortunately it failed to gain traction, and Mozilla shut off the service in 2016. The BrowserID protocol uses an email to identify a user:
JSON Web Signatures and JSON Web Tokens |
Theory
A sample run is:
Key pair: {"algorithm":"DS","y":"4c5f38cec2a9a0b39c2c98804a516dcd8cc4d8ab2ea613f475dddfd29da71aa29784154bcae09c7f1799974f98ed5b3af97a11f249713dc5cd6aab49471937352d948e4db67e588cf833d1915b0beb623e6153e6015264c17abb07786f10b7680a0da1947dc7ce13e8733ea07eaac9c7453ed5ae26788ddeacc5e60490a78f20","p":"ff600483db6abfc5b45eab78594b3533d550d9f1bf2a992a7a8daa6dc34f8045ad4e6e0c429d334eeeaaefd7e23d4810be00e4cc1492cba325ba81ff2d5a5b305a8d17eb3bf4a06a349d392e00d329744a5179380344e82a18c47933438f891e22aeef812d69c8f75e326cb70ea000c3f776dfdbd604638c2ef717fc26d02e17","q":"e21e04f911d1ed7991008ecaab3bf775984309c3","g":"c52a4a0ff3b7e61fdf1867ce84138369a6154f4afa92966e3c827e25cfa6cf508b90e5de419e1337e07a2e9e2a3cd5dea704d175f8ebf6af397d69e110b96afb17c7a03259329e4829b0d03bbc7896b15b4ade53e130858cc34d96269aa89041f409136c7242a38895c9d5bccad4f389af1d7a4bd1398bd072dffa896233397a"} JSON object: {"stuff":{"algorithm":"DS","y":"4c5f38cec2a9a0b39c2c98804a516dcd8cc4d8ab2ea613f475dddfd29da71aa29784154bcae09c7f1799974f98ed5b3af97a11f249713dc5cd6aab49471937352d948e4db67e588cf833d1915b0beb623e6153e6015264c17abb07786f10b7680a0da1947dc7ce13e8733ea07eaac9c7453ed5ae26788ddeacc5e60490a78f20","p":"ff600483db6abfc5b45eab78594b3533d550d9f1bf2a992a7a8daa6dc34f8045ad4e6e0c429d334eeeaaefd7e23d4810be00e4cc1492cba325ba81ff2d5a5b305a8d17eb3bf4a06a349d392e00d329744a5179380344e82a18c47933438f891e22aeef812d69c8f75e326cb70ea000c3f776dfdbd604638c2ef717fc26d02e17","q":"e21e04f911d1ed7991008ecaab3bf775984309c3","g":"c52a4a0ff3b7e61fdf1867ce84138369a6154f4afa92966e3c827e25cfa6cf508b90e5de419e1337e07a2e9e2a3cd5dea704d175f8ebf6af397d69e110b96afb17c7a03259329e4829b0d03bbc7896b15b4ade53e130858cc34d96269aa89041f409136c7242a38895c9d5bccad4f389af1d7a4bd1398bd072dffa896233397a"}} Signing: eyJhbGciOiJEUzE2MCJ9.eyJwcmluY2lwYWwiOnsiZW1haWwiOiJmcmVkQGhvbWUuY29tIn0sInB1YmtleSI6eyJ5Ijp7ImFyciI6WzEwOTgxMTUyLDIwNzUxMTYyNSwxNDM1MTUzMDgsMjI0MDYwMDA3LDE2NDA1NDMzNCwxNjgyOTA5ODgsNjU1NjU1MDIsMTMxODkwNDAxLDE2ODY2NTQ5MiwxNzUyODQ0OCwxODUwMzg5NTksMTA1NjUwMDkxLDY1NDA1MjY2LDEwMzAxNTk1NywyMjc0NDA0MywyNjAyNTkwOTcsMTA4OTQzNTAwLDE1NTc3MjEyMywxNTQ2MTMwMzcsMTc5NjA2NjQxLDIzMTA2Njk4NiwyNTQwNTYyMTEsMTg0MTIxODczLDE2MDM1NTc2MywxMjc1MDYyNTUsMjM1NTIyMDMzLDY4NTA0NTIyLDI3OTI4OTUyLDI2NTQ2MTE1OSwyNTYzMzUzMjUsMTg3NjA2NTQ3LDE0NzYwNjkyMiwxNzMxMDg2ODUsNDY3NjE5ODgsMTYxNTI2Njg0LDU5NTY3MTQ2LDE5NTUxXSwidCI6MzcsInMiOjB9LCJhbGdvcml0aG0iOiJEUyIsInAiOnsiYXJyIjpbMTE0MzA2NTgzLDI1OTA5NjUxNCw3MzYzMjgxNCwyMzQ3MzI4OTYsMTI4NDI4NzAsMTkxOTQ5MzEyLDEyMzYxMzgwNCw0NzYxOTIxNSw0NTAxOTAwOSwxNTA1MDgwMDIsNzUwNTE4NDMsMjQzNDQyMDYwLDE1NDY2NTc5NiwxMjE5MzkyMjMsMjM0OTM1MDgxLDU1MTY5OTM4LDIwMDU4MTIyNiwxNDc5NDcxODcsMTczNzQ4MzE0LDEzNjMxMTUwOSwxOTUyNDE0MDIsMjEzOTkzNzcyLDEyNDUyMDY4LDIzNzIyOTE4NSwyNDYwODM1NDMsMTY0ODM2NTkwLDI0MjA5MzEyMiwxMzQ1MDMxMjQsMTc0OTY1NTgzLDQ0NTQyMTcwLDI5MzA1NDk3LDIyMzY3Nzg1NSwxNTU5MjM3NjMsOTkyNjg0ODUsMTgwMzQwMTQ4LDQ3MzQzOTAsNjUzNzZdLCJ0IjozNywicyI6MH0sInEiOnsiYXJyIjpbMTM4NjExMTM5LDYyODc5NTc3LDkzNTc5OTUsMjQ5MDEwNDQ4LDgzNDMxODg5LDkyNjE3Nl0sInQiOjYsInMiOjB9LCJnIjp7ImFyciI6WzM2OTExNDgyLDIzNDg1ODY0NiwxNjAxNTc4MTAsMTI4MjM2ODE5LDU5MzU0OTA5LDE5Nzk2MzA4NywxNDQwMzQyNjEsMTE5ODEwNjE2LDY3NzAzNjYwLDE3Njc1MTY0NywyMjc5NDQwOTAsMTQwMDM3MTcyLDI0MDM3ODE2MCwxODU5NzE4ODUsMTk2OTAxMDE0LDQzNzE1ODQzLDE1NDMxMjI2NCwyMDkzMjI3ODksMTU4MDA2MDM5LDExMTAyMjM0NywxMTIxNDY4MTMsMTIzNzAyOTc1LDI0NTgyNjc2OSw0NDI4OTM3Myw4MDA3MzI2LDE2NTc1MzcyNiwxNTA2NDY0MSwyMTczODUxNDUsMjM3MzU5MDE0LDExNTU5MTIwNywxODQxOTM2ODYsMTc0MTUwOTAwLDY4Mzg3Njg5LDI1NTkxMDE2LDEzMjUyMTk1MSw3NzY1OTk2Myw1MDQ3NF0sInQiOjM3LCJzIjowfSwia2V5c2l6ZSI6IjEyOCJ9fQ.tqKA-VgO5G5spsCNKI4bawpjgNYi9mf2WhWKZh9fmJcmO2kb6Gv66Q
The following is some sample code
var jwcrypto = require("browserid-crypto"); require("browserid-crypto/lib/algs/ds"); var m="hello"; let LAST_PARAM = process.argv[process.argv.length-1] let PARAM_NAME = LAST_PARAM.split("=")[0].replace("--","") m = LAST_PARAM.split("=")[1] // random number generation is taken care of automatically // with auto-seeding that is optimized for server or browser // setup // more entropy can be added as follows // this can be useful to incorporate server-provided entropy // on clients that don't have any good entropy of their own // entropy should be either a 32 bit int, an array of ints, or a string jwcrypto.addEntropy('entropy'); // generate a key // we use DSA, which is "DS" in JSON Web Algorithm parlance // we use keysize 160, which has a specific interpretation based // on the algorithm, in this case DSA 1024/160, standard DSA. jwcrypto.generateKeypair({ algorithm: 'DSA', keysize: 160 }, function(err, keypair) { // error in err? // serialize the public key console.log("Key pair: ",keypair.publicKey.serialize()); // just the JSON object to embed in another structure console.log("\nJSON object: ",JSON.stringify({stuff: keypair.publicKey.toSimpleObject()})); // replace this with the key to sign var publicKeyToCertify = keypair.publicKey.serialize(); // create and sign a JWS var payload = {principal: {email: m}, pubkey: jwcrypto.loadPublicKey(publicKeyToCertify)}; jwcrypto.sign(payload, keypair.secretKey, function(err, jws) { // error in err? // serialize it console.log("\nSigning: ",jws.toString()); // replace with things to verify var signedObject = jws; var publicKey = keypair.publicKey; // verify it jwcrypto.verify(signedObject, publicKey, function(err, payload) { // if verification fails, then err tells you why // if verification succeeds, err is null, and payload is // the signed JS object. }); }); // replace this with the key to load var storedSecretKey = keypair.secretKey.serialize(); // also, if loading a secret key from somewhere var otherSecretKey = jwcrypto.loadSecretKey(storedSecretKey); });