Permalink
Browse files

versioning and conformance tests

tweaked DSA to accept parameter sets other than the default ones, added parameters to the pubkey/privkey data structures, added a whole bunch of conformance tests to prepare for data format changes, added beginning of data format new APIs, and upgrade some support packages
added base64 support to biginteger, started adding dispatching based on version
added formats for RSA and DSA keys
minimal bundle still includes native bigint
b64 fix by bwarner
added versioning support for assertions and certificates
added new format test vectors
fixed binaries
default version is old format
  • Loading branch information...
1 parent 664207a commit 04a7a2a18a64be873e539d3ca5abe0449418447d @benadida benadida committed Jul 13, 2012
View
@@ -2,4 +2,7 @@
libs/all.js
libs/minimal.js
bidbundle.js
-node_modules
+node_modules
+bidbundle.js
+bidbundle-min.js
+bidbundle-min.js.gz
View
@@ -82,8 +82,6 @@ Basic API
});
// also, if loading a secret key from somewhere
- // note how JWK determines automatically if it's a secret key
- // or public key. XXX should this be more explicit?
var otherSecretKey = jwcrypto.loadSecretKey(storedSecretKey);
// verify it
@@ -106,7 +104,7 @@ Sometimes the JSON object to sign should be a standard assertion with pre-define
// add special fields which will be encoded properly
// payload cannot contain reserved fields
- assertion.sign(payload, {issuer: "foo.com", expiresAt: new Date(),
+ assertion.sign(payload, {issuer: "foo.com", expiresAt: new Date(new Date().valueOf() + 5000),
issuedAt: new Date(), audience: "https://example.com"},
keypair.secretKey,
function(err, signedAssertion) {
@@ -132,15 +130,22 @@ Sometimes the JSON objects to sign are certificates
var keyToCertify = keypairToCertify.publicKey;
var principal = {email: "someone@example.com"};
+
var assertionParams = {issuer: "foo.com", issuedAt: new Date(),
expiresAt: new Date()};
+
+ // cert params, kid is optional, others are required
+ var certParams = {kid: "key-2012-08-11",
+ publicKey: keyToCertify,
+ principal: principal};
+
var additionalPayload = {};
// payload cannot contain reserved fields
- cert.sign(keyToCertify, principal,
- assertionParams, additionalPayload,
- keypair.secretKey,
- function(err, signedObject) {
+ cert.sign(certParams,
+ assertionParams, additionalPayload,
+ keypair.secretKey,
+ function(err, signedObject) {
// normal signedObject
// can be verified with jwcrypto.verify
@@ -176,4 +181,33 @@ Sometimes the JSON objects to sign are certificates
// if no error:
// certParamsArray is the array of individual cert params from each verification
// payload is the assertion payload, and assertionParams is the assertion params.
- });
+ });
+
+Versioning
+====
+
+The formats of public-keys, as well as the special payload parameters of assertions and certificates, will be versioned.
+
+Not indicating a version number in the serialized payload indicates
+the alpha format in the BrowserID specification from June
+2012. Otherwise, a version number is required. The BrowserID Beta version number is <tt>2012.08.15</tt>.
+
+By default, <tt>jwcrypto</tt> will use the latest format
+automatically, and will parse any past format (unless that becomes
+impossible, in which case we'll define behavior then.)
+
+The version of the data format can be discovered as:
+
+ jwcrypto.DATA_FORMAT_VERSION
+
+If one wishes to use <tt>jwcrypto</tt> with an older data format:
+
+ jwcrypto.setDataFormatVersion('2012.08.15');
+
+or, to use the pre-versioning format:
+
+ jwcrypto.setDataFormatVersion('');
+
+or, to go back to the library default:
+
+ jwcrypto.setDataFormatVersion();
View
@@ -41,7 +41,8 @@ var sk = jwcrypto.loadSecretKey(fs.readFileSync(argv.s));
var expires = new Date(new Date().valueOf() + (argv.d * 1000));
var cert = jwcrypto.cert.sign(
- pk, {}, {expiresAt: expires, issuedAt: new Date(), issuer: argv.i}, {},
+ {publicKey: pk, principal: {}},
+ {expiresAt: expires, issuedAt: new Date(), issuer: argv.i}, {},
sk, function(err, cert) {
console.log(cert);
}
View
@@ -36,23 +36,23 @@ jwcrypto.cert.verify(
pk = jwcrypto.loadPublicKey(JSON.stringify(components.payload['public-key']));
} else {
console.log("cert is properly signed");
- pk = certParams['public-key'];
+ pk = certParams.publicKey;
}
doAssertion(pk, components.payload.iat, components.payload.exp);
});
function doAssertion(publicKey, iat, exp) {
console.log("\n==== assertion ====");
-
+
var components = jwcrypto.extractComponents(full_assertion.signedAssertion);
console.log(components);
-
+
console.log("audience: " + components.payload.aud);
console.log("expires: " + new Date(components.payload.exp));
if (components.payload.exp < iat)
console.log("OY: assertion expires before cert is valid");
-
+
if (components.payload.exp > (exp + 5000))
console.log("OY: assertion was likely issued after cert expired");
View
@@ -0,0 +1,50 @@
+#!/usr/bin/env node
+
+var BigInteger = require("../libs/minimal").BigInteger;
+
+var args = require('optimist')
+.usage('Convert BigInt\nUsage: $0')
+.alias('i', 'in')
+.describe('i', 'format for input, can be dec,hex')
+.demand('i')
+.alias('o', 'out')
+.describe('o', 'format for output, can be dec,hex')
+.demand('o')
+.string('_');
+
+var argv = args.argv;
+
+if (argv.h) {
+ args.showHelp();
+ process.exit(1);
+}
+
+var the_bigint;
+
+switch (argv.i) {
+ case 'dec':
+ the_bigint = new BigInteger(argv._[0], 10);
+ break;
+ case 'hex':
+ the_bigint = new BigInteger(argv._[0], 16);
+ break;
+ case 'b64':
+ the_bigint = BigInteger.fromBase64(argv._[0]);
+ break;
+}
+
+var output;
+
+switch (argv.o) {
+ case 'dec':
+ output = the_bigint.toString(10);
+ break;
+ case 'hex':
+ output = the_bigint.toString(16);
+ break;
+ case 'b64':
+ output = the_bigint.toBase64();
+ break;
+}
+
+console.log(output);
@@ -0,0 +1,74 @@
+#!/usr/bin/env node
+
+//
+// generate a keypair quick
+//
+
+var jwcrypto = require("../index");
+require("../lib/algs/ds");
+require("../lib/algs/rs");
+
+if (process.argv[2])
+ jwcrypto.setDataFormatVersion(process.argv[2]);
+
+var ISSUED_AT = new Date();
+var EXPIRES_AT = new Date(new Date().valueOf() + 6000);
+var ISSUER = "exampleidp.com";
+var AUDIENCE = "https://example.com";
+var EMAIL = "user@exampleidp.com";
+
+// generate an RSA keypair
+jwcrypto.generateKeypair(
+ {algorithm: "RS", keysize: 256}, function(err, keypair) {
+ // the public key
+ console.log("ROOT RSA KEY");
+ console.log(keypair.publicKey.serialize());
+
+ console.log("ROOT RSA SECRET KEY");
+ console.log(keypair.secretKey.serialize());
+
+ // the user keypair
+ jwcrypto.generateKeypair(
+ {algorithm: "DS", keysize: 128}, function(err, user_keypair) {
+ console.log("USER DSA KEY");
+ console.log(user_keypair.publicKey.serialize());
+
+ console.log("USER DSA SECRET KEY");
+ console.log(user_keypair.secretKey.serialize());
+
+ // certify the user
+ jwcrypto.cert.sign(
+ {publicKey: user_keypair.publicKey, principal: {email: EMAIL}},
+ {issuer: ISSUER, issuedAt: ISSUED_AT, expiresAt: EXPIRES_AT},
+ {}, keypair.secretKey,
+ function(err, cert) {
+ console.log("CERT");
+ console.log(JSON.stringify({
+ issued_at: ISSUED_AT.valueOf(),
+ expires_at: EXPIRES_AT.valueOf(),
+ issuer: ISSUER,
+ email: EMAIL
+ }));
+ console.log(cert);
+
+ jwcrypto.assertion.sign(
+ {},
+ {expiresAt: EXPIRES_AT, issuedAt: ISSUED_AT,
+ audience: AUDIENCE},
+ user_keypair.secretKey,
+ function(err, assertion) {
+ console.log(JSON.stringify({
+ issued_at: ISSUED_AT.valueOf(),
+ expires_at: EXPIRES_AT.valueOf(),
+ audience: AUDIENCE
+ }));
+ console.log("BACKED ASSERTION");
+ console.log(jwcrypto.cert.bundle(cert, assertion));
+ }
+ );
+ }
+ )
+ }
+ );
+ });
+
Oops, something went wrong.

0 comments on commit 04a7a2a

Please sign in to comment.