Skip to content

Commit

Permalink
perf: various codepaths refactored
Browse files Browse the repository at this point in the history
  • Loading branch information
panva committed Feb 6, 2020
1 parent eb12f16 commit 3e3d7dd
Show file tree
Hide file tree
Showing 17 changed files with 182 additions and 221 deletions.
8 changes: 4 additions & 4 deletions lib/help/get_key.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ const importKey = require('../jwk/import')
const { KeyStore } = require('../jwks/keystore')

module.exports = (input, keyStoreAllowed = false) => {
if (input instanceof Key) {
return input
}

if (input instanceof KeyStore) {
if (!keyStoreAllowed) {
throw new TypeError('key argument for this operation must not be a JWKS.KeyStore instance')
Expand All @@ -12,10 +16,6 @@ module.exports = (input, keyStoreAllowed = false) => {
return input
}

if (input instanceof Key) {
return input
}

try {
return importKey(input)
} catch (err) {
Expand Down
122 changes: 57 additions & 65 deletions lib/help/key_object.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,6 @@ if (!keyObjectSupported) {
const toInput = Symbol('toInput')

const namedCurve = Symbol('namedCurve')
const map = new WeakMap()

const i = (ctx) => {
if (!map.has(ctx)) {
map.set(ctx, {})
}
return map.get(ctx)
}

asInput = (keyObject, needsPublic) => {
if (keyObject instanceof KeyObject) {
Expand Down Expand Up @@ -55,11 +47,11 @@ if (!keyObjectSupported) {

KeyObject = class KeyObject {
export ({ cipher, passphrase, type, format } = {}) {
if (i(this).type === 'secret') {
return Buffer.from(i(this).buffer)
if (this._type === 'secret') {
return this._buffer
}

if (i(this).type === 'public') {
if (this._type === 'public') {
if (format !== 'pem' && format !== 'der') {
throw new TypeError('format must be one of "pem" or "der"')
}
Expand All @@ -68,10 +60,10 @@ if (!keyObjectSupported) {
switch (type) {
case 'pkcs1':
if (format === 'pem') {
return i(this).pem
return this._pem
}

return pemToDer(i(this).pem)
return pemToDer(this._pem)
case 'spki': {
const PublicKeyInfo = asn1.get('PublicKeyInfo')
const pem = PublicKeyInfo.encode({
Expand All @@ -81,7 +73,7 @@ if (!keyObjectSupported) {
},
publicKey: {
unused: 0,
data: pemToDer(i(this).pem)
data: pemToDer(this._pem)
}
}, 'pem', { label: 'PUBLIC KEY' })

Expand All @@ -98,14 +90,14 @@ if (!keyObjectSupported) {
}

if (format === 'pem') {
return i(this).pem
return this._pem
}

return pemToDer(i(this).pem)
return pemToDer(this._pem)
}
}

if (i(this).type === 'private') {
if (this._type === 'private') {
if (format !== 'pem' && format !== 'der') {
throw new TypeError('format must be one of "pem" or "der"')
}
Expand All @@ -115,20 +107,20 @@ if (!keyObjectSupported) {
}

if (type === 'pkcs8') {
if (i(this).pkcs8) {
if (format === 'der' && typeof i(this).pkcs8 === 'string') {
return pemToDer(i(this).pkcs8)
if (this._pkcs8) {
if (format === 'der' && typeof this._pkcs8 === 'string') {
return pemToDer(this._pkcs8)
}

if (format === 'pem' && Buffer.isBuffer(i(this).pkcs8)) {
return derToPem(i(this).pkcs8, 'PRIVATE KEY')
if (format === 'pem' && Buffer.isBuffer(this._pkcs8)) {
return derToPem(this._pkcs8, 'PRIVATE KEY')
}

return i(this).pkcs8
return this._pkcs8
}

if (this.asymmetricKeyType === 'rsa') {
const parsed = i(this).asn1
const parsed = this._asn1
const RSAPrivateKey = asn1.get('RSAPrivateKey')
const privateKey = RSAPrivateKey.encode(parsed)
const PrivateKeyInfo = asn1.get('PrivateKeyInfo')
Expand All @@ -141,13 +133,13 @@ if (!keyObjectSupported) {
}
})

i(this).pkcs8 = pkcs8
this._pkcs8 = pkcs8

return this.export({ type, format })
}

if (this.asymmetricKeyType === 'ec') {
const parsed = i(this).asn1
const parsed = this._asn1
const ECPrivateKey = asn1.get('ECPrivateKey')
const privateKey = ECPrivateKey.encode({
version: parsed.version,
Expand All @@ -161,62 +153,62 @@ if (!keyObjectSupported) {
privateKey,
algorithm: {
algorithm: '1.2.840.10045.2.1'.split('.'),
parameters: OID.encode(i(this).asn1.parameters.value)
parameters: OID.encode(this._asn1.parameters.value)
}
})

i(this).pkcs8 = pkcs8
this._pkcs8 = pkcs8

return this.export({ type, format })
}
}

if (this.asymmetricKeyType === 'rsa' && type === 'pkcs1') {
if (format === 'pem') {
return i(this).pem
return this._pem
}

return pemToDer(i(this).pem)
return pemToDer(this._pem)
} else if (this.asymmetricKeyType === 'ec' && type === 'sec1') {
if (format === 'pem') {
return i(this).pem
return this._pem
}

return pemToDer(i(this).pem)
return pemToDer(this._pem)
} else {
throw new TypeError(`type must be one of "spki" or "${this.asymmetricKeyType === 'rsa' ? 'pkcs1' : 'sec1'}"`)
}
}
}

get type () {
return i(this).type
return this._type
}

get asymmetricKeyType () {
return i(this).asymmetricKeyType
return this._asymmetricKeyType
}

get symmetricKeySize () {
return i(this).symmetricKeySize
return this._symmetricKeySize
}

[toInput] (needsPublic) {
switch (i(this).type) {
switch (this._type) {
case 'secret':
return i(this).buffer
return this._buffer
case 'public':
return i(this).pem
return this._pem
default:
if (needsPublic) {
if (!('pub' in i(this))) {
i(this).pub = createPublicKey(this)
if (!('_pub' in this)) {
this._pub = createPublicKey(this)
}

return i(this).pub[toInput](false)
return this._pub[toInput](false)
}

return i(this).pem
return this._pem
}
}
}
Expand All @@ -227,9 +219,9 @@ if (!keyObjectSupported) {
}

const keyObject = new KeyObject()
i(keyObject).buffer = Buffer.from(buffer)
i(keyObject).symmetricKeySize = buffer.length
i(keyObject).type = 'secret'
keyObject._buffer = Buffer.from(buffer)
keyObject._symmetricKeySize = buffer.length
keyObject._type = 'secret'

return keyObject
}
Expand All @@ -247,16 +239,16 @@ if (!keyObjectSupported) {
const key = PublicKeyInfo.encode({
algorithm: {
algorithm: '1.2.840.10045.2.1'.split('.'),
parameters: OID.encode(i(input).asn1.parameters.value)
parameters: OID.encode(input._asn1.parameters.value)
},
publicKey: i(input).asn1.publicKey
publicKey: input._asn1.publicKey
})

return createPublicKey({ key, format: 'der', type: 'spki' })
}
case 'rsa': {
const RSAPublicKey = asn1.get('RSAPublicKey')
const key = RSAPublicKey.encode(i(input).asn1)
const key = RSAPublicKey.encode(input._asn1)
return createPublicKey({ key, format: 'der', type: 'pkcs1' })
}
}
Expand Down Expand Up @@ -310,10 +302,10 @@ if (!keyObjectSupported) {
switch (oid) {
case '1.2.840.10045.2.1': {
keyObject = new KeyObject()
i(keyObject).asn1 = parsed
i(keyObject).asymmetricKeyType = 'ec'
i(keyObject).type = 'public'
i(keyObject).pem = PublicKeyInfo.encode(parsed, 'pem', { label: 'PUBLIC KEY' })
keyObject._asn1 = parsed
keyObject._asymmetricKeyType = 'ec'
keyObject._type = 'public'
keyObject._pem = PublicKeyInfo.encode(parsed, 'pem', { label: 'PUBLIC KEY' })

break
}
Expand All @@ -333,10 +325,10 @@ if (!keyObjectSupported) {
const parsed = RSAPublicKey.decode(key, format, { label })

const keyObject = new KeyObject()
i(keyObject).asn1 = parsed
i(keyObject).asymmetricKeyType = 'rsa'
i(keyObject).type = 'public'
i(keyObject).pem = RSAPublicKey.encode(parsed, 'pem', { label: 'RSA PUBLIC KEY' })
keyObject._asn1 = parsed
keyObject._asymmetricKeyType = 'rsa'
keyObject._type = 'public'
keyObject._pem = RSAPublicKey.encode(parsed, 'pem', { label: 'RSA PUBLIC KEY' })

return keyObject
}
Expand Down Expand Up @@ -413,18 +405,18 @@ if (!keyObjectSupported) {
unsupported(oid)
}

i(keyObject).pkcs8 = key
keyObject._pkcs8 = key
return keyObject
}
case 'pkcs1': {
const RSAPrivateKey = asn1.get('RSAPrivateKey')
const parsed = RSAPrivateKey.decode(key, format, { label })

const keyObject = new KeyObject()
i(keyObject).asn1 = parsed
i(keyObject).asymmetricKeyType = 'rsa'
i(keyObject).type = 'private'
i(keyObject).pem = RSAPrivateKey.encode(parsed, 'pem', { label: 'RSA PRIVATE KEY' })
keyObject._asn1 = parsed
keyObject._asymmetricKeyType = 'rsa'
keyObject._type = 'private'
keyObject._pem = RSAPrivateKey.encode(parsed, 'pem', { label: 'RSA PRIVATE KEY' })

return keyObject
}
Expand All @@ -439,10 +431,10 @@ if (!keyObjectSupported) {
}

const keyObject = new KeyObject()
i(keyObject).asn1 = parsed
i(keyObject).asymmetricKeyType = 'ec'
i(keyObject).type = 'private'
i(keyObject).pem = ECPrivateKey.encode(parsed, 'pem', { label: 'EC PRIVATE KEY' })
keyObject._asn1 = parsed
keyObject._asymmetricKeyType = 'ec'
keyObject._type = 'private'
keyObject._pem = ECPrivateKey.encode(parsed, 'pem', { label: 'EC PRIVATE KEY' })

return keyObject
}
Expand Down
3 changes: 3 additions & 0 deletions lib/jwa/ecdsa.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ let sign, verify

if (dsaEncodingSupported) {
sign = (jwaAlg, nodeAlg, { [KEYOBJECT]: keyObject }, payload) => {
if (typeof payload === 'string') {
payload = Buffer.from(payload)
}
return signOneShot(nodeAlg, payload, { key: asInput(keyObject, false), dsaEncoding: 'ieee-p1363' })
}
verify = (jwaAlg, nodeAlg, { [KEYOBJECT]: keyObject }, payload, signature) => {
Expand Down
3 changes: 3 additions & 0 deletions lib/jwa/eddsa.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ const { KEYOBJECT } = require('../help/consts')
const { edDSASupported } = require('../help/runtime_support')

const sign = ({ [KEYOBJECT]: keyObject }, payload) => {
if (typeof payload === 'string') {
payload = Buffer.from(payload)
}
return signOneShot(undefined, payload, keyObject)
}

Expand Down
6 changes: 2 additions & 4 deletions lib/jwa/hmac.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@ const sign = (jwaAlg, hmacAlg, { [KEYOBJECT]: keyObject }, payload) => {
return hmac.digest()
}

const verify = (jwaAlg, hmacAlg, { [KEYOBJECT]: keyObject }, payload, signature) => {
const hmac = createHmac(hmacAlg, asInput(keyObject, false))
hmac.update(payload)
const expected = hmac.digest()
const verify = (jwaAlg, hmacAlg, key, payload, signature) => {
const expected = sign(jwaAlg, hmacAlg, key, payload)
const actual = signature

return timingSafeEqual(actual, expected)
Expand Down
Loading

0 comments on commit 3e3d7dd

Please sign in to comment.