B4A Library CovidPass - the reader

see bottom of this post for "important" update.
LOOK FURTHER DOWN FOR UPDATED VERSION. MAYBE POST #12
LOOK EVEN FURTHER DOWN FOR A LITTLE JSON PARSING ROUTINE AND EXPLANATION
LOOK EVEN FURTHER FURTHER FOR A PARSING CLASS. IN ADDITION TO THE EU GREEN PASS, I'VE ADDED THE FRENCH SANIPASS)
here's a fun project that cost me several nights' sleep. it reads what i hear is called a covid pass.

my government and many of my fellow citizens don't believe covid is real, so we're not allowed to have any covid-themed artifacts, such as proof one has been vaccinated (against what, right?). but they say other countries have such proofs.

i've tested it with some known, valid covid passes. there are none here, so i'm limited. try it and report back if you like.

a couple notes:
the library merely decodes the pass. it doesn't verify its validity. you need the public keys for that. and it doesn't generate a fake pass, since you'll only blame me if you're caught counterfeiting them.

i didn't attach a qr code scanner. we have a ton thanks to member schoeman's tireless work. once you have read the qr code, you feed the decoded string to my reader. unzip the attached to your additional libraries folder and add the library to your project. initialize it and call the decodePass() method. it should fit in with any scanner app you've written. just add the decodePass() with what the qr code says you scanned. display the result in a label or - why not - a webview!:)

images of covid qr codes that i found online were mostly bogus. the current version of the decoded string must begin with "HC1:". if you don't see that when you scan the qr code, don't bother with anything else. and even if "HC1:" is there, the code has to have been decoded correctly. i've tried with both google's version of zxing and zxing's own qr code reader. google always came back with something. zxing had some trouble occasionally, but i was scanning images from a browser. so, to be clear, if the decoded qr code returns a string beginning with "HC1:", then you call the decoder, passing the string. that "header" may change or other headers may exists for different types of covid-related digital forms. who knows what condition we'll all be in by that time.

the resultant string comes back to you as a json string (or json-like). i didn't feed it to a json parser, but it certainly looked like json.
see further down regarding json. it's dealt with in version 0.02, found below. the eu uses json, but the decoder returns the result in a slightly different format.

my interest at this point is hearing if valid passes are successfully decoded. as i said, i have virtually no access to such documents. validation seems pointless unless you're a volunteer covid policeman looking for fake passes. basically, if i see some kind of scannable code, i like to scan it. it's annoying when i can't decode it, like they're trying to keep something from me. if you find a covid pass on the ground, you can decode it with your app and claim your reward. maybe you should wear gloves before picking it up.

the library is govidpass - with a "g". i don't want to be sued by somebody who has copyrighted the word "covid"

update: the library itself is quite small. unfortunately the required dependencies put me over the limit for posting here. if you want a functioning library, download from here: ""

(i had to put the url in quotes because something very strange happened, and i couldn't make it go away)


there is a readme which basically instructs you to copy the jars to your additional libraries folder and to add some compiler options to your app. (thanks to yiankos1 for the heads up. and apologies for the inconvenience)
 
Last edited:

drgottjr

Expert
Licensed User
Longtime User
thanks. i just saw the sample you posted nov 9. unusual format, perhaps only used in the philippines. i need to look into it. also thanks for the link; i'll take a look. the specifications may be there.
 

Johan Schoeman

Expert
Licensed User
Longtime User
I can scan and read this one:

1638098363234.png


Result is:

B4X:
{"4":1624458597,"6":1624285797,"1":"AT","-260":{"1":{"v":[{"dn":1,"ma":"ORG-100030215","vp":"1119349007","dt":"2021-02-18","co":"AT","ci":"URN:UVCI:01:AT:10807843F94AEE0EE5093FBC254BD813#B","mp":"EU/1/20/1528","is":"Ministry of Health, Austria","sd":2,"tg":"840539006"}],"nam":{"fnt":"MUSTERFRAU<GOESSINGER","fn":"Musterfrau-Gößinger","gnt":"GABRIELE","gn":"Gabriele"},"ver":"1.2.1","dob":"1998-02-26"}}}

No joy with the QR code in post #13. It gives this error:

B4X:
*** Service (starter) Create ***
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
Scanned String = PK
��������#GS÷uÛçt����C����������certificate.jsonuSÛ¢Hý}jp¼àÓ"8ÃMÀnlLPHy¦
PìèÄv»{#v# 2ëäIÎÉäÿ3ʳßJ~òeÁ&½Þõzí^ûÝz {Å1ÎJάWüË0&uuǽEÉð¿±*Iµu¿ðeSà¶ÓS±ú^æyb'Ϻ/×PþIîUáGðÕ¯ONÞÁå"KÅÞÜG$2ti¡ºg*3ólCÑMÅâLÅ´À{éá@LÅAç!¢<uD©#ù7àg¬Â´í¸08Í^ðï)EXCeË/    Ø0òÅÁd0ýîx ík
¢Ö×÷/ý/%QÅ¡ümu¦%8AwI_î>Lý´5+De> *@^¤Íݼjot#ÊܳÝåYââܶ!Ù«    Eg®s
åO.QÆÎ8%]àºÜ_PV%(*+ú°g§Lû{Z?¿$;BßÄÔ>]Q÷Ç DPè¬AÄ!3)vâÏ1Ê|[b)6ç¸ ÆRuÅà¶çè¾b��ckkG5¯²6ïÓãßÞÞÀ(íSP`Ún$Ü´Âï~åÉsòÈíÁ?6$Åÿ=ôVOýØôè1iÞbcOôÊþiåT´xÈçØK¿¼ðÇk;3Ü,Óp,Wë».ZDgúE@ùpùÎ"i
±Õ ÝØgFc ègQîv-c<3§på?2Oë£Û.PgîÝL~ªæi(æþ×<)6⻣��h¤[©Öl¡BV]k§ÄYÛ©ßÜ=ùÉtQÏÊe38mwaX^#©¥GçkÚ¾vòiä$DÝ{öØáHþ¶NVÛnÊ0[ÈÃÍwõúmá_acòKºx²æ]]W|o ©+¿V{ÿÔ¹fÜ,;Á`¯°¾Zj(dÂtdìb²£ó[nÜ) ܱma'«ÿsºÙeL¾ßB{ªÉiT£Ò=âÔÔzçnAÿ.,×cÍöºoʶël
s\o¦µ5Öé)XY¦TRàP´Û
T,FhnÌ/+Ø ßPK��
��������#GS÷uÛçt����C��������������������������������������certificate.jsonPK������������>������¢��������
could not decode Base45 string: java.lang.IllegalArgumentException
main_bs1_scan_value (java line: 381)
java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.String.length()' on a null object reference
    at anywheresoftware.b4a.BA.addLogPrefix(BA.java:604)
    at anywheresoftware.b4a.keywords.Common.LogImpl(Common.java:191)
    at jhs.CovidGreenPassScan.main._bs1_scan_value(main.java:381)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:213)
    at anywheresoftware.b4a.BA$2.run(BA.java:387)
    at android.os.Handler.handleCallback(Handler.java:873)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7032)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965)
 

Attachments

  • covidGreenPassScan.zip
    24.3 KB · Views: 218
Last edited:

drgottjr

Expert
Licensed User
Longtime User
@Johan Schoeman
thanks for incorporating the library.

the qr code in #13 isn't an EU covid cert so the govidpass
library won't recognize it, plus it is most likely bogus.
by that i mean not only invalid but incorrectly formatted.
i've spent a lot of time with it, and i've been
unable to find another like it online to verify this belief.

the leading PK is the giveaway. it's the signature for
a (pk)zipped file, but it's not valid. the layout is very, very
similar to a zip archive. if you examine it and compare it
to a zip file structure, you'll see how close it is. the
structure of the certificate (it seems to be divoc or
possible cowin for s.e. asia use) is supposed to be a zip
file. that much i know for sure. the payload is buried in
the archive (you can see its name in clear text). it's a
compressed json string. at this point i am too tired to
continue with this project, but i am pretty sure it would be
possible to extract the compressed json part and
[un|de]compress it alone. having written a zip parser, i
know how i would go about it.

i'm giving up on the project, but i have amassed about a
dozen different decoder/recognizers since i first stumbled
upon the green pass. you would not believe what is out
there (or maybe you would).

the whole thing is a b4a class with some inline java (not
unlike how you built one of your early zxing coder/decoders).
i also moved my library code into it, so it's all under one
roof. i've separated all the scanning-related parts from the
parsing parts. unfortunately, all those additional jars are
still needed, but as a b4a class, it would be easier to modify
both the b4a code as well as the java. i'm never going to see
any of these codes here, and i did learn a lot, but the moment
has passed. if you want the class, i'll send it to you. i'm also
happy to answer any questions. pm me.
 

ismamokan

Member
I think so, its a compressed json string but anyhow, thanks so much for trying to decode the qrcode. I am very much interested on your class. again, thank you very much.
 

drgottjr

Expert
Licensed User
Longtime User
I think so, its a compressed json string but anyhow, thanks so much for trying to decode the qrcode. I am very much interested on your class. again, thank you very much.
if you don't mind my asking, exactly what is your interest? the certificates used in s.e. asia are different from those used in, eg, the e.u. in addition, the governments in s.e. asia make it very difficult (if not impossible) to read the digital certificates without accessing government websites. plus, these certificates are not things you will see in public. aside from attempting to read your own digital certificate, i don't see how the class (or my library) can help you. what is it you were hoping to do?
 

Johan Schoeman

Expert
Licensed User
Longtime User
An interesting read.

 

drgottjr

Expert
Licensed User
Longtime User
similar to the one i read and which served as the base for my library. assembling and de-sugaring the base45, cbor and cose dependencies was the interesting part. things start to drag when you realize that the e.u.'s version of a covid certificate is just one of many - mutually incompatible - versions.

as a coding exercise, it was useful. but unlike the ubiquitous qr codes one sees in print, in shop windows, in restaurants and at museum and airport entrances - all just waiting to be scanned - the only covid qr code you will see in practice is your own. or maybe you can amuse your friends by reading their covid certificates at a party.
 

drgottjr

Expert
Licensed User
Longtime User
just to tie up a loose end: the code posted by member ismamokan appears to be a pkpass (aka, apple wallet) file. pkpass is a zip file. it's readable as a zip file. as with any zip file, it can contain all sorts of mime types, the most conspicuous of these being a json file with all the meat you're looking for. a key is required to validate the certificate, but extracting the json is straightforward. unfortunately, the qr code uploaded to the forum seems to be corrupted.
 
Last edited:

Herbert32

Active Member
Licensed User
Longtime User
my government and many of my fellow citizens don't believe covid is real, so we're not allowed to have any covid-themed artifacts, such as proof one has been vaccinated (against what, right?). but they say other countries have such proofs.
hi & thx for sharing your work

may I ask where you are located?
 

drgottjr

Expert
Licensed User
Longtime User
are you from the covid police?:rolleyes:
 

Herbert32

Active Member
Licensed User
Longtime User
would I say 'yes' if I am? - just kidding

I just want to know which countries denies the existance of covid19. I heared from Turkmenistan that it's not allowed to talk public about it in 2020 but in july this year they made vaccination mandatory for citizens which are 18+yrs old...
 

drgottjr

Expert
Licensed User
Longtime User
now you are definitely sounding like covid police.
turkmenistan? very nice! 🇹🇲
 

Blu Blu

Member
Licensed User
Execuse me for distrub,
when i use your library ,it tells me that i need go_cose-X.X.X.jar and some others. I can't find anywhere to download these libraries.Could you help me???
Thank you very much in advance
 

drgottjr

Expert
Licensed User
Longtime User
1) the jars should be in the zip. another user says he can use the library, so they must have been included. please check.
2) you need to do 2 things with the jars:
a) copy them to your additional libraries folder
b) refer to them in your app
B4X:
#AdditionalJar: cbor-4.4.4
    #AdditionalJar: go_cose-java-1.1.0
    #AdditionalJar: base45
    #AdditionalJar: go_cbor-0.01.02
    #AdditionalJar: numbers-1.8.2

as i recall, i mention this in one of the early posts. i am sorry if i didn't
 

Blu Blu

Member
Licensed User
Sorry, this is my problem, because when I opened the zip, it showed that the file I requested did not exist, could you please help me check it again?
 

drgottjr

Expert
Licensed User
Longtime User
i will put the zip together again and upload to server again today. i have to find everything. i will post url here later today. you can check later.
 

drgottjr

Expert
Licensed User
Longtime User
ok, so here is link:
the .jars are too big to upload to forum, so you have to download archive from google drive. let me know if there is a problem.
follow the instructions. copy all .jars + the .xml file to your additional libraries folder. in your app, select the govid library to include in your project, and refer to all the other jars as follows:
B4X:
    #AdditionalJar: cbor-4.4.4
    #AdditionalJar: go_cose-java-1.1.0
    #AdditionalJar: base45-.0.0.3
    #AdditionalJar: go_cbor-0.01.02
    #AdditionalJar: numbers-1.8.2

at the time, it seemed very exciting to read a covid pass, but there really isn't all that much visible, plus it isn't like reading qr codes that you see every day everywhere. a covid pass is only on a person's phone, and you can only see it if the person shows it to you. very limited access. and without encryption keys, you don't know if the
pass is valid or not. more interesting is how the pass is decoded. if you know some java, you can study the library. the encoding uses Base45, CBOR Object Signing and Encryption (COSE), and HMAC for authentication. unfortunately, without keys - which are kept on servers - you can't say if the pass is real. you can only read somebody's name and the dates when vaccination or tests were carried out. those data could be real, they could be false. but at least we can know what the pass says:)
 

Blu Blu

Member
Licensed User
Thank you very much ,i try right now and i will tell you if everything is ok.Thank you also for the instruction how work one qr code, thank you very much
 

Blu Blu

Member
Licensed User
Thanks very much,
here is the string: gp.decodePass(EditText1.Text)={"4":1637148824,"6":1621593224,"1":"IT","-260":{"1":{"v":[{"dn":2,"ma":"ORG-100030215","vp":"1119349007","dt":"2021-04-10","co":"IT","ci":"01ITE7300E1AB2A84C719004F103DCB1F70A#6","mp":"EU/1/20/1528","is":"IT","sd":2,"tg":"840539006"}],"nam":{"fnt":"DI<CAPRIO","fn":"Di Caprio","gnt":"MARILU<TERESA","gn":"Marilù Teresa"},"ver":"1.0.0","dob":"1977-06-16"}}}
you are so awesome,I can never do it without you
Thank you again
 
Top