Skip to content

Commit

Permalink
Continue 2DDOC
Browse files Browse the repository at this point in the history
Add Certificate Type enum
Add address to struct conversion
  • Loading branch information
AlexPresso committed Aug 24, 2021
1 parent 197ba01 commit 1454b58
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 57 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Golang implementation of the covid certificates. At the moment it only includes

## Features
- Decode signed DCC (European QRCodes) data ✅
- Decode 2D-DOC data ❌ (planned)
- Decode 2D-DOC data
- Pretty-print decoded data as JSON ✅
- Download public-keys from european gateway ❌ (planned)
- Verify signature ❌ (planned)
Expand Down
51 changes: 26 additions & 25 deletions decoders/2ddoc.go
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
package decoders

import (
"encoding/json"
"github.com/alexpresso/gocovidcertificate/types"
"github.com/alexpresso/gocovidcertificate/utils"
"strconv"
"strings"
)

var TwoDPrefix = "DC"

func twoDDocDecode(input string) (data *types.TwoDDoc, err error) {
func twoDDocDecode(input string) (certificate *types.Certificate, err error) {
header, remaining, err := decodeHeader(input)
if err != nil {
return nil, err
}

message, remaining, err := decodeMessage(remaining)
message, signature, err := decodeData(remaining)
if err != nil {
return nil, err
}

signature, err := decodeSignature(remaining)
if err != nil {
return nil, err
}

return &types.TwoDDoc{
Header: *header,
Message: *message,
Signature: *signature,
return &types.Certificate{
Type: types.TWODDOC,
Data: &types.TwoDDoc{
Header: header,
Message: message,
Signature: signature,
},
}, nil
}

Expand Down Expand Up @@ -61,25 +61,26 @@ func decodeHeader(input string) (header *types.TwoDDocHeader, remaining string,
return header, utils.Substring(input, length, len(input)), err
}

func decodeMessage(input string) (message *types.TwoDDocMessage, remaining string, err error) {
remaining = input
data := make(map[string]string)
func decodeData(input string) (message *types.TwoDDocMessage, signature string, err error) {
data := make(map[string]interface{})

message = &types.TwoDDocMessage{
Data: data,
}
units := strings.Split(input, string(rune(31)))
groups := strings.Split(units[0], string(rune(29)))
signature = units[1]

return message, remaining, nil
}
for _, group := range groups {
key, value := decodeField(group)
data[key] = value
}

func decodeField(input string) (key string, value string, remaining string, err error) {
key = utils.Substring(input, 0, 2)
value = utils.Substring(input, 2, 4)
remaining = utils.Substring(input, 4, len(input))
jsonString, err := json.Marshal(data)
err = json.Unmarshal(jsonString, &message)

return
}

func decodeSignature(input string) (signature *types.TwoDDocSignature, err error) {
return nil, nil
func decodeField(input string) (key string, value string) {
key = utils.Substring(input, 0, 2)
value = utils.Substring(input, 2, len(input))
return
}
12 changes: 10 additions & 2 deletions decoders/dcc.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

var DCCPrefixes = map[string]bool{"HC1": true, "LT1": true}

func dccDecode(input string) (*types.COSE, error) {
func dccDecode(input string) (*types.Certificate, error) {
var err error
var bytes []byte

Expand All @@ -28,5 +28,13 @@ func dccDecode(input string) (*types.COSE, error) {
}
}

return utils.DecodeCOSE(bytes)
cose, err := utils.DecodeCOSE(bytes)
if err != nil {
return nil, err
}

return &types.Certificate{
Type: types.DCC,
Data: cose,
}, nil
}
3 changes: 2 additions & 1 deletion decoders/decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ package decoders

import (
"errors"
"github.com/alexpresso/gocovidcertificate/types"
"strings"
)

func Decode(input string) (interface{}, error) {
func Decode(input string) (*types.Certificate, error) {
if split := strings.Split(input, ":")[0]; DCCPrefixes[split] {
return dccDecode(input)
} else if strings.HasPrefix(input, TwoDPrefix) {
Expand Down
21 changes: 13 additions & 8 deletions types/2dcertificate.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package types

type TwoDDoc struct {
Header TwoDDocHeader
Message TwoDDocMessage
Signature TwoDDocSignature
Header *TwoDDocHeader
Message *TwoDDocMessage
Signature string
}

type TwoDDocHeader struct {
Expand All @@ -19,9 +19,14 @@ type TwoDDocHeader struct {
}

type TwoDDocMessage struct {
Data map[string]string
}

type TwoDDocSignature struct {
Raw string
Lastname string `json:"L0"`
Firstname string `json:"L1"`
DateOfBirth string `json:"L2"`
TargetedAgent string `json:"L3"`
VaccineATC string `json:"L4"`
Dose1Manufacturer string `json:"L5"`
Dose2Manufacturer string `json:"L6"`
Dose int `json:"L7,string"`
RequiredDoses int `json:"L8,string"`
Date int `json:"L9,string"`
}
13 changes: 13 additions & 0 deletions types/certificate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package types

const (
DCC CertificateName = "DCC"
TWODDOC CertificateName = "2DDOC"
)

type CertificateName string

type Certificate struct {
Type CertificateName
Data interface{}
}
40 changes: 20 additions & 20 deletions types/cose.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,35 @@ package types

// Signed see https://datatracker.ietf.org/doc/html/rfc8152#section-2
type Signed struct {
_ struct{} `cbor:",toarray"`
Protected []byte
Unprotected map[interface{}]interface{}
Content []byte
Signature []byte
_ struct{} `cbor:",toarray"`
Protected []byte
Unprotected map[interface{}]interface{}
Content []byte
Signature []byte
}

// Header see https://datatracker.ietf.org/doc/html/rfc8152#section-3.1 & https://www.iana.org/assignments/cose/cose.xhtml
type Header struct {
Alg int `cbor:"1,keyasint,omitempty"`
Kid []byte `cbor:"4,keyasint,omitempty"`
IV []byte `cbor:"5,keyasint,omitempty"`
Alg int `cbor:"1,keyasint,omitempty"`
Kid []byte `cbor:"4,keyasint,omitempty"`
IV []byte `cbor:"5,keyasint,omitempty"`
}

// Claims see https://datatracker.ietf.org/doc/html/draft-ietf-ace-cbor-web-token-08#section-3.1
type Claims struct {
Iss string `cbor:"1,keyasint"`
Sub string `cbor:"2,keyasint"`
Aud string `cbor:"3,keyasint"`
Exp int64 `cbor:"4,keyasint"`
Nbf int `cbor:"5,keyasint"`
Iat int64 `cbor:"6,keyasint"`
Cti []byte `cbor:"7,keyasint"`
HCData DccRoot `cbor:"-260,keyasint"`
LCData DccRoot `cbor:"-250,keyasint"`
Iss string `cbor:"1,keyasint"`
Sub string `cbor:"2,keyasint"`
Aud string `cbor:"3,keyasint"`
Exp int64 `cbor:"4,keyasint"`
Nbf int `cbor:"5,keyasint"`
Iat int64 `cbor:"6,keyasint"`
Cti []byte `cbor:"7,keyasint"`
HCData DccRoot `cbor:"-260,keyasint"`
LCData DccRoot `cbor:"-250,keyasint"`
}

type COSE struct {
Signed Signed `json:"-"`
Header Header
Claims Claims
Signed Signed `json:"-"`
Header Header
Claims Claims
}

0 comments on commit 1454b58

Please sign in to comment.