chore: crush git history - reborn from consolidation on 2026-03-10
This commit is contained in:
@@ -0,0 +1,263 @@
|
||||
/**
|
||||
* P2 Protocol Conformance Tests
|
||||
*
|
||||
* Additional test vectors for JWT (RS256, ES256), HTTP Signature edge cases,
|
||||
* and X.509/SPIFFE strictness beyond the base protocol-extensions.test.ts.
|
||||
*/
|
||||
|
||||
import { test } from 'node:test'
|
||||
import assert from 'node:assert'
|
||||
import { createSign, generateKeyPairSync } from 'node:crypto'
|
||||
import { jwtExtension } from '../../extensions/jwt.js'
|
||||
import { httpSignatureExtension } from '../../extensions/http-signature.js'
|
||||
import type { PredicateContext } from '../../extension/types.js'
|
||||
|
||||
const makeCtx = (overrides: Partial<PredicateContext['evalContext']> = {}): PredicateContext['evalContext'] => ({
|
||||
request: {
|
||||
body: undefined,
|
||||
headers: {},
|
||||
query: {},
|
||||
params: {},
|
||||
},
|
||||
response: {
|
||||
body: undefined,
|
||||
headers: {},
|
||||
statusCode: 200,
|
||||
},
|
||||
...overrides,
|
||||
} as PredicateContext['evalContext'])
|
||||
|
||||
const makeRoute = () => ({
|
||||
path: '/test',
|
||||
method: 'GET' as const,
|
||||
category: 'observer' as const,
|
||||
requires: [],
|
||||
ensures: [],
|
||||
invariants: [],
|
||||
regexPatterns: {},
|
||||
validateRuntime: true,
|
||||
})
|
||||
|
||||
// ============================================================================
|
||||
// JWT: RS256 and ES256 verification vectors
|
||||
// ============================================================================
|
||||
|
||||
test('jwt: validates RS256 signature with RSA public key', () => {
|
||||
const { privateKey, publicKey } = generateKeyPairSync('rsa', { modulusLength: 2048 })
|
||||
const payload = { sub: 'user-123', iat: Math.floor(Date.now() / 1000) }
|
||||
const header = { alg: 'RS256', typ: 'JWT' }
|
||||
const encodedHeader = Buffer.from(JSON.stringify(header)).toString('base64url')
|
||||
const encodedPayload = Buffer.from(JSON.stringify(payload)).toString('base64url')
|
||||
const signingInput = `${encodedHeader}.${encodedPayload}`
|
||||
const signer = createSign('RSA-SHA256')
|
||||
signer.update(signingInput)
|
||||
signer.end()
|
||||
const signature = signer.sign(privateKey).toString('base64url')
|
||||
const token = `${signingInput}.${signature}`
|
||||
|
||||
const ext = jwtExtension({
|
||||
keys: { default: publicKey.export({ type: 'spki', format: 'pem' }).toString() },
|
||||
verify: true,
|
||||
})
|
||||
const state = ext.onSuiteStart!({}) as Record<string, unknown>
|
||||
|
||||
const ctx: PredicateContext = {
|
||||
route: makeRoute(),
|
||||
evalContext: makeCtx({
|
||||
request: {
|
||||
body: undefined,
|
||||
headers: { authorization: `Bearer ${token}` },
|
||||
query: {},
|
||||
params: {},
|
||||
},
|
||||
}),
|
||||
accessor: [],
|
||||
extensionState: state,
|
||||
}
|
||||
|
||||
const result = ext.predicates!.jwt_valid!(ctx)
|
||||
assert.ok(result.success)
|
||||
assert.strictEqual(result.value, true)
|
||||
})
|
||||
|
||||
test('jwt: rejects RS256 token with wrong public key', () => {
|
||||
const { privateKey } = generateKeyPairSync('rsa', { modulusLength: 2048 })
|
||||
const { publicKey: wrongPublicKey } = generateKeyPairSync('rsa', { modulusLength: 2048 })
|
||||
const payload = { sub: 'user-123', iat: Math.floor(Date.now() / 1000) }
|
||||
const header = { alg: 'RS256', typ: 'JWT' }
|
||||
const encodedHeader = Buffer.from(JSON.stringify(header)).toString('base64url')
|
||||
const encodedPayload = Buffer.from(JSON.stringify(payload)).toString('base64url')
|
||||
const signingInput = `${encodedHeader}.${encodedPayload}`
|
||||
const signer = createSign('RSA-SHA256')
|
||||
signer.update(signingInput)
|
||||
signer.end()
|
||||
const signature = signer.sign(privateKey).toString('base64url')
|
||||
const token = `${signingInput}.${signature}`
|
||||
|
||||
const ext = jwtExtension({
|
||||
keys: { default: wrongPublicKey.export({ type: 'spki', format: 'pem' }).toString() },
|
||||
verify: true,
|
||||
})
|
||||
const state = ext.onSuiteStart!({}) as Record<string, unknown>
|
||||
|
||||
const ctx: PredicateContext = {
|
||||
route: makeRoute(),
|
||||
evalContext: makeCtx({
|
||||
request: {
|
||||
body: undefined,
|
||||
headers: { authorization: `Bearer ${token}` },
|
||||
query: {},
|
||||
params: {},
|
||||
},
|
||||
}),
|
||||
accessor: [],
|
||||
extensionState: state,
|
||||
}
|
||||
|
||||
const result = ext.predicates!.jwt_valid!(ctx)
|
||||
assert.ok(result.success)
|
||||
assert.strictEqual(result.value, false)
|
||||
})
|
||||
|
||||
test('jwt: validates ES256 signature with EC public key', () => {
|
||||
const { privateKey, publicKey } = generateKeyPairSync('ec', { namedCurve: 'P-256' })
|
||||
const payload = { sub: 'user-123', iat: Math.floor(Date.now() / 1000) }
|
||||
const header = { alg: 'ES256', typ: 'JWT' }
|
||||
const encodedHeader = Buffer.from(JSON.stringify(header)).toString('base64url')
|
||||
const encodedPayload = Buffer.from(JSON.stringify(payload)).toString('base64url')
|
||||
const signingInput = `${encodedHeader}.${encodedPayload}`
|
||||
const signer = createSign('SHA256')
|
||||
signer.update(signingInput)
|
||||
signer.end()
|
||||
const signature = signer.sign(privateKey).toString('base64url')
|
||||
const token = `${signingInput}.${signature}`
|
||||
|
||||
const ext = jwtExtension({
|
||||
keys: { default: publicKey.export({ type: 'spki', format: 'pem' }).toString() },
|
||||
verify: true,
|
||||
})
|
||||
const state = ext.onSuiteStart!({}) as Record<string, unknown>
|
||||
|
||||
const ctx: PredicateContext = {
|
||||
route: makeRoute(),
|
||||
evalContext: makeCtx({
|
||||
request: {
|
||||
body: undefined,
|
||||
headers: { authorization: `Bearer ${token}` },
|
||||
query: {},
|
||||
params: {},
|
||||
},
|
||||
}),
|
||||
accessor: [],
|
||||
extensionState: state,
|
||||
}
|
||||
|
||||
const result = ext.predicates!.jwt_valid!(ctx)
|
||||
assert.ok(result.success)
|
||||
assert.strictEqual(result.value, true)
|
||||
})
|
||||
|
||||
test('jwt: rejects ES256 token with wrong public key', () => {
|
||||
const { privateKey } = generateKeyPairSync('ec', { namedCurve: 'P-256' })
|
||||
const { publicKey: wrongPublicKey } = generateKeyPairSync('ec', { namedCurve: 'P-256' })
|
||||
const payload = { sub: 'user-123', iat: Math.floor(Date.now() / 1000) }
|
||||
const header = { alg: 'ES256', typ: 'JWT' }
|
||||
const encodedHeader = Buffer.from(JSON.stringify(header)).toString('base64url')
|
||||
const encodedPayload = Buffer.from(JSON.stringify(payload)).toString('base64url')
|
||||
const signingInput = `${encodedHeader}.${encodedPayload}`
|
||||
const signer = createSign('SHA256')
|
||||
signer.update(signingInput)
|
||||
signer.end()
|
||||
const signature = signer.sign(privateKey).toString('base64url')
|
||||
const token = `${signingInput}.${signature}`
|
||||
|
||||
const ext = jwtExtension({
|
||||
keys: { default: wrongPublicKey.export({ type: 'spki', format: 'pem' }).toString() },
|
||||
verify: true,
|
||||
})
|
||||
const state = ext.onSuiteStart!({}) as Record<string, unknown>
|
||||
|
||||
const ctx: PredicateContext = {
|
||||
route: makeRoute(),
|
||||
evalContext: makeCtx({
|
||||
request: {
|
||||
body: undefined,
|
||||
headers: { authorization: `Bearer ${token}` },
|
||||
query: {},
|
||||
params: {},
|
||||
},
|
||||
}),
|
||||
accessor: [],
|
||||
extensionState: state,
|
||||
}
|
||||
|
||||
const result = ext.predicates!.jwt_valid!(ctx)
|
||||
assert.ok(result.success)
|
||||
assert.strictEqual(result.value, false)
|
||||
})
|
||||
|
||||
// ============================================================================
|
||||
// HTTP Signature: negative corpus and edge cases
|
||||
// ============================================================================
|
||||
|
||||
test('httpSignature: rejects unsupported signature algorithm', () => {
|
||||
const { privateKey } = generateKeyPairSync('rsa', { modulusLength: 2048 })
|
||||
const signatureInput = 'sig1=("@method")'
|
||||
const signer = createSign('SHA512')
|
||||
signer.update('dummy')
|
||||
signer.end()
|
||||
const signature = signer.sign(privateKey).toString('base64')
|
||||
|
||||
const ext = httpSignatureExtension()
|
||||
const ctx: PredicateContext = {
|
||||
route: makeRoute(),
|
||||
evalContext: makeCtx({
|
||||
request: {
|
||||
body: undefined,
|
||||
headers: {
|
||||
signature: `sig1=:${signature}:`,
|
||||
'signature-input': signatureInput,
|
||||
},
|
||||
query: {},
|
||||
params: {},
|
||||
},
|
||||
}),
|
||||
accessor: [],
|
||||
extensionState: {},
|
||||
}
|
||||
|
||||
const result = ext.predicates!.signature_valid!(ctx)
|
||||
assert.ok(result.success)
|
||||
assert.strictEqual(result.value, false)
|
||||
})
|
||||
|
||||
test('httpSignature: rejects signature with mismatched label', () => {
|
||||
const { privateKey, publicKey } = generateKeyPairSync('rsa', { modulusLength: 2048 })
|
||||
const ext = httpSignatureExtension({ publicKey: publicKey.export({ type: 'spki', format: 'pem' }).toString() })
|
||||
const signatureInput = 'sig1=("@method")'
|
||||
const signer = createSign('SHA256')
|
||||
signer.update('dummy')
|
||||
signer.end()
|
||||
const signature = signer.sign(privateKey).toString('base64')
|
||||
|
||||
const ctx: PredicateContext = {
|
||||
route: makeRoute(),
|
||||
evalContext: makeCtx({
|
||||
request: {
|
||||
body: undefined,
|
||||
headers: {
|
||||
signature: `sig2=:${signature}:`,
|
||||
'signature-input': signatureInput,
|
||||
},
|
||||
query: {},
|
||||
params: {},
|
||||
},
|
||||
}),
|
||||
accessor: [],
|
||||
extensionState: {},
|
||||
}
|
||||
|
||||
const result = ext.predicates!.signature_valid!(ctx)
|
||||
assert.ok(result.success)
|
||||
assert.strictEqual(result.value, false)
|
||||
})
|
||||
Reference in New Issue
Block a user