crypto

package module
v0.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 27, 2020 License: MIT Imports: 8 Imported by: 0

README

exp-notif-crypto

GoDoc

exp-notif-crypto is a Go implementation of the crypto functions of Apple/Google’s Exposure Notification framework.

💡 Check out the example code here or on godoc.

Documentation

Overview

Package crypto is a Go implementation of the crypto functions of Apple/Google’s Exposure Notification framework.

Example
// Temporary Exposure Keys roll at a frequent cadence called `EKRollingPeriod`,
// which is set to 144, achieving a key validity of 24 hours. Each key is
// randomly and independently generated using a cryptographic random number
// generator. All devices sharing the same `EKRollingPeriod` roll keys at the
// same time — at the beginning of an interval whose ENIntervalNumber is a
// multiple of `EKRollingPeriod`.
log.Println("Creating `TemporaryExposureKey` ...")
tek := NewTemporaryExposureKey()
rollingStartNumber := NewRollingStartNumber(time.Now())
log.Printf("✅ Generated `TemporaryExposureKey` and `rollingStartNumber`: [% #x], %v",
	tek, rollingStartNumber)

// `RollingProximityIdentifierKey` is derived from `TemporaryExposureKey`.
// This RPIK should thus also rolled over at the beginning of an interval
// whose ENIntervalNumber is a multiple of `EKRollingPeriod`.
log.Println("Creating `RollingProximityIdentifierKey` ...")
rpik := NewRollingProximityIdentifierKey(tek)
log.Printf("✅ Generated `RollingProximityIdentifierKey`: [% #x]", rpik)

// `AssociatedEncryptedMetadataKey` is derived from `TemporaryExposureKey`.
// This AEMK should thus also rolled over at the beginning of an interval
// whose `ENIntervalNumber` is a multiple of `EKRollingPeriod`.
log.Println("Creating `AssociatedEncryptedMetadataKey` ...")
aemk := NewAssociatedEncryptedMetadataKey(tek)
log.Printf("✅ Generated `AssociatedEncryptedMetadataKey`: [% #x]", aemk)

// Each time the Bluetooth Low Energy MAC randomized address changes, we
// should derive a new `Rolling Proximity Identifier`.
// This privacy-preserving identifier can be broadcast in Bluetooth payloads.
// For example: an RPI to be broadcast 42 minutes after TEK was created.
enin := NewENIntervalNumber(time.Now().Add(42 * time.Minute))
log.Println("Creating `RollingProximityIdentifier` ...")
rpi := NewRollingProximityIdentifier(rpik, enin)
log.Printf("✅ Generated `RollingProximityIdentifier`: [% #x]", rpi)

// For every broadcast, `AssociatedEncryptedMetadata` is generated.
// This data can only be decrypted later if the the user broadcasting it tested
// positive and revealed (uploaded) their `TemporaryExposure`.
log.Println("Creating `AssociatedEncryptedMetadata` ...")
aem := XORKeyStreamAssociatedMetadata(aemk, rpi, []byte("bluetooth metadata..."))
log.Printf("✅ Generated `AssociatedEncryptedMetadata`: [% #x]\n", aem)

// In case of positive diagnosis, a set of TEK and rollingStartNumber ("Diagnosis Key") pairs
// are sent to a central server ...

// Other users periodically download the Diagnosis Key set and match against
// a local repository of previously received RPIs, by subsequently deriving
// the RPK and RPI by running the same hash functions. Let's say for instance
// another user received the TEK we created above, and they previously received
// the RPI we broadcast.
type diagnosisKey struct {
	tek                TemporaryExposureKey
	rollingStartNumber ENIntervalNumber
}
downloadedDiagKeys := []diagnosisKey{
	{tek: tek, rollingStartNumber: rollingStartNumber},                        // Should match
	{tek: tek, rollingStartNumber: rollingStartNumber - EKRollingPeriod*10*3}, // Should NOT match, TEK from 3 days ago
	{tek: NewTemporaryExposureKey(), rollingStartNumber: rollingStartNumber},  // Should NOT match, different TEK
}

// Example: A device scanned a RPI and AEM over Bluetooth LE.
receivedRPI := rpi
receivedAEM := aem

for _, diagKey := range downloadedDiagKeys {
	receivedTEK := diagKey.tek
	derivedRPIK := NewRollingProximityIdentifierKey(receivedTEK)
	derivedAEMK := NewAssociatedEncryptedMetadataKey(receivedTEK)
	var match bool

	for i := 0; i < EKRollingPeriod; i++ {
		enin := diagKey.rollingStartNumber + ENIntervalNumber(i)
		derivedRPI := NewRollingProximityIdentifier(derivedRPIK, enin)

		if bytes.Equal(derivedRPI[:], receivedRPI[:]) {
			// There's a match!
			// With the derived AEM key, we can now decrypt the AEM that was
			// previously received over Bluetooth.
			metadata := XORKeyStreamAssociatedMetadata(derivedAEMK, derivedRPI, receivedAEM)
			log.Printf("🎉 MATCH: [% #x], interval since `rollingStartNumber` (%v), metadata: [%s]\n", derivedRPI, i, metadata)

			match = true
			break
		}
	}
	if !match {
		log.Printf("❌ No match: [% #x], rollingStartNumber: %v\n",
			diagKey.tek, diagKey.rollingStartNumber)
	}
}
Output:

Index

Examples

Constants

View Source
const EKRollingPeriod = 144

EKRollingPeriod is the duration for which a TemporaryExposureKey is valid (in multiples of 10 minutes). In the protocol, EKRollingPeriod is defined as 144, achieving a key validity of 24 hours.

Variables

This section is empty.

Functions

func XORKeyStreamAssociatedMetadata

func XORKeyStreamAssociatedMetadata(
	aemk AssociatedEncryptedMetadataKey,
	rpi RollingProximityIdentifier,
	data []byte,
) []byte

XORKeyStreamAssociatedMetadata is used to encrypt or decrypt metadata.

Types

type AssociatedEncryptedMetadata

type AssociatedEncryptedMetadata [16]byte

AssociatedEncryptedMetadata is data encrypted along with the RollingProximityIdentifier, and can only be decrypted later if the user broadcasting it tested positive and reveals their TemporaryExposure Key.

type AssociatedEncryptedMetadataKey

type AssociatedEncryptedMetadataKey [16]byte

AssociatedEncryptedMetadataKey is derived from a TemporaryExposureKey in order to encrypt additional metadata.

func NewAssociatedEncryptedMetadataKey

func NewAssociatedEncryptedMetadataKey(tek TemporaryExposureKey) AssociatedEncryptedMetadataKey

NewAssociatedEncryptedMetadataKey returns a new AssociatedEncryptedMetadataKey. It uses HKDF to derive a key from the given TemporaryExposureKey.

type ENIntervalNumber

type ENIntervalNumber uint32

ENIntervalNumber is a number for each 10 minute time window that’s shared between all devices participating in the protocol. These time windows are derived from timestamps in Unix Epoch Time.

func NewENIntervalNumber

func NewENIntervalNumber(t time.Time) ENIntervalNumber

NewENIntervalNumber returns the `ENIntervalNumber`, e.g. the 10 minute time window since Unix Epoch Time, that the given time `t` is in.

func NewRollingStartNumber

func NewRollingStartNumber(t time.Time) ENIntervalNumber

NewRollingStartNumber returns the `ENIntervalNumber` for the start period of a TemporaryExposureKey with generation time `t`.

type RollingProximityIdentifier

type RollingProximityIdentifier [16]byte

RollingProximityIdentifier is a privacy-preserving identifier that is broadcast in Bluetooth payloads.

func NewRollingProximityIdentifier

func NewRollingProximityIdentifier(rpik RollingProximityIdentifierKey, enin ENIntervalNumber) (rpi RollingProximityIdentifier)

NewRollingProximityIdentifier returns a new RollingProximityIdentifier.

type RollingProximityIdentifierKey

type RollingProximityIdentifierKey [16]byte

RollingProximityIdentifierKey (RPIK) is derived from a TemporaryExposureKey and is used in order to derive RollingProximityIdentifier values.

func NewRollingProximityIdentifierKey

func NewRollingProximityIdentifierKey(tek TemporaryExposureKey) RollingProximityIdentifierKey

NewRollingProximityIdentifierKey returns a new RollingProximityIdentifierKey. It uses HKDF to derive a key from the given TemporaryExposureKey.

type TemporaryExposureKey

type TemporaryExposureKey [16]byte

TemporaryExposureKey is a key generated using a cryptographic random number generator. All devices generate a new TEK at the same time — at the beginning of an interval whose ENIntervalNumber is a multiple of EKRollingPeriod.

func NewTemporaryExposureKey

func NewTemporaryExposureKey() (tek TemporaryExposureKey)

NewTemporaryExposureKey returns a new TemporaryExposureKey using `crypto/rand`.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL