Skip to content

Commit 211d7af

Browse files
committed
1 parent 2619091 commit 211d7af

26 files changed

+613
-145
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ calculation loop when the private key's private exponent was outright
3030
invalid or tampered with.
3131

3232
The new methods still allow to import private RSA keys with these
33-
optimization key parameters missing but its disabled by default and one
33+
optimization key parameters missing but it is disabled by default and one
3434
should choose to enable it when working with keys from trusted sources
3535

3636
It is recommended not to use @panva/jose versions with this feature in

P-256K/index.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// rename 'secp256k1' to 'P-256K'
2+
3+
const { rename } = require('../lib/jwk/key/secp256k1_crv')
4+
rename('P-256K')
5+
6+
module.exports = require('../lib')

README.md

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ The following specifications are implemented by @panva/jose
1818
- JSON Web Key Thumbprint - [RFC7638][spec-thumbprint]
1919
- JWS Unencoded Payload Option - [RFC7797][spec-b64]
2020
- CFRG Elliptic Curve Signatures (EdDSA) - [RFC8037][spec-okp]
21+
- secp256k1 curve EC Key support - [JOSE Registrations for WebAuthn Algorithms][draft-secp256k1]
2122

2223
The test suite utilizes examples defined in [RFC7520][spec-cookbook] to confirm its JOSE
2324
implementation is correct.
@@ -47,7 +48,7 @@ Legend:
4748
| -- | -- | -- |
4849
| RSASSA-PKCS1-v1_5 || RS256, RS384, RS512 |
4950
| RSASSA-PSS || PS256, PS384, PS512 |
50-
| ECDSA || ES256, ES384, ES512 |
51+
| ECDSA || ES256, ES256K, ES384, ES512 |
5152
| Edwards-curve DSA || EdDSA |
5253
| HMAC with SHA-2 || HS256, HS384, HS512 |
5354

@@ -247,6 +248,32 @@ jose.JWE.decrypt(
247248
)
248249
```
249250

251+
#### secp256k1
252+
253+
Note: the secp256k1 JOSE parameters registration and the RFC is still in a draft state. If the WG
254+
draft changes its mind about the parameter names again the new values will be propagated as a MINOR
255+
library version.
256+
257+
When you require `@panva/jose` you can work with `secp256k1` EC keys right away, the EC JWK `crv`
258+
used is as per the specification `secp256k1`.
259+
260+
```js
261+
const jose = require('@panva/jose')
262+
let key = jose.JWK.generateSync('EC', 'secp256k1')
263+
key = jose.JWK.asKey(fs.readFileSync('path/to/key/file'))
264+
key.crv === 'secp256k1'
265+
```
266+
267+
For legacy reasons the unregistered EC JWK `crv` value `P-256K` is also supported but you must
268+
require `@panva/jose` like so to use it:
269+
270+
```js
271+
const jose = require('@panva/jose/P-256K')
272+
let key = jose.JWK.generateSync('EC', 'P-256K')
273+
key = jose.JWK.asKey(fs.readFileSync('path/to/key/file'))
274+
key.crv === 'P-256K'
275+
```
276+
250277
## FAQ
251278

252279
#### Semver?
@@ -315,6 +342,7 @@ in terms of performance and API (not having well defined errors).
315342
[spec-jws]: https://tools.ietf.org/html/rfc7515
316343
[spec-jwt]: https://tools.ietf.org/html/rfc7519
317344
[spec-okp]: https://tools.ietf.org/html/rfc8037
345+
[draft-secp256k1]: https://tools.ietf.org/html/draft-ietf-cose-webauthn-algorithms-01
318346
[spec-thumbprint]: https://tools.ietf.org/html/rfc7638
319347
[suggest-feature]: https://github.com/panva/jose/issues/new?labels=enhancement&template=feature-request.md&title=proposal%3A+
320348
[support-patreon]: https://www.patreon.com/panva

lib/help/consts.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
const { name: secp256k1 } = require('../jwk/key/secp256k1_crv')
2+
13
module.exports.KEYOBJECT = Symbol('KEYOBJECT')
24
module.exports.PRIVATE_MEMBERS = Symbol('PRIVATE_MEMBERS')
35
module.exports.PUBLIC_MEMBERS = Symbol('PUBLIC_MEMBERS')
@@ -18,7 +20,7 @@ module.exports.OPS = OPS
1820
module.exports.USES = USES
1921

2022
module.exports.OKP_CURVES = new Set(['Ed25519', 'Ed448', 'X25519', 'X448'])
21-
module.exports.EC_CURVES = new Set(['P-256', 'P-384', 'P-521'])
23+
module.exports.EC_CURVES = new Set(['P-256', secp256k1, 'P-384', 'P-521'])
2224
module.exports.ECDH_ALGS = ['ECDH-ES', 'ECDH-ES+A128KW', 'ECDH-ES+A192KW', 'ECDH-ES+A256KW']
2325

2426
module.exports.KEYLENGTHS = {

lib/help/ecdsa_signatures.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const getParamSize = keySize => ((keySize / 8) | 0) + (keySize % 8 === 0 ? 0 : 1
1010

1111
const paramBytesForAlg = {
1212
ES256: getParamSize(256),
13+
ES256K: getParamSize(256),
1314
ES384: getParamSize(384),
1415
ES512: getParamSize(521)
1516
}

lib/help/key_utils.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,29 @@
11
const { createPublicKey } = require('crypto')
22

3-
const base64url = require('./base64url')
3+
const { name: secp256k1 } = require('../jwk/key/secp256k1_crv')
44
const errors = require('../errors')
5+
6+
const base64url = require('./base64url')
57
const asn1 = require('./asn1')
68
const computePrimes = require('./rsa_primes')
79
const { OKP_CURVES, EC_CURVES } = require('./consts')
810

911
const oidHexToCurve = new Map([
1012
['06082a8648ce3d030107', 'P-256'],
13+
['06052b8104000a', secp256k1],
1114
['06052b81040022', 'P-384'],
1215
['06052b81040023', 'P-521']
1316
])
1417
const EC_KEY_OID = '1.2.840.10045.2.1'.split('.')
1518
const crvToOid = new Map([
1619
['P-256', '1.2.840.10045.3.1.7'.split('.')],
20+
[secp256k1, '1.3.132.0.10'.split('.')],
1721
['P-384', '1.3.132.0.34'.split('.')],
1822
['P-521', '1.3.132.0.35'.split('.')]
1923
])
2024
const crvToOidBuf = new Map([
2125
['P-256', Buffer.from('06082a8648ce3d030107', 'hex')],
26+
[secp256k1, Buffer.from('06052b8104000a', 'hex')],
2227
['P-384', Buffer.from('06052b81040022', 'hex')],
2328
['P-521', Buffer.from('06052b81040023', 'hex')]
2429
])

lib/help/node_alg.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
module.exports = alg => `sha${alg.substr(-3)}`
1+
module.exports = alg => `sha${alg.substr(2, 3)}`

lib/index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ interface KeyParameters extends BasicParameters {
1515
x5t?: string
1616
'x5t#S256'?: string
1717
}
18-
type ECCurve = 'P-256' | 'P-384' | 'P-521'
18+
type ECCurve = 'P-256' | 'secp256k1' | 'P-384' | 'P-521'
1919
type OKPCurve = 'Ed25519' | 'Ed448' | 'X25519' | 'X448'
2020
type keyType = 'RSA' | 'EC' | 'OKP' | 'oct'
2121
type asymmetricKeyObjectTypes = 'private' | 'public'

lib/jwa/ecdh/derive.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const { createECDH, createHash, constants: { POINT_CONVERSION_UNCOMPRESSED } } = require('crypto')
22

33
const base64url = require('../../help/base64url')
4+
const { name: secp256k1 } = require('../../jwk/key/secp256k1_crv')
45

56
const crvToCurve = (crv) => {
67
switch (crv) {
@@ -10,9 +11,12 @@ const crvToCurve = (crv) => {
1011
return 'secp384r1'
1112
case 'P-521':
1213
return 'secp521r1'
14+
case 'secp256k1':
1315
case 'X448':
1416
case 'X25519':
1517
return crv
18+
case secp256k1:
19+
return 'secp256k1'
1620
}
1721
}
1822

lib/jwa/ecdsa.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const verify = (jwaAlg, nodeAlg, { [KEYOBJECT]: keyObject }, payload, signature)
1818
}
1919

2020
module.exports = (JWA) => {
21-
['ES256', 'ES384', 'ES512'].forEach((jwaAlg) => {
21+
['ES256', 'ES384', 'ES512', 'ES256K'].forEach((jwaAlg) => {
2222
const nodeAlg = resolveNodeAlg(jwaAlg)
2323

2424
assert(!JWA.sign.has(jwaAlg), `sign alg ${jwaAlg} already registered`)

0 commit comments

Comments
 (0)