Package: cwa-qr
Python implementation of the Corona-Warn-App (CWA) Event RegistrationThis is an implementation of the Protocol used to generate event and location QR codes for the Corona-Warn-App (CWA) as described inCorona-Warn-App: Documentation – Event Registration - Summary.This is not an official implementation – use it at your own risk(as far as that's possible, these days…).StateThe Interface described in the Document is implemented, the undocumented pieces (Public Key Value, Seed Length, Versions etc.) have been taken from the Open Source iOS Client Application. As far as I know the interface has been fully implemented, but without an actual positive Corona Test there is no way to do an End-to-End verification.UsageUse as follows:#!/usr/bin/env python3fromdatetimeimportdatetime,time,timezoneimportcwa_qr# Construct Event-Descriptorevent_description=cwa_qr.CwaEventDescription()event_description.location_description='Zuhause'event_description.location_address='Gau-Odernheim'event_description.start_date_time=datetime(2021,4,25,8,0).astimezone(timezone.utc)event_description.end_date_time=datetime(2021,4,25,18,0).astimezone(timezone.utc)event_description.location_type=cwa_qr.CwaLocation.permanent_workplaceevent_description.default_check_in_length_in_minutes=4*60# Renew QR-Code every night at 4:00seed_date=event_description.seed=cwa_qr.rollover_date(datetime.now(),time(4,0))print("seedDate",seed_date)event_description.seed="Some Secret"+str(seed_date)# Generate QR-Codeqr=cwa_qr.generate_qr_code(event_description)# Save as PNGimg=qr.make_image(fill_color="black",back_color="white")img.save('example.png')print("generated example.png")Seeexample_full.pyfor an example using all features.CwaEventDescriptionlocation_description: Description of the Location, Optional, String, max 100 Characterslocation_address: Address of the Location, Optional, String, max 100 Charactersstart_date_time: Start of the Event, Optional, datetime in UTCend_date_time: End of the Event, Optional, datetime in UTCCaution, QR-Codes generated with different start/end times will have different Event-IDs and not warn users that
have checked in with the other Code.Do not usedatetime.now()for start/end-date. For repeating Events usecwa_qr.rollover_dateto get a defined rollover.location_type: Type of the Location, Optional, one ofcwa.CwaLocation.unspecifiedcwa.CwaLocation.permanent_othercwa.CwaLocation.temporary_othercwa.CwaLocation.permanent_retailcwa.CwaLocation.permanent_food_servicecwa.CwaLocation.permanent_craftcwa.CwaLocation.permanent_workplacecwa.CwaLocation.permanent_educational_institutioncwa.CwaLocation.permanent_public_buildingcwa.CwaLocation.temporary_cultural_eventcwa.CwaLocation.temporary_club_activitycwa.CwaLocation.temporary_private_eventcwa.CwaLocation.temporary_worship_servicedefault_check_in_length_in_minutes: Default Check-out time in minutes, Optionalseed: Seed to rotate the QR-Code, Optional,[str, bytes, int, float, date, datetime]orNone(Default).Use with caution & read below!If unsure, leave blank.Rotating QR-CodesFrom theDocumentation:Profiling of VenuesAn adversary can collect this information for a single venue by scanning the QR code and extracting and storing the
data. To mitigate the risk, CWA encourages owners to regularly generate new QR codes for their venues. The more
frequent QR codes are updated, the more difficult it is to keep a central database with venue data up-to-date.However, a new QR code should only be generatedwhen no visitor is at the event or location, because
visitors can only warn each otherwith the same QR code.From an Application-Developers point of view, special care must be taken to decide if and when QR codes should be
changed. A naive approach, i.e. changing the QR-Code on every call, would render the complete Warning-Chain totally
uselesswithout anyone noticing. Therefore, the Default of this Library as of 2021/04/26 is tonot seed the
QR-Codes with random values. This results in every QR-Code being generated without an explicit Seed to be identical,
which minimizes the Risk of having QR-Codes that do not warn users as expected at the increased risk of profiling of
Venues.As an Application-Developer you are encouraged toask you user if and when they want their QR-Codes to changeand
explain to them that they should only rotate their Codeswhen they are sure that nobody is at the location or in the
venuefor at least 30 Minutes, to allow airborne particles to settle or get filtered out. Donot make assumptionsregarding a good time to rotate QR-Codes (i.e. always at 4:00 am) because they will fail so warn people in some
important Situations (nightclubs, hotels, night-shift working)without anyone noticing.To disable rotation of QR-Codes, specify None as the Seed (Default behaviour).The Library also gives you a utility to allow rotating QR-Codes at a given time of the day. Please make
sure to also integrate some kind of Secret into the seed, to prevent an adversary from calculating  future QR-Codes.
The Secretmust stay constantover time, or the resulting QR-Codes will not correctly trigger warnings.importiofromdatetimeimportdatetime,timeimportcwa_qr# Construct Event-Descriptorevent_description=cwa_qr.CwaEventDescription()# …seed_date=cwa_qr.rollover_date(datetime.now(),time(4,0))event_description.seed="Some Secret"+str(seed_date)this will keep the date-based seed until 4:00 am on the next day and only then roll over to the next day.
Seetest_rollover.pyfor an in-depth look at the rollover code.PostersThis Library has Support for compositing the QR-Code with a Poster, explaining its usage:
"Checken Sie ein, stoppen Sie das Virus". The Poster-Functionality works by composing the QR-Code SVG with the
Poster-SVG and thus only supports SVG-Output. Both Landscape and Portrait-Posters are supported.You can usepyrsvgif you need to convert the poster to a PNG
orsvglibto convert it to a PDF.Seeexample_full.pyfor an Example on how to use the Poster-Functionality.Python 2/3This library supports Python 3.7+, however there is a backport to Python 2 available athttps://github.com/MaZderMind/cwa-qr/tree/py2