Add node modules and compiled JavaScript from main (#54)
Co-authored-by: Oliver King <oking3@uncc.edu>
This commit is contained in:
committed by
GitHub
parent
4a983766a0
commit
52d71d28bd
8
node_modules/jose/lib/help/asn1/algorithm_identifier.js
generated
vendored
Normal file
8
node_modules/jose/lib/help/asn1/algorithm_identifier.js
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
const oids = require('./oids')
|
||||
|
||||
module.exports = function () {
|
||||
this.seq().obj(
|
||||
this.key('algorithm').objid(oids),
|
||||
this.key('parameters').optional().choice({ namedCurve: this.objid(oids), null: this.null_() })
|
||||
)
|
||||
}
|
10
node_modules/jose/lib/help/asn1/ec_private_key.js
generated
vendored
Normal file
10
node_modules/jose/lib/help/asn1/ec_private_key.js
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
const oids = require('./oids')
|
||||
|
||||
module.exports = function () {
|
||||
this.seq().obj(
|
||||
this.key('version').int(),
|
||||
this.key('privateKey').octstr(),
|
||||
this.key('parameters').explicit(0).optional().choice({ namedCurve: this.objid(oids) }),
|
||||
this.key('publicKey').explicit(1).optional().bitstr()
|
||||
)
|
||||
}
|
29
node_modules/jose/lib/help/asn1/index.js
generated
vendored
Normal file
29
node_modules/jose/lib/help/asn1/index.js
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
const asn1 = require('@panva/asn1.js')
|
||||
|
||||
const types = new Map()
|
||||
|
||||
const AlgorithmIdentifier = asn1.define('AlgorithmIdentifier', require('./algorithm_identifier'))
|
||||
types.set('AlgorithmIdentifier', AlgorithmIdentifier)
|
||||
|
||||
const ECPrivateKey = asn1.define('ECPrivateKey', require('./ec_private_key'))
|
||||
types.set('ECPrivateKey', ECPrivateKey)
|
||||
|
||||
const PrivateKeyInfo = asn1.define('PrivateKeyInfo', require('./private_key_info')(AlgorithmIdentifier))
|
||||
types.set('PrivateKeyInfo', PrivateKeyInfo)
|
||||
|
||||
const PublicKeyInfo = asn1.define('PublicKeyInfo', require('./public_key_info')(AlgorithmIdentifier))
|
||||
types.set('PublicKeyInfo', PublicKeyInfo)
|
||||
|
||||
const PrivateKey = asn1.define('PrivateKey', require('./private_key'))
|
||||
types.set('PrivateKey', PrivateKey)
|
||||
|
||||
const OneAsymmetricKey = asn1.define('OneAsymmetricKey', require('./one_asymmetric_key')(AlgorithmIdentifier, PrivateKey))
|
||||
types.set('OneAsymmetricKey', OneAsymmetricKey)
|
||||
|
||||
const RSAPrivateKey = asn1.define('RSAPrivateKey', require('./rsa_private_key'))
|
||||
types.set('RSAPrivateKey', RSAPrivateKey)
|
||||
|
||||
const RSAPublicKey = asn1.define('RSAPublicKey', require('./rsa_public_key'))
|
||||
types.set('RSAPublicKey', RSAPublicKey)
|
||||
|
||||
module.exports = types
|
14
node_modules/jose/lib/help/asn1/oids.js
generated
vendored
Normal file
14
node_modules/jose/lib/help/asn1/oids.js
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
const oids = {
|
||||
'1 2 840 10045 3 1 7': 'P-256',
|
||||
'1 3 132 0 10': 'secp256k1',
|
||||
'1 3 132 0 34': 'P-384',
|
||||
'1 3 132 0 35': 'P-521',
|
||||
'1 2 840 10045 2 1': 'ecPublicKey',
|
||||
'1 2 840 113549 1 1 1': 'rsaEncryption',
|
||||
'1 3 101 110': 'X25519',
|
||||
'1 3 101 111': 'X448',
|
||||
'1 3 101 112': 'Ed25519',
|
||||
'1 3 101 113': 'Ed448'
|
||||
}
|
||||
|
||||
module.exports = oids
|
7
node_modules/jose/lib/help/asn1/one_asymmetric_key.js
generated
vendored
Normal file
7
node_modules/jose/lib/help/asn1/one_asymmetric_key.js
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
module.exports = (AlgorithmIdentifier, PrivateKey) => function () {
|
||||
this.seq().obj(
|
||||
this.key('version').int(),
|
||||
this.key('algorithm').use(AlgorithmIdentifier),
|
||||
this.key('privateKey').use(PrivateKey)
|
||||
)
|
||||
}
|
5
node_modules/jose/lib/help/asn1/private_key.js
generated
vendored
Normal file
5
node_modules/jose/lib/help/asn1/private_key.js
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
module.exports = function () {
|
||||
this.octstr().contains().obj(
|
||||
this.key('privateKey').octstr()
|
||||
)
|
||||
}
|
7
node_modules/jose/lib/help/asn1/private_key_info.js
generated
vendored
Normal file
7
node_modules/jose/lib/help/asn1/private_key_info.js
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
module.exports = (AlgorithmIdentifier) => function () {
|
||||
this.seq().obj(
|
||||
this.key('version').int(),
|
||||
this.key('algorithm').use(AlgorithmIdentifier),
|
||||
this.key('privateKey').octstr()
|
||||
)
|
||||
}
|
6
node_modules/jose/lib/help/asn1/public_key_info.js
generated
vendored
Normal file
6
node_modules/jose/lib/help/asn1/public_key_info.js
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
module.exports = AlgorithmIdentifier => function () {
|
||||
this.seq().obj(
|
||||
this.key('algorithm').use(AlgorithmIdentifier),
|
||||
this.key('publicKey').bitstr()
|
||||
)
|
||||
}
|
13
node_modules/jose/lib/help/asn1/rsa_private_key.js
generated
vendored
Normal file
13
node_modules/jose/lib/help/asn1/rsa_private_key.js
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
module.exports = function () {
|
||||
this.seq().obj(
|
||||
this.key('version').int({ 0: 'two-prime', 1: 'multi' }),
|
||||
this.key('n').int(),
|
||||
this.key('e').int(),
|
||||
this.key('d').int(),
|
||||
this.key('p').int(),
|
||||
this.key('q').int(),
|
||||
this.key('dp').int(),
|
||||
this.key('dq').int(),
|
||||
this.key('qi').int()
|
||||
)
|
||||
}
|
6
node_modules/jose/lib/help/asn1/rsa_public_key.js
generated
vendored
Normal file
6
node_modules/jose/lib/help/asn1/rsa_public_key.js
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
module.exports = function () {
|
||||
this.seq().obj(
|
||||
this.key('n').int(),
|
||||
this.key('e').int()
|
||||
)
|
||||
}
|
64
node_modules/jose/lib/help/base64url.js
generated
vendored
Normal file
64
node_modules/jose/lib/help/base64url.js
generated
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
let encode
|
||||
let encodeBuffer
|
||||
if (Buffer.isEncoding('base64url')) {
|
||||
encode = (input, encoding = 'utf8') => Buffer.from(input, encoding).toString('base64url')
|
||||
encodeBuffer = (buf) => buf.toString('base64url')
|
||||
} else {
|
||||
const fromBase64 = (base64) => base64.replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_')
|
||||
encode = (input, encoding = 'utf8') => fromBase64(Buffer.from(input, encoding).toString('base64'))
|
||||
encodeBuffer = (buf) => fromBase64(buf.toString('base64'))
|
||||
}
|
||||
|
||||
const decodeToBuffer = (input) => {
|
||||
return Buffer.from(input, 'base64')
|
||||
}
|
||||
|
||||
const decode = (input, encoding = 'utf8') => {
|
||||
return decodeToBuffer(input).toString(encoding)
|
||||
}
|
||||
|
||||
const b64uJSON = {
|
||||
encode: (input) => {
|
||||
return encode(JSON.stringify(input))
|
||||
},
|
||||
decode: (input, encoding = 'utf8') => {
|
||||
return JSON.parse(decode(input, encoding))
|
||||
}
|
||||
}
|
||||
|
||||
b64uJSON.decode.try = (input, encoding = 'utf8') => {
|
||||
try {
|
||||
return b64uJSON.decode(input, encoding)
|
||||
} catch (err) {
|
||||
return decode(input, encoding)
|
||||
}
|
||||
}
|
||||
|
||||
const bnToBuf = (bn) => {
|
||||
let hex = BigInt(bn).toString(16)
|
||||
if (hex.length % 2) {
|
||||
hex = `0${hex}`
|
||||
}
|
||||
|
||||
const len = hex.length / 2
|
||||
const u8 = new Uint8Array(len)
|
||||
|
||||
let i = 0
|
||||
let j = 0
|
||||
while (i < len) {
|
||||
u8[i] = parseInt(hex.slice(j, j + 2), 16)
|
||||
i += 1
|
||||
j += 2
|
||||
}
|
||||
|
||||
return u8
|
||||
}
|
||||
|
||||
const encodeBigInt = (bn) => encodeBuffer(Buffer.from(bnToBuf(bn)))
|
||||
|
||||
module.exports.decode = decode
|
||||
module.exports.decodeToBuffer = decodeToBuffer
|
||||
module.exports.encode = encode
|
||||
module.exports.encodeBuffer = encodeBuffer
|
||||
module.exports.JSON = b64uJSON
|
||||
module.exports.encodeBigInt = encodeBigInt
|
18
node_modules/jose/lib/help/consts.js
generated
vendored
Normal file
18
node_modules/jose/lib/help/consts.js
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
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')
|
||||
module.exports.JWK_MEMBERS = Symbol('JWK_MEMBERS')
|
||||
module.exports.KEY_MANAGEMENT_ENCRYPT = Symbol('KEY_MANAGEMENT_ENCRYPT')
|
||||
module.exports.KEY_MANAGEMENT_DECRYPT = Symbol('KEY_MANAGEMENT_DECRYPT')
|
||||
|
||||
const USES_MAPPING = {
|
||||
sig: new Set(['sign', 'verify']),
|
||||
enc: new Set(['encrypt', 'decrypt', 'wrapKey', 'unwrapKey', 'deriveKey'])
|
||||
}
|
||||
const OPS = new Set([...USES_MAPPING.sig, ...USES_MAPPING.enc])
|
||||
const USES = new Set(Object.keys(USES_MAPPING))
|
||||
|
||||
module.exports.USES_MAPPING = USES_MAPPING
|
||||
module.exports.OPS = OPS
|
||||
module.exports.USES = USES
|
1
node_modules/jose/lib/help/deep_clone.js
generated
vendored
Normal file
1
node_modules/jose/lib/help/deep_clone.js
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
module.exports = obj => JSON.parse(JSON.stringify(obj))
|
180
node_modules/jose/lib/help/ecdsa_signatures.js
generated
vendored
Normal file
180
node_modules/jose/lib/help/ecdsa_signatures.js
generated
vendored
Normal file
@ -0,0 +1,180 @@
|
||||
const MAX_OCTET = 0x80
|
||||
const CLASS_UNIVERSAL = 0
|
||||
const PRIMITIVE_BIT = 0x20
|
||||
const TAG_SEQ = 0x10
|
||||
const TAG_INT = 0x02
|
||||
const ENCODED_TAG_SEQ = (TAG_SEQ | PRIMITIVE_BIT) | (CLASS_UNIVERSAL << 6)
|
||||
const ENCODED_TAG_INT = TAG_INT | (CLASS_UNIVERSAL << 6)
|
||||
|
||||
const getParamSize = keySize => ((keySize / 8) | 0) + (keySize % 8 === 0 ? 0 : 1)
|
||||
|
||||
const paramBytesForAlg = {
|
||||
ES256: getParamSize(256),
|
||||
ES256K: getParamSize(256),
|
||||
ES384: getParamSize(384),
|
||||
ES512: getParamSize(521)
|
||||
}
|
||||
|
||||
const countPadding = (buf, start, stop) => {
|
||||
let padding = 0
|
||||
while (start + padding < stop && buf[start + padding] === 0) {
|
||||
++padding
|
||||
}
|
||||
|
||||
const needsSign = buf[start + padding] >= MAX_OCTET
|
||||
if (needsSign) {
|
||||
--padding
|
||||
}
|
||||
|
||||
return padding
|
||||
}
|
||||
|
||||
module.exports.derToJose = (signature, alg) => {
|
||||
if (!Buffer.isBuffer(signature)) {
|
||||
throw new TypeError('ECDSA signature must be a Buffer')
|
||||
}
|
||||
|
||||
if (!paramBytesForAlg[alg]) {
|
||||
throw new Error(`Unknown algorithm "${alg}"`)
|
||||
}
|
||||
|
||||
const paramBytes = paramBytesForAlg[alg]
|
||||
|
||||
// the DER encoded param should at most be the param size, plus a padding
|
||||
// zero, since due to being a signed integer
|
||||
const maxEncodedParamLength = paramBytes + 1
|
||||
|
||||
const inputLength = signature.length
|
||||
|
||||
let offset = 0
|
||||
if (signature[offset++] !== ENCODED_TAG_SEQ) {
|
||||
throw new Error('Could not find expected "seq"')
|
||||
}
|
||||
|
||||
let seqLength = signature[offset++]
|
||||
if (seqLength === (MAX_OCTET | 1)) {
|
||||
seqLength = signature[offset++]
|
||||
}
|
||||
|
||||
if (inputLength - offset < seqLength) {
|
||||
throw new Error(`"seq" specified length of ${seqLength}", only ${inputLength - offset}" remaining`)
|
||||
}
|
||||
|
||||
if (signature[offset++] !== ENCODED_TAG_INT) {
|
||||
throw new Error('Could not find expected "int" for "r"')
|
||||
}
|
||||
|
||||
const rLength = signature[offset++]
|
||||
|
||||
if (inputLength - offset - 2 < rLength) {
|
||||
throw new Error(`"r" specified length of "${rLength}", only "${inputLength - offset - 2}" available`)
|
||||
}
|
||||
|
||||
if (maxEncodedParamLength < rLength) {
|
||||
throw new Error(`"r" specified length of "${rLength}", max of "${maxEncodedParamLength}" is acceptable`)
|
||||
}
|
||||
|
||||
const rOffset = offset
|
||||
offset += rLength
|
||||
|
||||
if (signature[offset++] !== ENCODED_TAG_INT) {
|
||||
throw new Error('Could not find expected "int" for "s"')
|
||||
}
|
||||
|
||||
const sLength = signature[offset++]
|
||||
|
||||
if (inputLength - offset !== sLength) {
|
||||
throw new Error(`"s" specified length of "${sLength}", expected "${inputLength - offset}"`)
|
||||
}
|
||||
|
||||
if (maxEncodedParamLength < sLength) {
|
||||
throw new Error(`"s" specified length of "${sLength}", max of "${maxEncodedParamLength}" is acceptable`)
|
||||
}
|
||||
|
||||
const sOffset = offset
|
||||
offset += sLength
|
||||
|
||||
if (offset !== inputLength) {
|
||||
throw new Error(`Expected to consume entire buffer, but "${inputLength - offset}" bytes remain`)
|
||||
}
|
||||
|
||||
const rPadding = paramBytes - rLength
|
||||
|
||||
const sPadding = paramBytes - sLength
|
||||
|
||||
const dst = Buffer.allocUnsafe(rPadding + rLength + sPadding + sLength)
|
||||
|
||||
for (offset = 0; offset < rPadding; ++offset) {
|
||||
dst[offset] = 0
|
||||
}
|
||||
signature.copy(dst, offset, rOffset + Math.max(-rPadding, 0), rOffset + rLength)
|
||||
|
||||
offset = paramBytes
|
||||
|
||||
for (const o = offset; offset < o + sPadding; ++offset) {
|
||||
dst[offset] = 0
|
||||
}
|
||||
signature.copy(dst, offset, sOffset + Math.max(-sPadding, 0), sOffset + sLength)
|
||||
|
||||
return dst
|
||||
}
|
||||
|
||||
module.exports.joseToDer = (signature, alg) => {
|
||||
if (!Buffer.isBuffer(signature)) {
|
||||
throw new TypeError('ECDSA signature must be a Buffer')
|
||||
}
|
||||
|
||||
if (!paramBytesForAlg[alg]) {
|
||||
throw new TypeError(`Unknown algorithm "${alg}"`)
|
||||
}
|
||||
|
||||
const paramBytes = paramBytesForAlg[alg]
|
||||
|
||||
const signatureBytes = signature.length
|
||||
if (signatureBytes !== paramBytes * 2) {
|
||||
throw new Error(`"${alg}" signatures must be "${paramBytes * 2}" bytes, saw "${signatureBytes}"`)
|
||||
}
|
||||
|
||||
const rPadding = countPadding(signature, 0, paramBytes)
|
||||
const sPadding = countPadding(signature, paramBytes, signature.length)
|
||||
const rLength = paramBytes - rPadding
|
||||
const sLength = paramBytes - sPadding
|
||||
|
||||
const rsBytes = 1 + 1 + rLength + 1 + 1 + sLength
|
||||
|
||||
const shortLength = rsBytes < MAX_OCTET
|
||||
|
||||
const dst = Buffer.allocUnsafe((shortLength ? 2 : 3) + rsBytes)
|
||||
|
||||
let offset = 0
|
||||
dst[offset++] = ENCODED_TAG_SEQ
|
||||
if (shortLength) {
|
||||
// Bit 8 has value "0"
|
||||
// bits 7-1 give the length.
|
||||
dst[offset++] = rsBytes
|
||||
} else {
|
||||
// Bit 8 of first octet has value "1"
|
||||
// bits 7-1 give the number of additional length octets.
|
||||
dst[offset++] = MAX_OCTET | 1 // eslint-disable-line no-tabs
|
||||
// length, base 256
|
||||
dst[offset++] = rsBytes & 0xff
|
||||
}
|
||||
dst[offset++] = ENCODED_TAG_INT
|
||||
dst[offset++] = rLength
|
||||
if (rPadding < 0) {
|
||||
dst[offset++] = 0
|
||||
offset += signature.copy(dst, offset, 0, paramBytes)
|
||||
} else {
|
||||
offset += signature.copy(dst, offset, rPadding, paramBytes)
|
||||
}
|
||||
dst[offset++] = ENCODED_TAG_INT
|
||||
dst[offset++] = sLength
|
||||
if (sPadding < 0) {
|
||||
dst[offset++] = 0
|
||||
signature.copy(dst, offset, paramBytes)
|
||||
} else {
|
||||
signature.copy(dst, offset, paramBytes + sPadding)
|
||||
}
|
||||
|
||||
return dst
|
||||
}
|
1
node_modules/jose/lib/help/epoch.js
generated
vendored
Normal file
1
node_modules/jose/lib/help/epoch.js
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
module.exports = (date) => Math.floor(date.getTime() / 1000)
|
5
node_modules/jose/lib/help/generate_iv.js
generated
vendored
Normal file
5
node_modules/jose/lib/help/generate_iv.js
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
const { randomBytes } = require('crypto')
|
||||
|
||||
const { IVLENGTHS } = require('../registry')
|
||||
|
||||
module.exports = alg => randomBytes(IVLENGTHS.get(alg) / 8)
|
35
node_modules/jose/lib/help/get_key.js
generated
vendored
Normal file
35
node_modules/jose/lib/help/get_key.js
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
const errors = require('../errors')
|
||||
const Key = require('../jwk/key/base')
|
||||
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')
|
||||
}
|
||||
|
||||
return input
|
||||
}
|
||||
|
||||
try {
|
||||
return importKey(input)
|
||||
} catch (err) {
|
||||
if (err instanceof errors.JOSEError && !(err instanceof errors.JWKImportFailed)) {
|
||||
throw err
|
||||
}
|
||||
|
||||
let msg
|
||||
if (keyStoreAllowed) {
|
||||
msg = 'key must be an instance of a key instantiated by JWK.asKey, a valid JWK.asKey input, or a JWKS.KeyStore instance'
|
||||
} else {
|
||||
msg = 'key must be an instance of a key instantiated by JWK.asKey, or a valid JWK.asKey input'
|
||||
}
|
||||
|
||||
throw new TypeError(msg)
|
||||
}
|
||||
}
|
5
node_modules/jose/lib/help/is_disjoint.js
generated
vendored
Normal file
5
node_modules/jose/lib/help/is_disjoint.js
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
module.exports = (a = {}, b = {}) => {
|
||||
const keysA = Object.keys(a)
|
||||
const keysB = new Set(Object.keys(b))
|
||||
return !keysA.some((ka) => keysB.has(ka))
|
||||
}
|
1
node_modules/jose/lib/help/is_object.js
generated
vendored
Normal file
1
node_modules/jose/lib/help/is_object.js
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
module.exports = a => !!a && a.constructor === Object
|
435
node_modules/jose/lib/help/key_object.js
generated
vendored
Normal file
435
node_modules/jose/lib/help/key_object.js
generated
vendored
Normal file
@ -0,0 +1,435 @@
|
||||
const { keyObjectSupported } = require('./runtime_support')
|
||||
|
||||
let createPublicKey
|
||||
let createPrivateKey
|
||||
let createSecretKey
|
||||
let KeyObject
|
||||
let asInput
|
||||
|
||||
if (keyObjectSupported) {
|
||||
({ createPublicKey, createPrivateKey, createSecretKey, KeyObject } = require('crypto'))
|
||||
asInput = (input) => input
|
||||
} else {
|
||||
const { EOL } = require('os')
|
||||
|
||||
const errors = require('../errors')
|
||||
const isObject = require('./is_object')
|
||||
const asn1 = require('./asn1')
|
||||
const toInput = Symbol('toInput')
|
||||
|
||||
const namedCurve = Symbol('namedCurve')
|
||||
|
||||
asInput = (keyObject, needsPublic) => {
|
||||
if (keyObject instanceof KeyObject) {
|
||||
return keyObject[toInput](needsPublic)
|
||||
}
|
||||
|
||||
return createSecretKey(keyObject)[toInput](needsPublic)
|
||||
}
|
||||
|
||||
const pemToDer = pem => Buffer.from(pem.replace(/(?:-----(?:BEGIN|END)(?: (?:RSA|EC))? (?:PRIVATE|PUBLIC) KEY-----|\s)/g, ''), 'base64')
|
||||
const derToPem = (der, label) => `-----BEGIN ${label}-----${EOL}${(der.toString('base64').match(/.{1,64}/g) || []).join(EOL)}${EOL}-----END ${label}-----`
|
||||
const unsupported = (input) => {
|
||||
const label = typeof input === 'string' ? input : `OID ${input.join('.')}`
|
||||
throw new errors.JOSENotSupported(`${label} is not supported in your Node.js runtime version`)
|
||||
}
|
||||
|
||||
KeyObject = class KeyObject {
|
||||
export ({ cipher, passphrase, type, format } = {}) {
|
||||
if (this._type === 'secret') {
|
||||
return this._buffer
|
||||
}
|
||||
|
||||
if (this._type === 'public') {
|
||||
if (this.asymmetricKeyType === 'rsa') {
|
||||
switch (type) {
|
||||
case 'pkcs1':
|
||||
if (format === 'pem') {
|
||||
return this._pem
|
||||
}
|
||||
|
||||
return pemToDer(this._pem)
|
||||
case 'spki': {
|
||||
const PublicKeyInfo = asn1.get('PublicKeyInfo')
|
||||
const pem = PublicKeyInfo.encode({
|
||||
algorithm: {
|
||||
algorithm: 'rsaEncryption',
|
||||
parameters: { type: 'null' }
|
||||
},
|
||||
publicKey: {
|
||||
unused: 0,
|
||||
data: pemToDer(this._pem)
|
||||
}
|
||||
}, 'pem', { label: 'PUBLIC KEY' })
|
||||
|
||||
return format === 'pem' ? pem : pemToDer(pem)
|
||||
}
|
||||
default:
|
||||
throw new TypeError(`The value ${type} is invalid for option "type"`)
|
||||
}
|
||||
}
|
||||
|
||||
if (this.asymmetricKeyType === 'ec') {
|
||||
if (type !== 'spki') {
|
||||
throw new TypeError(`The value ${type} is invalid for option "type"`)
|
||||
}
|
||||
|
||||
if (format === 'pem') {
|
||||
return this._pem
|
||||
}
|
||||
|
||||
return pemToDer(this._pem)
|
||||
}
|
||||
}
|
||||
|
||||
if (this._type === 'private') {
|
||||
if (passphrase !== undefined || cipher !== undefined) {
|
||||
throw new errors.JOSENotSupported('encrypted private keys are not supported in your Node.js runtime version')
|
||||
}
|
||||
|
||||
if (type === 'pkcs8') {
|
||||
if (this._pkcs8) {
|
||||
if (format === 'der' && typeof this._pkcs8 === 'string') {
|
||||
return pemToDer(this._pkcs8)
|
||||
}
|
||||
|
||||
if (format === 'pem' && Buffer.isBuffer(this._pkcs8)) {
|
||||
return derToPem(this._pkcs8, 'PRIVATE KEY')
|
||||
}
|
||||
|
||||
return this._pkcs8
|
||||
}
|
||||
|
||||
if (this.asymmetricKeyType === 'rsa') {
|
||||
const parsed = this._asn1
|
||||
const RSAPrivateKey = asn1.get('RSAPrivateKey')
|
||||
const privateKey = RSAPrivateKey.encode(parsed)
|
||||
const PrivateKeyInfo = asn1.get('PrivateKeyInfo')
|
||||
const pkcs8 = PrivateKeyInfo.encode({
|
||||
version: 0,
|
||||
privateKey,
|
||||
algorithm: {
|
||||
algorithm: 'rsaEncryption',
|
||||
parameters: { type: 'null' }
|
||||
}
|
||||
})
|
||||
|
||||
this._pkcs8 = pkcs8
|
||||
|
||||
return this.export({ type, format })
|
||||
}
|
||||
|
||||
if (this.asymmetricKeyType === 'ec') {
|
||||
const parsed = this._asn1
|
||||
const ECPrivateKey = asn1.get('ECPrivateKey')
|
||||
const privateKey = ECPrivateKey.encode({
|
||||
version: parsed.version,
|
||||
privateKey: parsed.privateKey,
|
||||
publicKey: parsed.publicKey
|
||||
})
|
||||
const PrivateKeyInfo = asn1.get('PrivateKeyInfo')
|
||||
const pkcs8 = PrivateKeyInfo.encode({
|
||||
version: 0,
|
||||
privateKey,
|
||||
algorithm: {
|
||||
algorithm: 'ecPublicKey',
|
||||
parameters: this._asn1.parameters
|
||||
}
|
||||
})
|
||||
|
||||
this._pkcs8 = pkcs8
|
||||
|
||||
return this.export({ type, format })
|
||||
}
|
||||
}
|
||||
|
||||
if (this.asymmetricKeyType === 'rsa' && type === 'pkcs1') {
|
||||
if (format === 'pem') {
|
||||
return this._pem
|
||||
}
|
||||
|
||||
return pemToDer(this._pem)
|
||||
} else if (this.asymmetricKeyType === 'ec' && type === 'sec1') {
|
||||
if (format === 'pem') {
|
||||
return this._pem
|
||||
}
|
||||
|
||||
return pemToDer(this._pem)
|
||||
} else {
|
||||
throw new TypeError(`The value ${type} is invalid for option "type"`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get type () {
|
||||
return this._type
|
||||
}
|
||||
|
||||
get asymmetricKeyType () {
|
||||
return this._asymmetricKeyType
|
||||
}
|
||||
|
||||
get symmetricKeySize () {
|
||||
return this._symmetricKeySize
|
||||
}
|
||||
|
||||
[toInput] (needsPublic) {
|
||||
switch (this._type) {
|
||||
case 'secret':
|
||||
return this._buffer
|
||||
case 'public':
|
||||
return this._pem
|
||||
default:
|
||||
if (needsPublic) {
|
||||
if (!('_pub' in this)) {
|
||||
this._pub = createPublicKey(this)
|
||||
}
|
||||
|
||||
return this._pub[toInput](false)
|
||||
}
|
||||
|
||||
return this._pem
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
createSecretKey = (buffer) => {
|
||||
if (!Buffer.isBuffer(buffer) || !buffer.length) {
|
||||
throw new TypeError('input must be a non-empty Buffer instance')
|
||||
}
|
||||
|
||||
const keyObject = new KeyObject()
|
||||
keyObject._buffer = Buffer.from(buffer)
|
||||
keyObject._symmetricKeySize = buffer.length
|
||||
keyObject._type = 'secret'
|
||||
|
||||
return keyObject
|
||||
}
|
||||
|
||||
createPublicKey = (input) => {
|
||||
if (input instanceof KeyObject) {
|
||||
if (input.type !== 'private') {
|
||||
throw new TypeError(`Invalid key object type ${input.type}, expected private.`)
|
||||
}
|
||||
|
||||
switch (input.asymmetricKeyType) {
|
||||
case 'ec': {
|
||||
const PublicKeyInfo = asn1.get('PublicKeyInfo')
|
||||
const key = PublicKeyInfo.encode({
|
||||
algorithm: {
|
||||
algorithm: 'ecPublicKey',
|
||||
parameters: input._asn1.parameters
|
||||
},
|
||||
publicKey: input._asn1.publicKey
|
||||
})
|
||||
|
||||
return createPublicKey({ key, format: 'der', type: 'spki' })
|
||||
}
|
||||
case 'rsa': {
|
||||
const RSAPublicKey = asn1.get('RSAPublicKey')
|
||||
const key = RSAPublicKey.encode(input._asn1)
|
||||
return createPublicKey({ key, format: 'der', type: 'pkcs1' })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof input === 'string' || Buffer.isBuffer(input)) {
|
||||
input = { key: input, format: 'pem' }
|
||||
}
|
||||
|
||||
if (!isObject(input)) {
|
||||
throw new TypeError('input must be a string, Buffer or an object')
|
||||
}
|
||||
|
||||
const { format, passphrase } = input
|
||||
let { key, type } = input
|
||||
|
||||
if (typeof key !== 'string' && !Buffer.isBuffer(key)) {
|
||||
throw new TypeError('key must be a string or Buffer')
|
||||
}
|
||||
|
||||
if (format !== 'pem' && format !== 'der') {
|
||||
throw new TypeError('format must be one of "pem" or "der"')
|
||||
}
|
||||
|
||||
let label
|
||||
if (format === 'pem') {
|
||||
key = key.toString()
|
||||
switch (key.split(/\r?\n/g)[0].toString()) {
|
||||
case '-----BEGIN PUBLIC KEY-----':
|
||||
type = 'spki'
|
||||
label = 'PUBLIC KEY'
|
||||
break
|
||||
case '-----BEGIN RSA PUBLIC KEY-----':
|
||||
type = 'pkcs1'
|
||||
label = 'RSA PUBLIC KEY'
|
||||
break
|
||||
case '-----BEGIN CERTIFICATE-----':
|
||||
throw new errors.JOSENotSupported('X.509 certificates are not supported in your Node.js runtime version')
|
||||
case '-----BEGIN PRIVATE KEY-----':
|
||||
case '-----BEGIN EC PRIVATE KEY-----':
|
||||
case '-----BEGIN RSA PRIVATE KEY-----':
|
||||
return createPublicKey(createPrivateKey(key))
|
||||
default:
|
||||
throw new TypeError('unknown/unsupported PEM type')
|
||||
}
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case 'spki': {
|
||||
const PublicKeyInfo = asn1.get('PublicKeyInfo')
|
||||
const parsed = PublicKeyInfo.decode(key, format, { label })
|
||||
|
||||
let type, keyObject
|
||||
switch (parsed.algorithm.algorithm) {
|
||||
case 'ecPublicKey': {
|
||||
keyObject = new KeyObject()
|
||||
keyObject._asn1 = parsed
|
||||
keyObject._asymmetricKeyType = 'ec'
|
||||
keyObject._type = 'public'
|
||||
keyObject._pem = PublicKeyInfo.encode(parsed, 'pem', { label: 'PUBLIC KEY' })
|
||||
|
||||
break
|
||||
}
|
||||
case 'rsaEncryption': {
|
||||
type = 'pkcs1'
|
||||
keyObject = createPublicKey({ type, key: parsed.publicKey.data, format: 'der' })
|
||||
break
|
||||
}
|
||||
default:
|
||||
unsupported(parsed.algorithm.algorithm)
|
||||
}
|
||||
|
||||
return keyObject
|
||||
}
|
||||
case 'pkcs1': {
|
||||
const RSAPublicKey = asn1.get('RSAPublicKey')
|
||||
const parsed = RSAPublicKey.decode(key, format, { label })
|
||||
|
||||
// special case when private pkcs1 PEM / DER is used with createPublicKey
|
||||
if (parsed.n === BigInt(0)) {
|
||||
return createPublicKey(createPrivateKey({ key, format, type, passphrase }))
|
||||
}
|
||||
|
||||
const keyObject = new KeyObject()
|
||||
keyObject._asn1 = parsed
|
||||
keyObject._asymmetricKeyType = 'rsa'
|
||||
keyObject._type = 'public'
|
||||
keyObject._pem = RSAPublicKey.encode(parsed, 'pem', { label: 'RSA PUBLIC KEY' })
|
||||
|
||||
return keyObject
|
||||
}
|
||||
case 'pkcs8':
|
||||
case 'sec1':
|
||||
return createPublicKey(createPrivateKey({ format, key, type, passphrase }))
|
||||
default:
|
||||
throw new TypeError(`The value ${type} is invalid for option "type"`)
|
||||
}
|
||||
}
|
||||
|
||||
createPrivateKey = (input, hints) => {
|
||||
if (typeof input === 'string' || Buffer.isBuffer(input)) {
|
||||
input = { key: input, format: 'pem' }
|
||||
}
|
||||
|
||||
if (!isObject(input)) {
|
||||
throw new TypeError('input must be a string, Buffer or an object')
|
||||
}
|
||||
|
||||
const { format, passphrase } = input
|
||||
let { key, type } = input
|
||||
|
||||
if (typeof key !== 'string' && !Buffer.isBuffer(key)) {
|
||||
throw new TypeError('key must be a string or Buffer')
|
||||
}
|
||||
|
||||
if (passphrase !== undefined) {
|
||||
throw new errors.JOSENotSupported('encrypted private keys are not supported in your Node.js runtime version')
|
||||
}
|
||||
|
||||
if (format !== 'pem' && format !== 'der') {
|
||||
throw new TypeError('format must be one of "pem" or "der"')
|
||||
}
|
||||
|
||||
let label
|
||||
if (format === 'pem') {
|
||||
key = key.toString()
|
||||
switch (key.split(/\r?\n/g)[0].toString()) {
|
||||
case '-----BEGIN PRIVATE KEY-----':
|
||||
type = 'pkcs8'
|
||||
label = 'PRIVATE KEY'
|
||||
break
|
||||
case '-----BEGIN EC PRIVATE KEY-----':
|
||||
type = 'sec1'
|
||||
label = 'EC PRIVATE KEY'
|
||||
break
|
||||
case '-----BEGIN RSA PRIVATE KEY-----':
|
||||
type = 'pkcs1'
|
||||
label = 'RSA PRIVATE KEY'
|
||||
break
|
||||
default:
|
||||
throw new TypeError('unknown/unsupported PEM type')
|
||||
}
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case 'pkcs8': {
|
||||
const PrivateKeyInfo = asn1.get('PrivateKeyInfo')
|
||||
const parsed = PrivateKeyInfo.decode(key, format, { label })
|
||||
|
||||
let type, keyObject
|
||||
switch (parsed.algorithm.algorithm) {
|
||||
case 'ecPublicKey': {
|
||||
type = 'sec1'
|
||||
keyObject = createPrivateKey({ type, key: parsed.privateKey, format: 'der' }, { [namedCurve]: parsed.algorithm.parameters.value })
|
||||
break
|
||||
}
|
||||
case 'rsaEncryption': {
|
||||
type = 'pkcs1'
|
||||
keyObject = createPrivateKey({ type, key: parsed.privateKey, format: 'der' })
|
||||
break
|
||||
}
|
||||
default:
|
||||
unsupported(parsed.algorithm.algorithm)
|
||||
}
|
||||
|
||||
keyObject._pkcs8 = key
|
||||
return keyObject
|
||||
}
|
||||
case 'pkcs1': {
|
||||
const RSAPrivateKey = asn1.get('RSAPrivateKey')
|
||||
const parsed = RSAPrivateKey.decode(key, format, { label })
|
||||
|
||||
const keyObject = new KeyObject()
|
||||
keyObject._asn1 = parsed
|
||||
keyObject._asymmetricKeyType = 'rsa'
|
||||
keyObject._type = 'private'
|
||||
keyObject._pem = RSAPrivateKey.encode(parsed, 'pem', { label: 'RSA PRIVATE KEY' })
|
||||
|
||||
return keyObject
|
||||
}
|
||||
case 'sec1': {
|
||||
const ECPrivateKey = asn1.get('ECPrivateKey')
|
||||
let parsed = ECPrivateKey.decode(key, format, { label })
|
||||
|
||||
if (!('parameters' in parsed) && !hints[namedCurve]) {
|
||||
throw new Error('invalid sec1')
|
||||
} else if (!('parameters' in parsed)) {
|
||||
parsed = { ...parsed, parameters: { type: 'namedCurve', value: hints[namedCurve] } }
|
||||
}
|
||||
|
||||
const keyObject = new KeyObject()
|
||||
keyObject._asn1 = parsed
|
||||
keyObject._asymmetricKeyType = 'ec'
|
||||
keyObject._type = 'private'
|
||||
keyObject._pem = ECPrivateKey.encode(parsed, 'pem', { label: 'EC PRIVATE KEY' })
|
||||
|
||||
return keyObject
|
||||
}
|
||||
default:
|
||||
throw new TypeError(`The value ${type} is invalid for option "type"`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { createPublicKey, createPrivateKey, createSecretKey, KeyObject, asInput }
|
300
node_modules/jose/lib/help/key_utils.js
generated
vendored
Normal file
300
node_modules/jose/lib/help/key_utils.js
generated
vendored
Normal file
@ -0,0 +1,300 @@
|
||||
const { EOL } = require('os')
|
||||
|
||||
const errors = require('../errors')
|
||||
|
||||
const { keyObjectSupported } = require('./runtime_support')
|
||||
const { createPublicKey } = require('./key_object')
|
||||
const base64url = require('./base64url')
|
||||
const asn1 = require('./asn1')
|
||||
const computePrimes = require('./rsa_primes')
|
||||
const { OKP_CURVES, EC_CURVES } = require('../registry')
|
||||
|
||||
const formatPem = (base64pem, descriptor) => `-----BEGIN ${descriptor} KEY-----${EOL}${(base64pem.match(/.{1,64}/g) || []).join(EOL)}${EOL}-----END ${descriptor} KEY-----`
|
||||
|
||||
const okpToJWK = {
|
||||
private (crv, keyObject) {
|
||||
const der = keyObject.export({ type: 'pkcs8', format: 'der' })
|
||||
const OneAsymmetricKey = asn1.get('OneAsymmetricKey')
|
||||
const { privateKey: { privateKey: d } } = OneAsymmetricKey.decode(der)
|
||||
|
||||
return {
|
||||
...okpToJWK.public(crv, createPublicKey(keyObject)),
|
||||
d: base64url.encodeBuffer(d)
|
||||
}
|
||||
},
|
||||
public (crv, keyObject) {
|
||||
const der = keyObject.export({ type: 'spki', format: 'der' })
|
||||
|
||||
const PublicKeyInfo = asn1.get('PublicKeyInfo')
|
||||
|
||||
const { publicKey: { data: x } } = PublicKeyInfo.decode(der)
|
||||
|
||||
return {
|
||||
kty: 'OKP',
|
||||
crv,
|
||||
x: base64url.encodeBuffer(x)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const keyObjectToJWK = {
|
||||
rsa: {
|
||||
private (keyObject) {
|
||||
const der = keyObject.export({ type: 'pkcs8', format: 'der' })
|
||||
|
||||
const PrivateKeyInfo = asn1.get('PrivateKeyInfo')
|
||||
const RSAPrivateKey = asn1.get('RSAPrivateKey')
|
||||
|
||||
const { privateKey } = PrivateKeyInfo.decode(der)
|
||||
const { version, n, e, d, p, q, dp, dq, qi } = RSAPrivateKey.decode(privateKey)
|
||||
|
||||
if (version !== 'two-prime') {
|
||||
throw new errors.JOSENotSupported('Private RSA keys with more than two primes are not supported')
|
||||
}
|
||||
|
||||
return {
|
||||
kty: 'RSA',
|
||||
n: base64url.encodeBigInt(n),
|
||||
e: base64url.encodeBigInt(e),
|
||||
d: base64url.encodeBigInt(d),
|
||||
p: base64url.encodeBigInt(p),
|
||||
q: base64url.encodeBigInt(q),
|
||||
dp: base64url.encodeBigInt(dp),
|
||||
dq: base64url.encodeBigInt(dq),
|
||||
qi: base64url.encodeBigInt(qi)
|
||||
}
|
||||
},
|
||||
public (keyObject) {
|
||||
const der = keyObject.export({ type: 'spki', format: 'der' })
|
||||
|
||||
const PublicKeyInfo = asn1.get('PublicKeyInfo')
|
||||
const RSAPublicKey = asn1.get('RSAPublicKey')
|
||||
|
||||
const { publicKey: { data: publicKey } } = PublicKeyInfo.decode(der)
|
||||
const { n, e } = RSAPublicKey.decode(publicKey)
|
||||
|
||||
return {
|
||||
kty: 'RSA',
|
||||
n: base64url.encodeBigInt(n),
|
||||
e: base64url.encodeBigInt(e)
|
||||
}
|
||||
}
|
||||
},
|
||||
ec: {
|
||||
private (keyObject) {
|
||||
const der = keyObject.export({ type: 'pkcs8', format: 'der' })
|
||||
|
||||
const PrivateKeyInfo = asn1.get('PrivateKeyInfo')
|
||||
const ECPrivateKey = asn1.get('ECPrivateKey')
|
||||
|
||||
const { privateKey, algorithm: { parameters: { value: crv } } } = PrivateKeyInfo.decode(der)
|
||||
const { privateKey: d, publicKey } = ECPrivateKey.decode(privateKey)
|
||||
|
||||
if (typeof publicKey === 'undefined') {
|
||||
if (keyObjectSupported) {
|
||||
return {
|
||||
...keyObjectToJWK.ec.public(createPublicKey(keyObject)),
|
||||
d: base64url.encodeBuffer(d)
|
||||
}
|
||||
}
|
||||
|
||||
throw new errors.JOSENotSupported('Private EC keys without the public key embedded are not supported in your Node.js runtime version')
|
||||
}
|
||||
|
||||
const x = publicKey.data.slice(1, ((publicKey.data.length - 1) / 2) + 1)
|
||||
const y = publicKey.data.slice(((publicKey.data.length - 1) / 2) + 1)
|
||||
|
||||
return {
|
||||
kty: 'EC',
|
||||
crv,
|
||||
d: base64url.encodeBuffer(d),
|
||||
x: base64url.encodeBuffer(x),
|
||||
y: base64url.encodeBuffer(y)
|
||||
}
|
||||
},
|
||||
public (keyObject) {
|
||||
const der = keyObject.export({ type: 'spki', format: 'der' })
|
||||
|
||||
const PublicKeyInfo = asn1.get('PublicKeyInfo')
|
||||
|
||||
const { publicKey: { data: publicKey }, algorithm: { parameters: { value: crv } } } = PublicKeyInfo.decode(der)
|
||||
|
||||
const x = publicKey.slice(1, ((publicKey.length - 1) / 2) + 1)
|
||||
const y = publicKey.slice(((publicKey.length - 1) / 2) + 1)
|
||||
|
||||
return {
|
||||
kty: 'EC',
|
||||
crv,
|
||||
x: base64url.encodeBuffer(x),
|
||||
y: base64url.encodeBuffer(y)
|
||||
}
|
||||
}
|
||||
},
|
||||
ed25519: {
|
||||
private (keyObject) {
|
||||
return okpToJWK.private('Ed25519', keyObject)
|
||||
},
|
||||
public (keyObject) {
|
||||
return okpToJWK.public('Ed25519', keyObject)
|
||||
}
|
||||
},
|
||||
ed448: {
|
||||
private (keyObject) {
|
||||
return okpToJWK.private('Ed448', keyObject)
|
||||
},
|
||||
public (keyObject) {
|
||||
return okpToJWK.public('Ed448', keyObject)
|
||||
}
|
||||
},
|
||||
x25519: {
|
||||
private (keyObject) {
|
||||
return okpToJWK.private('X25519', keyObject)
|
||||
},
|
||||
public (keyObject) {
|
||||
return okpToJWK.public('X25519', keyObject)
|
||||
}
|
||||
},
|
||||
x448: {
|
||||
private (keyObject) {
|
||||
return okpToJWK.private('X448', keyObject)
|
||||
},
|
||||
public (keyObject) {
|
||||
return okpToJWK.public('X448', keyObject)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.keyObjectToJWK = (keyObject) => {
|
||||
if (keyObject.type === 'private') {
|
||||
return keyObjectToJWK[keyObject.asymmetricKeyType].private(keyObject)
|
||||
}
|
||||
|
||||
return keyObjectToJWK[keyObject.asymmetricKeyType].public(keyObject)
|
||||
}
|
||||
|
||||
const concatEcPublicKey = (x, y) => ({
|
||||
unused: 0,
|
||||
data: Buffer.concat([
|
||||
Buffer.alloc(1, 4),
|
||||
base64url.decodeToBuffer(x),
|
||||
base64url.decodeToBuffer(y)
|
||||
])
|
||||
})
|
||||
|
||||
const jwkToPem = {
|
||||
RSA: {
|
||||
private (jwk, { calculateMissingRSAPrimes }) {
|
||||
const RSAPrivateKey = asn1.get('RSAPrivateKey')
|
||||
|
||||
if ('oth' in jwk) {
|
||||
throw new errors.JOSENotSupported('Private RSA keys with more than two primes are not supported')
|
||||
}
|
||||
|
||||
if (jwk.p || jwk.q || jwk.dp || jwk.dq || jwk.qi) {
|
||||
if (!(jwk.p && jwk.q && jwk.dp && jwk.dq && jwk.qi)) {
|
||||
throw new errors.JWKInvalid('all other private key parameters must be present when any one of them is present')
|
||||
}
|
||||
} else if (calculateMissingRSAPrimes) {
|
||||
jwk = computePrimes(jwk)
|
||||
} else if (!calculateMissingRSAPrimes) {
|
||||
throw new errors.JOSENotSupported('importing private RSA keys without all other private key parameters is not enabled, see documentation and its advisory on how and when its ok to enable it')
|
||||
}
|
||||
|
||||
return RSAPrivateKey.encode({
|
||||
version: 0,
|
||||
n: BigInt(`0x${base64url.decodeToBuffer(jwk.n).toString('hex')}`),
|
||||
e: BigInt(`0x${base64url.decodeToBuffer(jwk.e).toString('hex')}`),
|
||||
d: BigInt(`0x${base64url.decodeToBuffer(jwk.d).toString('hex')}`),
|
||||
p: BigInt(`0x${base64url.decodeToBuffer(jwk.p).toString('hex')}`),
|
||||
q: BigInt(`0x${base64url.decodeToBuffer(jwk.q).toString('hex')}`),
|
||||
dp: BigInt(`0x${base64url.decodeToBuffer(jwk.dp).toString('hex')}`),
|
||||
dq: BigInt(`0x${base64url.decodeToBuffer(jwk.dq).toString('hex')}`),
|
||||
qi: BigInt(`0x${base64url.decodeToBuffer(jwk.qi).toString('hex')}`)
|
||||
}, 'pem', { label: 'RSA PRIVATE KEY' })
|
||||
},
|
||||
public (jwk) {
|
||||
const RSAPublicKey = asn1.get('RSAPublicKey')
|
||||
|
||||
return RSAPublicKey.encode({
|
||||
version: 0,
|
||||
n: BigInt(`0x${base64url.decodeToBuffer(jwk.n).toString('hex')}`),
|
||||
e: BigInt(`0x${base64url.decodeToBuffer(jwk.e).toString('hex')}`)
|
||||
}, 'pem', { label: 'RSA PUBLIC KEY' })
|
||||
}
|
||||
},
|
||||
EC: {
|
||||
private (jwk) {
|
||||
const ECPrivateKey = asn1.get('ECPrivateKey')
|
||||
|
||||
return ECPrivateKey.encode({
|
||||
version: 1,
|
||||
privateKey: base64url.decodeToBuffer(jwk.d),
|
||||
parameters: { type: 'namedCurve', value: jwk.crv },
|
||||
publicKey: concatEcPublicKey(jwk.x, jwk.y)
|
||||
}, 'pem', { label: 'EC PRIVATE KEY' })
|
||||
},
|
||||
public (jwk) {
|
||||
const PublicKeyInfo = asn1.get('PublicKeyInfo')
|
||||
|
||||
return PublicKeyInfo.encode({
|
||||
algorithm: {
|
||||
algorithm: 'ecPublicKey',
|
||||
parameters: { type: 'namedCurve', value: jwk.crv }
|
||||
},
|
||||
publicKey: concatEcPublicKey(jwk.x, jwk.y)
|
||||
}, 'pem', { label: 'PUBLIC KEY' })
|
||||
}
|
||||
},
|
||||
OKP: {
|
||||
private (jwk) {
|
||||
const OneAsymmetricKey = asn1.get('OneAsymmetricKey')
|
||||
|
||||
const b64 = OneAsymmetricKey.encode({
|
||||
version: 0,
|
||||
privateKey: { privateKey: base64url.decodeToBuffer(jwk.d) },
|
||||
algorithm: { algorithm: jwk.crv }
|
||||
}, 'der')
|
||||
|
||||
// TODO: WHYYY? https://github.com/indutny/asn1.js/issues/110
|
||||
b64.write('04', 12, 1, 'hex')
|
||||
|
||||
return formatPem(b64.toString('base64'), 'PRIVATE')
|
||||
},
|
||||
public (jwk) {
|
||||
const PublicKeyInfo = asn1.get('PublicKeyInfo')
|
||||
|
||||
return PublicKeyInfo.encode({
|
||||
algorithm: { algorithm: jwk.crv },
|
||||
publicKey: {
|
||||
unused: 0,
|
||||
data: base64url.decodeToBuffer(jwk.x)
|
||||
}
|
||||
}, 'pem', { label: 'PUBLIC KEY' })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.jwkToPem = (jwk, { calculateMissingRSAPrimes = false } = {}) => {
|
||||
switch (jwk.kty) {
|
||||
case 'EC':
|
||||
if (!EC_CURVES.has(jwk.crv)) {
|
||||
throw new errors.JOSENotSupported(`unsupported EC key curve: ${jwk.crv}`)
|
||||
}
|
||||
break
|
||||
case 'OKP':
|
||||
if (!OKP_CURVES.has(jwk.crv)) {
|
||||
throw new errors.JOSENotSupported(`unsupported OKP key curve: ${jwk.crv}`)
|
||||
}
|
||||
break
|
||||
case 'RSA':
|
||||
break
|
||||
default:
|
||||
throw new errors.JOSENotSupported(`unsupported key type: ${jwk.kty}`)
|
||||
}
|
||||
|
||||
if (jwk.d) {
|
||||
return jwkToPem[jwk.kty].private(jwk, { calculateMissingRSAPrimes })
|
||||
}
|
||||
|
||||
return jwkToPem[jwk.kty].public(jwk)
|
||||
}
|
1
node_modules/jose/lib/help/node_alg.js
generated
vendored
Normal file
1
node_modules/jose/lib/help/node_alg.js
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
module.exports = alg => `sha${alg.substr(2, 3)}`
|
170
node_modules/jose/lib/help/rsa_primes.js
generated
vendored
Normal file
170
node_modules/jose/lib/help/rsa_primes.js
generated
vendored
Normal file
@ -0,0 +1,170 @@
|
||||
const { randomBytes } = require('crypto')
|
||||
|
||||
const base64url = require('./base64url')
|
||||
const errors = require('../errors')
|
||||
|
||||
const ZERO = BigInt(0)
|
||||
const ONE = BigInt(1)
|
||||
const TWO = BigInt(2)
|
||||
|
||||
const toJWKParameter = (n) => {
|
||||
const hex = n.toString(16)
|
||||
return base64url.encodeBuffer(Buffer.from(hex.length % 2 ? `0${hex}` : hex, 'hex'))
|
||||
}
|
||||
const fromBuffer = buf => BigInt(`0x${buf.toString('hex')}`)
|
||||
const bitLength = n => n.toString(2).length
|
||||
|
||||
const eGcdX = (a, b) => {
|
||||
let x = ZERO
|
||||
let y = ONE
|
||||
let u = ONE
|
||||
let v = ZERO
|
||||
|
||||
while (a !== ZERO) {
|
||||
const q = b / a
|
||||
const r = b % a
|
||||
const m = x - (u * q)
|
||||
const n = y - (v * q)
|
||||
b = a
|
||||
a = r
|
||||
x = u
|
||||
y = v
|
||||
u = m
|
||||
v = n
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
const gcd = (a, b) => {
|
||||
let shift = ZERO
|
||||
while (!((a | b) & ONE)) {
|
||||
a >>= ONE
|
||||
b >>= ONE
|
||||
shift++
|
||||
}
|
||||
while (!(a & ONE)) {
|
||||
a >>= ONE
|
||||
}
|
||||
do {
|
||||
while (!(b & ONE)) {
|
||||
b >>= ONE
|
||||
}
|
||||
if (a > b) {
|
||||
const x = a
|
||||
a = b
|
||||
b = x
|
||||
}
|
||||
b -= a
|
||||
} while (b)
|
||||
|
||||
return a << shift
|
||||
}
|
||||
|
||||
const modPow = (a, b, n) => {
|
||||
a = toZn(a, n)
|
||||
let result = ONE
|
||||
let x = a
|
||||
while (b > 0) {
|
||||
const leastSignificantBit = b % TWO
|
||||
b = b / TWO
|
||||
if (leastSignificantBit === ONE) {
|
||||
result = result * x
|
||||
result = result % n
|
||||
}
|
||||
x = x * x
|
||||
x = x % n
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const randBetween = (min, max) => {
|
||||
const interval = max - min
|
||||
const bitLen = bitLength(interval)
|
||||
let rnd
|
||||
do {
|
||||
rnd = fromBuffer(randBits(bitLen))
|
||||
} while (rnd > interval)
|
||||
return rnd + min
|
||||
}
|
||||
|
||||
const randBits = (bitLength) => {
|
||||
const byteLength = Math.ceil(bitLength / 8)
|
||||
const rndBytes = randomBytes(byteLength)
|
||||
// Fill with 0's the extra bits
|
||||
rndBytes[0] = rndBytes[0] & (2 ** (bitLength % 8) - 1)
|
||||
return rndBytes
|
||||
}
|
||||
|
||||
const toZn = (a, n) => {
|
||||
a = a % n
|
||||
return (a < 0) ? a + n : a
|
||||
}
|
||||
|
||||
const odd = (n) => {
|
||||
let r = n
|
||||
while (r % TWO === ZERO) {
|
||||
r = r / TWO
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// not sold on these values
|
||||
const maxCountWhileNoY = 30
|
||||
const maxCountWhileInot0 = 22
|
||||
|
||||
const getPrimeFactors = (e, d, n) => {
|
||||
const r = odd(e * d - ONE)
|
||||
|
||||
let countWhileNoY = 0
|
||||
let y
|
||||
do {
|
||||
countWhileNoY++
|
||||
if (countWhileNoY === maxCountWhileNoY) {
|
||||
throw new errors.JWKImportFailed('failed to calculate missing primes')
|
||||
}
|
||||
|
||||
let countWhileInot0 = 0
|
||||
let i = modPow(randBetween(TWO, n), r, n)
|
||||
let o = ZERO
|
||||
while (i !== ONE) {
|
||||
countWhileInot0++
|
||||
if (countWhileInot0 === maxCountWhileInot0) {
|
||||
throw new errors.JWKImportFailed('failed to calculate missing primes')
|
||||
}
|
||||
o = i
|
||||
i = (i * i) % n
|
||||
}
|
||||
if (o !== (n - ONE)) {
|
||||
y = o
|
||||
}
|
||||
} while (!y)
|
||||
|
||||
const p = gcd(y - ONE, n)
|
||||
const q = n / p
|
||||
|
||||
return p > q ? { p, q } : { p: q, q: p }
|
||||
}
|
||||
|
||||
module.exports = (jwk) => {
|
||||
const e = fromBuffer(base64url.decodeToBuffer(jwk.e))
|
||||
const d = fromBuffer(base64url.decodeToBuffer(jwk.d))
|
||||
const n = fromBuffer(base64url.decodeToBuffer(jwk.n))
|
||||
|
||||
if (d >= n) {
|
||||
throw new errors.JWKInvalid('invalid RSA private exponent')
|
||||
}
|
||||
|
||||
const { p, q } = getPrimeFactors(e, d, n)
|
||||
const dp = d % (p - ONE)
|
||||
const dq = d % (q - ONE)
|
||||
const qi = toZn(eGcdX(toZn(q, p), p), p)
|
||||
|
||||
return {
|
||||
...jwk,
|
||||
p: toJWKParameter(p),
|
||||
q: toJWKParameter(q),
|
||||
dp: toJWKParameter(dp),
|
||||
dq: toJWKParameter(dq),
|
||||
qi: toJWKParameter(qi)
|
||||
}
|
||||
}
|
11
node_modules/jose/lib/help/runtime_support.js
generated
vendored
Normal file
11
node_modules/jose/lib/help/runtime_support.js
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
const { diffieHellman, KeyObject, sign, verify } = require('crypto')
|
||||
|
||||
const [major, minor] = process.version.substr(1).split('.').map(x => parseInt(x, 10))
|
||||
|
||||
module.exports = {
|
||||
oaepHashSupported: major > 12 || (major === 12 && minor >= 9),
|
||||
keyObjectSupported: !!KeyObject && major >= 12,
|
||||
edDSASupported: !!sign && !!verify,
|
||||
dsaEncodingSupported: major > 13 || (major === 13 && minor >= 2) || (major === 12 && minor >= 16),
|
||||
improvedDH: !!diffieHellman
|
||||
}
|
53
node_modules/jose/lib/help/secs.js
generated
vendored
Normal file
53
node_modules/jose/lib/help/secs.js
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
const minute = 60
|
||||
const hour = minute * 60
|
||||
const day = hour * 24
|
||||
const week = day * 7
|
||||
const year = day * 365.25
|
||||
|
||||
const REGEX = /^(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)$/i
|
||||
|
||||
module.exports = (str) => {
|
||||
const matched = REGEX.exec(str)
|
||||
|
||||
if (!matched) {
|
||||
throw new TypeError(`invalid time period format ("${str}")`)
|
||||
}
|
||||
|
||||
const value = parseFloat(matched[1])
|
||||
const unit = matched[2].toLowerCase()
|
||||
|
||||
switch (unit) {
|
||||
case 'sec':
|
||||
case 'secs':
|
||||
case 'second':
|
||||
case 'seconds':
|
||||
case 's':
|
||||
return Math.round(value)
|
||||
case 'minute':
|
||||
case 'minutes':
|
||||
case 'min':
|
||||
case 'mins':
|
||||
case 'm':
|
||||
return Math.round(value * minute)
|
||||
case 'hour':
|
||||
case 'hours':
|
||||
case 'hr':
|
||||
case 'hrs':
|
||||
case 'h':
|
||||
return Math.round(value * hour)
|
||||
case 'day':
|
||||
case 'days':
|
||||
case 'd':
|
||||
return Math.round(value * day)
|
||||
case 'week':
|
||||
case 'weeks':
|
||||
case 'w':
|
||||
return Math.round(value * week)
|
||||
case 'year':
|
||||
case 'years':
|
||||
case 'yr':
|
||||
case 'yrs':
|
||||
case 'y':
|
||||
return Math.round(value * year)
|
||||
}
|
||||
}
|
18
node_modules/jose/lib/help/timing_safe_equal.js
generated
vendored
Normal file
18
node_modules/jose/lib/help/timing_safe_equal.js
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
const { timingSafeEqual: TSE } = require('crypto')
|
||||
|
||||
const paddedBuffer = (input, length) => {
|
||||
if (input.length === length) {
|
||||
return input
|
||||
}
|
||||
|
||||
const buffer = Buffer.alloc(length)
|
||||
input.copy(buffer)
|
||||
return buffer
|
||||
}
|
||||
|
||||
const timingSafeEqual = (a, b) => {
|
||||
const length = Math.max(a.length, b.length)
|
||||
return TSE(paddedBuffer(a, length), paddedBuffer(b, length))
|
||||
}
|
||||
|
||||
module.exports = timingSafeEqual
|
10
node_modules/jose/lib/help/uint64be.js
generated
vendored
Normal file
10
node_modules/jose/lib/help/uint64be.js
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
const MAX_INT32 = Math.pow(2, 32)
|
||||
|
||||
module.exports = (value, buf = Buffer.allocUnsafe(8)) => {
|
||||
const high = Math.floor(value / MAX_INT32)
|
||||
const low = value % MAX_INT32
|
||||
|
||||
buf.writeUInt32BE(high, 0)
|
||||
buf.writeUInt32BE(low, 4)
|
||||
return buf
|
||||
}
|
41
node_modules/jose/lib/help/validate_crit.js
generated
vendored
Normal file
41
node_modules/jose/lib/help/validate_crit.js
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
const { JOSECritNotUnderstood, JWSInvalid } = require('../errors')
|
||||
|
||||
const DEFINED = new Set([
|
||||
'alg', 'jku', 'jwk', 'kid', 'x5u', 'x5c', 'x5t', 'x5t#S256', 'typ', 'cty',
|
||||
'crit', 'enc', 'zip', 'epk', 'apu', 'apv', 'iv', 'tag', 'p2s', 'p2c'
|
||||
])
|
||||
|
||||
module.exports = function validateCrit (Err, protectedHeader, unprotectedHeader, understood) {
|
||||
if (protectedHeader && 'crit' in protectedHeader) {
|
||||
if (
|
||||
!Array.isArray(protectedHeader.crit) ||
|
||||
protectedHeader.crit.length === 0 ||
|
||||
protectedHeader.crit.some(s => typeof s !== 'string' || !s)
|
||||
) {
|
||||
throw new Err('"crit" Header Parameter MUST be an array of non-empty strings when present')
|
||||
}
|
||||
const whitelisted = new Set(understood)
|
||||
const combined = { ...protectedHeader, ...unprotectedHeader }
|
||||
protectedHeader.crit.forEach((parameter) => {
|
||||
if (DEFINED.has(parameter)) {
|
||||
throw new Err(`The critical list contains a non-extension Header Parameter ${parameter}`)
|
||||
}
|
||||
if (!whitelisted.has(parameter)) {
|
||||
throw new JOSECritNotUnderstood(`critical "${parameter}" is not understood`)
|
||||
}
|
||||
if (parameter === 'b64') {
|
||||
if (!('b64' in protectedHeader)) {
|
||||
throw new JWSInvalid('"b64" critical parameter must be integrity protected')
|
||||
}
|
||||
if (typeof protectedHeader.b64 !== 'boolean') {
|
||||
throw new JWSInvalid('"b64" critical parameter must be a boolean')
|
||||
}
|
||||
} else if (!(parameter in combined)) {
|
||||
throw new Err(`critical parameter "${parameter}" is missing`)
|
||||
}
|
||||
})
|
||||
}
|
||||
if (unprotectedHeader && 'crit' in unprotectedHeader) {
|
||||
throw new Err('"crit" Header Parameter MUST be integrity protected when present')
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user