Skip to content

Commit

Permalink
refactor: key keyObject property is private
Browse files Browse the repository at this point in the history
  • Loading branch information
panva committed Feb 28, 2019
1 parent ca4355b commit 4460c4c
Show file tree
Hide file tree
Showing 16 changed files with 47 additions and 40 deletions.
5 changes: 3 additions & 2 deletions lib/help/symbols.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
module.exports.THUMBPRINT_MATERIAL = Symbol('THUMBPRINT_MATERIAL')
module.exports.PUBLIC_MEMBERS = Symbol('PUBLIC_MEMBERS')
module.exports.KEYOBJECT = Symbol('KEYOBJECT')
module.exports.PRIVATE_MEMBERS = Symbol('PRIVATE_MEMBERS')
module.exports.PUBLIC_MEMBERS = Symbol('PUBLIC_MEMBERS')
module.exports.THUMBPRINT_MATERIAL = Symbol('THUMBPRINT_MATERIAL')
9 changes: 5 additions & 4 deletions lib/jwa/aes_cbc_hmac_sha2.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const { strict: assert } = require('assert')
const { JWEInvalid, JWEDecryptionFailed } = require('../errors')
const uint64be = require('../help/uint64be')
const timingSafeEqual = require('../help/timing_safe_equal')
const { KEYOBJECT } = require('../help/symbols')

const checkInput = function (size, iv, tag) {
if (iv.length !== 16) {
Expand All @@ -16,7 +17,7 @@ const checkInput = function (size, iv, tag) {
}
}

const encrypt = (size, sign, { keyObject }, cleartext, { iv, aad = Buffer.alloc(0) }) => {
const encrypt = (size, sign, { [KEYOBJECT]: keyObject }, cleartext, { iv, aad = Buffer.alloc(0) }) => {
const key = keyObject.export()
checkInput(size, iv)

Expand All @@ -27,12 +28,12 @@ const encrypt = (size, sign, { keyObject }, cleartext, { iv, aad = Buffer.alloc(
const macData = Buffer.concat([aad, iv, ciphertext, uint64be(aad.length * 8)])

const macKey = key.slice(0, keySize)
const tag = sign({ keyObject: macKey }, macData).slice(0, keySize)
const tag = sign({ [KEYOBJECT]: macKey }, macData).slice(0, keySize)

return { ciphertext, tag }
}

const decrypt = (size, sign, { keyObject }, ciphertext, { iv, tag = Buffer.alloc(0), aad = Buffer.alloc(0) }) => {
const decrypt = (size, sign, { [KEYOBJECT]: keyObject }, ciphertext, { iv, tag = Buffer.alloc(0), aad = Buffer.alloc(0) }) => {
checkInput(size, iv, tag)

const keySize = size / 8
Expand All @@ -41,7 +42,7 @@ const decrypt = (size, sign, { keyObject }, ciphertext, { iv, tag = Buffer.alloc
const macKey = key.slice(0, keySize)

const macData = Buffer.concat([aad, iv, ciphertext, uint64be(aad.length * 8)])
const expectedTag = sign({ keyObject: macKey }, macData, tag).slice(0, keySize)
const expectedTag = sign({ [KEYOBJECT]: macKey }, macData, tag).slice(0, keySize)
const macCheckPassed = timingSafeEqual(tag, expectedTag)

let cleartext
Expand Down
5 changes: 3 additions & 2 deletions lib/jwa/aes_gcm.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const { createCipheriv, createDecipheriv } = require('crypto')
const { strict: assert } = require('assert')
const { JWEInvalid, JWEDecryptionFailed } = require('../errors')
const { KEYOBJECT } = require('../help/symbols')

const checkInput = function (size, iv, tag) {
if (iv.length !== 12) {
Expand All @@ -13,7 +14,7 @@ const checkInput = function (size, iv, tag) {
}
}

const encrypt = (size, { keyObject }, cleartext, { iv, aad = Buffer.alloc(0) }) => {
const encrypt = (size, { [KEYOBJECT]: keyObject }, cleartext, { iv, aad = Buffer.alloc(0) }) => {
checkInput(size, iv)

const cipher = createCipheriv(`AES-${size}-GCM`, keyObject, iv)
Expand All @@ -25,7 +26,7 @@ const encrypt = (size, { keyObject }, cleartext, { iv, aad = Buffer.alloc(0) })
return { ciphertext, tag }
}

const decrypt = (size, { keyObject }, ciphertext, { iv, tag = Buffer.alloc(0), aad = Buffer.alloc(0) }) => {
const decrypt = (size, { [KEYOBJECT]: keyObject }, ciphertext, { iv, tag = Buffer.alloc(0), aad = Buffer.alloc(0) }) => {
checkInput(size, iv, tag)

try {
Expand Down
5 changes: 3 additions & 2 deletions lib/jwa/aes_kw.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const { createCipheriv, createDecipheriv } = require('crypto')
const { strict: assert } = require('assert')
const uint64be = require('../help/uint64be')
const timingSafeEqual = require('../help/timing_safe_equal')
const { KEYOBJECT } = require('../help/symbols')

const checkInput = (data) => {
if (data !== undefined && data.length % 8 !== 0) {
Expand Down Expand Up @@ -29,7 +30,7 @@ const split = (input, size) => {
return output
}

const wrapKey = (size, { keyObject }, payload) => {
const wrapKey = (size, { [KEYOBJECT]: keyObject }, payload) => {
const iv = Buffer.alloc(16)
let R = split(payload, 8)
let A
Expand All @@ -52,7 +53,7 @@ const wrapKey = (size, { keyObject }, payload) => {
return { wrapped: Buffer.concat(R) }
}

const unwrapKey = (size, { keyObject }, payload) => {
const unwrapKey = (size, { [KEYOBJECT]: keyObject }, payload) => {
checkInput(payload)

const iv = Buffer.alloc(16)
Expand Down
5 changes: 3 additions & 2 deletions lib/jwa/ecdh/kw.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ const { strict: assert } = require('assert')

const ECKey = require('../../jwk/key/ec')
const derive = require('./derive')
const { KEYOBJECT } = require('../../help/symbols')

const wrapKey = (wrap, derive, key, payload) => {
const epk = ECKey.generateSync(key.crv)

const derivedKey = derive(epk, key, payload)

const result = wrap({ keyObject: derivedKey }, payload)
const result = wrap({ [KEYOBJECT]: derivedKey }, payload)
result.header = { epk: { kty: 'EC', crv: key.crv, x: epk.x, y: epk.y } }

return result
Expand All @@ -17,7 +18,7 @@ const wrapKey = (wrap, derive, key, payload) => {
const unwrapKey = (unwrap, derive, key, payload, { apu, apv, epk }) => {
const derivedKey = derive(key, epk, { apu, apv })

return unwrap({ keyObject: derivedKey }, payload)
return unwrap({ [KEYOBJECT]: derivedKey }, payload)
}

module.exports = (JWA) => {
Expand Down
5 changes: 3 additions & 2 deletions lib/jwa/ecdsa.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const { createSign, createVerify } = require('crypto')
const { strict: assert } = require('assert')
const { derToJose, joseToDer } = require('../help/ecdsa_signatures')
const { KEYOBJECT } = require('../help/symbols')

const resolveNodeAlg = (alg) => {
switch (alg) {
Expand All @@ -13,13 +14,13 @@ const resolveNodeAlg = (alg) => {
}
}

const sign = (jwaAlg, nodeAlg, { keyObject }, payload) => {
const sign = (jwaAlg, nodeAlg, { [KEYOBJECT]: keyObject }, payload) => {
const sign = createSign(nodeAlg)
sign.update(payload)
return derToJose(sign.sign(keyObject), jwaAlg)
}

const verify = (jwaAlg, nodeAlg, { keyObject }, payload, signature) => {
const verify = (jwaAlg, nodeAlg, { [KEYOBJECT]: keyObject }, payload, signature) => {
const verify = createVerify(nodeAlg)
verify.update(payload)

Expand Down
5 changes: 3 additions & 2 deletions lib/jwa/hmac.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const { createHmac } = require('crypto')
const { strict: assert } = require('assert')
const { KEYOBJECT } = require('../help/symbols')

const timingSafeEqual = require('../help/timing_safe_equal')

Expand All @@ -14,13 +15,13 @@ const resolveHmacAlg = (alg) => {
}
}

const sign = (jwaAlg, hmacAlg, { keyObject }, payload) => {
const sign = (jwaAlg, hmacAlg, { [KEYOBJECT]: keyObject }, payload) => {
const hmac = createHmac(hmacAlg, keyObject)
hmac.update(payload)
return hmac.digest()
}

const verify = (jwaAlg, hmacAlg, { keyObject }, payload, signature) => {
const verify = (jwaAlg, hmacAlg, { [KEYOBJECT]: keyObject }, payload, signature) => {
const hmac = createHmac(hmacAlg, keyObject)
hmac.update(payload)
const expected = hmac.digest()
Expand Down
9 changes: 5 additions & 4 deletions lib/jwa/pbes2.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const { strict: assert } = require('assert')
const { pbkdf2Sync: pbkdf2, randomBytes } = require('crypto')
const { KEYOBJECT } = require('../help/symbols')

const base64url = require('../help/base64url')

Expand All @@ -14,7 +15,7 @@ const concatSalt = (alg, p2s) => {
])
}

const wrapKey = (keylen, sha, concat, wrap, { keyObject }, payload) => {
const wrapKey = (keylen, sha, concat, wrap, { [KEYOBJECT]: keyObject }, payload) => {
// Note that if password-based encryption is used for multiple
// recipients, it is expected that each recipient use different values
// for the PBES2 parameters "p2s" and "p2c".
Expand All @@ -25,16 +26,16 @@ const wrapKey = (keylen, sha, concat, wrap, { keyObject }, payload) => {

const derivedKey = pbkdf2(keyObject.export(), salt, p2c, keylen, sha)

const result = wrap({ keyObject: derivedKey }, payload)
const result = wrap({ [KEYOBJECT]: derivedKey }, payload)
result.header = { p2c, p2s: base64url.encode(p2s) }

return result
}

const unwrapKey = (keylen, sha, concat, unwrap, { keyObject }, payload, { p2c, p2s }) => {
const unwrapKey = (keylen, sha, concat, unwrap, { [KEYOBJECT]: keyObject }, payload, { p2c, p2s }) => {
const salt = concat(p2s)
const derivedKey = pbkdf2(keyObject.export(), salt, p2c, keylen, sha)
return unwrap({ keyObject: derivedKey }, payload)
return unwrap({ [KEYOBJECT]: derivedKey }, payload)
}

module.exports = (JWA) => {
Expand Down
5 changes: 3 additions & 2 deletions lib/jwa/rsaes.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const { strict: assert } = require('assert')
const { publicEncrypt, privateDecrypt, constants } = require('crypto')
const { KEYOBJECT } = require('../help/symbols')

const resolvePadding = (alg) => {
switch (alg) {
Expand All @@ -10,11 +11,11 @@ const resolvePadding = (alg) => {
}
}

const wrapKey = (padding, { keyObject }, payload) => {
const wrapKey = (padding, { [KEYOBJECT]: keyObject }, payload) => {
return { wrapped: publicEncrypt({ key: keyObject, padding }, payload) }
}

const unwrapKey = (padding, { keyObject }, payload) => {
const unwrapKey = (padding, { [KEYOBJECT]: keyObject }, payload) => {
return privateDecrypt({ key: keyObject, padding }, payload)
}

Expand Down
5 changes: 3 additions & 2 deletions lib/jwa/rsassa.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const { createSign, createVerify, constants } = require('crypto')
const { strict: assert } = require('assert')
const { KEYOBJECT } = require('../help/symbols')

const resolveNodeAlg = (alg) => {
switch (alg) {
Expand All @@ -23,13 +24,13 @@ const resolvePadding = (alg) => {
return constants.RSA_PKCS1_PSS_PADDING
}

const sign = (nodeAlg, padding, { keyObject }, payload) => {
const sign = (nodeAlg, padding, { [KEYOBJECT]: keyObject }, payload) => {
const sign = createSign(nodeAlg)
sign.update(payload)
return sign.sign({ key: keyObject, padding })
}

const verify = (nodeAlg, padding, { keyObject }, payload, signature) => {
const verify = (nodeAlg, padding, { [KEYOBJECT]: keyObject }, payload, signature) => {
const verify = createVerify(nodeAlg)
verify.update(payload)
return verify.verify({ key: keyObject, padding }, signature)
Expand Down
5 changes: 3 additions & 2 deletions lib/jwe/encrypt.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const { deflateRawSync } = require('zlib')
const serializers = require('./serializers')
const { JWEInvalid } = require('../errors')
const Key = require('../jwk/key/base')
const { KEYOBJECT } = require('../help/symbols')

const generateCEK = require('./generate_cek')
const generateIV = require('../help/generate_iv')
Expand Down Expand Up @@ -123,10 +124,10 @@ class Encrypt {
let direct

if (key.kty === 'oct' && alg === 'dir') {
this[CEK] = new OctKey(key.keyObject, { use: 'enc', alg: enc })
this[CEK] = new OctKey(key[KEYOBJECT], { use: 'enc', alg: enc })
wrapped = ''
} else {
({ wrapped, header: generatedHeader, direct } = wrapKey(alg, key, this[CEK].keyObject.export(), { enc, alg }))
({ wrapped, header: generatedHeader, direct } = wrapKey(alg, key, this[CEK][KEYOBJECT].export(), { enc, alg }))
if (direct) {
this[CEK] = new OctKey(createSecretKey(wrapped), { use: 'enc', alg: enc })
}
Expand Down
7 changes: 4 additions & 3 deletions lib/jwk/key/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ const { pemToJwk } = require('../../help/key_utils')
const thumbprint = require('../thumbprint')
const { THUMBPRINT_MATERIAL, PUBLIC_MEMBERS, PRIVATE_MEMBERS } = require('../../help/symbols')
const KeyObject = require('../../help/key_object')
const { KEYOBJECT } = require('../../help/symbols')

const USES = new Set(['sig', 'enc'])

const defineLazyComponents = (obj) => {
const props = obj.keyObject.type === 'private' ? obj.constructor[PRIVATE_MEMBERS] : obj.constructor[PUBLIC_MEMBERS]
const props = obj[KEYOBJECT].type === 'private' ? obj.constructor[PRIVATE_MEMBERS] : obj.constructor[PUBLIC_MEMBERS]
Object.defineProperties(obj, [...props].reduce((acc, component) => {
acc[component] = {
get () {
const jwk = pemToJwk(this.keyObject)
const jwk = pemToJwk(this[KEYOBJECT])
Object.defineProperties(
this,
Object.entries(jwk)
Expand Down Expand Up @@ -51,7 +52,7 @@ class Key {
}

Object.defineProperties(this, {
keyObject: { value: keyObject instanceof KeyObject ? keyObject : undefined },
[KEYOBJECT]: { value: keyObject instanceof KeyObject ? keyObject : undefined },
kty: { value: keyObject.type === 'secret' ? 'oct' : keyObject.asymmetricKeyType.toUpperCase(), enumerable: true },
private: { value: keyObject.type === 'private', enumerable: keyObject.type === 'private' },
public: { value: keyObject.type === 'public', enumerable: keyObject.type === 'public' },
Expand Down
11 changes: 6 additions & 5 deletions lib/jwk/key/oct.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const { randomBytes, createSecretKey } = require('crypto')

const Key = require('./base')
const base64url = require('../../help/base64url')
const { KEYOBJECT } = require('../../help/symbols')
const { THUMBPRINT_MATERIAL, PUBLIC_MEMBERS, PRIVATE_MEMBERS } = require('../../help/symbols')

const SIG_ALGS = new Set([
Expand Down Expand Up @@ -43,14 +44,14 @@ class OctKey extends Key {
super(...args)
Object.defineProperties(this, {
length: {
value: this.keyObject ? this.keyObject.symmetricKeySize * 8 : undefined
value: this[KEYOBJECT] ? this[KEYOBJECT].symmetricKeySize * 8 : undefined
},
k: {
enumerable: true,
get () {
if (this.keyObject) {
if (this[KEYOBJECT]) {
Object.defineProperty(this, 'k', {
value: base64url.encode(this.keyObject.export()),
value: base64url.encode(this[KEYOBJECT].export()),
configurable: false
})
} else {
Expand All @@ -76,14 +77,14 @@ class OctKey extends Key {
}

[THUMBPRINT_MATERIAL] () {
if (!this.keyObject) {
if (!this[KEYOBJECT]) {
throw new TypeError('reference "oct" keys without "k" cannot have their "kid" calculated')
}
return { k: this.k, kty: 'oct' }
}

algorithms (operation, { use = this.use, alg = this.alg } = {}) {
if (!this.keyObject) {
if (!this[KEYOBJECT]) {
return new Set()
}

Expand Down
2 changes: 0 additions & 2 deletions test/jwk/ec.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ Object.entries({
test(`${crv} EC Private key`, hasNoProperties, key, 'k', 'e', 'n', 'p', 'q', 'dp', 'dq', 'qi')
test(`${crv} EC Private key`, hasProperties, key, 'x', 'y', 'd')
test(`${crv} EC Private key`, hasProperty, key, 'alg', undefined)
test(`${crv} EC Private key`, hasProperty, key, 'keyObject', keyObject)
test(`${crv} EC Private key`, hasProperty, key, 'kid', kid)
test(`${crv} EC Private key`, hasProperty, key, 'kty', 'EC')
test(`${crv} EC Private key`, hasProperty, key, 'length', parseInt(crv.substr(2), 10))
Expand Down Expand Up @@ -153,7 +152,6 @@ Object.entries({
test(`${crv} EC Public key`, hasNoProperties, key, 'k', 'e', 'n', 'p', 'q', 'dp', 'dq', 'qi', 'd')
test(`${crv} EC Public key`, hasProperties, key, 'x', 'y')
test(`${crv} EC Public key`, hasProperty, key, 'alg', undefined)
test(`${crv} EC Public key`, hasProperty, key, 'keyObject', keyObject)
test(`${crv} EC Public key`, hasProperty, key, 'kid', kid)
test(`${crv} EC Public key`, hasProperty, key, 'kty', 'EC')
test(`${crv} EC Public key`, hasProperty, key, 'length', parseInt(crv.substr(2), 10))
Expand Down
2 changes: 0 additions & 2 deletions test/jwk/oct.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ test('oct key (with use)', hasProperty, new OctKey(keyObject, { use: 'sig' }), '
test('oct key', hasNoProperties, key, 'e', 'n', 'd', 'p', 'q', 'dp', 'dq', 'qi', 'crv', 'x', 'y')
test('oct key', hasProperty, key, 'alg', undefined)
test('oct key', hasProperty, key, 'k', 'c2VjcmV0')
test('oct key', hasProperty, key, 'keyObject', keyObject)
test('oct key', hasProperty, key, 'kid', 'DWBh0SEIAPYh1x5uvot4z3AhaikHkxNJa3Ada2fT-Cg')
test('oct key', hasProperty, key, 'kty', 'oct')
test('oct key', hasProperty, key, 'length', 48)
Expand Down Expand Up @@ -93,7 +92,6 @@ test('they may be imported from', t => {
kid: '4p9o4_DcKoT6Qg2BI_mSgMP_MsXwFqogKuI26CunKAM'
})

t.is(key.keyObject, undefined)
t.is(key.k, undefined)
t.false(key.private)
t.false(key.public)
Expand Down
2 changes: 0 additions & 2 deletions test/jwk/rsa.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ test(`RSA key .algorithms invalid operation`, t => {
test(`RSA Private key`, hasNoProperties, key, 'k', 'x', 'y')
test(`RSA Private key`, hasProperties, key, 'e', 'n', 'p', 'q', 'dp', 'dq', 'qi', 'd')
test(`RSA Private key`, hasProperty, key, 'alg', undefined)
test(`RSA Private key`, hasProperty, key, 'keyObject', keyObject)
test(`RSA Private key`, hasProperty, key, 'kid', 'Bj1ccHv-y_ZoejJKWhAhBHLpnGSlawNAQUAMEQBd5L8')
test(`RSA Private key`, hasProperty, key, 'kty', 'RSA')
test(`RSA Private key`, hasProperty, key, 'length', 2048)
Expand Down Expand Up @@ -146,7 +145,6 @@ test(`RSA key .algorithms invalid operation`, t => {
test(`RSA Public key`, hasNoProperties, key, 'k', 'x', 'y', 'd', 'p', 'q', 'dp', 'dq', 'qi')
test(`RSA Public key`, hasProperties, key, 'e', 'n')
test(`RSA Public key`, hasProperty, key, 'alg', undefined)
test(`RSA Public key`, hasProperty, key, 'keyObject', keyObject)
test(`RSA Public key`, hasProperty, key, 'kid', 'Bj1ccHv-y_ZoejJKWhAhBHLpnGSlawNAQUAMEQBd5L8')
test(`RSA Public key`, hasProperty, key, 'kty', 'RSA')
test(`RSA Public key`, hasProperty, key, 'length', 2048)
Expand Down

0 comments on commit 4460c4c

Please sign in to comment.