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
15
node_modules/jose/lib/jws/index.js
generated
vendored
Normal file
15
node_modules/jose/lib/jws/index.js
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
const Sign = require('./sign')
|
||||
const { verify } = require('./verify')
|
||||
|
||||
const single = (serialization, payload, key, protectedHeader, unprotectedHeader) => {
|
||||
return new Sign(payload)
|
||||
.recipient(key, protectedHeader, unprotectedHeader)
|
||||
.sign(serialization)
|
||||
}
|
||||
|
||||
module.exports.Sign = Sign
|
||||
module.exports.sign = single.bind(undefined, 'compact')
|
||||
module.exports.sign.flattened = single.bind(undefined, 'flattened')
|
||||
module.exports.sign.general = single.bind(undefined, 'general')
|
||||
|
||||
module.exports.verify = verify
|
104
node_modules/jose/lib/jws/serializers.js
generated
vendored
Normal file
104
node_modules/jose/lib/jws/serializers.js
generated
vendored
Normal file
@ -0,0 +1,104 @@
|
||||
const isObject = require('../help/is_object')
|
||||
let validateCrit = require('../help/validate_crit')
|
||||
const { JWSInvalid } = require('../errors')
|
||||
|
||||
validateCrit = validateCrit.bind(undefined, JWSInvalid)
|
||||
|
||||
const compactSerializer = (payload, [recipient]) => {
|
||||
return `${recipient.protected}.${payload}.${recipient.signature}`
|
||||
}
|
||||
compactSerializer.validate = (jws, { 0: { unprotectedHeader, protectedHeader }, length }) => {
|
||||
if (length !== 1 || unprotectedHeader) {
|
||||
throw new JWSInvalid('JWS Compact Serialization doesn\'t support multiple recipients or JWS unprotected headers')
|
||||
}
|
||||
validateCrit(protectedHeader, unprotectedHeader, protectedHeader ? protectedHeader.crit : undefined)
|
||||
}
|
||||
|
||||
const flattenedSerializer = (payload, [recipient]) => {
|
||||
const { header, signature, protected: prot } = recipient
|
||||
|
||||
return {
|
||||
payload,
|
||||
...prot ? { protected: prot } : undefined,
|
||||
...header ? { header } : undefined,
|
||||
signature
|
||||
}
|
||||
}
|
||||
flattenedSerializer.validate = (jws, { 0: { unprotectedHeader, protectedHeader }, length }) => {
|
||||
if (length !== 1) {
|
||||
throw new JWSInvalid('Flattened JWS JSON Serialization doesn\'t support multiple recipients')
|
||||
}
|
||||
validateCrit(protectedHeader, unprotectedHeader, protectedHeader ? protectedHeader.crit : undefined)
|
||||
}
|
||||
|
||||
const generalSerializer = (payload, recipients) => {
|
||||
return {
|
||||
payload,
|
||||
signatures: recipients.map(({ header, signature, protected: prot }) => {
|
||||
return {
|
||||
...prot ? { protected: prot } : undefined,
|
||||
...header ? { header } : undefined,
|
||||
signature
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
generalSerializer.validate = (jws, recipients) => {
|
||||
let validateB64 = false
|
||||
recipients.forEach(({ protectedHeader, unprotectedHeader }) => {
|
||||
if (protectedHeader && !validateB64 && 'b64' in protectedHeader) {
|
||||
validateB64 = true
|
||||
}
|
||||
validateCrit(protectedHeader, unprotectedHeader, protectedHeader ? protectedHeader.crit : undefined)
|
||||
})
|
||||
|
||||
if (validateB64) {
|
||||
const values = recipients.map(({ protectedHeader }) => protectedHeader && protectedHeader.b64)
|
||||
if (!values.every((actual, i, [expected]) => actual === expected)) {
|
||||
throw new JWSInvalid('the "b64" Header Parameter value MUST be the same for all recipients')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const isJSON = (input) => {
|
||||
return isObject(input) && (typeof input.payload === 'string' || Buffer.isBuffer(input.payload))
|
||||
}
|
||||
|
||||
const isValidRecipient = (recipient) => {
|
||||
return isObject(recipient) && typeof recipient.signature === 'string' &&
|
||||
(recipient.header === undefined || isObject(recipient.header)) &&
|
||||
(recipient.protected === undefined || typeof recipient.protected === 'string')
|
||||
}
|
||||
|
||||
const isMultiRecipient = (input) => {
|
||||
if (Array.isArray(input.signatures) && input.signatures.every(isValidRecipient)) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
const detect = (input) => {
|
||||
if (typeof input === 'string' && input.split('.').length === 3) {
|
||||
return 'compact'
|
||||
}
|
||||
|
||||
if (isJSON(input)) {
|
||||
if (isMultiRecipient(input)) {
|
||||
return 'general'
|
||||
}
|
||||
|
||||
if (isValidRecipient(input)) {
|
||||
return 'flattened'
|
||||
}
|
||||
}
|
||||
|
||||
throw new JWSInvalid('JWS malformed or invalid serialization')
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
compact: compactSerializer,
|
||||
flattened: flattenedSerializer,
|
||||
general: generalSerializer,
|
||||
detect
|
||||
}
|
130
node_modules/jose/lib/jws/sign.js
generated
vendored
Normal file
130
node_modules/jose/lib/jws/sign.js
generated
vendored
Normal file
@ -0,0 +1,130 @@
|
||||
const base64url = require('../help/base64url')
|
||||
const isDisjoint = require('../help/is_disjoint')
|
||||
const isObject = require('../help/is_object')
|
||||
const deepClone = require('../help/deep_clone')
|
||||
const { JWSInvalid } = require('../errors')
|
||||
const { sign } = require('../jwa')
|
||||
const getKey = require('../help/get_key')
|
||||
|
||||
const serializers = require('./serializers')
|
||||
|
||||
const PROCESS_RECIPIENT = Symbol('PROCESS_RECIPIENT')
|
||||
|
||||
class Sign {
|
||||
constructor (payload) {
|
||||
if (typeof payload === 'string') {
|
||||
payload = base64url.encode(payload)
|
||||
} else if (Buffer.isBuffer(payload)) {
|
||||
payload = base64url.encodeBuffer(payload)
|
||||
this._binary = true
|
||||
} else if (isObject(payload)) {
|
||||
payload = base64url.JSON.encode(payload)
|
||||
} else {
|
||||
throw new TypeError('payload argument must be a Buffer, string or an object')
|
||||
}
|
||||
|
||||
this._payload = payload
|
||||
this._recipients = []
|
||||
}
|
||||
|
||||
/*
|
||||
* @public
|
||||
*/
|
||||
recipient (key, protectedHeader, unprotectedHeader) {
|
||||
key = getKey(key)
|
||||
|
||||
if (protectedHeader !== undefined && !isObject(protectedHeader)) {
|
||||
throw new TypeError('protectedHeader argument must be a plain object when provided')
|
||||
}
|
||||
|
||||
if (unprotectedHeader !== undefined && !isObject(unprotectedHeader)) {
|
||||
throw new TypeError('unprotectedHeader argument must be a plain object when provided')
|
||||
}
|
||||
|
||||
if (!isDisjoint(protectedHeader, unprotectedHeader)) {
|
||||
throw new JWSInvalid('JWS Protected and JWS Unprotected Header Parameter names must be disjoint')
|
||||
}
|
||||
|
||||
this._recipients.push({
|
||||
key,
|
||||
protectedHeader: protectedHeader ? deepClone(protectedHeader) : undefined,
|
||||
unprotectedHeader: unprotectedHeader ? deepClone(unprotectedHeader) : undefined
|
||||
})
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
/*
|
||||
* @private
|
||||
*/
|
||||
[PROCESS_RECIPIENT] (recipient, first) {
|
||||
const { key, protectedHeader, unprotectedHeader } = recipient
|
||||
|
||||
if (key.use === 'enc') {
|
||||
throw new TypeError('a key with "use":"enc" is not usable for signing')
|
||||
}
|
||||
|
||||
const joseHeader = {
|
||||
protected: protectedHeader || {},
|
||||
unprotected: unprotectedHeader || {}
|
||||
}
|
||||
|
||||
let alg = joseHeader.protected.alg || joseHeader.unprotected.alg
|
||||
|
||||
if (!alg) {
|
||||
alg = key.alg || [...key.algorithms('sign')][0]
|
||||
if (recipient.protectedHeader) {
|
||||
joseHeader.protected.alg = recipient.protectedHeader.alg = alg
|
||||
} else {
|
||||
joseHeader.protected = recipient.protectedHeader = { alg }
|
||||
}
|
||||
}
|
||||
|
||||
if (!alg) {
|
||||
throw new JWSInvalid('could not resolve a usable "alg" for a recipient')
|
||||
}
|
||||
|
||||
recipient.header = unprotectedHeader
|
||||
recipient.protected = Object.keys(joseHeader.protected).length ? base64url.JSON.encode(joseHeader.protected) : ''
|
||||
|
||||
if (first && joseHeader.protected.crit && joseHeader.protected.crit.includes('b64') && joseHeader.protected.b64 === false) {
|
||||
if (this._binary) {
|
||||
this._payload = base64url.decodeToBuffer(this._payload)
|
||||
} else {
|
||||
this._payload = base64url.decode(this._payload)
|
||||
}
|
||||
}
|
||||
|
||||
const data = Buffer.concat([
|
||||
Buffer.from(recipient.protected || ''),
|
||||
Buffer.from('.'),
|
||||
Buffer.from(this._payload)
|
||||
])
|
||||
|
||||
recipient.signature = base64url.encodeBuffer(sign(alg, key, data))
|
||||
}
|
||||
|
||||
/*
|
||||
* @public
|
||||
*/
|
||||
sign (serialization) {
|
||||
const serializer = serializers[serialization]
|
||||
if (!serializer) {
|
||||
throw new TypeError('serialization must be one of "compact", "flattened", "general"')
|
||||
}
|
||||
|
||||
if (!this._recipients.length) {
|
||||
throw new JWSInvalid('missing recipients')
|
||||
}
|
||||
|
||||
serializer.validate(this, this._recipients)
|
||||
|
||||
this._recipients.forEach((recipient, i) => {
|
||||
this[PROCESS_RECIPIENT](recipient, i === 0)
|
||||
})
|
||||
|
||||
return serializer(this._payload, this._recipients)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Sign
|
202
node_modules/jose/lib/jws/verify.js
generated
vendored
Normal file
202
node_modules/jose/lib/jws/verify.js
generated
vendored
Normal file
@ -0,0 +1,202 @@
|
||||
const { EOL } = require('os')
|
||||
|
||||
const base64url = require('../help/base64url')
|
||||
const isDisjoint = require('../help/is_disjoint')
|
||||
const isObject = require('../help/is_object')
|
||||
let validateCrit = require('../help/validate_crit')
|
||||
const getKey = require('../help/get_key')
|
||||
const { KeyStore } = require('../jwks')
|
||||
const errors = require('../errors')
|
||||
const { check, verify } = require('../jwa')
|
||||
const JWK = require('../jwk')
|
||||
|
||||
const { detect: resolveSerialization } = require('./serializers')
|
||||
|
||||
validateCrit = validateCrit.bind(undefined, errors.JWSInvalid)
|
||||
const SINGLE_RECIPIENT = new Set(['compact', 'flattened', 'preparsed'])
|
||||
|
||||
/*
|
||||
* @public
|
||||
*/
|
||||
const jwsVerify = (skipDisjointCheck, serialization, jws, key, { crit = [], complete = false, algorithms } = {}) => {
|
||||
key = getKey(key, true)
|
||||
|
||||
if (algorithms !== undefined && (!Array.isArray(algorithms) || algorithms.some(s => typeof s !== 'string' || !s))) {
|
||||
throw new TypeError('"algorithms" option must be an array of non-empty strings')
|
||||
} else if (algorithms) {
|
||||
algorithms = new Set(algorithms)
|
||||
}
|
||||
|
||||
if (!Array.isArray(crit) || crit.some(s => typeof s !== 'string' || !s)) {
|
||||
throw new TypeError('"crit" option must be an array of non-empty strings')
|
||||
}
|
||||
|
||||
if (!serialization) {
|
||||
serialization = resolveSerialization(jws)
|
||||
}
|
||||
|
||||
let prot // protected header
|
||||
let header // unprotected header
|
||||
let payload
|
||||
let signature
|
||||
let alg
|
||||
|
||||
// treat general format with one recipient as flattened
|
||||
// skips iteration and avoids multi errors in this case
|
||||
if (serialization === 'general' && jws.signatures.length === 1) {
|
||||
serialization = 'flattened'
|
||||
const { signatures, ...root } = jws
|
||||
jws = { ...root, ...signatures[0] }
|
||||
}
|
||||
|
||||
let decoded
|
||||
|
||||
if (SINGLE_RECIPIENT.has(serialization)) {
|
||||
let parsedProt = {}
|
||||
|
||||
switch (serialization) {
|
||||
case 'compact': // compact serialization format
|
||||
([prot, payload, signature] = jws.split('.'))
|
||||
break
|
||||
case 'flattened': // flattened serialization format
|
||||
({ protected: prot, payload, signature, header } = jws)
|
||||
break
|
||||
case 'preparsed': { // from the JWT module
|
||||
({ decoded } = jws);
|
||||
([prot, payload, signature] = jws.token.split('.'))
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (!header) {
|
||||
skipDisjointCheck = true
|
||||
}
|
||||
|
||||
if (decoded) {
|
||||
parsedProt = decoded.header
|
||||
} else if (prot) {
|
||||
try {
|
||||
parsedProt = base64url.JSON.decode(prot)
|
||||
} catch (err) {
|
||||
throw new errors.JWSInvalid('could not parse JWS protected header')
|
||||
}
|
||||
} else {
|
||||
skipDisjointCheck = skipDisjointCheck || true
|
||||
}
|
||||
|
||||
if (!skipDisjointCheck && !isDisjoint(parsedProt, header)) {
|
||||
throw new errors.JWSInvalid('JWS Protected and JWS Unprotected Header Parameter names must be disjoint')
|
||||
}
|
||||
|
||||
const combinedHeader = { ...parsedProt, ...header }
|
||||
validateCrit(parsedProt, header, crit)
|
||||
|
||||
alg = parsedProt.alg || (header && header.alg)
|
||||
if (!alg) {
|
||||
throw new errors.JWSInvalid('missing JWS signature algorithm')
|
||||
} else if (algorithms && !algorithms.has(alg)) {
|
||||
throw new errors.JOSEAlgNotWhitelisted('alg not whitelisted')
|
||||
}
|
||||
|
||||
if (key instanceof KeyStore) {
|
||||
const keystore = key
|
||||
const keys = keystore.all({ kid: combinedHeader.kid, alg: combinedHeader.alg, key_ops: ['verify'] })
|
||||
switch (keys.length) {
|
||||
case 0:
|
||||
throw new errors.JWKSNoMatchingKey()
|
||||
case 1:
|
||||
// treat the call as if a Key instance was passed in
|
||||
// skips iteration and avoids multi errors in this case
|
||||
key = keys[0]
|
||||
break
|
||||
default: {
|
||||
const errs = []
|
||||
for (const key of keys) {
|
||||
try {
|
||||
return jwsVerify(true, serialization, jws, key, { crit, complete, algorithms: algorithms ? [...algorithms] : undefined })
|
||||
} catch (err) {
|
||||
errs.push(err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
const multi = new errors.JOSEMultiError(errs)
|
||||
if ([...multi].some(e => e instanceof errors.JWSVerificationFailed)) {
|
||||
throw new errors.JWSVerificationFailed()
|
||||
}
|
||||
throw multi
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (key === JWK.EmbeddedJWK) {
|
||||
if (!isObject(combinedHeader.jwk)) {
|
||||
throw new errors.JWSInvalid('JWS Header Parameter "jwk" must be a JSON object')
|
||||
}
|
||||
key = JWK.asKey(combinedHeader.jwk)
|
||||
if (key.type !== 'public') {
|
||||
throw new errors.JWSInvalid('JWS Header Parameter "jwk" must be a public key')
|
||||
}
|
||||
} else if (key === JWK.EmbeddedX5C) {
|
||||
if (!Array.isArray(combinedHeader.x5c) || !combinedHeader.x5c.length || combinedHeader.x5c.some(c => typeof c !== 'string' || !c)) {
|
||||
throw new errors.JWSInvalid('JWS Header Parameter "x5c" must be a JSON array of certificate value strings')
|
||||
}
|
||||
key = JWK.asKey(
|
||||
`-----BEGIN CERTIFICATE-----${EOL}${(combinedHeader.x5c[0].match(/.{1,64}/g) || []).join(EOL)}${EOL}-----END CERTIFICATE-----`,
|
||||
{ x5c: combinedHeader.x5c }
|
||||
)
|
||||
}
|
||||
|
||||
check(key, 'verify', alg)
|
||||
|
||||
const toBeVerified = Buffer.concat([
|
||||
Buffer.from(prot || ''),
|
||||
Buffer.from('.'),
|
||||
Buffer.isBuffer(payload) ? payload : Buffer.from(payload)
|
||||
])
|
||||
|
||||
if (!verify(alg, key, toBeVerified, base64url.decodeToBuffer(signature))) {
|
||||
throw new errors.JWSVerificationFailed()
|
||||
}
|
||||
|
||||
if (combinedHeader.b64 === false) {
|
||||
payload = Buffer.from(payload)
|
||||
} else {
|
||||
payload = base64url.decodeToBuffer(payload)
|
||||
}
|
||||
|
||||
if (complete) {
|
||||
const result = { payload, key }
|
||||
if (prot) result.protected = parsedProt
|
||||
if (header) result.header = header
|
||||
return result
|
||||
}
|
||||
|
||||
return payload
|
||||
}
|
||||
|
||||
// general serialization format
|
||||
const { signatures, ...root } = jws
|
||||
const errs = []
|
||||
for (const recipient of signatures) {
|
||||
try {
|
||||
return jwsVerify(false, 'flattened', { ...root, ...recipient }, key, { crit, complete, algorithms: algorithms ? [...algorithms] : undefined })
|
||||
} catch (err) {
|
||||
errs.push(err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
const multi = new errors.JOSEMultiError(errs)
|
||||
if ([...multi].some(e => e instanceof errors.JWSVerificationFailed)) {
|
||||
throw new errors.JWSVerificationFailed()
|
||||
} else if ([...multi].every(e => e instanceof errors.JWKSNoMatchingKey)) {
|
||||
throw new errors.JWKSNoMatchingKey()
|
||||
}
|
||||
throw multi
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
bare: jwsVerify,
|
||||
verify: jwsVerify.bind(undefined, false, undefined)
|
||||
}
|
Reference in New Issue
Block a user