diff --git a/.eslintrc.json b/.eslintrc.json index 6f19eb1..8d343cc 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -4,5 +4,8 @@ "es6": true, "node": true, "browser": true + }, + "rules": { + "no-console": ["error", { "allow": ["error"] }] } } diff --git a/.gitignore b/.gitignore index c9106a7..805eb31 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules .nyc_output +package-lock.json diff --git a/README.md b/README.md index 26b7c42..286adb9 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ The SSB ids contain a tag at the end. This function returns it. So if you have a string like `@gaQw6zD4pHrg8zmrqku24zTSAINhRg=.ed25519` this function would return `ed25519`. This is useful as SSB start providing features for different encryption methods and cyphers. -### loadOrCreateSync (filename) => keys +### loadOrCreateSync (filename, [generateOpts]) => keys Load a file containing the your private key. the file will also contain a comment with a warning about keeping the file secret. @@ -99,12 +99,13 @@ variations and parts `loadOrCreate` (async), `load`, `create` using the combined function is easiest. `keys` is an object as described in [`keys`](#keys) section. +`generateOpts` is optional but if provided has the shape `{curve, seed, feedFormat}`. -### loadOrCreate (filename, cb) +### loadOrCreate (filename, [generateOpts,] cb) If a sync file access method is not available, `loadOrCreate` can be called with a callback. that callback will be called with `cb(null, keys)`. If loading -the keys errored, new keys are created. +the keys errored, new keys are created. `generateOpts` is optional but if provided has the shape `{curve, seed, feedFormat}`. ### generate(curve, seed, feedFormat) => keys diff --git a/index.js b/index.js index dbcccac..7dfe960 100644 --- a/index.js +++ b/index.js @@ -62,18 +62,22 @@ exports.generate = function (curve, seed, feedFormat) { var storage = require("./storage")(exports.generate); for (var key in storage) exports[key] = storage[key]; -exports.loadOrCreate = function (filename, cb) { +exports.loadOrCreate = function (filename, generateOpts, cb) { + if (!cb) { + cb = generateOpts; + generateOpts = null; + } exports.load(filename, function (err, keys) { if (!err) return cb(null, keys); - exports.create(filename, cb); + exports.create(filename, generateOpts, cb); }); }; -exports.loadOrCreateSync = function (filename) { +exports.loadOrCreateSync = function (filename, generateOpts) { try { return exports.loadSync(filename); } catch (err) { - return exports.createSync(filename); + return exports.createSync(filename, generateOpts); } }; diff --git a/storage.js b/storage.js index ef82540..f3fafc2 100644 --- a/storage.js +++ b/storage.js @@ -84,27 +84,38 @@ ${legacy ? keys.private : JSON.stringify(keys, null, 2)} return reconstructKeys(fs.readFileSync(filename, "ascii")); }; - exports.create = function (filename, curve, legacy, cb) { + function curveOrOpts(opts) { + return !opts ? {} : isObject(opts) ? opts : { curve: opts }; + } + + exports.create = function (filename, generateOpts, legacy, cb) { if (isFunction(legacy)) (cb = legacy), (legacy = null); - if (isFunction(curve)) (cb = curve), (curve = null); + if (isFunction(generateOpts)) (cb = generateOpts), (generateOpts = null); + + const { curve, seed, feedFormat } = curveOrOpts(generateOpts); filename = toFile(filename); - var keys = generate(curve); + var keys = generate(curve, seed, feedFormat); var keyfile = constructKeys(keys, legacy); mkdirp(path.dirname(filename), function (err) { if (err) return cb(err); - fs.writeFile(filename, keyfile, { mode: 0x100, flag: "wx" }, function ( - err - ) { - if (err) return cb(err); - cb(null, keys); - }); + fs.writeFile( + filename, + keyfile, + { mode: 0x100, flag: "wx" }, + function (err) { + if (err) return cb(err); + cb(null, keys); + } + ); }); }; - exports.createSync = function (filename, curve, legacy) { + exports.createSync = function (filename, generateOpts, legacy) { + const { curve, seed, feedFormat } = curveOrOpts(generateOpts); + filename = toFile(filename); - var keys = generate(curve); + var keys = generate(curve, seed, feedFormat); var keyfile = constructKeys(keys, legacy); mkdirp.sync(path.dirname(filename)); fs.writeFileSync(filename, keyfile, { mode: 0x100, flag: "wx" }); diff --git a/test/fs.js b/test/fs.js index 95ae449..6abf888 100644 --- a/test/fs.js +++ b/test/fs.js @@ -67,6 +67,19 @@ tape("loadOrCreate can create", function (t) { }); }); +tape("loadOrCreate can create buttwoo-v1 keys", function (t) { + var keyPath = path.join(os.tmpdir(), `ssb-keys-21-${Date.now()}`); + t.equal(fs.existsSync(keyPath), false); + + ssbkeys.loadOrCreate(keyPath, { feedFormat: "buttwoo-v1" }, (err, keys) => { + t.error(err); + t.true(keys.id.startsWith("ssb:feed/buttwoo-v1/")); + t.equals(keys.id.length, 64); + t.false(keys.id.endsWith(".ed25519")); + t.end(); + }); +}); + tape("loadOrCreateSync can load", function (t) { var keyPath = path.join(os.tmpdir(), `ssb-keys-3-${Date.now()}`); var keys = ssbkeys.generate("ed25519"); @@ -89,6 +102,17 @@ tape("loadOrCreateSync can create", function (t) { t.end(); }); +tape("loadOrCreateSync can create buttwoo-v1 keys", function (t) { + var keyPath = path.join(os.tmpdir(), `ssb-keys-41-${Date.now()}`); + t.equal(fs.existsSync(keyPath), false); + + const keys = ssbkeys.loadOrCreateSync(keyPath, { feedFormat: "buttwoo-v1" }); + t.true(keys.id.startsWith("ssb:feed/buttwoo-v1/")); + t.equals(keys.id.length, 64); + t.false(keys.id.endsWith(".ed25519")); + t.end(); +}); + tape("don't create dir for fully-specified path", function (t) { const keyPath = path.join(os.tmpdir(), `ssb-keys-5-${Date.now()}`); t.equal(fs.existsSync(keyPath), false);