mirror of
https://github.com/fluencelabs/js-libp2p-crypto
synced 2025-03-15 19:31:05 +00:00
feat(keys): implement generateKeyPairFromSeed for ed25519
Implement generateKeyPairFromSeed for ed25519 - this will produce the same keypair for the same seed (or first 32 bytes of reader) as given to GenerateKeyPairWithReader in go-libp2p.
This commit is contained in:
parent
20326199d9
commit
e5b7c1f622
@ -22,6 +22,22 @@ exports.generateKey = function (callback) {
|
|||||||
done(null, keys)
|
done(null, keys)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// seed should be a 32 byte uint8array
|
||||||
|
exports.generateKeyFromSeed = function (seed, callback) {
|
||||||
|
const done = (err, res) => setImmediate(() => {
|
||||||
|
callback(err, res)
|
||||||
|
})
|
||||||
|
|
||||||
|
let keys
|
||||||
|
try {
|
||||||
|
keys = nacl.sign.keyPair.fromSeed(seed)
|
||||||
|
} catch (err) {
|
||||||
|
done(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
done(null, keys)
|
||||||
|
}
|
||||||
|
|
||||||
exports.hashAndSign = function (key, msg, callback) {
|
exports.hashAndSign = function (key, msg, callback) {
|
||||||
setImmediate(() => {
|
setImmediate(() => {
|
||||||
callback(null, Buffer.from(nacl.sign.detached(msg, key)))
|
callback(null, Buffer.from(nacl.sign.detached(msg, key)))
|
||||||
|
13
src/index.js
13
src/index.js
@ -30,6 +30,19 @@ exports.generateKeyPair = (type, bits, cb) => {
|
|||||||
key.generateKeyPair(bits, cb)
|
key.generateKeyPair(bits, cb)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generates a keypair of the given type and bitsize
|
||||||
|
// seed is a 32 byte uint8array
|
||||||
|
exports.generateKeyPairFromSeed = (type, seed, bits, cb) => {
|
||||||
|
let key = keys[type.toLowerCase()]
|
||||||
|
if (!key) {
|
||||||
|
return cb(new Error('invalid or unsupported key type'))
|
||||||
|
}
|
||||||
|
if (type.toLowerCase() !== 'ed25519') {
|
||||||
|
return cb(new Error('Seed key derivation is unimplemented for RSA or secp256k1'))
|
||||||
|
}
|
||||||
|
key.generateKeyPairFromSeed(seed, bits, cb)
|
||||||
|
}
|
||||||
|
|
||||||
// Converts a protobuf serialized public key into its
|
// Converts a protobuf serialized public key into its
|
||||||
// representative object
|
// representative object
|
||||||
exports.unmarshalPublicKey = (buf) => {
|
exports.unmarshalPublicKey = (buf) => {
|
||||||
|
@ -117,6 +117,27 @@ function generateKeyPair (_bits, cb) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function generateKeyPairFromSeed (seed, _bits, cb) {
|
||||||
|
if (cb === undefined && typeof _bits === 'function') {
|
||||||
|
cb = _bits
|
||||||
|
}
|
||||||
|
|
||||||
|
crypto.generateKeyFromSeed(seed, (err, keys) => {
|
||||||
|
if (err) {
|
||||||
|
return cb(err)
|
||||||
|
}
|
||||||
|
let privkey
|
||||||
|
try {
|
||||||
|
privkey = new Ed25519PrivateKey(keys.secretKey, keys.publicKey)
|
||||||
|
} catch (err) {
|
||||||
|
cb(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cb(null, privkey)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function ensure (cb) {
|
function ensure (cb) {
|
||||||
if (typeof cb !== 'function') {
|
if (typeof cb !== 'function') {
|
||||||
throw new Error('callback is required')
|
throw new Error('callback is required')
|
||||||
@ -138,5 +159,6 @@ module.exports = {
|
|||||||
Ed25519PrivateKey,
|
Ed25519PrivateKey,
|
||||||
unmarshalEd25519PrivateKey,
|
unmarshalEd25519PrivateKey,
|
||||||
unmarshalEd25519PublicKey,
|
unmarshalEd25519PublicKey,
|
||||||
generateKeyPair
|
generateKeyPair,
|
||||||
|
generateKeyPairFromSeed
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,70 @@ describe('ed25519', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('generates a valid key from seed', (done) => {
|
||||||
|
var seed = crypto.randomBytes(32)
|
||||||
|
crypto.generateKeyPairFromSeed('Ed25519', seed, 512, (err, seededkey) => {
|
||||||
|
if (err) return done(err)
|
||||||
|
expect(
|
||||||
|
seededkey
|
||||||
|
).to.be.an.instanceof(
|
||||||
|
ed25519.Ed25519PrivateKey
|
||||||
|
)
|
||||||
|
|
||||||
|
seededkey.hash((err, digest) => {
|
||||||
|
if (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(digest).to.have.length(34)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('generates the same key from the same seed', (done) => {
|
||||||
|
var seed = crypto.randomBytes(32)
|
||||||
|
crypto.generateKeyPairFromSeed('Ed25519', seed, 512, (err, seededkey1) => {
|
||||||
|
if (err) return done(err)
|
||||||
|
crypto.generateKeyPairFromSeed('Ed25519', seed, 512, (err, seededkey2) => {
|
||||||
|
if (err) return done(err)
|
||||||
|
expect(
|
||||||
|
seededkey1.equals(seededkey2)
|
||||||
|
).to.be.eql(
|
||||||
|
true
|
||||||
|
)
|
||||||
|
expect(
|
||||||
|
seededkey1.public.equals(seededkey2.public)
|
||||||
|
).to.be.eql(
|
||||||
|
true
|
||||||
|
)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('generates different keys for different seeds', (done) => {
|
||||||
|
var seed1 = crypto.randomBytes(32)
|
||||||
|
crypto.generateKeyPairFromSeed('Ed25519', seed1, 512, (err, seededkey1) => {
|
||||||
|
if (err) return done(err)
|
||||||
|
var seed2 = crypto.randomBytes(32)
|
||||||
|
crypto.generateKeyPairFromSeed('Ed25519', seed2, 512, (err, seededkey2) => {
|
||||||
|
if (err) return done(err)
|
||||||
|
expect(
|
||||||
|
seededkey1.equals(seededkey2)
|
||||||
|
).to.be.eql(
|
||||||
|
false
|
||||||
|
)
|
||||||
|
expect(
|
||||||
|
seededkey1.public.equals(seededkey2.public)
|
||||||
|
).to.be.eql(
|
||||||
|
false
|
||||||
|
)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
it('signs', (done) => {
|
it('signs', (done) => {
|
||||||
const text = crypto.randomBytes(512)
|
const text = crypto.randomBytes(512)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user