Skip to content
This repository has been archived by the owner on Feb 5, 2023. It is now read-only.

Commit

Permalink
feat: Initial version
Browse files Browse the repository at this point in the history
  • Loading branch information
ffflorian committed Jul 1, 2020
1 parent 9e9b3fc commit 1a23380
Show file tree
Hide file tree
Showing 11 changed files with 348 additions and 40 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: Build
name: Pull request

on: [push, pull_request]
on: pull_request

jobs:
build_lint_test:
Expand Down Expand Up @@ -28,5 +28,5 @@ jobs:
run: |
yarn
yarn lint
yarn dist
yarn test
yarn dist
58 changes: 58 additions & 0 deletions .github/workflows/push_master.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: Build

on:
push:
branches:
- master

jobs:
build_test_release:
name: Build, test and release
runs-on: ubuntu-latest
if: |
!contains(github.event.head_commit.message, '[ci skip]') &&
!contains(github.event.head_commit.message, '[skip ci]')
steps:
- name: Checkout repository
uses: actions/checkout@v1
- name: Set up Node.js
uses: actions/setup-node@v1
with:
node-version: 14.x
- name: Get yarn cache
id: yarn-cache
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v1
with:
path: ${{ steps.yarn-cache.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: ${{ runner.os }}-yarn-
- name: Build, lint and test
run: |
yarn
yarn lint
yarn test
yarn dist
- name: Release on npm
run: |
git config --global "user.email" "${GIT_AUTHOR_EMAIL}"
git config --global "user.name" "${GIT_AUTHOR_NAME}"
REPO_URL="$(git remote get-url origin | sed -n "s/https:\/\/github.com\//https:\/\/${GIT_AUTHOR_NAME}:${GH_TOKEN}@github.com\//p")"
yarn release -r "${REPO_URL}"
env:
GIT_AUTHOR_NAME: ffflobot
GIT_AUTHOR_EMAIL: ffflobot@users.noreply.github.com
GIT_COMMITTER_NAME: ffflobot
GIT_COMMITTER_EMAIL: ffflobot@users.noreply.github.com
GH_TOKEN: ${{ secrets.GH_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
if: "!startsWith(github.event.head_commit.message, 'chore')"
- name: Release on GitHub
run: |
rm .npmrc
echo "//npm.pkg.github.com/:_authToken=${GH_TOKEN}" > ~/.npmrc
sed -i "s/\"name\": \"/\"name\": \"@ffflorian\//" package.json
npm publish --registry=https://npm.pkg.github.com || true
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
if: "!startsWith(github.event.head_commit.message, 'chore')"
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
node_modules/
dist/
*.log
/proto/
!/proto/export.proto
13 changes: 3 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
# ts-boilerplate [![Build Status](https://github.com/ffflorian/ts-boilerplate/workflows/Build/badge.svg)](https://github.com/ffflorian/ts-boilerplate/actions/) [![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=ffflorian/ts-boilerplate)](https://dependabot.com)
# exposure-keys [![Build Status](https://github.com/ffflorian/exposure-keys/workflows/Build/badge.svg)](https://github.com/ffflorian/exposure-keys/actions/) [![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=ffflorian/exposure-keys)](https://dependabot.com)

A boilerplate for a modern™ TypeScript project.
A library to load and save Temporary Exposure Keys (TEK). For more information see https://www.google.com/covid19/exposurenotifications.

## Installation

Fork this repository or just [generate a new one](https://github.com/ffflorian/ts-boilerplate/generate) from this template.

## Usage

- Clone your new repository
- Run `yarn` in the new repository
- Start coding
- Don't forget to update the `package.json`!
Run `yarn add exposure-keys` or `npm install exposure-keys`.
27 changes: 21 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
"my-cli": "dist/cli.js"
},
"dependencies": {
"jszip": "3.5.0"
},
"description": "A boilerplate for a modern™ TypeScript project.",
"description": "Temporary Exposure Keys (TEK) library",
"devDependencies": {
"@ffflorian/eslint-config": "0.5.1",
"@ffflorian/prettier-config": "0.0.6",
Expand All @@ -30,6 +31,7 @@
"jasmine": "3.5.0",
"lint-staged": "10.2.11",
"prettier": "2.0.5",
"protobufjs": "6.9.0",
"rimraf": "3.0.2",
"semantic-release": "17.1.1",
"ts-node": "8.10.2",
Expand All @@ -39,10 +41,21 @@
"node": ">= 10.9"
},
"files": [
"dist"
"dist",
"proto/export.js",
"proto/export.d.ts"
],
"keywords": [
"cli",
"tek",
"temporary",
"exposure",
"keys",
"google",
"apple",
"corona",
"covid",
"covid19",
"covid-19",
"typescript"
],
"husky": {
Expand All @@ -63,12 +76,14 @@
]
},
"main": "dist/index.js",
"name": "@ffflorian/ts-boilerplate",
"name": "exposure-keys",
"prettier": "@ffflorian/prettier-config",
"private": true,
"repository": "https://github.com/ffflorian/ts-boilerplate.git",
"repository": "https://github.com/ffflorian/exposure-keys.git",
"scripts": {
"build": "tsc",
"build": "yarn build:proto && yarn build:ts",
"build:proto": "pbjs --t static-module -w commonjs --es6 -o proto/export.js proto/export.proto && pbts --out proto/export.d.ts --no-comments proto/export.js",
"build:ts": "tsc",
"clean": "rimraf dist",
"dist": "yarn clean && yarn build",
"fix": "yarn fix:other && yarn fix:ts",
Expand Down
117 changes: 117 additions & 0 deletions proto/export.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto2";

option go_package = "github.com/google/exposure-notifications-server/internal/pb/export;export";

// Protobuf definition for exports of confirmed temporary exposure keys.
//
// The full file format is documented under "Exposure Key Export File Format
// and Verification" at https://www.google.com/covid19/exposurenotifications/
//
// These files have a 16-byte, space-padded header before the protobuf data
// starts. They will be contained in a zip archive, alongside a signature
// file verifying the contents.
message TemporaryExposureKeyExport {
// Time window of keys in this file based on arrival to server, in UTC
// seconds
optional fixed64 start_timestamp = 1;
optional fixed64 end_timestamp = 2;

// Region for which these keys came from (e.g., country)
optional string region = 3;

// E.g., Batch 2 of 10. Ordinal, 1-based numbering.
// Note: Not yet supported on iOS. Use values of 1 for both.
optional int32 batch_num = 4;
optional int32 batch_size = 5;

// Information about signatures
repeated SignatureInfo signature_infos = 6;

// The TemporaryExposureKeys for initial release of keys.
// Keys should be included in this list for initial release,
// whereas revised or revoked keys should go in revised_keys.
repeated TemporaryExposureKey keys = 7;

// TemporaryExposureKeys that have changed status.
// Keys should be included in this list if they have changed status
// or have been revoked.
repeated TemporaryExposureKey revised_keys = 8;
}

message SignatureInfo {
// No longer need to set these. Old code that still does will be fine
// as these were largely noops anyway.
reserved 1, 2;
reserved "app_bundle_id", "android_package";
// Key version for rollovers
// Must be in character class [a-zA-Z0-9_]. E.g., 'v1'
optional string verification_key_version = 3;
// Alias with which to identify public key to be used for verification
// Must be in character class [a-zA-Z0-9_]
// For cross-compatibility with Apple, use MCC
// (https://en.wikipedia.org/wiki/Mobile_country_code).
optional string verification_key_id = 4;
// ASN.1 OID for Algorithm Identifier. Supported algorithms are
// either 1.2.840.10045.4.3.2 or 1.2.840.10045.4.3.4
optional string signature_algorithm = 5;
}

message TemporaryExposureKey {
// Key of infected user
optional bytes key_data = 1;

// Varying risks associated with exposure depending on type of verification
// Ignored by the v1.5 client API when report_type is set.
optional int32 transmission_risk_level = 2 [deprecated = true];

// The interval number since epoch for which a key starts
optional int32 rolling_start_interval_number = 3;

// Increments of 10 minutes describing how long a key is valid
optional int32 rolling_period = 4 [default = 144]; // defaults to 24 hours

// Data type representing why this key was published.
enum ReportType {
UNKNOWN = 0; // Never returned by the client API.
CONFIRMED_TEST = 1;
CONFIRMED_CLINICAL_DIAGNOSIS = 2;
SELF_REPORT = 3;
RECURSIVE = 4;
REVOKED = 5; // Used to revoke a key, never returned by client API.
}

// Type of diagnosis associated with a key.
optional ReportType report_type = 5;

// Number of days elapsed between symptom onset and the TEK being used.
// E.g. 2 means TEK is 2 days after onset of symptoms.
optional sint32 days_since_onset_of_symptoms = 6;
}

message TEKSignatureList {
repeated TEKSignature signatures = 1;
}

message TEKSignature {
// Info about the signing key, version, algorithm, etc.
optional SignatureInfo signature_info = 1;
// E.g., Batch 2 of 10
optional int32 batch_num = 2;
optional int32 batch_size = 3;
// Signature in X9.62 format (ASN.1 SEQUENCE of two INTEGER fields)
optional bytes signature = 4;
}
23 changes: 23 additions & 0 deletions src/ExposureKeys.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {TemporaryExposureKeyExport, TEKSignatureList} from '../proto/export';
import {loadAsync} from 'jszip';

export async function loadZip(fileContent: Buffer): Promise<{keys: Buffer; signature: Buffer}> {
const unzippedData = await loadAsync(fileContent);
const keys = await unzippedData.file('export.bin')?.async('nodebuffer');
const signature = await unzippedData.file('export.sig')?.async('nodebuffer');

if (!keys || !signature) {
throw new Error('Invalid zip file');
}

return {keys, signature};
}

export function loadKeys(fileContent: Buffer): TemporaryExposureKeyExport {
const bytesPadding = 16;
return TemporaryExposureKeyExport.decode(fileContent.slice(bytesPadding));
}

export function loadSignature(fileContent: Buffer): TEKSignatureList {
return TEKSignatureList.decode(fileContent);
}
10 changes: 1 addition & 9 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1 @@
/*
* This is your index file.
*
* Example:
*
* ```
* export * from './project';
* ```
*/
export * from './ExposureKeys';
11 changes: 0 additions & 11 deletions src/project.ts

This file was deleted.

2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"alwaysStrict": true,
"declaration": true,
"forceConsistentCasingInFileNames": true,
"lib": ["esnext"],
"lib": ["esnext", "DOM"],
"module": "commonjs",
"moduleResolution": "node",
"noEmitOnError": true,
Expand Down
Loading

0 comments on commit 1a23380

Please sign in to comment.