-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
304 additions
and
136 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package decoders | ||
|
||
import ( | ||
"encoding/json" | ||
"github.com/alexpresso/gocovidcertificate/types" | ||
"github.com/alexpresso/gocovidcertificate/utils" | ||
"strconv" | ||
"strings" | ||
) | ||
|
||
var TwoDPrefix = "DC" | ||
|
||
func twoDDocDecode(input string) (certificate *types.Certificate, err error) { | ||
header, remaining, err := decodeHeader(input) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
message, signature, err := decodeData(remaining) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &types.Certificate{ | ||
Type: types.TWODDOC, | ||
Data: &types.TwoDDoc{ | ||
Header: header, | ||
Message: message, | ||
Signature: signature, | ||
}, | ||
}, nil | ||
} | ||
|
||
func decodeHeader(input string) (header *types.TwoDDocHeader, remaining string, err error) { | ||
length := 22 | ||
version, err := strconv.Atoi(utils.Substring(input, 2, 4)) | ||
if err != nil { | ||
return nil, "", err | ||
} | ||
|
||
header = &types.TwoDDocHeader{ | ||
IDFlag: utils.Substring(input, 0, 2), | ||
Version: version, | ||
Issuer: utils.Substring(input, 4, 8), | ||
CertID: utils.Substring(input, 8, 12), | ||
DocumentDate: utils.Substring(input, 12, 16), | ||
SignatureDate: utils.Substring(input, 16, 20), | ||
DocumentTypeID: utils.Substring(input, 20, 22), | ||
} | ||
|
||
switch version { | ||
case 3: | ||
header.PerimeterID = utils.Substring(input, 22, 24) | ||
length = 24 | ||
case 4: | ||
header.PerimeterID = utils.Substring(input, 22, 24) | ||
header.CountryID = utils.Substring(input, 24, 26) | ||
length = 26 | ||
} | ||
|
||
return header, utils.Substring(input, length, len(input)), err | ||
} | ||
|
||
func decodeData(input string) (message *types.TwoDDocMessage, signature string, err error) { | ||
data := make(map[string]interface{}) | ||
|
||
units := strings.Split(input, string(rune(31))) | ||
groups := strings.Split(units[0], string(rune(29))) | ||
signature = units[1] | ||
|
||
for _, group := range groups { | ||
key, value := decodeField(group) | ||
data[key] = value | ||
} | ||
|
||
jsonString, err := json.Marshal(data) | ||
err = json.Unmarshal(jsonString, &message) | ||
|
||
return | ||
} | ||
|
||
func decodeField(input string) (key string, value string) { | ||
key = utils.Substring(input, 0, 2) | ||
value = utils.Substring(input, 2, len(input)) | ||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package decoders | ||
|
||
import ( | ||
"github.com/alexpresso/gocovidcertificate/types" | ||
"github.com/alexpresso/gocovidcertificate/utils" | ||
"strings" | ||
) | ||
|
||
var DCCPrefixes = map[string]bool{"HC1": true, "LT1": true} | ||
|
||
func dccDecode(input string) (*types.Certificate, error) { | ||
var err error | ||
var bytes []byte | ||
|
||
for prefix := range DCCPrefixes { | ||
input = strings.TrimPrefix(input, prefix+":") | ||
} | ||
|
||
bytes, err = utils.Base45decode(input) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
if bytes[0] == 0x78 { | ||
bytes, err = utils.ZlibDecompress(bytes) | ||
if err != nil { | ||
return nil, err | ||
} | ||
} | ||
|
||
cose, err := utils.DecodeCOSE(bytes) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &types.Certificate{ | ||
Type: types.DCC, | ||
Data: cose, | ||
}, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package decoders | ||
|
||
import ( | ||
"errors" | ||
"github.com/alexpresso/gocovidcertificate/types" | ||
"strings" | ||
) | ||
|
||
func Decode(input string) (*types.Certificate, error) { | ||
if split := strings.Split(input, ":")[0]; DCCPrefixes[split] { | ||
return dccDecode(input) | ||
} else if strings.HasPrefix(input, TwoDPrefix) { | ||
return twoDDocDecode(input) | ||
} | ||
|
||
return nil, errors.New("unsupported code format") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package types | ||
|
||
type TwoDDoc struct { | ||
Header *TwoDDocHeader | ||
Message *TwoDDocMessage | ||
Signature string | ||
} | ||
|
||
type TwoDDocHeader struct { | ||
IDFlag string | ||
Version int | ||
Issuer string | ||
CertID string | ||
DocumentDate string | ||
SignatureDate string | ||
DocumentTypeID string | ||
PerimeterID string | ||
CountryID string | ||
} | ||
|
||
type TwoDDocMessage struct { | ||
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"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,57 +1,13 @@ | ||
package types | ||
|
||
// DccRoot see https://github.com/ehn-dcc-development/ehn-dcc-schema | ||
type DccRoot struct { | ||
DCC covidCertificate `cbor:"1,keyasint"` | ||
} | ||
|
||
type covidCertificate struct { | ||
Version string `cbor:"ver" json:"version"` | ||
DateOfBirth string `cbor:"dob" json:"dateOfBirth"` | ||
Name name `cbor:"nam" json:"name"` | ||
Vaccines []vaccineEntry `cbor:"v" json:"vaccines"` | ||
Tests []testEntry `cbor:"t" json:"tests"` | ||
Recoveries []recoveryEntry `cbor:"r" json:"recoveries"` | ||
} | ||
|
||
type name struct { | ||
Surname string `cbor:"fn" json:"surname"` | ||
StdSurname string `cbor:"fnt" json:"stdSurname"` | ||
Forename string `cbor:"gn" json:"forename"` | ||
StdForename string `cbor:"gnt" json:"stdForename"` | ||
} | ||
|
||
type vaccineEntry struct { | ||
TargetedAgent string `cbor:"tg" json:"targetedAgent"` | ||
Vaccine string `cbor:"vp" json:"vaccine"` | ||
Product string `cbor:"mp" json:"product"` | ||
Manufacturer string `cbor:"ma" json:"manufacturer"` | ||
Dose int64 `cbor:"dn" json:"doseNumber"` | ||
DoseSeries int64 `cbor:"sd" json:"doseSeries"` | ||
Date string `cbor:"dt" json:"date"` | ||
Country string `cbor:"co" json:"country"` | ||
Issuer string `cbor:"is" json:"issuer"` | ||
CertificateID string `cbor:"ci" json:"certificateID"` | ||
} | ||
const ( | ||
DCC CertificateType = "DCC" | ||
TWODDOC CertificateType = "2DDOC" | ||
) | ||
|
||
type testEntry struct { | ||
TargetedAgent string `cbor:"tg" json:"targetedAgent"` | ||
TestType string `cbor:"tt" json:"testType"` | ||
Name string `cbor:"nm" json:"name"` | ||
Manufacturer string `cbor:"ma" json:"manufacturer"` | ||
SampleDatetime string `cbor:"sc" json:"sampleDatetime"` | ||
TestResult string `cbor:"tr" json:"testResult"` | ||
TestingCentre string `cbor:"tc" json:"testingCentre"` | ||
Country string `cbor:"co" json:"country"` | ||
Issuer string `cbor:"is" json:"issuer"` | ||
CertificateID string `cbor:"ci" json:"certificateID"` | ||
} | ||
type CertificateType string | ||
|
||
type recoveryEntry struct { | ||
TargetedAgent string `cbor:"tg" json:"targetedAgent"` | ||
Country string `cbor:"co" json:"country"` | ||
Issuer string `cbor:"is" json:"issuer"` | ||
ValidFrom string `cbor:"df" json:"validFrom"` | ||
ValidUntil string `cbor:"du" json:"validUntil"` | ||
CertificateID string `cbor:"ci" json:"certificateID"` | ||
type Certificate struct { | ||
Type CertificateType | ||
Data interface{} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.