diff --git a/src/core/components/pre-start.js b/src/core/components/pre-start.js index e69f20845d..2ef29f6ce7 100644 --- a/src/core/components/pre-start.js +++ b/src/core/components/pre-start.js @@ -7,6 +7,9 @@ const waterfall = require('async/waterfall') const Keychain = require('libp2p-keychain') const mergeOptions = require('merge-options') const NoKeychain = require('./no-keychain') +const KeyTransformDatastore = require('datastore-core').KeytransformDatastore +const keychainTransformer = require('../../utils/keychain-encoder') + /* * Load stuff from Repo into memory */ @@ -49,7 +52,9 @@ module.exports = function preStart (self) { // most likely an init or upgrade has happened } else if (pass) { const keychainOptions = Object.assign({ passPhrase: pass }, config.Keychain) - self._keychain = new Keychain(self._repo.keys, keychainOptions) + const keychainTransformedDatastore = new KeyTransformDatastore(self._repo.keys, keychainTransformer) + self._keychain = new Keychain(keychainTransformedDatastore, keychainOptions) + // self._keychain = new Keychain(self._repo.keys, keychainOptions) self.log('keychain constructed') } else { self._keychain = new NoKeychain() diff --git a/src/utils/keychain-encoder.js b/src/utils/keychain-encoder.js new file mode 100644 index 0000000000..8b13d6a007 --- /dev/null +++ b/src/utils/keychain-encoder.js @@ -0,0 +1,47 @@ +'use strict' +const base32 = require('base32.js') +const Key = require('interface-datastore').Key +const KEY_PREFIX = 'key_' + +module.exports = { + /** + * Encode baseNamespace of a Key to base32 + * + * @param {Key} key + * @returns {Key} + * + * @example convert(new Key('/info/self.data')) + * // => Key('/info/key_onswyzq.data') + */ + convert (key) { + const encoder = new base32.Encoder({ type: 'rfc4648' }) + const baseNameBuff = Buffer.from(key.baseNamespace()) + const encodedBaseNamespace = KEY_PREFIX + encoder.finalize(baseNameBuff).toLowerCase() + const namespaces = key.namespaces() + namespaces[namespaces.length - 1] = encodedBaseNamespace // Replace the baseNamespace with encoded one + return Key.withNamespaces(namespaces) + }, + + /** + * Decode baseNamespace of a Key from base32 + * + * @param {Key} key + * @returns {Key} + * + * @example invert(new Key('/info/key_onswyzq.data')) + * // => Key('/info/self.data') + */ + invert (key) { + const baseNamespace = key.baseNamespace() + if (!baseNamespace.startsWith(KEY_PREFIX)) { + throw Error('Unknown format of key\'s name!') + } + + const decoder = new base32.Decoder({ type: 'rfc4648' }) + const decodedBaseNamespace = decoder.finalize(baseNamespace.replace(KEY_PREFIX, '').toUpperCase()) + const namespaces = key.namespaces() + namespaces[namespaces.length - 1] = Buffer.from(decodedBaseNamespace).toString() // Replace the baseNamespace with encoded one + + return Key.withNamespaces(namespaces) + } +} diff --git a/test/utils-test/keychain-encode.spec.js b/test/utils-test/keychain-encode.spec.js new file mode 100644 index 0000000000..a6ddb597e4 --- /dev/null +++ b/test/utils-test/keychain-encode.spec.js @@ -0,0 +1,30 @@ +/* eslint-env mocha */ +'use strict' + +const encoder = require('../../src/utils/keychain-encoder') +const Key = require('interface-datastore').Key + +const expect = require('chai').expect + +function test (input, expected, fnc) { + input = new Key(input) + const output = fnc(input) + + expect(output.toString()).to.equal(expected) +} + +describe('keychain-encode', () => { + it('encode keys', () => { + test('/self', '/key_onswyzq', encoder.convert) + test('bbbba', '/key_mjrgeytb', encoder.convert) + test('/some/path/self', '/some/path/key_onswyzq', encoder.convert) + }) + it('decode keys', () => { + test('/key_onswyzq', '/self', encoder.invert) + test('key_mjrgeytb', '/bbbba', encoder.invert) + test('/some/path/key_onswyzq', '/some/path/self', encoder.invert) + }) + it('decode expects specific format', () => { + expect(() => { encoder.invert(new Key('/some/path/onswyzq')) }).to.throw('Unknown') + }) +})