Python Implementation of the CoronaWarnApp (CWA) Event Registration

Overview

Python implementation of the Corona-Warn-App (CWA) Event Registration

GitHub PyPI

This is an implementation of the Protocol used to generate event and location QR codes for the Corona-Warn-App (CWA) as described in Corona-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…).

State

The 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.

Usage

Use as follows:

#!/usr/bin/env python3

import io
from datetime import datetime, time, timezone

import cwa_qr
import qrcode.image.svg

# Construct Event-Descriptor
event_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.lowlevel.LOCATION_TYPE_PERMANENT_WORKPLACE
event_description.default_check_in_length_in_minutes = 4 * 60

# Renew QR-Code every night at 4:00
event_description.seed = cwa_qr.rollover_date(datetime.now(), time(4, 0))

# Generate QR-Code
qr = cwa_qr.generate_qr_code(event_description)

# Render QR-Code to PNG-File
img = qr.make_image(fill_color="black", back_color="white")
img.save('example.png')
print("generated example.png")

# Render QR-Code to PNG BytesIO-Object for further usage
img_bytes = io.BytesIO()
img.save(img_bytes)
print(len(img_bytes.getvalue()), " bytes of png")

# Render QR-Code to SVG-File
svg = qr.make_image(image_factory=qrcode.image.svg.SvgPathFillImage)
svg.save('example.svg')

# Render QR-Code to SVG BytesIO-Object for further usage
svg_bytes = io.BytesIO()
svg.save(svg_bytes)
print(len(svg_bytes.getvalue()), " bytes of svg")

CwaEventDescription

  • location_description: Description of the Location, Optional, String, max 100 Characters
  • location_address: Address of the Location, Optional, String, max 100 Characters
  • start_date_time: Start of the Event, Optional, datetime in UTC
  • end_date_time: End of the Event, Optional, datetime in UTC Caution, 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 use datetime.now() for start/end-date. For repeating Events use cwa_qr.rollover_date to get a defined rollover.
  • location_type: Type of the Location, Optional, one of
    • cwa.lowlevel.LOCATION_TYPE_UNSPECIFIED = 0
    • cwa.lowlevel.LOCATION_TYPE_PERMANENT_OTHER = 1
    • cwa.lowlevel.LOCATION_TYPE_TEMPORARY_OTHER = 2
    • cwa.lowlevel.LOCATION_TYPE_PERMANENT_RETAIL = 3
    • cwa.lowlevel.LOCATION_TYPE_PERMANENT_FOOD_SERVICE = 4
    • cwa.lowlevel.LOCATION_TYPE_PERMANENT_CRAFT = 5
    • cwa.lowlevel.LOCATION_TYPE_PERMANENT_WORKPLACE = 6
    • cwa.lowlevel.LOCATION_TYPE_PERMANENT_EDUCATIONAL_INSTITUTION = 7
    • cwa.lowlevel.LOCATION_TYPE_PERMANENT_PUBLIC_BUILDING = 8
    • cwa.lowlevel.LOCATION_TYPE_TEMPORARY_CULTURAL_EVENT = 9
    • cwa.lowlevel.LOCATION_TYPE_TEMPORARY_CLUB_ACTIVITY = 10
    • cwa.lowlevel.LOCATION_TYPE_TEMPORARY_PRIVATE_EVENT = 11
    • cwa.lowlevel.LOCATION_TYPE_TEMPORARY_WORSHIP_SERVICE = 12
  • default_check_in_length_in_minutes: Default Check-out time in minutes, Optional
  • seed: Seed to rotate the QR-Code, Optional, [str, bytes, int, float, date, datetime] or None (Default). Use with caution & read below! If unsure, leave blank.

Rotating QR-Codes

From the Documentation:

Profiling of Venues

An 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 generated when no visitor is at the event or location, because visitors can only warn each other with 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 useless without anyone noticing. Therefore, the Default of this Library as of 2021/04/26 is to not 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 to ask you user if and when they want their QR-Codes to change and explain to them that they should only rotate their Codes when they are sure that nobody is at the location or in the venue for at least 30 Minutes, to allow airborne particles to settle or get filtered out. Do not make assumptions regarding 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 Secret must stay constant over time, or the resulting QR-Codes will not correctly trigger warnings.

import io
from datetime import datetime, time

import cwa_qr

# Construct Event-Descriptor
event_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. See test_rollover.py for an in-depth look at the rollover code.

Python 2/3

This library supports Python 3.6+, however there is a backport to Python 2 available at https://github.com/MaZderMind/cwa-qr/tree/py2

Comments
  • Add poster generating capabilities

    Add poster generating capabilities

    This PR adds a small helper class/function to generate CWA-posters.

    Two layouts are included - the official portrait one as well as a landscape-version which has been inspired by the first one.

    Since I'm not very good at graphics stuff, this might not be the best way to achieve the desired result - so feel free to discard this PR if it's not up to your standards :-)

    (Since I ìsorted the imports of the files I touched with this PR, some sorting of the imports has occurred)

    opened by pc-coholic 5
  • Change Default to not Seed QR-Codes and provide Utility for custom rollover Seed

    Change Default to not Seed QR-Codes and provide Utility for custom rollover Seed

    From the Documentation:

    Profiling of Venues

    An 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 generated when no visitor is at the event or location, because visitors can only warn each other with 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 useless without anyone noticing. Therefore, the Default of this Library changed in this PR is to not 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 to ask you user if and when they want their QR-Codes to change and explain to them that they should only rotate their Codes when they are sure that nobody is at the location or in the venue for at least 30 Minutes, to allow airborne particles to settle or get filtered out. Do not make assumptions regarding 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). This PR gives authors a utility to allow rotating QR-Codes at a time of day specified by your user:

    import io
    from datetime import datetime, time
    
    import cwa
    
    # Construct Event-Descriptor
    eventDescription = cwa.CwaEventDescription()
    # …
    eventDescription.seed = cwa.rolloverDate(datetime.now(), time(4, 0))
    

    this will keep the date-based seed until 4:00 am on the next day and only then roll over to the next day. See test_rollover.py for an in-depth look at the rollover code.

    opened by MaZderMind 4
  • Bump pillow from 8.3.2 to 9.0.0

    Bump pillow from 8.3.2 to 9.0.0

    Bumps pillow from 8.3.2 to 9.0.0.

    Release notes

    Sourced from pillow's releases.

    9.0.0

    https://pillow.readthedocs.io/en/stable/releasenotes/9.0.0.html

    Changes

    ... (truncated)

    Changelog

    Sourced from pillow's changelog.

    9.0.0 (2022-01-02)

    • Restrict builtins for ImageMath.eval(). CVE-2022-22817 #5923 [radarhere]

    • Ensure JpegImagePlugin stops at the end of a truncated file #5921 [radarhere]

    • Fixed ImagePath.Path array handling. CVE-2022-22815, CVE-2022-22816 #5920 [radarhere]

    • Remove consecutive duplicate tiles that only differ by their offset #5919 [radarhere]

    • Improved I;16 operations on big endian #5901 [radarhere]

    • Limit quantized palette to number of colors #5879 [radarhere]

    • Fixed palette index for zeroed color in FASTOCTREE quantize #5869 [radarhere]

    • When saving RGBA to GIF, make use of first transparent palette entry #5859 [radarhere]

    • Pass SAMPLEFORMAT to libtiff #5848 [radarhere]

    • Added rounding when converting P and PA #5824 [radarhere]

    • Improved putdata() documentation and data handling #5910 [radarhere]

    • Exclude carriage return in PDF regex to help prevent ReDoS #5912 [hugovk]

    • Fixed freeing pointer in ImageDraw.Outline.transform #5909 [radarhere]

    • Added ImageShow support for xdg-open #5897 [m-shinder, radarhere]

    • Support 16-bit grayscale ImageQt conversion #5856 [cmbruns, radarhere]

    • Convert subsequent GIF frames to RGB or RGBA #5857 [radarhere]

    ... (truncated)

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 1
  • CWA-Posters

    CWA-Posters

    This builds upon and supersedes #9

    This PR adds a small helper class/function to generate CWA-posters. Two layouts are included - the official portrait one as well as a landscape-version which has been inspired by the first one.

    Thanks to @pc-coholic for doing the hard work ;)

    opened by MaZderMind 1
  • Add explicit exports to the main module

    Add explicit exports to the main module

    I'm not a 100% sure on this since this isn't on PyPI and I just copied the cwa module as suggested in the README. However, I think the example in the README is wrong when it says

    import cwa
    …
    eventDescription = cwa.CwaEventDescription()
    

    It should either be

    from cwa import cwa
    

    Or the cwa main module should expose the public API directly, as this PR proposes.

    opened by raphaelm 1
  • Fix README

    Fix README

    The README file contains some typos and capitalization mistakes. This PR aims to fix that in order to make the file more aesthetically pleasing.

    Many thanks for creating this tool.

    opened by fynngodau 1
  • Loosen version requirements

    Loosen version requirements

    It makes sense for a Python project to pin specific versions, but it can be annoying for a dependency. In our case, we could not use cwa-qr in an environment where we also use protobuf 3.19, even though they work fine together. I therefore propose loosening the constraint.

    opened by raphaelm 0
  • Bump pillow from 8.2.0 to 8.3.2

    Bump pillow from 8.2.0 to 8.3.2

    Bumps pillow from 8.2.0 to 8.3.2.

    Release notes

    Sourced from pillow's releases.

    8.3.2

    https://pillow.readthedocs.io/en/stable/releasenotes/8.3.2.html

    Security

    • CVE-2021-23437 Raise ValueError if color specifier is too long [hugovk, radarhere]

    • Fix 6-byte OOB read in FliDecode [wiredfool]

    Python 3.10 wheels

    • Add support for Python 3.10 #5569, #5570 [hugovk, radarhere]

    Fixed regressions

    • Ensure TIFF RowsPerStrip is multiple of 8 for JPEG compression #5588 [kmilos, radarhere]

    • Updates for ImagePalette channel order #5599 [radarhere]

    • Hide FriBiDi shim symbols to avoid conflict with real FriBiDi library #5651 [nulano]

    8.3.1

    https://pillow.readthedocs.io/en/stable/releasenotes/8.3.1.html

    Changes

    8.3.0

    https://pillow.readthedocs.io/en/stable/releasenotes/8.3.0.html

    Changes

    ... (truncated)

    Changelog

    Sourced from pillow's changelog.

    8.3.2 (2021-09-02)

    • CVE-2021-23437 Raise ValueError if color specifier is too long [hugovk, radarhere]

    • Fix 6-byte OOB read in FliDecode [wiredfool]

    • Add support for Python 3.10 #5569, #5570 [hugovk, radarhere]

    • Ensure TIFF RowsPerStrip is multiple of 8 for JPEG compression #5588 [kmilos, radarhere]

    • Updates for ImagePalette channel order #5599 [radarhere]

    • Hide FriBiDi shim symbols to avoid conflict with real FriBiDi library #5651 [nulano]

    8.3.1 (2021-07-06)

    • Catch OSError when checking if fp is sys.stdout #5585 [radarhere]

    • Handle removing orientation from alternate types of EXIF data #5584 [radarhere]

    • Make Image.array take optional dtype argument #5572 [t-vi, radarhere]

    8.3.0 (2021-07-01)

    • Use snprintf instead of sprintf. CVE-2021-34552 #5567 [radarhere]

    • Limit TIFF strip size when saving with LibTIFF #5514 [kmilos]

    • Allow ICNS save on all operating systems #4526 [baletu, radarhere, newpanjing, hugovk]

    • De-zigzag JPEG's DQT when loading; deprecate convert_dict_qtables #4989 [gofr, radarhere]

    • Replaced xml.etree.ElementTree #5565 [radarhere]

    ... (truncated)

    Commits
    • 8013f13 8.3.2 version bump
    • 23c7ca8 Update CHANGES.rst
    • 8450366 Update release notes
    • a0afe89 Update test case
    • 9e08eb8 Raise ValueError if color specifier is too long
    • bd5cf7d FLI tests for Oss-fuzz crash.
    • 94a0cf1 Fix 6-byte OOB read in FliDecode
    • cece64f Add 8.3.2 (2021-09-02) [CI skip]
    • e422386 Add release notes for Pillow 8.3.2
    • 08dcbb8 Pillow 8.3.2 supports Python 3.10 [ci skip]
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Change API to Python-Style

    Change API to Python-Style

    I do too much java… therefore the API does not use snake_case for methods and variables. This should be changed before a tagged & published release.

    Also the Module-Name should be changed to "cwa_qr" to match the Github-Name.

    opened by MaZderMind 0
  • qr-code alignment on poster

    qr-code alignment on poster

    First of all: Thank you! That's great work.

    I have just a little design issue: example_full.py generates a svg_bytes with 70198 bytes length. With that amount of data the qr-code is aligned into the center of the poster/portrait.svg

    In my test i had smaller amounts of data in my event_description. And with e.g. only 61444 bytes you get a smaller qr-code and its alignment is a little more left then it should be. Perhaps it would help to check svg_bytes.getbuffer().nbytes to determine the necessary scale dynamically

    (i guess with the landscape template it is the same, but i didn't test it.) grafik

    opened by wolf128058 1
Releases(v1.2.2)
Owner
MaZderMind
Program everything.
MaZderMind
PyTorch implementation of Anomaly Transformer: Time Series Anomaly Detection with Association Discrepancy

Anomaly Transformer in PyTorch This is an implementation of Anomaly Transformer: Time Series Anomaly Detection with Association Discrepancy. This pape

spencerbraun 160 Dec 19, 2022
2D&3D human pose estimation

Human Pose Estimation Papers [CVPR 2016] - 201511 [IJCAI 2016] - 201602 Other Action Recognition with Joints-Pooled 3D Deep Convolutional Descriptors

133 Jan 02, 2023
An implementation of Equivariant e2 convolutional kernals into a convolutional self attention network, applied to radio astronomy data.

EquivariantSelfAttention An implementation of Equivariant e2 convolutional kernals into a convolutional self attention network, applied to radio astro

2 Nov 09, 2021
SGoLAM - Simultaneous Goal Localization and Mapping

SGoLAM - Simultaneous Goal Localization and Mapping PyTorch implementation of the MultiON runner-up entry, SGoLAM: Simultaneous Goal Localization and

10 Jan 05, 2023
Code for CoMatch: Semi-supervised Learning with Contrastive Graph Regularization

CoMatch: Semi-supervised Learning with Contrastive Graph Regularization (Salesforce Research) This is a PyTorch implementation of the CoMatch paper [B

Salesforce 107 Dec 14, 2022
Embracing Single Stride 3D Object Detector with Sparse Transformer

SST: Single-stride Sparse Transformer This is the official implementation of paper: Embracing Single Stride 3D Object Detector with Sparse Transformer

TuSimple 385 Dec 28, 2022
Add-on for importing and auto setup of character creator 3 character exports.

CC3 Blender Tools An add-on for importing and automatically setting up materials for Character Creator 3 character exports. Using Blender in the Chara

260 Jan 05, 2023
Evolution Strategies in PyTorch

Evolution Strategies This is a PyTorch implementation of Evolution Strategies. Requirements Python 3.5, PyTorch = 0.2.0, numpy, gym, universe, cv2 Wh

Andrew Gambardella 333 Nov 14, 2022
Open source implementation of AceNAS: Learning to Rank Ace Neural Architectures with Weak Supervision of Weight Sharing

AceNAS This repo is the experiment code of AceNAS, and is not considered as an official release. We are working on integrating AceNAS as a built-in st

Yuge Zhang 6 Sep 07, 2022
Pytorch implementation of Nueral Style transfer

Nueral Style Transfer Pytorch implementation of Nueral style transfer algorithm , it is used to apply artistic styles to content images . Content is t

Abhinav 9 Oct 15, 2022
百度2021年语言与智能技术竞赛机器阅读理解Pytorch版baseline

项目说明: 百度2021年语言与智能技术竞赛机器阅读理解Pytorch版baseline 比赛链接:https://aistudio.baidu.com/aistudio/competition/detail/66?isFromLuge=true 官方的baseline版本是基于paddlepadd

周俊贤 54 Nov 23, 2022
Official PyTorch implemention of our paper "Learning to Rectify for Robust Learning with Noisy Labels".

WarPI The official PyTorch implemention of our paper "Learning to Rectify for Robust Learning with Noisy Labels". Run python main.py --corruption_type

Haoliang Sun 3 Sep 03, 2022
GarmentNets: Category-Level Pose Estimation for Garments via Canonical Space Shape Completion

GarmentNets This repository contains the source code for the paper GarmentNets: Category-Level Pose Estimation for Garments via Canonical Space Shape

Columbia Artificial Intelligence and Robotics Lab 43 Nov 21, 2022
Equivariant Imaging: Learning Beyond the Range Space

Equivariant Imaging: Learning Beyond the Range Space Equivariant Imaging: Learning Beyond the Range Space Dongdong Chen, Julián Tachella, Mike E. Davi

Dongdong Chen 46 Jan 01, 2023
People Interaction Graph

Gihan Jayatilaka*, Jameel Hassan*, Suren Sritharan*, Janith Senananayaka, Harshana Weligampola, et. al., 2021. Holistic Interpretation of Public Scenes Using Computer Vision and Temporal Graphs to Id

University of Peradeniya : COVID Research Group 1 Aug 24, 2022
DGN pymarl - Implementation of DGN on Pymarl, which could be trained by VDN or QMIX

This is the implementation of DGN on Pymarl, which could be trained by VDN or QM

4 Nov 23, 2022
Joint Channel and Weight Pruning for Model Acceleration on Mobile Devices

Joint Channel and Weight Pruning for Model Acceleration on Mobile Devices Abstract For practical deep neural network design on mobile devices, it is e

11 Dec 30, 2022
unofficial pytorch implement of "Squareplus: A Softplus-Like Algebraic Rectifier"

SquarePlus (Pytorch implement) unofficial pytorch implement of "Squareplus: A Softplus-Like Algebraic Rectifier" SquarePlus Squareplus is a Softplus-L

SeeFun 3 Dec 29, 2021
Optimized code based on M2 for faster image captioning training

Transformer Captioning This repository contains the code for Transformer-based image captioning. Based on meshed-memory-transformer, we further optimi

lyricpoem 16 Dec 16, 2022
PyTorch implementation for our paper "Deep Facial Synthesis: A New Challenge"

FSGAN Here is the official PyTorch implementation for our paper "Deep Facial Synthesis: A New Challenge". This project achieve the translation between

Deng-Ping Fan 32 Oct 10, 2022