Skip to content

Commit b13bf71

Browse files
author
Alan Shaw
committed
feat: use async/await
This PR changes this module to remove callbacks and use async/await. The API is unchanged aside from the obvious removal of the `callback` parameter. depends on `multihashing-async` PR TODO refs ipfs/js-ipfs#1670 License: MIT Signed-off-by: Alan Shaw <[email protected]>
1 parent 1602c44 commit b13bf71

File tree

7 files changed

+212
-304
lines changed

7 files changed

+212
-304
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,5 @@ build
3232
node_modules
3333

3434
dist
35+
36+
package-lock.json

.travis.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ language: node_js
44

55
matrix:
66
include:
7-
- node_js: 6
8-
env: CXX=g++-4.8
97
- node_js: 8
108
env: CXX=g++-4.8
9+
- node_js: 10
10+
env: CXX=g++-4.8
1111
# - node_js: stable
1212
# env: CXX=g++-4.8
1313

README.md

+31-29
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010

1111
> Support for secp256k1 keys in js-libp2p-crypto
1212
13-
This repo contains a [js-libp2p-crypto](https://github.com/libp2p/js-libp2p-crypto)-compatible
14-
implementation of cryptographic signature generation and verification using the
15-
[secp256k1 elliptic curve](https://en.bitcoin.it/wiki/Secp256k1) popularized by Bitcoin and other
13+
This repo contains a [js-libp2p-crypto](https://github.com/libp2p/js-libp2p-crypto)-compatible
14+
implementation of cryptographic signature generation and verification using the
15+
[secp256k1 elliptic curve](https://en.bitcoin.it/wiki/Secp256k1) popularized by Bitcoin and other
1616
crypto currencies.
1717

1818
## Lead Captain
@@ -25,14 +25,14 @@ crypto currencies.
2525
- [Usage](#usage)
2626
- [Example](#example)
2727
- [API](#api)
28-
- [`generateKeyPair([bits,] callback)`](#generatekeypairbits-callback)
28+
- [`generateKeyPair([bits])`](#generatekeypairbits)
2929
- [`unmarshalSecp256k1PublicKey(bytes)`](#unmarshalsecp256k1publickeybytes)
30-
- [`unmarshalSecp256k1PrivateKey(bytes, callback)`](#unmarshalsecp256k1privatekeybytes-callback)
30+
- [`unmarshalSecp256k1PrivateKey(bytes)`](#unmarshalsecp256k1privatekeybytes)
3131
- [`Secp256k1PublicKey`](#secp256k1publickey)
32-
- [`.verify(data, sig, callback)`](#verifydata-sig-callback)
32+
- [`.verify(data, sig)`](#verifydata-sig)
3333
- [`Secp256k1PrivateKey`](#secp256k1privatekey)
3434
- [`.public`](#public)
35-
- [`.sign(data, callback)`](#signdata-callback)
35+
- [`.sign(data)`](#signdata)
3636
- [Contribute](#contribute)
3737
- [License](#license)
3838

@@ -54,63 +54,65 @@ instances of the `Secp256k1PublicKey` or `Secp256k1PrivateKey` classes provided
5454

5555
```js
5656
const crypto = require('libp2p-crypto')
57-
5857
const msg = Buffer.from('Hello World')
5958

60-
crypto.generateKeyPair('secp256k1', 256, (err, key) => {
61-
// assuming no error, key will be an instance of Secp256k1PrivateKey
62-
// the public key is available as key.public
63-
key.sign(msg, (err, sig) => {
64-
key.public.verify(msg, sig, (err, valid) => {
65-
assert(valid, 'Something went horribly wrong')
66-
})
67-
})
68-
})
59+
const key = await crypto.generateKeyPair('secp256k1', 256)
60+
// assuming no error, key will be an instance of Secp256k1PrivateKey
61+
// the public key is available as key.public
62+
const sig = await key.sign(msg)
63+
64+
const valid = await key.public.verify(msg, sig)
65+
assert(valid, 'Something went horribly wrong')
6966
```
7067

7168
## API
7269

7370
The functions below are the public API of this module.
74-
For usage within libp2p-crypto, see the [libp2p-crypto API documentation](https://github.com/libp2p/js-libp2p-crypto#api).
71+
For usage within `libp2p-crypto`, see the [`libp2p-crypto` API documentation](https://github.com/libp2p/js-libp2p-crypto#api).
7572

76-
### `generateKeyPair([bits, ] callback)`
73+
### `generateKeyPair([bits])`
7774
- `bits: Number` - Optional, included for compatibility with js-libp2p-crypto. Ignored if present; private keys will always be 256 bits.
78-
- `callback: Function`
75+
76+
Returns `Promise<Secp256k1PrivateKey>`
7977

8078
### `unmarshalSecp256k1PublicKey(bytes)`
8179
- `bytes: Buffer`
8280

8381
Converts a serialized secp256k1 public key into an instance of `Secp256k1PublicKey` and returns it
8482

85-
### `unmarshalSecp256k1PrivateKey(bytes, callback)`
83+
### `unmarshalSecp256k1PrivateKey(bytes)`
8684
- `bytes: Buffer`
87-
- `callback: Function`
8885

89-
Converts a serialized secp256k1 private key into an instance of `Secp256k1PrivateKey`, passing it to `callback` on success
86+
Returns `Promise<Secp256k1PrivateKey>`
87+
88+
Converts a serialized secp256k1 private key into an instance of `Secp256k1PrivateKey`.
9089

9190
### `Secp256k1PublicKey`
9291

93-
#### `.verify(data, sig, callback)`
92+
#### `.verify(data, sig)`
9493
- `data: Buffer`
9594
- `sig: Buffer`
96-
- `callback: Function`
9795

98-
Calculates the SHA-256 hash of `data`, and verifies the DER-encoded signature in `sig`, passing the result to `callback`
96+
Returns `Promise<Boolean>`
97+
98+
Calculates the SHA-256 hash of `data`, and verifies the DER-encoded signature in `sig`.
9999

100100
### `Secp256k1PrivateKey`
101101

102102
#### `.public`
103103

104104
Accessor for the `Secp256k1PublicKey` associated with this private key.
105105

106-
#### `.sign(data, callback)`
106+
#### `.sign(data)`
107107
- `data: Buffer`
108108

109-
Calculates the SHA-256 hash of `data` and signs it, passing the DER-encoded signature to `callback`
109+
Returns `Promise<Buffer>`
110+
111+
Calculates the SHA-256 hash of `data` and signs it, resolves with the DER-encoded signature.
110112

111113
## Contribute
112114

113-
Feel free to join in. All welcome. Open an [issue](https://github.com/libp2p/js-libp2p-crypto/issues)!
115+
Feel free to join in. All welcome. Open an [issue](https://github.com/libp2p/js-libp2p-crypto-secp256k1/issues)!
114116

115117
This repository falls under the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).
116118

package.json

+13-16
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,16 @@
88
"secp256k1": "secp256k1/js"
99
},
1010
"scripts": {
11-
"lint": "aegir-lint",
12-
"build": "aegir-build",
11+
"lint": "aegir lint",
12+
"build": "aegir build",
1313
"test": "npm run test:node && npm run test:browser",
14-
"test:node": "aegir-test --env node",
15-
"test:browser": "aegir-test --env browser",
16-
"release": "aegir-release",
17-
"release-minor": "aegir-release --type minor",
18-
"release-major": "aegir-release --type major",
19-
"coverage": "aegir-coverage",
20-
"coverage-publish": "aegir-coverage publish"
14+
"test:node": "aegir test -t node",
15+
"test:browser": "aegir test -t browser",
16+
"release": "aegir release",
17+
"release-minor": "aegir release --type minor",
18+
"release-major": "aegir release --type major",
19+
"coverage": "aegir coverage",
20+
"coverage-publish": "aegir coverage publish"
2121
},
2222
"keywords": [
2323
"IPFS",
@@ -27,18 +27,15 @@
2727
],
2828
"license": "MIT",
2929
"dependencies": {
30-
"async": "^2.6.0",
31-
"multihashing-async": "~0.4.8",
32-
"nodeify": "^1.0.1",
33-
"safe-buffer": "^5.1.2",
30+
"multihashing-async": "^0.5.1",
3431
"secp256k1": "^3.5.0"
3532
},
3633
"devDependencies": {
37-
"aegir": "^13.1.0",
34+
"aegir": "^17.0.0",
3835
"benchmark": "^2.1.4",
39-
"libp2p-crypto": "~0.13.0",
4036
"chai": "^4.1.2",
41-
"dirty-chai": "^2.0.1"
37+
"dirty-chai": "^2.0.1",
38+
"libp2p-crypto": "^0.14.0"
4239
},
4340
"engines": {
4441
"node": ">=6.0.0",

src/crypto.js

+27-36
Original file line numberDiff line numberDiff line change
@@ -2,49 +2,40 @@
22

33
const secp256k1 = require('secp256k1')
44
const multihashing = require('multihashing-async')
5-
const setImmediate = require('async/setImmediate')
65

76
const HASH_ALGORITHM = 'sha2-256'
87

98
module.exports = (randomBytes) => {
109
const privateKeyLength = 32
1110

12-
function generateKey (callback) {
13-
const done = (err, res) => setImmediate(() => callback(err, res))
14-
11+
async function generateKey () {
1512
let privateKey
1613
do {
1714
privateKey = randomBytes(32)
1815
} while (!secp256k1.privateKeyVerify(privateKey))
19-
20-
done(null, privateKey)
16+
return privateKey
2117
}
2218

23-
function hashAndSign (key, msg, callback) {
24-
const done = (err, res) => setImmediate(() => callback(err, res))
25-
26-
multihashing.digest(msg, HASH_ALGORITHM, (err, digest) => {
27-
if (err) { return done(err) }
28-
29-
try {
30-
const sig = secp256k1.sign(digest, key)
31-
const sigDER = secp256k1.signatureExport(sig.signature)
32-
return done(null, sigDER)
33-
} catch (err) { done(err) }
19+
async function hashAndSign (key, msg) {
20+
const digest = await new Promise((resolve, reject) => {
21+
multihashing.digest(msg, HASH_ALGORITHM, (err, digest) => {
22+
if (err) return reject(err)
23+
resolve(digest)
24+
})
3425
})
26+
const sig = secp256k1.sign(digest, key)
27+
return secp256k1.signatureExport(sig.signature)
3528
}
3629

37-
function hashAndVerify (key, sig, msg, callback) {
38-
const done = (err, res) => setImmediate(() => callback(err, res))
39-
40-
multihashing.digest(msg, HASH_ALGORITHM, (err, digest) => {
41-
if (err) { return done(err) }
42-
try {
43-
sig = secp256k1.signatureImport(sig)
44-
const valid = secp256k1.verify(digest, sig, key)
45-
return done(null, valid)
46-
} catch (err) { done(err) }
30+
async function hashAndVerify (key, sig, msg) {
31+
const digest = await new Promise((resolve, reject) => {
32+
multihashing.digest(msg, HASH_ALGORITHM, (err, digest) => {
33+
if (err) return reject(err)
34+
resolve(digest)
35+
})
4736
})
37+
sig = secp256k1.signatureImport(sig)
38+
return secp256k1.verify(digest, sig, key)
4839
}
4940

5041
function compressPublicKey (key) {
@@ -76,14 +67,14 @@ module.exports = (randomBytes) => {
7667
}
7768

7869
return {
79-
generateKey: generateKey,
80-
privateKeyLength: privateKeyLength,
81-
hashAndSign: hashAndSign,
82-
hashAndVerify: hashAndVerify,
83-
compressPublicKey: compressPublicKey,
84-
decompressPublicKey: decompressPublicKey,
85-
validatePrivateKey: validatePrivateKey,
86-
validatePublicKey: validatePublicKey,
87-
computePublicKey: computePublicKey
70+
generateKey,
71+
privateKeyLength,
72+
hashAndSign,
73+
hashAndVerify,
74+
compressPublicKey,
75+
decompressPublicKey,
76+
validatePrivateKey,
77+
validatePublicKey,
78+
computePublicKey
8879
}
8980
}

src/index.js

+23-37
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,8 @@ module.exports = (keysProtobuf, randomBytes, crypto) => {
1111
this._key = key
1212
}
1313

14-
verify (data, sig, callback) {
15-
ensure(callback)
16-
crypto.hashAndVerify(this._key, sig, data, callback)
14+
async verify (data, sig) {
15+
return crypto.hashAndVerify(this._key, sig, data)
1716
}
1817

1918
marshal () {
@@ -31,9 +30,13 @@ module.exports = (keysProtobuf, randomBytes, crypto) => {
3130
return this.bytes.equals(key.bytes)
3231
}
3332

34-
hash (callback) {
35-
ensure(callback)
36-
multihashing(this.bytes, 'sha2-256', callback)
33+
async hash () {
34+
return new Promise((resolve, reject) => {
35+
multihashing(this.bytes, 'sha2-256', (err, res) => {
36+
if (err) return reject(err)
37+
resolve(res)
38+
})
39+
})
3740
}
3841
}
3942

@@ -45,9 +48,8 @@ module.exports = (keysProtobuf, randomBytes, crypto) => {
4548
crypto.validatePublicKey(this._publicKey)
4649
}
4750

48-
sign (message, callback) {
49-
ensure(callback)
50-
crypto.hashAndSign(this._key, message, callback)
51+
async sign (message) {
52+
return crypto.hashAndSign(this._key, message)
5153
}
5254

5355
get public () {
@@ -69,43 +71,27 @@ module.exports = (keysProtobuf, randomBytes, crypto) => {
6971
return this.bytes.equals(key.bytes)
7072
}
7173

72-
hash (callback) {
73-
ensure(callback)
74-
multihashing(this.bytes, 'sha2-256', callback)
74+
async hash () {
75+
return new Promise((resolve, reject) => {
76+
multihashing(this.bytes, 'sha2-256', (err, res) => {
77+
if (err) return reject(err)
78+
resolve(res)
79+
})
80+
})
7581
}
7682
}
7783

78-
function unmarshalSecp256k1PrivateKey (bytes, callback) {
79-
callback(null, new Secp256k1PrivateKey(bytes), null)
84+
async function unmarshalSecp256k1PrivateKey (bytes) {
85+
return new Secp256k1PrivateKey(bytes)
8086
}
8187

8288
function unmarshalSecp256k1PublicKey (bytes) {
8389
return new Secp256k1PublicKey(bytes)
8490
}
8591

86-
function generateKeyPair (_bits, callback) {
87-
if (callback === undefined && typeof _bits === 'function') {
88-
callback = _bits
89-
}
90-
91-
ensure(callback)
92-
93-
crypto.generateKey((err, privateKeyBytes) => {
94-
if (err) { return callback(err) }
95-
96-
let privkey
97-
try {
98-
privkey = new Secp256k1PrivateKey(privateKeyBytes)
99-
} catch (err) { return callback(err) }
100-
101-
callback(null, privkey)
102-
})
103-
}
104-
105-
function ensure (callback) {
106-
if (typeof callback !== 'function') {
107-
throw new Error('callback is required')
108-
}
92+
async function generateKeyPair () {
93+
const privateKeyBytes = await crypto.generateKey()
94+
return new Secp256k1PrivateKey(privateKeyBytes)
10995
}
11096

11197
return {

0 commit comments

Comments
 (0)