mirror of
https://github.com/danbulant/jose
synced 2026-05-24 12:35:36 +00:00
refactor: key instance detection refactor
This commit is contained in:
parent
26bdb732a5
commit
34d7f3fee7
12 changed files with 34 additions and 17 deletions
|
|
@ -3,5 +3,8 @@ import globalThis from './global.js'
|
||||||
export default globalThis.crypto
|
export default globalThis.crypto
|
||||||
|
|
||||||
export function isCryptoKey(key: unknown): key is CryptoKey {
|
export function isCryptoKey(key: unknown): key is CryptoKey {
|
||||||
return key instanceof globalThis.CryptoKey
|
if (typeof globalThis.CryptoKey === 'undefined') {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return key != null && key instanceof globalThis.CryptoKey
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import type { AesKwUnwrapFunction, AesKwWrapFunction } from '../interfaces.d'
|
||||||
import { concat } from '../../lib/buffer_utils.js'
|
import { concat } from '../../lib/buffer_utils.js'
|
||||||
import getSecretKey from './secret_key.js'
|
import getSecretKey from './secret_key.js'
|
||||||
import { isCryptoKey, getKeyObject } from './webcrypto.js'
|
import { isCryptoKey, getKeyObject } from './webcrypto.js'
|
||||||
|
import isKeyObject from './is_key_object.js'
|
||||||
|
|
||||||
function checkKeySize(key: KeyObject, alg: string) {
|
function checkKeySize(key: KeyObject, alg: string) {
|
||||||
if (key.symmetricKeySize! << 3 !== parseInt(alg.substr(1, 3), 10)) {
|
if (key.symmetricKeySize! << 3 !== parseInt(alg.substr(1, 3), 10)) {
|
||||||
|
|
@ -12,7 +13,7 @@ function checkKeySize(key: KeyObject, alg: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function ensureKeyObject(key: unknown, alg: string, usage: KeyUsage) {
|
function ensureKeyObject(key: unknown, alg: string, usage: KeyUsage) {
|
||||||
if (key instanceof KeyObject) {
|
if (isKeyObject(key)) {
|
||||||
return key
|
return key
|
||||||
}
|
}
|
||||||
if (key instanceof Uint8Array) {
|
if (key instanceof Uint8Array) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { KeyObject } from 'crypto'
|
import { KeyObject } from 'crypto'
|
||||||
import { JWEInvalid, JOSENotSupported } from '../../util/errors.js'
|
import { JWEInvalid, JOSENotSupported } from '../../util/errors.js'
|
||||||
|
import isKeyObject from './is_key_object.js'
|
||||||
|
|
||||||
const checkCekLength = (enc: string, cek: KeyObject | Uint8Array) => {
|
const checkCekLength = (enc: string, cek: KeyObject | Uint8Array) => {
|
||||||
let expected: number
|
let expected: number
|
||||||
|
|
@ -27,7 +28,7 @@ const checkCekLength = (enc: string, cek: KeyObject | Uint8Array) => {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cek instanceof KeyObject && cek.type === 'secret') {
|
if (isKeyObject(cek) && cek.type === 'secret') {
|
||||||
if (cek.symmetricKeySize! << 3 !== expected) {
|
if (cek.symmetricKeySize! << 3 !== expected) {
|
||||||
throw new JWEInvalid('Invalid Content Encryption Key length')
|
throw new JWEInvalid('Invalid Content Encryption Key length')
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import timingSafeEqual from './timing_safe_equal.js'
|
||||||
import cbcTag from './cbc_tag.js'
|
import cbcTag from './cbc_tag.js'
|
||||||
import { isCryptoKey, getKeyObject } from './webcrypto.js'
|
import { isCryptoKey, getKeyObject } from './webcrypto.js'
|
||||||
import type { KeyLike } from '../../types.d'
|
import type { KeyLike } from '../../types.d'
|
||||||
|
import isKeyObject from './is_key_object.js'
|
||||||
|
|
||||||
async function cbcDecrypt(
|
async function cbcDecrypt(
|
||||||
enc: string,
|
enc: string,
|
||||||
|
|
@ -21,7 +22,7 @@ async function cbcDecrypt(
|
||||||
) {
|
) {
|
||||||
const keySize = parseInt(enc.substr(1, 3), 10)
|
const keySize = parseInt(enc.substr(1, 3), 10)
|
||||||
|
|
||||||
if (cek instanceof KeyObject) {
|
if (isKeyObject(cek)) {
|
||||||
// eslint-disable-next-line no-param-reassign
|
// eslint-disable-next-line no-param-reassign
|
||||||
cek = cek.export()
|
cek = cek.export()
|
||||||
}
|
}
|
||||||
|
|
@ -99,7 +100,7 @@ const decrypt: DecryptFunction = async (
|
||||||
if (isCryptoKey(cek)) {
|
if (isCryptoKey(cek)) {
|
||||||
// eslint-disable-next-line no-param-reassign
|
// eslint-disable-next-line no-param-reassign
|
||||||
key = getKeyObject(cek, enc, new Set(['decrypt']))
|
key = getKeyObject(cek, enc, new Set(['decrypt']))
|
||||||
} else if (cek instanceof Uint8Array || cek instanceof KeyObject) {
|
} else if (cek instanceof Uint8Array || isKeyObject(cek)) {
|
||||||
key = cek
|
key = cek
|
||||||
} else {
|
} else {
|
||||||
throw new TypeError('invalid key input')
|
throw new TypeError('invalid key input')
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { KeyObject, diffieHellman, generateKeyPair as generateKeyPairCb } from 'crypto'
|
import { diffieHellman, generateKeyPair as generateKeyPairCb } from 'crypto'
|
||||||
import { promisify } from 'util'
|
import { promisify } from 'util'
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
|
|
@ -11,6 +11,7 @@ import { encoder, concat, uint32be, lengthAndInput, concatKdf } from '../../lib/
|
||||||
import digest from './digest.js'
|
import digest from './digest.js'
|
||||||
import { JOSENotSupported } from '../../util/errors.js'
|
import { JOSENotSupported } from '../../util/errors.js'
|
||||||
import { isCryptoKey, getKeyObject } from './webcrypto.js'
|
import { isCryptoKey, getKeyObject } from './webcrypto.js'
|
||||||
|
import isKeyObject from './is_key_object.js'
|
||||||
|
|
||||||
const generateKeyPair = promisify(generateKeyPairCb)
|
const generateKeyPair = promisify(generateKeyPairCb)
|
||||||
|
|
||||||
|
|
@ -33,7 +34,7 @@ export const deriveKey: EcdhESDeriveKeyFunction = async (
|
||||||
// eslint-disable-next-line no-param-reassign
|
// eslint-disable-next-line no-param-reassign
|
||||||
publicKey = getKeyObject(publicKey, 'ECDH-ES')
|
publicKey = getKeyObject(publicKey, 'ECDH-ES')
|
||||||
}
|
}
|
||||||
if (!(publicKey instanceof KeyObject)) {
|
if (!isKeyObject(publicKey)) {
|
||||||
throw new TypeError('invalid key input')
|
throw new TypeError('invalid key input')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -41,7 +42,7 @@ export const deriveKey: EcdhESDeriveKeyFunction = async (
|
||||||
// eslint-disable-next-line no-param-reassign
|
// eslint-disable-next-line no-param-reassign
|
||||||
privateKey = getKeyObject(privateKey, 'ECDH-ES', new Set(['deriveBits', 'deriveKey']))
|
privateKey = getKeyObject(privateKey, 'ECDH-ES', new Set(['deriveBits', 'deriveKey']))
|
||||||
}
|
}
|
||||||
if (!(privateKey instanceof KeyObject)) {
|
if (!isKeyObject(privateKey)) {
|
||||||
throw new TypeError('invalid key input')
|
throw new TypeError('invalid key input')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -54,7 +55,7 @@ export const generateEpk: GenerateEpkFunction = async (key: unknown) => {
|
||||||
// eslint-disable-next-line no-param-reassign
|
// eslint-disable-next-line no-param-reassign
|
||||||
key = getKeyObject(key)
|
key = getKeyObject(key)
|
||||||
}
|
}
|
||||||
if (!(key instanceof KeyObject)) {
|
if (!isKeyObject(key)) {
|
||||||
throw new TypeError('invalid key input')
|
throw new TypeError('invalid key input')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import { concat } from '../../lib/buffer_utils.js'
|
||||||
import cbcTag from './cbc_tag.js'
|
import cbcTag from './cbc_tag.js'
|
||||||
import type { KeyLike } from '../../types.d'
|
import type { KeyLike } from '../../types.d'
|
||||||
import { isCryptoKey, getKeyObject } from './webcrypto.js'
|
import { isCryptoKey, getKeyObject } from './webcrypto.js'
|
||||||
|
import isKeyObject from './is_key_object.js'
|
||||||
|
|
||||||
async function cbcEncrypt(
|
async function cbcEncrypt(
|
||||||
enc: string,
|
enc: string,
|
||||||
|
|
@ -18,7 +19,7 @@ async function cbcEncrypt(
|
||||||
) {
|
) {
|
||||||
const keySize = parseInt(enc.substr(1, 3), 10)
|
const keySize = parseInt(enc.substr(1, 3), 10)
|
||||||
|
|
||||||
if (cek instanceof KeyObject) {
|
if (isKeyObject(cek)) {
|
||||||
// eslint-disable-next-line no-param-reassign
|
// eslint-disable-next-line no-param-reassign
|
||||||
cek = cek.export()
|
cek = cek.export()
|
||||||
}
|
}
|
||||||
|
|
@ -67,7 +68,7 @@ const encrypt: EncryptFunction = async (
|
||||||
if (isCryptoKey(cek)) {
|
if (isCryptoKey(cek)) {
|
||||||
// eslint-disable-next-line no-param-reassign
|
// eslint-disable-next-line no-param-reassign
|
||||||
key = getKeyObject(cek, enc, new Set(['encrypt']))
|
key = getKeyObject(cek, enc, new Set(['encrypt']))
|
||||||
} else if (cek instanceof Uint8Array || cek instanceof KeyObject) {
|
} else if (cek instanceof Uint8Array || isKeyObject(cek)) {
|
||||||
key = cek
|
key = cek
|
||||||
} else {
|
} else {
|
||||||
throw new TypeError('invalid key input')
|
throw new TypeError('invalid key input')
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { KeyObject, createPublicKey } from 'crypto'
|
import { KeyObject, createPublicKey } from 'crypto'
|
||||||
import { JOSENotSupported } from '../../util/errors.js'
|
import { JOSENotSupported } from '../../util/errors.js'
|
||||||
import { isCryptoKey, getKeyObject } from './webcrypto.js'
|
import { isCryptoKey, getKeyObject } from './webcrypto.js'
|
||||||
|
import isKeyObject from './is_key_object.js'
|
||||||
|
|
||||||
const p256 = Buffer.from([42, 134, 72, 206, 61, 3, 1, 7])
|
const p256 = Buffer.from([42, 134, 72, 206, 61, 3, 1, 7])
|
||||||
const p384 = Buffer.from([43, 129, 4, 0, 34])
|
const p384 = Buffer.from([43, 129, 4, 0, 34])
|
||||||
|
|
@ -29,7 +30,7 @@ const getNamedCurve = (key: unknown, raw?: boolean): string => {
|
||||||
// eslint-disable-next-line no-param-reassign
|
// eslint-disable-next-line no-param-reassign
|
||||||
key = getKeyObject(key)
|
key = getKeyObject(key)
|
||||||
}
|
}
|
||||||
if (!(key instanceof KeyObject)) {
|
if (!isKeyObject(key)) {
|
||||||
throw new TypeError('invalid key input')
|
throw new TypeError('invalid key input')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
5
src/runtime/node/is_key_object.ts
Normal file
5
src/runtime/node/is_key_object.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
import { KeyObject } from 'crypto'
|
||||||
|
|
||||||
|
export default function isKeyObject(obj: unknown): obj is KeyObject {
|
||||||
|
return obj != null && obj instanceof KeyObject
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,7 @@ import Asn1SequenceDecoder from './asn1_sequence_decoder.js'
|
||||||
import { JOSENotSupported } from '../../util/errors.js'
|
import { JOSENotSupported } from '../../util/errors.js'
|
||||||
import getNamedCurve from './get_named_curve.js'
|
import getNamedCurve from './get_named_curve.js'
|
||||||
import { isCryptoKey, getKeyObject } from './webcrypto.js'
|
import { isCryptoKey, getKeyObject } from './webcrypto.js'
|
||||||
|
import isKeyObject from './is_key_object.js'
|
||||||
|
|
||||||
const [major, minor] = process.version
|
const [major, minor] = process.version
|
||||||
.substr(1)
|
.substr(1)
|
||||||
|
|
@ -21,7 +22,7 @@ const keyToJWK: JWKConvertFunction = (key: unknown): JWK => {
|
||||||
throw new TypeError('CryptoKey is not extractable')
|
throw new TypeError('CryptoKey is not extractable')
|
||||||
}
|
}
|
||||||
keyObject = getKeyObject(key)
|
keyObject = getKeyObject(key)
|
||||||
} else if (key instanceof KeyObject) {
|
} else if (isKeyObject(key)) {
|
||||||
keyObject = key
|
keyObject = key
|
||||||
} else {
|
} else {
|
||||||
throw new TypeError('invalid key input')
|
throw new TypeError('invalid key input')
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { promisify } from 'util'
|
import { promisify } from 'util'
|
||||||
import { KeyObject, pbkdf2 as pbkdf2cb } from 'crypto'
|
import { pbkdf2 as pbkdf2cb } from 'crypto'
|
||||||
import type { Pbes2KWDecryptFunction, Pbes2KWEncryptFunction } from '../interfaces.d'
|
import type { Pbes2KWDecryptFunction, Pbes2KWEncryptFunction } from '../interfaces.d'
|
||||||
import random from './random.js'
|
import random from './random.js'
|
||||||
import { p2s as concatSalt } from '../../lib/buffer_utils.js'
|
import { p2s as concatSalt } from '../../lib/buffer_utils.js'
|
||||||
|
|
@ -7,11 +7,12 @@ import { encode as base64url } from './base64url.js'
|
||||||
import { wrap, unwrap } from './aeskw.js'
|
import { wrap, unwrap } from './aeskw.js'
|
||||||
import checkP2s from '../../lib/check_p2s.js'
|
import checkP2s from '../../lib/check_p2s.js'
|
||||||
import { isCryptoKey, getKeyObject } from './webcrypto.js'
|
import { isCryptoKey, getKeyObject } from './webcrypto.js'
|
||||||
|
import isKeyObject from './is_key_object.js'
|
||||||
|
|
||||||
const pbkdf2 = promisify(pbkdf2cb)
|
const pbkdf2 = promisify(pbkdf2cb)
|
||||||
|
|
||||||
function getPassword(key: unknown, alg: string) {
|
function getPassword(key: unknown, alg: string) {
|
||||||
if (key instanceof KeyObject) {
|
if (isKeyObject(key)) {
|
||||||
return key.export()
|
return key.export()
|
||||||
}
|
}
|
||||||
if (key instanceof Uint8Array) {
|
if (key instanceof Uint8Array) {
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import { KeyObject, publicEncrypt, constants, privateDecrypt } from 'crypto'
|
||||||
import type { RsaEsDecryptFunction, RsaEsEncryptFunction } from '../interfaces.d'
|
import type { RsaEsDecryptFunction, RsaEsEncryptFunction } from '../interfaces.d'
|
||||||
import checkModulusLength from './check_modulus_length.js'
|
import checkModulusLength from './check_modulus_length.js'
|
||||||
import { isCryptoKey, getKeyObject } from './webcrypto.js'
|
import { isCryptoKey, getKeyObject } from './webcrypto.js'
|
||||||
|
import isKeyObject from './is_key_object.js'
|
||||||
|
|
||||||
const checkKey = (key: KeyObject, alg: string) => {
|
const checkKey = (key: KeyObject, alg: string) => {
|
||||||
if (key.type === 'secret' || key.asymmetricKeyType !== 'rsa') {
|
if (key.type === 'secret' || key.asymmetricKeyType !== 'rsa') {
|
||||||
|
|
@ -40,7 +41,7 @@ const resolveOaepHash = (alg: string) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
function ensureKeyObject(key: unknown, alg: string, ...usages: KeyUsage[]) {
|
function ensureKeyObject(key: unknown, alg: string, ...usages: KeyUsage[]) {
|
||||||
if (key instanceof KeyObject) {
|
if (isKeyObject(key)) {
|
||||||
return key
|
return key
|
||||||
}
|
}
|
||||||
if (isCryptoKey(key)) {
|
if (isCryptoKey(key)) {
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ export default webcrypto
|
||||||
export function isCryptoKey(key: unknown): key is CryptoKey {
|
export function isCryptoKey(key: unknown): key is CryptoKey {
|
||||||
if (webcrypto !== undefined) {
|
if (webcrypto !== undefined) {
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
return key instanceof webcrypto.CryptoKey
|
return key != null && key instanceof webcrypto.CryptoKey
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue