import * as cbor from 'cbor-web' ; import base45 from 'base45' ; import zlib from 'zlib' ; import { CertInfo , Trustlist } from './trustlist' ; import { Cose1 } from './cose1' ; import { Buffer } from 'buffer' ; import crypto from 'crypto-browserify' ; const ClaimKeyHcert = - 260 ; const ClaimKeyEuDgcV1 = 1 ; export interface EuDgcCert { "v" : EuDgcVaccincation [ ] ; "dob" : string ; "nam" : { "fn" : string ; "gn" : string ; "fnt" : string ; "gnt" : string ; } ; "ver" : string ; } export interface EuDgcVaccincation { "ci" : string ; "co" : string ; "dn" : number ; "dt" : string ; "is" : string ; "ma" : string ; "mp" : string ; "sd" : number ; "tg" : string ; "vp" : string ; } export interface ValidationOptions { certFilter ? : ( certInfo : CertInfo ) => boolean ; explicitCerts ? : CertInfo [ ] ; } export class EuDgc { param encodedData returns static async parse ( encodedData ) { return new Promise ( ( resolve , reject ) => { if ( encodedData . indexOf ( "HC1:" ) == 0 ) { encodedData = encodedData . substring ( 4 ) ; } const decodedData = base45 . decode ( encodedData ) ; zlib . inflate ( decodedData , function ( error , buf ) { const cborWeb = cbor ; try { cborWeb . decodeFirst ( buf , function ( error , obj ) { if ( error ) { reject ( error ) ; return ; } const t = obj ; const cwt = t . toJSON ( ) . value [ 2 ] ; cbor . decodeFirst ( cwt , function ( error , obj ) { if ( error ) { reject ( error ) ; return ; } const t2 = obj ; const hcertRaw = t2 . get ( ClaimKeyHcert ) ; const eudgc = hcertRaw . get ( ClaimKeyEuDgcV1 ) ; console . log ( JSON . stringify ( eudgc , null , 4 ) ) ; resolve ( eudgc ) ; } ) ; } ) ; } catch ( error ) { reject ( error ) ; } } ) ; } ) ; } static async validate ( encodedData , options ? ) { const cose1 = await Cose1 . valueOf ( encodedData ) ; if ( ! cose1 ) { return null ; } const raw = cose1 . makeDataForVerification ( ) ; const signature = Buffer . from ( cose1 . encodeSignature ( cose1 . signatures ) ) . toString ( "hex" ) ; var certInfos = await Trustlist . instance . getCertInfos ( ) ; if ( options ?. explicitCerts ) { certInfos = [ ... options ?. explicitCerts ] ; } if ( options ?. certFilter ) { const oldCount = certInfos . length ; certInfos = certInfos . filter ( options ?. certFilter ) ; if ( certInfos . length != oldCount ) { console . info ( "#" + ( oldCount - certInfos . length ) + " of " + oldCount + " certifcates removed by filter" ) ; } } for ( let i = 0 , n = certInfos . length ; i < n ; i ++ ) { const certInfo = certInfos [ i ] ; try { const verify = crypto . createVerify ( "sha256" ) ; verify . update ( raw ) ; const verification = verify . verify ( certInfo . pubkey , signature , "hex" ) ; if ( verification ) { const now = new Date ( ) . getTime ( ) ; const timeValid = now >= certInfo . notbefore && now <= certInfo . notafter ; if ( timeValid ) { return certInfo ; } } } catch ( e ) { console . warn ( "unable to handle cert " + ( i + 1 ) + " of " + n + ": " + certInfo . subject + ": " + e ) ; } } throw "Not matching certificate found" ; } } export const EuDgc_parse = EuDgc . parse ; export const EuDgc_validate = EuDgc . validate ; if ( typeof window !== "undefined" ) { ( window as any ) . EuDgc_parse = EuDgc . parse ; ( window as any ) . EuDgc_validate = EuDgc . validate ; } console . log ( "eudgc.ts" ) ;