Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | 41x 41x 41x 41x 41x 41x 5x 5x 6x 5x 1x 1x 5x 5x 5x 5x 5x 5x 5x 5x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x | import { verify } from '@noble/secp256k1';
import { base64ToBytes, bytesToHex, utf8ToBytes } from 'micro-stacks/common';
import base64url from './base64url';
import { joseToDerES256 } from './ecdsa-sig-formatter';
import { hashSha256 } from 'micro-stacks/crypto-sha';
import type { SignedToken } from './types';
export class TokenVerifier {
tokenType: string;
rawPublicKey: string;
constructor(signingAlgorithm: string, rawPublicKey: string) {
this.tokenType = 'JWT';
this.rawPublicKey = rawPublicKey;
}
verify(
token: string | SignedToken,
// @param {Boolean} strict - whether a signature s should be no more than 1/2 prime order.
// true makes signatures compatible with libsecp256k1, false makes signatures compatible with openssl
strict = false
): boolean {
if (typeof token === 'string') {
return this.verifyCompact(token, strict);
} else if (typeof token === 'object') {
return this.verifyExpanded(token, strict);
} else E{
return false;
}
}
verifyCompact(token: string, strict?: boolean): boolean {
// decompose the token into parts
const tokenParts = token.split('.');
// calculate the signing input hash
const signingInput = tokenParts[0] + '.' + tokenParts[1];
const performVerify = (signingInputHash: Uint8Array) => {
const signature = tokenParts[2];
// extract the signature as a DER array
const formatted: string = joseToDerES256(signature);
// verify the signed hash
return verify(
bytesToHex(base64ToBytes(formatted)),
bytesToHex(signingInputHash),
this.rawPublicKey,
{
// TODO: this should be true default
// is not compat with legacy tokens.
// change reflected here https://github.com/paulmillr/noble-secp256k1/releases/tag/1.4.0
strict,
}
);
};
const signingInputHash = hashSha256(utf8ToBytes(signingInput));
return performVerify(signingInputHash);
}
verifyExpanded(token: SignedToken, strict?: boolean): boolean {
const signingInput = [token['header'].join('.'), base64url.encode(token['payload'])].join('.');
let verified = true;
const performVerify = (signingInputHash: Uint8Array) => {
token['signature'].map((signature: string) => {
const formatted: string = joseToDerES256(signature);
const signatureVerified = verify(
bytesToHex(base64ToBytes(formatted)),
bytesToHex(signingInputHash),
this.rawPublicKey,
{
strict,
}
);
Iif (!signatureVerified) {
verified = false;
}
});
return verified;
};
const signingInputHash = hashSha256(utf8ToBytes(signingInput));
return performVerify(signingInputHash);
}
}
|