dcc-decoder
Version:
<img alttext="COVID Green Logo" src="https://raw.githubusercontent.com/lfph/artwork/master/projects/covidgreen/stacked/color/covidgreen-stacked-color.png" width="300" />
92 lines (82 loc) • 2.26 kB
text/typescript
import cose from 'cose-js'
import cbor from 'cbor'
import NodeRSA from 'node-rsa'
import { SigningKey } from '../types'
import { ALGOS, CBOR_STRUCTURE } from '../types/hcert'
import * as errors from '../types/errors'
async function verifyECDSA(
message: Buffer,
keys: SigningKey[]
): Promise<boolean | Error> {
for (const key of keys) {
try {
const verifiedBuf = await cose.sign.verify(message, {
key: {
kid: key.kid,
x: Buffer.from(key.x, 'base64'),
y: Buffer.from(key.y, 'base64'),
},
})
if (verifiedBuf) {
// console.log('key worked', key.kid, key.country)
return true
}
} catch (e) {
console.log('Sig failed', key.kid, e)
}
}
return errors.invalidSignature()
}
const EMPTY_BUFFER = Buffer.alloc(0)
const rsaOptions = {
signingScheme: {
scheme: 'pss',
hash: 'sha256',
saltLength: 32,
},
}
async function verifyRSA(
message: Buffer,
keys: SigningKey[]
): Promise<boolean | Error> {
const decoded = cbor.decodeFirstSync(Buffer.from(message)).value
const protectedHeader = decoded[CBOR_STRUCTURE.PROTECTED_HEADER].length
? decoded[CBOR_STRUCTURE.PROTECTED_HEADER]
: cbor.encode(EMPTY_BUFFER)
const signature = decoded[CBOR_STRUCTURE.SIGNATURE]
const sigStructure = [
'Signature1',
protectedHeader,
EMPTY_BUFFER,
decoded[CBOR_STRUCTURE.PAYLOAD],
]
const toBeSigned = cbor.encode(sigStructure)
for (const key of keys) {
try {
const rsa = new NodeRSA(key.pem, 'pkcs8-public-pem')
rsa.setOptions(rsaOptions)
const result = rsa.verify(toBeSigned, signature, 'buffer')
// console.log('RESULT:', result)
if (result) {
// console.log('key worked', key.kid, key.country)
return true
}
} catch (e) {
console.log('Sig failed', key.kid, e)
}
}
return errors.invalidSignature()
}
export default async function verifySignature(
message: Buffer,
algo: ALGOS,
keys: SigningKey[]
): Promise<boolean | Error> {
if (algo === ALGOS.ECDSA_256) {
return verifyECDSA(message, keys)
} else if (algo === ALGOS.RSA_PSS_256) {
return verifyRSA(message, keys)
} else {
return errors.unknownSigAlgo()
}
}