├── .gitignore ├── tools ├── modexp2pubkey ├── modexp2pubkey.o ├── Makefile └── modexp2pubkey.c ├── emv ├── pinasker.go ├── applicationconfig.go ├── applicationhint.go ├── apduresponse.go ├── tacset.go ├── terminal.go ├── contextconfig.go ├── applicationfile.go ├── certificatemanager.go ├── generatedac.go ├── application.go ├── applicationinformation.go ├── cryptogramtype.go ├── transactionresult.go ├── apdu.go ├── transaction.go ├── processingoptions.go ├── proprietarytemplate.go ├── taglist.go ├── applicationfilelist.go ├── publickey.go ├── dataobjectlist.go ├── cardinformation.go ├── consts.go ├── card.go └── context.go ├── tlv ├── tlvdecoder.go ├── tlvencoder.go ├── tlv_test.go ├── ber.go └── tlv.go ├── certs ├── A000000003 │ ├── 144.pem │ ├── 151.pem │ ├── 5.pem │ ├── 6.pem │ ├── 152.pem │ ├── 3.pem │ ├── 1.pem │ ├── 150.pem │ ├── 153.pem │ ├── 16.pem │ ├── 32.pem │ ├── 80.pem │ ├── 7.pem │ ├── 149.pem │ ├── 243.pem │ ├── 81.pem │ ├── 8.pem │ ├── 82.pem │ ├── 146.pem │ ├── 88.pem │ ├── 9.pem │ ├── 148.pem │ └── 83.pem ├── A000000010 │ ├── 0.pem │ ├── 253.pem │ ├── 252.pem │ ├── 255.pem │ ├── 251.pem │ └── 254.pem ├── A000000025 │ ├── 1.pem │ ├── 4.pem │ ├── 96.pem │ ├── 98.pem │ ├── 2.pem │ ├── 3.pem │ ├── 100.pem │ ├── 102.pem │ ├── 150.pem │ ├── 82.pem │ ├── 101.pem │ ├── 14.pem │ ├── 151.pem │ ├── 193.pem │ ├── 200.pem │ ├── 161.pem │ ├── 15.pem │ ├── 103.pem │ ├── 152.pem │ ├── 194.pem │ ├── 201.pem │ ├── 104.pem │ ├── 153.pem │ ├── 16.pem │ ├── 195.pem │ └── 202.pem ├── A000000029 │ ├── 151.pem │ ├── 5.pem │ ├── 6.pem │ ├── 152.pem │ ├── 3.pem │ ├── 1.pem │ ├── 150.pem │ ├── 153.pem │ ├── 7.pem │ ├── 14.pem │ ├── 149.pem │ ├── 15.pem │ ├── 8.pem │ ├── 103.pem │ ├── 146.pem │ ├── 9.pem │ └── 148.pem ├── a000000004 │ ├── 0.pem │ ├── 1.pem │ ├── 253.pem │ ├── 34.pem │ ├── 9.pem │ ├── 2.pem │ ├── 252.pem │ ├── 255.pem │ ├── 240.pem │ ├── 3.pem │ ├── 247.pem │ ├── 248.pem │ ├── 251.pem │ ├── 254.pem │ ├── 82.pem │ ├── 4.pem │ ├── 243.pem │ ├── 250.pem │ ├── 5.pem │ ├── 241.pem │ ├── 249.pem │ ├── 246.pem │ ├── 239.pem │ ├── 245.pem │ └── 6.pem ├── 501649FF20 │ ├── 5.pem │ ├── 7.pem │ └── 35.pem ├── A000000065 │ ├── 7.pem │ ├── 8.pem │ ├── 9.pem │ ├── 218.pem │ ├── 10.pem │ ├── 15.pem │ ├── 16.pem │ ├── 234.pem │ ├── 12.pem │ ├── 17.pem │ ├── 18.pem │ ├── 235.pem │ ├── 14.pem │ ├── 20.pem │ └── 236.pem ├── A000000141 │ ├── 2.pem │ ├── 5.pem │ └── 4.pem ├── A000000333 │ ├── 1.pem │ ├── 10.pem │ ├── 2.pem │ ├── 8.pem │ ├── 12.pem │ ├── 3.pem │ ├── 9.pem │ ├── 4.pem │ └── 11.pem ├── B012345678 │ ├── 5.pem │ ├── 246.pem │ ├── 243.pem │ ├── 247.pem │ ├── 0.pem │ ├── 2.pem │ ├── 248.pem │ ├── 245.pem │ └── 249.pem ├── A000000524 │ ├── 106.pem │ ├── 107.pem │ ├── 108.pem │ └── 109.pem └── A000000384 │ ├── 193.pem │ ├── 194.pem │ └── 195.pem ├── applicationsorter.go ├── filecertificatemanager.go ├── main.go ├── readme.md └── transactionprocessor.go /.gitignore: -------------------------------------------------------------------------------- 1 | emv-kernel 2 | -------------------------------------------------------------------------------- /tools/modexp2pubkey: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenboxal/emv-kernel/HEAD/tools/modexp2pubkey -------------------------------------------------------------------------------- /tools/modexp2pubkey.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/greenboxal/emv-kernel/HEAD/tools/modexp2pubkey.o -------------------------------------------------------------------------------- /emv/pinasker.go: -------------------------------------------------------------------------------- 1 | package emv 2 | 3 | type PinAsker interface { 4 | RetrievePin() (string, error) 5 | } 6 | -------------------------------------------------------------------------------- /tlv/tlvdecoder.go: -------------------------------------------------------------------------------- 1 | package tlv 2 | 3 | type TlvDecoder interface { 4 | DecodeTlv(data []byte) error 5 | } 6 | -------------------------------------------------------------------------------- /tlv/tlvencoder.go: -------------------------------------------------------------------------------- 1 | package tlv 2 | 3 | type TlvEncoder interface { 4 | EncodeTlv() ([]byte, error) 5 | } 6 | -------------------------------------------------------------------------------- /emv/applicationconfig.go: -------------------------------------------------------------------------------- 1 | package emv 2 | 3 | type ApplicationConfig struct { 4 | Aid []byte 5 | Tac TacSet 6 | } 7 | -------------------------------------------------------------------------------- /emv/applicationhint.go: -------------------------------------------------------------------------------- 1 | package emv 2 | 3 | type ApplicationHint struct { 4 | Name []byte 5 | Partial bool 6 | } 7 | -------------------------------------------------------------------------------- /emv/apduresponse.go: -------------------------------------------------------------------------------- 1 | package emv 2 | 3 | type ApduResponse struct { 4 | Body []byte 5 | SW1 byte 6 | SW2 byte 7 | } 8 | -------------------------------------------------------------------------------- /emv/tacset.go: -------------------------------------------------------------------------------- 1 | package emv 2 | 3 | type TacSet struct { 4 | Default uint64 5 | Denial uint64 6 | Online uint64 7 | } 8 | -------------------------------------------------------------------------------- /emv/terminal.go: -------------------------------------------------------------------------------- 1 | package emv 2 | 3 | type Terminal struct { 4 | Type int 5 | CountryCode []byte 6 | CurrencyCode int 7 | } 8 | -------------------------------------------------------------------------------- /emv/contextconfig.go: -------------------------------------------------------------------------------- 1 | package emv 2 | 3 | type ContextConfig struct { 4 | Terminal Terminal 5 | Applications []*ApplicationConfig 6 | } 7 | -------------------------------------------------------------------------------- /emv/applicationfile.go: -------------------------------------------------------------------------------- 1 | package emv 2 | 3 | type ApplicationFile struct { 4 | Sfi int 5 | Start int 6 | End int 7 | SdaCount int 8 | } 9 | -------------------------------------------------------------------------------- /emv/certificatemanager.go: -------------------------------------------------------------------------------- 1 | package emv 2 | 3 | type CertificateManager interface { 4 | GetSchemePublicKey(rid []byte, index int) (*PublicKey, error) 5 | } 6 | -------------------------------------------------------------------------------- /emv/generatedac.go: -------------------------------------------------------------------------------- 1 | package emv 2 | 3 | import "github.com/greenboxal/emv-kernel/tlv" 4 | 5 | type GeneratedAC struct { 6 | Raw tlv.Tlv `tlv:"other"` 7 | } 8 | -------------------------------------------------------------------------------- /emv/application.go: -------------------------------------------------------------------------------- 1 | package emv 2 | 3 | type Application struct { 4 | DedicatedFileName []byte `tlv:"84"` 5 | Template ProprietaryTemplate `tlv:"a5"` 6 | } 7 | -------------------------------------------------------------------------------- /emv/applicationinformation.go: -------------------------------------------------------------------------------- 1 | package emv 2 | 3 | type ApplicationInformation struct { 4 | Name []byte `tlv:"4F"` 5 | Label string `tlv:"50"` 6 | Priority int `tlv:"87"` 7 | } 8 | -------------------------------------------------------------------------------- /emv/cryptogramtype.go: -------------------------------------------------------------------------------- 1 | package emv 2 | 3 | type CryptogramType int 4 | 5 | const ( 6 | _ CryptogramType = iota 7 | 8 | AacCryptogram 9 | TcCryptogram 10 | ArqcCryptogram 11 | ) 12 | -------------------------------------------------------------------------------- /emv/transactionresult.go: -------------------------------------------------------------------------------- 1 | package emv 2 | 3 | type TransactionResult struct { 4 | Approved bool 5 | ShouldGoOnline bool 6 | CryptogramType CryptogramType 7 | Cryptogram []byte 8 | } 9 | -------------------------------------------------------------------------------- /emv/apdu.go: -------------------------------------------------------------------------------- 1 | package emv 2 | 3 | type Apdu struct { 4 | Class byte 5 | Instruction byte 6 | P1 byte 7 | P2 byte 8 | Data []byte 9 | Expected byte 10 | } 11 | -------------------------------------------------------------------------------- /certs/A000000003/144.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MFowDQYJKoZIhvcNAQEBBQADSQAwRgJBAMJrPLODPkLYJw3BDImZstoYEGg4ZQ2g 3 | 2/FU79URAK0UR0GyqH1ogfhjDjNI3qP3gDjpshppfrKmcW0yy/JghvECAQM= 4 | -----END PUBLIC KEY----- 5 | -------------------------------------------------------------------------------- /emv/transaction.go: -------------------------------------------------------------------------------- 1 | package emv 2 | 3 | import "time" 4 | 5 | type Transaction struct { 6 | Type int 7 | Date time.Time 8 | Amount int 9 | AdditionalAmount int 10 | } 11 | -------------------------------------------------------------------------------- /certs/A000000003/151.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MHowDQYJKoZIhvcNAQEBBQADaQAwZgJhAK8HVOrtl3BDq29B1jEqseIqaAkXW+so 3 | 5w1fmbLfGMrnNRk0G7vTJ9C4vp1NDhXwfTbqPjoFyJL1sZo+nTQTsNl+etEKX13o 4 | 44hgwK0ASx4G9AQMKVrLRXp4hVG2EnwLKQIBAw== 5 | -----END PUBLIC KEY----- 6 | -------------------------------------------------------------------------------- /certs/A000000003/5.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MHowDQYJKoZIhvcNAQEBBQADaQAwZgJhANATXOikQ2x/nVzGZUfjDqQC+YEFtxci 3 | 4kvAjcyAq35x7CO4zmodxqwqjPVVQ9dKiueziPmxdLfw11bCLLtZdPkBala2Acym 4 | THHwS3jobFAbGTpVVtU4ns5N6iWKuX9SowIBAw== 5 | -----END PUBLIC KEY----- 6 | -------------------------------------------------------------------------------- /certs/A000000003/6.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MHowDQYJKoZIhvcNAQEBBQADaQAwZgJhAPk0/AMr5ZtgmppkngREbxs2XR0joeZX 3 | TkkBcFJ+3zLzmDJhWbObY9B+leYnbX/Lt4aSUYK8Bmf72PZWazYcpBo43fInCRuH 4 | +k9HuseArEfhWmoPtlOT6zRz6NGToH61eQIBAw== 5 | -----END PUBLIC KEY----- 6 | -------------------------------------------------------------------------------- /certs/A000000010/0.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MHowDQYJKoZIhvcNAQEBBQADaQAwZgJhAJ4VIUIS9jCKyni4C9mGrCh1FoRsjVSK 3 | ntCkLn2ZfJAsPhItG53DCZX04lx13X7goM4pO4zAK5dyeO8lbXYRlJJHZJQv5xT6 4 | AuTVfygro7K2LJ4472UXgj8sqDG93202PQIBAw== 5 | -----END PUBLIC KEY----- 6 | -------------------------------------------------------------------------------- /certs/A000000010/253.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MHowDQYJKoZIhvcNAQEBBQADaQAwZgJhALNXK6Sa5Me3oAGeUYnhQs/N7ZSY3bXw 3 | RwVnqwunE7jaImQkYilVtUuTer/vqtl5GeN3Yh4iGWq8FBnVrcEjSEIJ6ny3Ap5m 4 | oNVMW0XIrWFa7baungovdTEOqJYShyQSRQIBAg== 5 | -----END PUBLIC KEY----- 6 | -------------------------------------------------------------------------------- /certs/A000000025/1.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MHowDQYJKoZIhvcNAQEBBQADaQAwZgJhAK+tcBD4hOKCRlD3ZNR9eVGhbu1tu4gf 3 | OE3ttnAuD7VcD775RaIBdwXlKG+iSaWR4ZS9zXSyFyC0TOmG8UQjeiX5V4nzi0fq 4 | lX+a2yNy9tXUE0ChR+rCrzJOg1iuESDvPwIBAw== 5 | -----END PUBLIC KEY----- 6 | -------------------------------------------------------------------------------- /certs/A000000025/4.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MHowDQYJKoZIhvcNAQEBBQADaQAwZgJhAND1Q/A/JRcTPvK6ShEESGdYYw3P46iD 3 | x3tOSETjmpvWNg0j5mROHgcfGW3fLkpotKPZPRQmjXJA9qFPDXFMF4J9J50ZLoiT 4 | GvcwByeunagKPw42auumF3gXFzeYnh7jCQIBAw== 5 | -----END PUBLIC KEY----- 6 | -------------------------------------------------------------------------------- /certs/A000000025/96.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MHowDQYJKoZIhvcNAQEBBQADaQAwZgJhAND1Q/A/JRcTPvK6ShEESGdYYw3P46iD 3 | x3tOSETjmpvWNg0j5mROHgcfGW3fLkpotKPZPRQmjXJA9qFPDXFMF4J9J50ZLoiT 4 | GvcwByeunagKPw42auumF3gXFzeYnh7jCQIBAw== 5 | -----END PUBLIC KEY----- 6 | -------------------------------------------------------------------------------- /certs/A000000025/98.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MHowDQYJKoZIhvcNAQEBBQADaQAwZgJhALop3oMJDY1fTf/OuYkYmVp2j0HQGD4a 3 | yj741e2QYoU+QIDg0omlzt1N2Wsf6ixTQoQ2zhWiob/mnUYZfT9aebz49IWL/6BO 4 | 2wf8W+hWDZzjj1w8o8dC7f2647Xm3aRVVwIBAw== 5 | -----END PUBLIC KEY----- 6 | -------------------------------------------------------------------------------- /certs/A000000029/151.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MHowDQYJKoZIhvcNAQEBBQADaQAwZgJhAK8HVOrtl3BDq29B1jEqseIqaAkXW+so 3 | 5w1fmbLfGMrnNRk0G7vTJ9C4vp1NDhXwfTbqPjoFyJL1sZo+nTQTsNl+etEKX13o 4 | 44hgwK0ASx4G9AQMKVrLRXp4hVG2EnwLKQIBAw== 5 | -----END PUBLIC KEY----- 6 | -------------------------------------------------------------------------------- /certs/A000000029/5.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MHowDQYJKoZIhvcNAQEBBQADaQAwZgJhANATXOikQ2x/nVzGZUfjDqQC+YEFtxci 3 | 4kvAjcyAq35x7CO4zmodxqwqjPVVQ9dKiueziPmxdLfw11bCLLtZdPkBala2Acym 4 | THHwS3jobFAbGTpVVtU4ns5N6iWKuX9SowIBAw== 5 | -----END PUBLIC KEY----- 6 | -------------------------------------------------------------------------------- /certs/A000000029/6.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MHowDQYJKoZIhvcNAQEBBQADaQAwZgJhAPk0/AMr5ZtgmppkngREbxs2XR0joeZX 3 | TkkBcFJ+3zLzmDJhWbObY9B+leYnbX/Lt4aSUYK8Bmf72PZWazYcpBo43fInCRuH 4 | +k9HuseArEfhWmoPtlOT6zRz6NGToH61eQIBAw== 5 | -----END PUBLIC KEY----- 6 | -------------------------------------------------------------------------------- /certs/a000000004/0.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MHowDQYJKoZIhvcNAQEBBQADaQAwZgJhAJ4VIUIS9jCKyni4C9mGrCh1FoRsjVSK 3 | ntCkLn2ZfJAsPhItG53DCZX04lx13X7goM4pO4zAK5dyeO8lbXYRlJJHZJQv5xT6 4 | AuTVfygro7K2LJ4472UXgj8sqDG93202PQIBAw== 5 | -----END PUBLIC KEY----- 6 | -------------------------------------------------------------------------------- /certs/a000000004/1.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MHowDQYJKoZIhvcNAQEBBQADaQAwZgJhANIBBxbJ+1Jk2MkaFPTzL4mB7pVPIAh+ 3 | 13zcWGhDFyjTY3xjLM8nGKT12S6oqxZquZLS3iTp+9x8q5cpQB6RxQLXKzn2hm9c 4 | CYsSQ7Eyr+5l9QNuFoMjEWM4+AQINLmHJQIBAw== 5 | -----END PUBLIC KEY----- 6 | -------------------------------------------------------------------------------- /certs/a000000004/253.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MHowDQYJKoZIhvcNAQEBBQADaQAwZgJhALNXK6Sa5Me3oAGeUYnhQs/N7ZSY3bXw 3 | RwVnqwunE7jaImQkYilVtUuTer/vqtl5GeN3Yh4iGWq8FBnVrcEjSEIJ6ny3Ap5m 4 | oNVMW0XIrWFa7baungovdTEOqJYShyQSRQIBAg== 5 | -----END PUBLIC KEY----- 6 | -------------------------------------------------------------------------------- /certs/a000000004/34.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MHowDQYJKoZIhvcNAQEBBQADaQAwZgJhALvkOHfMKMDOHhS8FOhHcxfiGDZFMdFV 3 | u4rFtjwNbihN0kJZGTiZ+cBMMLrxZ9V5KUUfZ669O70NQURFAYR9jwLywqLRSBfZ 4 | euJiXcFjv4tITED/tRdJzt3pQ0+yoKQQmQIBAw== 5 | -----END PUBLIC KEY----- 6 | -------------------------------------------------------------------------------- /certs/a000000004/9.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MHowDQYJKoZIhvcNAQEBBQADaQAwZgJhAJZ7YmRDbJaqkwV3alkZxw2nljQPmZem 3 | xu977x1Nv5y0KJ+3mQq/8fOuaS8ShEskUqUK4HX7Mnl2pA6AKPJ5sePMtiOVfWlv 4 | wSJcouyVDi1BXpqpMf8YsTFo1mH70G8KuwIBAw== 5 | -----END PUBLIC KEY----- 6 | -------------------------------------------------------------------------------- /tools/Makefile: -------------------------------------------------------------------------------- 1 | CC = clang 2 | OBJ = modexp2pubkey.o 3 | LIBS = -lssl -lcrypto 4 | 5 | %.o: %.c $(DEPS) 6 | $(CC) -c -o $@ $< $(CFLAGS) 7 | 8 | modexp2pubkey: $(OBJ) 9 | $(CC) -o $@ $^ $(CFLAGS) $(LIBS) 10 | 11 | .PHONY: clean 12 | 13 | clean: 14 | rm -f *.o 15 | -------------------------------------------------------------------------------- /certs/A000000003/152.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGKMA0GCSqGSIb3DQEBAQUAA3kAMHYCcQDKAm5SppXnK9MK+SgZbu3J+vSmGfJJ 3 | Lj+zEWl4nCdv+7fUMRZke6ng0QajVC45ZSks93gj3TTKjux942fggHCJUHfH762T 4 | mSTLGHBn2/ksseeFkXvTi6zgwZTKEt8M5belAnWsYb58O0Noh8qYyf05AgED 5 | -----END PUBLIC KEY----- 6 | -------------------------------------------------------------------------------- /certs/A000000003/3.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGKMA0GCSqGSIb3DQEBAQUAA3kAMHYCcQCz5eZnUGxHyq+xKiYzgZNQhGaX3WWn 3 | luXOd8V8Ympm9wu2MJEWEq0oMpCbgGIpG+ykbNM7Zqb5ydSM7YtPyFYcih2PsVhi 4 | yetgF43qK+H4Ijb/z/TzhDwnIXnc3ThNVBBT2mpqDTzkj9wtxOPg7uFfAgED 5 | -----END PUBLIC KEY----- 6 | -------------------------------------------------------------------------------- /certs/A000000010/252.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGKMA0GCSqGSIb3DQEBAQUAA3kAMHYCcQCze/0qlnStYiHBoAEIHGJlPcKAsKm9 3 | BSxnfJE856DZAud7EvTU15A3sem5I6i7P6w8YSBFuzkU+N9B6aG2G/pbQXBaaR0J 4 | zm9TD+SLMCQNmPTmkv/WqtuHJDuoWXqyN1huzyWPQUh1G+XaWjvmzDS9AgEC 5 | -----END PUBLIC KEY----- 6 | -------------------------------------------------------------------------------- /certs/A000000010/255.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGKMA0GCSqGSIb3DQEBAQUAA3kAMHYCcQC4VcxkMTr5nEU9GBZC7n3SGmfQ/1DG 3 | H+ITvNwYr7zQdyLv3SWU79wifaPaI63MkOP6kHRTrMlUxHMjvtz41IYsRX0l9HsW 4 | 18NQK+CBkT5bBILYOEhAZdpfZlngCp5dVwraHsavjFeWAHURlYH8gUaNAgED 5 | -----END PUBLIC KEY----- 6 | -------------------------------------------------------------------------------- /certs/A000000025/2.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGKMA0GCSqGSIb3DQEBAQUAA3kAMHYCcQCvS40jD9/LFTjpdXlaHbQMOWpTWfqj 3 | GuCVy1IqXILn//slKGDsKDPsPUpmXxM92TTuEUjYHit+A/kpld3363yQp1q5jmnJ 4 | LskaUzsh4cSRi0Ov7VeA3hOjK70368OE+j3RpFPjJ8VgJNrK6nSqBSxNAgED 5 | -----END PUBLIC KEY----- 6 | -------------------------------------------------------------------------------- /certs/A000000029/152.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGKMA0GCSqGSIb3DQEBAQUAA3kAMHYCcQDKAm5SppXnK9MK+SgZbu3J+vSmGfJJ 3 | Lj+zEWl4nCdv+7fUMRZke6ng0QajVC45ZSks93gj3TTKjux942fggHCJUHfH762T 4 | mSTLGHBn2/ksseeFkXvTi6zgwZTKEt8M5belAnWsYb58O0Noh8qYyf05AgED 5 | -----END PUBLIC KEY----- 6 | -------------------------------------------------------------------------------- /certs/A000000029/3.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGKMA0GCSqGSIb3DQEBAQUAA3kAMHYCcQCz5eZnUGxHyq+xKiYzgZNQhGaX3WWn 3 | luXOd8V8Ympm9wu2MJEWEq0oMpCbgGIpG+ykbNM7Zqb5ydSM7YtPyFYcih2PsVhi 4 | yetgF43qK+H4Ijb/z/TzhDwnIXnc3ThNVBBT2mpqDTzkj9wtxOPg7uFfAgED 5 | -----END PUBLIC KEY----- 6 | -------------------------------------------------------------------------------- /certs/a000000004/2.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGKMA0GCSqGSIb3DQEBAQUAA3kAMHYCcQDPQmThcC00yol9H5tmxdY2kerMYSyP 3 | FHEWuyLQxGNJW9W6cPsVOEiJUiC4re7D57qzHqIsHcmXL6An1UJlvr8K46I6igkY 4 | fyHIVmB7mL2m/JCBFoFsUCs+WKFFJU7v7iozNRECJAKLZ4Cdy4BY4kiVAgED 5 | -----END PUBLIC KEY----- 6 | -------------------------------------------------------------------------------- /certs/a000000004/252.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGKMA0GCSqGSIb3DQEBAQUAA3kAMHYCcQCze/0qlnStYiHBoAEIHGJlPcKAsKm9 3 | BSxnfJE856DZAud7EvTU15A3sem5I6i7P6w8YSBFuzkU+N9B6aG2G/pbQXBaaR0J 4 | zm9TD+SLMCQNmPTmkv/WqtuHJDuoWXqyN1huzyWPQUh1G+XaWjvmzDS9AgEC 5 | -----END PUBLIC KEY----- 6 | -------------------------------------------------------------------------------- /certs/a000000004/255.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGKMA0GCSqGSIb3DQEBAQUAA3kAMHYCcQC4VcxkMTr5nEU9GBZC7n3SGmfQ/1DG 3 | H+ITvNwYr7zQdyLv3SWU79wifaPaI63MkOP6kHRTrMlUxHMjvtz41IYsRX0l9HsW 4 | 18NQK+CBkT5bBILYOEhAZdpfZlngCp5dVwraHsavjFeWAHURlYH8gUaNAgED 5 | -----END PUBLIC KEY----- 6 | -------------------------------------------------------------------------------- /certs/501649FF20/5.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC1pYtUONOwIju85NQplMqcB5PK 3 | HlNlQ/nnVjuZtnF3u5APCrxbvt8xK+QOCQEj3vlDvDIcHCy+9tsh63AK18/LYmIc 4 | yBLJ9HNV8uQimPuao/A5NxVyp/3oLj3owu4aMRzTSPQ4et2J+v7jaXcyb+WG6nlm 5 | ilCNkdOl+5sEKGbxfQIBAw== 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000003/1.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDGlgNCE9fYVGmEV50dDw6lGc/4 3 | 3v/EKTVM86hxpvcYPxIo2lx0cMBVOHEAy5NacSxOKGTfXWS6k/5+Y+cfJbHl9SmF 4 | devhxjqmF3BpF5EdwqdawoslHH70DyNlkSSQuTm8ohJKMKKPVEAsNK7KMxq2fh55 5 | soXdV3G12f956mMLdQIBAw== 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000025/3.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCwwsbipjhpM80XwjlJa/SMV+OJ 3 | Fk8qlr/xM0Oa6Kd7IEmL1NxpWasMLQXQcjrzZokBk3tnTlovqS3dXnjqnXXXliAX 4 | PMJps19GOz1Kr/J5T5Lmx6P7lTJdirlZYMMGa+VICHvLbOEmiBRKi0pmIorkZZxj 5 | TJnjYBFYTAlQgqOj4wIBAw== 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000029/1.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDGlgNCE9fYVGmEV50dDw6lGc/4 3 | 3v/EKTVM86hxpvcYPxIo2lx0cMBVOHEAy5NacSxOKGTfXWS6k/5+Y+cfJbHl9SmF 4 | devhxjqmF3BpF5EdwqdawoslHH70DyNlkSSQuTm8ohJKMKKPVEAsNK7KMxq2fh55 5 | soXdV3G12f956mMLdQIBAw== 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000065/7.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC42riD7xtXY+T4YfnqMESydmNd 3 | QC865ea2wFR+No55o2Nm2sVgm27EhtoajSACyk9O/Cyw7BVzoLCReWnrYGRbrt8R 4 | wFDF0H/tgX0R6EoXSFmg2uf3k18QkinArE7lv7PWVTOmefBIbFrvzJNzeYM77EXX 5 | nc+XtSKLGRD6A3ZTMQIDAQAB 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000065/8.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC3RnDa0dyJg2UgAOWn8vizXf0I 3 | PuWT5bqJXJVynyut6cir892c4kDEUcbO/8do2Dy6x2q7j+pY8BPGRwB8/3YXusKu 4 | OYGBbyXMflI47zTE8C0LAcJPgMLGXn53Q6T6jiMgaiPs4pDCbqVtsIXFxeriYpJF 5 | H8gpL5lXvo/yD61T5QIBAw== 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000065/9.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC3Ko/vWyfytVA5j9zCVvcUutSX 3 | /1YJS3QIMoy2JqpvDmqd+DiOuYh7yTAXC8wSE+kPwHDVLI3ND/nhD602gB/pP8mY 4 | pyFwUJHxi8fJgkHK3BWiudp/uWMULAq2QNXQE153666VrxtP763PnAEjZr3aBFXB 5 | VkpogQ1xJ2dtSTiQvQIBAw== 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000141/2.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCv11Npm2/C5cvqy7axR8VypX7e 3 | mPRii1bLXt7IBtptzIyFy0WFkzBGdG0N15/dvnVJVCEWu60v0190qMM/dG/Q7FvG 4 | JBsRKyEvjF9Khkr0A72UTD/aGST9TXzfeQdDBskiUTuIPCTlZ6/CpkHzXf7/nKKC 5 | X5+kQJ1l08lfMnKJ0wIBAw== 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000333/1.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC76QZtJRdRHSOce/p3iEFEriDH 3 | Ny9RUUfozmU3xUwKak1F+MpNKQhwzaWfE0TvcdF9PzXZLz8Gd40NUR7Cp9xP/q30 4 | +xJTzjensrWjdBInvvclJNp6K3sctCa+4nvFE7DLEauZvBvGHfWsbMTYMdCEh4jN 5 | dPbVQ603xaK0xdWpOwIBAw== 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/B012345678/5.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCh9eHJvYZQvUOrbuVriR73RZwK 3 | JPqE+RJ9Gmx51JMPbbGFLiUQ8YthzTVNuDo1a9GQuIq43wQoTQKkIEp7bLfFVRl3 4 | qbNjeco94aCOafMByVzBwgUGlZJ19Bcj3V0pJSkFeeWpWw32Mj/I6Sc9b4SRmMSZ 5 | YgkWbZv8lzw2HMgm4QIBAw== 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/a000000004/240.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGcMA0GCSqGSIb3DQEBAQUAA4GKADCBhgKBgHVjxRtSdqpjcKuEBVIkFGRYMra+ 3 | 8qmJx3FHWy6NxlTcilv/nijjH/GjcKQNw//rBryFSH1fHLYcJEH9ccvNBdiD+N5B 4 | OyQ6/J3KdosGHjW4hLXSG2sBaqNroS2rz+SfjlKMiTw0x9R5OXfkzJmrCWQNnHqr 5 | fsX/P0Dj1NGN9+OnAgED 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/a000000004/3.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDCSQdH/hfrBYTIjUexYCcEFQrc 3 | iMW5mL1ZzgQ+3r8P/uMJOseVatO2rUVUxt4ZoXjW2ilb4V1SIGRePIExZm+kvluE 4 | /hMepEsDkwdji550qMQlZPiSpk3xyxVxK3NuM3Txu7aBk3FgLYlw6XuQB5PHwqia 5 | ShZJpZvmgFdN0LYBRQIBAw== 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000003/150.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC3RYbRmiB75mJ8WwqvvESi7PWi 3 | lC06Js4ZxP+u7pIFIYaJIuiT54OCJaOUeiYUeW+ywGKM6MEeOCWlbTsbuu94Olxq 4 | gfNvhiU5USb6mDxSFtMWbUis3opDEhL/djp/edntt/7Xa0hd5Fvrgpo9RzCEijZt 5 | MyTDAnAy/40WoeRNjQIBAw== 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000003/153.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCrefzJUgiWln53bmRETl3N1uE2 3 | EYdPOYVyJSBCUpXupL0MJ4HefzHNPQQfVl90cwbu1ilUsX7aujpsW4Wh3hvrmjQU 4 | GvOPz4J5yd6g1aZxDQjbQSTwQZRVh+IDWbq0e3V1rZQmLUsl8mSvM97c8o4JYV6T 5 | feMu3APFREX+fjgndwIBAw== 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000003/16.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCfJwHAkJzL2MPtPgccafd2FgAi 3 | /zKZgH7XoDXtV1J3DiMtVsw74Vm9jwyotZQ1aIki9Ab1XHVjlFe7q+/pqGsiae8i 4 | PjS5GqbfLMrQO0rUtEPWFXXKlghF5saQQBAeIx2e+BGtmbBxUGWg5mFEnEG0sCO3 5 | cW0eSv8ckHBOVa4SJQIBAw== 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000003/32.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCZjSrZRqYPxZfZOAfbVLKwpVCH 3 | HkPxd58HOvCNmwSr0XyKfao+Zu5EPzD5Jkj8U9pXp4NksGL+21D3I1uTfhbl9tnm 4 | uo8Qb7Ml7KJRJREc4EtDCYzeqKQUJvxtlPikdhntsSeJWBgIaSz7ofOOgAjMXgIG 5 | ahiJ1S93uaEh5ll/OQIBAw== 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000003/80.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDREZdZAFe4QZbC9NEajzwFQI9C 3 | KjXXAvkBBupbAZuyiuYHqpzevNDYGjjUjH67AGLShzaewMQhJCRqww2AzWAqtyON 4 | UQhN7UaYFixZ0l6sHmYlW02yNSUm7wmCw7itPRzOhbAdtXiOdeCfRL5zYTZt750e 5 | ExewXl0P9SkPiKDbRwIDAQAB 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000010/251.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCpVI37OYtIEj+vQebPpK4eI1K1 3 | GKtLzv7NsLPt7AkCh9iLEiWfNhwcwIjl8GZJRBfo7ou/iZHisy/xb5lGl4QrPWyz 4 | eiu1dCpEC2NWxiqjPbPEVeWe3feGRwHQOluD7p6b2Dq5MwKsLf5j5mEgsFHPCB9W 5 | MmpxMD2VK7M2/xJhDQIBAg== 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000010/254.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCmU+rBwPeGyHJPc38XKZfWPRwy 3 | UcREAgSbhluuh30POYy/vopgNeJK+ghr796TUeVLlXCO5nLwlovNUNzkD3gzIrKr 4 | oE7xN+8Yq/A8fbxYE66u86p3l7oV331bocuvf9UgtaSC2NP+4QUHeHERPiOkmvOS 5 | ZVSnD+EO1yjPeTtioQIBAw== 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000025/100.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCw3VUQR9r80Q2aXjPPR6kzPjsk 3 | 7Ffo8GanLe1g6IGorUJ3fGet3wcIBCq5Q2Ae5gJIVAtn4GNwGO6zkRrpyHPa1my0 4 | C8j03HfrJZUlK2HCFRj3m3BqrCnn0/1NJZ23K25tRG3WA4bbQPX9sHbYA3TJk7S7 5 | LR25d8OHCJf536RU9QIBAw== 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000025/102.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC9FHiHe5MzYS0lfZ48nCNQPigz 3 | a3I8cfR8JYNmcDlTYPU8EG/XTe7qKRJZwAGvvntKg2VPbi2egUjiyx2SI6xZA9oY 4 | tDP441KSJ1Bd6EdI8kH3v80hRuXpqMXSoG0ZCXCHoGn5rj1hDHyOEhRIGk8nAloa 5 | LtuKnNr6RFaQUR24BQIBAw== 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000025/150.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC8mqKUsf3SYxduMkPY9Ei7/8tq 3 | vQLDGBEon1CFqSYrixt8ZHfrWAVdnvMqg9G3LUoUceyjDOdlhcP9BTcraG+St5Wx 4 | ZAlZIBUjIwFJEY1S0kJb0RyGPZsqfErQor/bymeycTspD0k81VIeXd8F7xBA/CON 5 | CoUcjj47Kx8NXZ1K7QIBAw== 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000025/82.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4MUFOC0YTkivTW0s2gCvB4egc 3 | laJ8lY9TggA99kYVTKkvwc4Cw74EekXpsCqQibS5AngjfJZRkqD8yGu0m8gq5v3C 4 | 3nCQBrhsdnbv31l2JvrWM6T33EjERdN+tV/LOxq7lbqqgm1TkOFf0U7UA/otDLhB 5 | xlBglSTsVV47xWypVwIDAQAB 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000029/150.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC3RYbRmiB75mJ8WwqvvESi7PWi 3 | lC06Js4ZxP+u7pIFIYaJIuiT54OCJaOUeiYUeW+ywGKM6MEeOCWlbTsbuu94Olxq 4 | gfNvhiU5USb6mDxSFtMWbUis3opDEhL/djp/edntt/7Xa0hd5Fvrgpo9RzCEijZt 5 | MyTDAnAy/40WoeRNjQIBAw== 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000029/153.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCrefzJUgiWln53bmRETl3N1uE2 3 | EYdPOYVyJSBCUpXupL0MJ4HefzHNPQQfVl90cwbu1ilUsX7aujpsW4Wh3hvrmjQU 4 | GvOPz4J5yd6g1aZxDQjbQSTwQZRVh+IDWbq0e3V1rZQmLUsl8mSvM97c8o4JYV6T 5 | feMu3APFREX+fjgndwIBAw== 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000065/218.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDcdEnsJJROpMCe83ZW9TkFlN5P 3 | FoavxLHCHIk/XzrvxagQngalI4nAQU59+8RCk7BNX06FUo+oXxqXBrqqoDTotEER 4 | wEOxzJUwnGlGIllx1LFYkJ9EOHJoEnd/rE0Gh5p6pBCJ8N0sJ7PqojqNAuKpqbjt 5 | rQyjKukbODdAz1Dl5QIBAw== 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000333/10.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCyqxtumsVada39W7w0SQ5TxMM4 3 | HzTmDn+sIcwrJt00RitkpvriSV7R3Tg7gTi+oQD/m3oRGBfnuYaal0KxnlydrFb4 4 | uIJ/EbBaCOzPno1ehbD3z6ZE7/Ppt5ZojzjgBt6yHhAcAQKJA6BgI6xaq4Y1+OMH 5 | pTrHQr3Oaig/WF9I7wIBAw== 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000524/106.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCSeV6qT+OeswRB/pUtVCN3jgL4 3 | Z4O4ndfFh66App9NbcVer7ZgQEDYdccgAkJe5SnOTqJv2GS612AWDCqgxa+SOBiU 4 | pcu8irOvJkFgbDebkno5fLHpueou+MCpwN3ruBsPiROhGPcEQVbqfSOvYm6vMMLJ 5 | 7OhTTTVj71/pXediSQIBAw== 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/B012345678/246.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCh9eHJvYZQvUOrbuVriR73RZwK 3 | JPqE+RJ9Gmx51JMPbbGFLiUQ8YthzTVNuDo1a9GQuIq43wQoTQKkIEp7bLfFVRl3 4 | qbNjeco94aCOafMByVzBwgUGlZJ19Bcj3V0pJSkFeeWpWw32Mj/I6Sc9b4SRmMSZ 5 | YgkWbZv8lzw2HMgm4QIBAw== 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/a000000004/247.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCU6mL21YMg41TAIq3c8FWdjPIG 3 | zZLoaVZJBc4h1yD5cbeuo3SDDr4XVxFaheCI1Bxrd89eyCHzCx2JBBe/L6MeWQje 4 | 1fpnf4x7GErQkCj93pa2phCYUKqAAXXqvNu7aEqWwutjed/qCNMv4jMf4QMjOtWN 5 | zbHm4HfLnyTq7FwlrwIDAQAB 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/a000000004/248.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCh9eHJvYZQvUOrbuVriR73RZwK 3 | JPqE+RJ9Gmx51JMPbbGFLiUQ8YthzTVNuDo1a9GQuIq43wQoTQKkIEp7bLfFVRl3 4 | qbNjeco94aCOafMByVzBwgUGlZJ19Bcj3V0pJSkFeeWpWw32Mj/I6Sc9b4SRmMSZ 5 | YgkWbZv8lzw2HMgm4QIBAw== 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/a000000004/251.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCpVI37OYtIEj+vQebPpK4eI1K1 3 | GKtLzv7NsLPt7AkCh9iLEiWfNhwcwIjl8GZJRBfo7ou/iZHisy/xb5lGl4QrPWyz 4 | eiu1dCpEC2NWxiqjPbPEVeWe3feGRwHQOluD7p6b2Dq5MwKsLf5j5mEgsFHPCB9W 5 | MmpxMD2VK7M2/xJhDQIBAg== 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/a000000004/254.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCmU+rBwPeGyHJPc38XKZfWPRwy 3 | UcREAgSbhluuh30POYy/vopgNeJK+ghr796TUeVLlXCO5nLwlovNUNzkD3gzIrKr 4 | oE7xN+8Yq/A8fbxYE66u86p3l7oV331bocuvf9UgtaSC2NP+4QUHeHERPiOkmvOS 5 | ZVSnD+EO1yjPeTtioQIBAw== 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/a000000004/82.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4MUFOC0YTkivTW0s2gCvB4egc 3 | laJ8lY9TggA99kYVTKkvwc4Cw74EekXpsCqQibS5AngjfJZRkqD8yGu0m8gq5v3C 4 | 3nCQBrhsdnbv31l2JvrWM6T33EjERdN+tV/LOxq7lbqqgm1TkOFf0U7UA/otDLhB 5 | xlBglSTsVV47xWypVwIDAQAB 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /emv/processingoptions.go: -------------------------------------------------------------------------------- 1 | package emv 2 | 3 | import "github.com/greenboxal/emv-kernel/tlv" 4 | 5 | type ProcessingOptions struct { 6 | ApplicationInterchangeProfile int `tlv:"82"` 7 | ApplicationFileList ApplicationFileList `tlv:"94"` 8 | 9 | Raw tlv.Tlv `tlv:"other"` 10 | } 11 | -------------------------------------------------------------------------------- /certs/501649FF20/7.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGtMA0GCSqGSIb3DQEBAQUAA4GbADCBlwKBkQCxx5W7j2Uz6RLY1SCqT+NlrpKj 3 | Gle7JTgiqBJk4bjNMLBTN/tKCRDskl7cpJQSmJl0IdSlewYMqGb87ONGkcDoqg9P 4 | fMxGcJ9+kk2HZowZbzEzOIePAnr1F7ZnOGJEIQ5qIA1G87ycchGTB11vZPVdVwPG 5 | SnNG2nNMhN5OuZKB1bWc2NZTWgY1Pf0iej9jlEMCAQM= 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000003/7.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGtMA0GCSqGSIb3DQEBAQUAA4GbADCBlwKBkQConyWlb6baJYyMqLQEJ9kntKHr 3 | TX6jJruxL5fe1wrl5EgPycXoqXIXcRChzDGNBtL49cSESsX6eaTcRwuxHtY1aZwX 4 | CBuQ8bmE8S6SwcUpJ22K+Ox/KEkgl9jNW+zqFv5AiPbPq0obQjKKG5lvkniwt+Mx 5 | HKXvhWwviIR0uDYSqC5OANDNQGmmeDFAQz1Qcl8CAQM= 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000029/7.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGtMA0GCSqGSIb3DQEBAQUAA4GbADCBlwKBkQConyWlb6baJYyMqLQEJ9kntKHr 3 | TX6jJruxL5fe1wrl5EgPycXoqXIXcRChzDGNBtL49cSESsX6eaTcRwuxHtY1aZwX 4 | CBuQ8bmE8S6SwcUpJ22K+Ox/KEkgl9jNW+zqFv5AiPbPq0obQjKKG5lvkniwt+Mx 5 | HKXvhWwviIR0uDYSqC5OANDNQGmmeDFAQz1Qcl8CAQM= 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000141/5.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGtMA0GCSqGSIb3DQEBAQUAA4GbADCBlwKBkQC1Flj7+1dCP2kOc1LaLlJ+rDcj 3 | 4vCx2FIe20T0EityDQRapUwpkMv6s7s6762vpsv2XzObdblCI8JxS9I1SxIonu6K 4 | lPdUVNze8K778MLIjhoWFfbwM3h9/57pSGPAHkoLGZLwJWJIca0snFcjS1/WybW+ 5 | l4IdDrlEoyH05bKoUW7bkhF8tKsNOVBKgTDEvQ0CAQM= 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000333/2.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGtMA0GCSqGSIb3DQEBAQUAA4GbADCBlwKBkQCjdnq9G2qmnX8/vyjAkt6e0eZY 3 | ul8JCa96HM2Qc3O3IQ/esWKHuo544VKfRDl2/Sf5kexn2V5fTpaxJ8qyOWqU1uRc 4 | 2kTKTEhnVw1rB1QvjUv5/5eXXbmJFRXmb1JdKzy+ttZiv7bD8zjpOwIUK/xEFzo3 5 | ZMVqrdICB1sm3C+ffXrnS9fQD9Be5DADJmPSelcCAQM= 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000333/8.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGtMA0GCSqGSIb3DQEBAQUAA4GbADCBlwKBkQC2FkXt/VSY+yRkRAN6D6GMDxAe 3 | vY76VFc85uan+/Y+0h1mNAhSsCEc9e72oc2Yn2avIajrGdvY28NwbRNTY6DWg9BG 4 | ME9ag2vBvGMoIa/novddo8UKx0xUWnVFYiBBNxaWY8/MCwbmfiEJ66Qbxn/yDMis 5 | gNe27hqVRls7JldTPqVtktU55QZDYOpIUP7S0b8CAQM= 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/a000000004/4.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGtMA0GCSqGSIb3DQEBAQUAA4GbADCBlwKBkQCm2kKDh6UC1937enTT9BK+diYn 3 | GXslQ1t6gXFqcAFX3dBvfMmdbKKMJHBSfiwDYWucWSFzV8JnT1g7O6XH3PKDhpLQ 4 | I+NWJCC0YVxDnKl8RNyaJJz857O/si9oIow68TMpqkphPPjdhTUCNz1i5JqyVtK8 5 | FxIOVK7c7W2WpCh6zFwEZ31KWjINuL7i93Xl/sUCAQM= 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/501649FF20/35.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGtMA0GCSqGSIb3DQEBAQUAA4GbADCBlwKBkQDDeu05ypjahGu33Jmq5H+l2mR1 3 | SntlYoJItOqhz21wPNBSuJlMoqzHb+ovehUgdY+6dEplf0WNqGrJ6tN4x19iCicA 4 | nqSfuDAdaXB6NUjKRV/LFlXG0jDMYSwq6Cd/LfwuEDJ4wWrcZD7axSNAK35Hmho/ 5 | eMyYJqKPXwOmuc27iafzyLAUo2ttIFTBfiAstOMCAQM= 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000003/149.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGtMA0GCSqGSIb3DQEBAQUAA4GbADCBlwKBkQC+nh+l6agDhSmZxKtDLbKGANzZ 3 | 2rdt+qpHNVoP43sVCKxr84hg08bC5bEqPKrypwBackHrqndxESx0z5oGNGUvvKDl 4 | mAxUpkdh6hAaEU4PC1VyrdV9AQt8nIh+EEyk7hJy2mbZl7mpC1ptYkq2xX5zyPkZ 5 | AA619oSJjvjD2++zMMYmYL7YjqeOkJr/BfbaYnsCAQM= 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000003/243.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGtMA0GCSqGSIb3DQEBAQUAA4GbADCBlwKBkQCY8Mdw8jhkwudm3wLR6DPf9P/p 3 | LWluFkLwqIxWlMZHnRbbFTe/4p5P3G5uiv0bDrfqASRyPDMxeb8Z6T8QZYsvd26C 4 | nofa7anJSoszghmaNQwHeXfJev8I/RExCslQpyw8pQAu9RP8zChuZG48U4dTXVCV 5 | FLOzJuEjT5y0jDbd1EtBbSNlQDSmb0A7pRHF76MCAQM= 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000003/81.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGtMA0GCSqGSIb3DQEBAQUAA4GbADCBlwKBkQDbX6KdH9qMFjSwTcz/FIq+5jx3 3 | IDXHmFHTUSEHWG4CqRf3x+iF58Sn1SlxChRTNM5n3EEssVl7d6olQ7mNGc8suAxS 4 | K9vqDxsRP6LIYhbIxhCi1Y8pzzNVzrG9PvQQ0e3R964PFol5ed4oxu8pPgoZKCvR 5 | 15PxMxUj/HGiKIAEaMAaNlPRTGtIUaXAKUeOdX8CAQM= 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000025/101.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGtMA0GCSqGSIb3DQEBAQUAA4GbADCBlwKBkQDlPrQfg53ftHTycs0Mvjc9VGjr 3 | P1DznJW99NOfqCuY2ryUdrbqNQwNzhzZIHXYxE0eVygxkPlrNTfZ5jLEYYFevSuv 4 | Nokd9r+x0w+gt1LEPcoCV9Nd/0zPyY+EGY1RUuxh17X3S9CTg70OKqQimP+wLw15 5 | rbcNciQ+5Tf3VTaoqN+WJYLp5oEvOgvgKkNlQA0CAQM= 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000025/14.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGtMA0GCSqGSIb3DQEBAQUAA4GbADCBlwKBkQCqlKjG2tJPm6VqJ8CbAQIIGVaL 3 | gaAmvp/Qo0FsqacRZu1QhO2RztR91Ffbfmy81T5WC8XfSKvDgJk7bVSfUZbPp337 4 | IKApYYjpaaJ3LoxBQWZfi7JRa6LHtfyR+NoE6NUS6w9kEVFvuG/AIc5+lp2pTTOT 5 | eQmlOlf5B8QMIgCdp1Mss75QmuFzs5rWoBulu4UCAQM= 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000025/151.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGtMA0GCSqGSIb3DQEBAQUAA4GbADCBlwKBkQDheP/oNLS3Z688mlEflz2OhQXF 3 | /LLTdoB1q3zJRqlVeJlVh5qvc3QHFRUhmW36Q8WOaxMOsdhjuF3J/7QFCUeiZ2qm 4 | oGGkp64e2w42ppfofgN1F+uJIxNodbosoQh8un7HZT5eKKDCYaAzryfjpntku6Jp 5 | VjB+xH5nTj+Lcis64EmNsWx5hTENnz0RcwDTKwkCAQM= 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000025/193.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGtMA0GCSqGSIb3DQEBAQUAA4GbADCBlwKBkQDmnjGcNNG0+0Ou1L2Lum96i3Y/ 3 | L27l3ffJJXmphPicSpwVsnA3dkxYrH5F77w04Tjla6OPdugDEpqN3rXhzIxrMM9j 4 | SpycEiS/HwqaGNee1B688b54CHrot9L4lrHei354QWGhOKDyFprTPhRtGxarWV+d 5 | fZi+ZxBi0hf0TraMaGQMfVdGWgY/a6x3bT4trGECAQM= 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000025/200.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGtMA0GCSqGSIb3DQEBAQUAA4GbADCBlwKBkQC/DPztcI+2sEjjAUM26iSqAH15 3 | Z7iqTmE9JtAVxP54BdnbExztDSqO1QTDtczUjDMZnlpb9kTaBDtU2/YCdvBbF1D6 4 | s5CYx1EdBLq8ZJSC3c98xCyMQ1urjdDrGmIMMREdGqr5r2Vx7r1M9aCEltV+er27 5 | UYDgpC2oaauV+2IO/yZBw3Aq874LDBOOrvIC4h0CAQM= 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000029/14.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGtMA0GCSqGSIb3DQEBAQUAA4GbADCBlwKBkQCqlKjG2tJPm6VqJ8CbAQIIGVaL 3 | gaAmvp/Qo0FsqacRZu1QhO2RztR91Ffbfmy81T5WC8XfSKvDgJk7bVSfUZbPp337 4 | IKApYYjpaaJ3LoxBQWZfi7JRa6LHtfyR+NoE6NUS6w9kEVFvuG/AIc5+lp2pTTOT 5 | eQmlOlf5B8QMIgCdp1Mss75QmuFzs5rWoBulu4UCAQM= 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000029/149.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGtMA0GCSqGSIb3DQEBAQUAA4GbADCBlwKBkQC+nh+l6agDhSmZxKtDLbKGANzZ 3 | 2rdt+qpHNVoP43sVCKxr84hg08bC5bEqPKrypwBackHrqndxESx0z5oGNGUvvKDl 4 | mAxUpkdh6hAaEU4PC1VyrdV9AQt8nIh+EEyk7hJy2mbZl7mpC1ptYkq2xX5zyPkZ 5 | AA619oSJjvjD2++zMMYmYL7YjqeOkJr/BfbaYnsCAQM= 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000065/10.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGtMA0GCSqGSIb3DQEBAQUAA4GbADCBlwKBkQCZtjRk7gtJV+T9I7+SPRK2FGm4 3 | //iBQ0ay7Wp4D4mI6pzwQzvB5lXwXvpm0MmAmPJbZZ16JbhHijbkiXYNBx9UzfdB 4 | aUjtcz2BY0naKq3aIn7kWTYgPL9ijNAzqrpeWm5K43+6y0YRtBE+1CdSnGNvbDME 5 | +KvdbZrWYFFq6H9/Ld8dL6RMFkcn5Wu8m6I8AoUCAQM= 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000065/15.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGtMA0GCSqGSIb3DQEBAQUAA4GbADCBlwKBkQCe+63eQHHU75jJaesyr4VIZGAu 3 | UV1lAf3ldrMQlkpPfCzoQqvvr8XcniamGbzyYU/gc3W5JJvvoJz+5wIy51/9ZHVx 4 | KAx2/8qHURrSVbmKa1d1ka8B0AO9a/fh/OTf0g0NApftXsol3iYfN+/p4XX7XxLS 5 | UD2M+wYKYxOFEf4OElzzpkOv19Ztz5aCvSRt3qECAQM= 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000065/16.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGtMA0GCSqGSIb3DQEBAQUAA4GbADCBlwKBkQCZtjRk7gtJV+T9I7+SPRK2FGm4 3 | //iBQ0ay7Wp4D4mI6pzwQzvB5lXwXvpm0MmAmPJbZZ16JbhHijbkiXYNBx9UzfdB 4 | aUjtcz2BY0naKq3aIn7kWTYgPL9ijNAzqrpeWm5K43+6y0YRtBE+1CdSnGNvbDME 5 | +KvdbZrWYFFq6H9/Ld8dL6RMFkcn5Wu8m6I8AoUCAQM= 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000065/234.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGtMA0GCSqGSIb3DQEBAQUAA4GbADCBlwKBkQCpeWwp45wtRP3a5+4TQdpUYdzk 3 | 3LMUONWDsrwIRbZKo30FWxkNf1FS5QV6X7nNJ2NOrEADooA8gE4i1JJzihZDaaF/ 4 | Jl+AFsYi2gYxSU8DstpNXn0T9wgvm9inOTsRmscKOehhtkWx+/KbqcwbilqXtahE 5 | TbD8pbxRHmjnsB163LjkbZZIqZXiVvdxUlG0MbMCAQM= 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000333/12.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGtMA0GCSqGSIb3DQEBAQUAA4GbADCBlwKBkQDe2eG8jnScrXSUhL+0ckRbyB/6 3 | qJcHZIw0KqMNG+YNXtD2zquiXGg9RQPLEcr5GjlydZPPK+6ugDLvrMRP342jHWAH 4 | E51FlehlXHSVz0ap1ZOoPjxlssvyrx7qAtH5aVGpRmFrWrIcoL800S0F9q4YNQin 5 | rHpGkTvc5f3DkUynUAGLEwylutSa2MAikaylz/0CAQM= 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000384/193.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGtMA0GCSqGSIb3DQEBAQUAA4GbADCBlwKBkQCtbgDliCzu9XivsAKYD72QEIkQ 3 | C5ISANZELBdtk9pck5m4Qny+GcGy5jj1/HiHXIK+fOWQFg0OigQkI3TlxLXzB+dB 4 | LKj7LoS7T0Ida0wuCCVbJXf1XgZnZzvX16PXTgg9wZtZenZTETWnw7Hbk1NAReHV 5 | LdtRcKz6poiSLBh2TP5Z49BXjEGnvWBSDK3FjdkCAQM= 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000524/107.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGtMA0GCSqGSIb3DQEBAQUAA4GbADCBlwKBkQDJ39tiWtpLXoYEn4WgI3YntZUk 3 | 9SvUmbTFSCwe4BLWGhRG6Tg8wLfuKSLTI6Xs2hKUHqgXfPpRLaa1t2Y6ibeTsQ0x 4 | TLt3brltCxc07efhWRcTkV6Zkbe06KAXppASea691hNsn+fgxsv5THf6YGtinQCx 5 | +JBHOQXrTa0a2TspwsGCmoL4gLCJhrk4dhHuQJ0CAQM= 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/B012345678/243.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGtMA0GCSqGSIb3DQEBAQUAA4GbADCBlwKBkQCY8Mdw8jhkwudm3wLR6DPf9P/p 3 | LWluFkLwqIxWlMZHnRbbFTe/4p5P3G5uiv0bDrfqASRyPDMxeb8Z6T8QZYsvd26C 4 | nofa7anJSoszghmaNQwHeXfJev8I/RExCslQpyw8pQAu9RP8zChuZG48U4dTXVCV 5 | FLOzJuEjT5y0jDbd1EtBbSNlQDSmb0A7pRHF76MCAQM= 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/B012345678/247.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGtMA0GCSqGSIb3DQEBAQUAA4GbADCBlwKBkQCY8Mdw8jhkwudm3wLR6DPf9P/p 3 | LWluFkLwqIxWlMZHnRbbFTe/4p5P3G5uiv0bDrfqASRyPDMxeb8Z6T8QZYsvd26C 4 | nofa7anJSoszghmaNQwHeXfJev8I/RExCslQpyw8pQAu9RP8zChuZG48U4dTXVCV 5 | FLOzJuEjT5y0jDbd1EtBbSNlQDSmb0A7pRHF76MCAQM= 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/a000000004/243.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGtMA0GCSqGSIb3DQEBAQUAA4GbADCBlwKBkQCY8Mdw8jhkwudm3wLR6DPf9P/p 3 | LWluFkLwqIxWlMZHnRbbFTe/4p5P3G5uiv0bDrfqASRyPDMxeb8Z6T8QZYsvd26C 4 | nofa7anJSoszghmaNQwHeXfJev8I/RExCslQpyw8pQAu9RP8zChuZG48U4dTXVCV 5 | FLOzJuEjT5y0jDbd1EtBbSNlQDSmb0A7pRHF76MCAQM= 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/a000000004/250.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGtMA0GCSqGSIb3DQEBAQUAA4GbADCBlwKBkQCpD81Vqi1dmWPjXtD0QBd2mYMv 3 | Sca6sVza5XlL6T+TTURi1dEnYuSMOLqD2ERd6qdBlaMBoQKy8RTq2g0YDuXnpcc+ 4 | DE4R9npD3atdVWg7FHTMBif0S40wiKSS/6ra1PQkItDnATU2w8Sa09D66WRZsPax 5 | tgVlOKPW1EZA+URnsQiGfexA+q7NdAwA4reohS0CAQM= 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000025/161.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGvMA0GCSqGSIb3DQEBAQUAA4GdADCBmQKBkQCZ0XOWQh7j+Rm6VJ2VVL4NT5LL 3 | i1O0h47WDMWy3u3Hm4XIvW/S8jwi5os4Gu63QVOvs8lubJatAY5zwgJdHud2Iqcr 4 | 7pc8Gve5CEaNdP21Pc6DgFI+OMMNCooiZSlyaCTiCeZo9J9DsOjNL+UnznzEHzP0 5 | NPldbi/i9Yk3IDLy1lBDQPjFQtKYtJmlPZWvQIMCAwEAAQ== 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/B012345678/0.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIG9MA0GCSqGSIb3DQEBAQUAA4GrADCBpwKBoQCca+WtsQtL49ziCZtLIQZyuJZW 3 | 66CRIE9hPsxiO+3Jxtd7Zg6Lrup/fOMPGxU4eaTjZFk0PR/kes29QfzXEAMMK6HZ 4 | RhWXmCxuG90IVUtyb17/eRPOWeeeNXKVwyHibQuL4nCpRCNFx1PiqirPydMIUGAv 5 | 5srADG3fa42dm0h5soJrBCoH8OWuUmo9PE0ixyueqlLu2Ik4ZvhmOHrAWhOZAgED 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /certs/A000000003/8.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIHNMA0GCSqGSIb3DQEBAQUAA4G7ADCBtwKBsQDZ/W7XXVHQ4wZkvRVwI+qh/6hx 3 | 5NplZyuGPSVegeE3pR3k9yvMnkSs4SEn+H4mPTr53ZzzXKSnsB6QcAC6hdJJVML8 4 | owdIJd3UwMjxhssCD2g+AvLerTlpEz8G94RRZqzrV8oPwmA0RUaYEdKTv++6+rV2 5 | MbPdkeeWv4UKJQEvGuOPBapcTW0DsdwuVoYSeFk4u8mzzTqRDB2lWlqSGKzg96IS 6 | h3UmgvFYMqZ41uHtCwIBAw== 7 | -----END PUBLIC KEY----- 8 | -------------------------------------------------------------------------------- /certs/A000000003/82.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIHNMA0GCSqGSIb3DQEBAQUAA4G7ADCBtwKBsQCv90D42+dj8zOhATpDciBVyOIv 3 | QXeeIZsOHECdYK/UXIeJxX7s1x6kommmdZFswcXhoFo1vXRaeflFVc4pYSrJM4dp 4 | ZluHw8qOGsSVf59h+nv/5OF2Mek3g3yr9D3WGD1jYKIoo+vHOh0c3HK/CZU8gSA6 5 | t+SSFI5Mt3TN36rDVE0N1PjIoOnHC4d+p58sIuTOUsafPvN29hsPQ6VA/pbGP1hj 6 | EMO245x4xNZHyttZMwIBAw== 7 | -----END PUBLIC KEY----- 8 | -------------------------------------------------------------------------------- /certs/A000000025/15.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIHNMA0GCSqGSIb3DQEBAQUAA4G7ADCBtwKBsQDI1awnpeH7iZeMfGR5r5k6s4AO 3 | skOZb7sq4mtnsjrEgsS3RgBaUa+n0tg+iU9ZGiNXsw+FuFYn/xXaEikPcPBXZlUr 4 | oRrTS3EJ+kneKdywEJZwh1oX6pVUnpI0e5SKofBFdW3la3B+OGPlmmy+mcEnLvZf 5 | tmy7TP8HDzYCnddiGLISQmRbUcp1KvN+cL4ahP8xB53ABI6SiIPsT63Ul6cZOFwr 6 | u+vFpmql5WVdGANOxQIBAw== 7 | -----END PUBLIC KEY----- 8 | -------------------------------------------------------------------------------- /certs/A000000029/15.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIHNMA0GCSqGSIb3DQEBAQUAA4G7ADCBtwKBsQDI1awnpeH7iZeMfGR5r5k6s4AO 3 | skOZb7sq4mtnsjrEgsS3RgBaUa+n0tg+iU9ZGiNXsw+FuFYn/xXaEikPcPBXZlUr 4 | oRrTS3EJ+kneKdywEJZwh1oX6pVUnpI0e5SKofBFdW3la3B+OGPlmmy+mcEnLvZf 5 | tmy7TP8HDzYCnddiGLISQmRbUcp1KvN+cL4ahP8xB53ABI6SiIPsT63Ul6cZOFwr 6 | u+vFpmql5WVdGANOxQIBAw== 7 | -----END PUBLIC KEY----- 8 | -------------------------------------------------------------------------------- /certs/A000000029/8.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIHNMA0GCSqGSIb3DQEBAQUAA4G7ADCBtwKBsQDZ/W7XXVHQ4wZkvRVwI+qh/6hx 3 | 5NplZyuGPSVegeE3pR3k9yvMnkSs4SEn+H4mPTr53ZzzXKSnsB6QcAC6hdJJVML8 4 | owdIJd3UwMjxhssCD2g+AvLerTlpEz8G94RRZqzrV8oPwmA0RUaYEdKTv++6+rV2 5 | MbPdkeeWv4UKJQEvGuOPBapcTW0DsdwuVoYSeFk4u8mzzTqRDB2lWlqSGKzg96IS 6 | h3UmgvFYMqZ41uHtCwIBAw== 7 | -----END PUBLIC KEY----- 8 | -------------------------------------------------------------------------------- /certs/A000000065/12.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIHNMA0GCSqGSIb3DQEBAQUAA4G7ADCBtwKBsQCt8FzUxbSQsIfDRnsPMEN1BDiE 3 | hGEoi/79YZjdV23DrXp8+gfboSjCR6jqsw3DowsC/NfxyBZ5ZUY2Jv7/irGqYaS5 4 | rvCe4SsAmEKhq6Aa20orFwZoeB7JK2D2Bf0SsrKm8f5zS+UQ9g3F0YnkAUUbYrTg 5 | aFHsIOv/RSKqzC6c3Im8XYzeXWM8/XciD/a71Km0QUc8w8b+/I0T5Xw96X4SafoZ 6 | 9lUhWyNWPtHRhg2GgQIBAw== 7 | -----END PUBLIC KEY----- 8 | -------------------------------------------------------------------------------- /certs/A000000065/17.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIHNMA0GCSqGSIb3DQEBAQUAA4G7ADCBtwKBsQCiWDqkB0bjpjwiR49XbR78X7BG 3 | E1pvxznoK1UDX3Gwm+tWbtuZaN1km5S23twDOJmITpCMJ74c0pHlQ292JVMpd2Pa 4 | o7iQ13jA8B4zRM7N+zunDX4FW4x2DQF5pAPWtV8rOwg5ErGDrbeSdEG+0zlaGZ7v 5 | 4N69H1/DJkAz2oVvSouTkWiFvUL5wfRWqrjPqDrFdIM+teh7udTABqS1NGvZ4X4T 6 | mrZVLZxYvAQRlTNkhQIBAw== 7 | -----END PUBLIC KEY----- 8 | -------------------------------------------------------------------------------- /certs/A000000065/18.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIHNMA0GCSqGSIb3DQEBAQUAA4G7ADCBtwKBsQCt8FzUxbSQsIfDRnsPMEN1BDiE 3 | hGEoi/79YZjdV23DrXp8+gfboSjCR6jqsw3DowsC/NfxyBZ5ZUY2Jv7/irGqYaS5 4 | rvCe4SsAmEKhq6Aa20orFwZoeB7JK2D2Bf0SsrKm8f5zS+UQ9g3F0YnkAUUbYrTg 5 | aFHsIOv/RSKqzC6c3Im8XYzeXWM8/XciD/a71Km0QUc8w8b+/I0T5Xw96X4SafoZ 6 | 9lUhWyNWPtHRhg2GgQIBAw== 7 | -----END PUBLIC KEY----- 8 | -------------------------------------------------------------------------------- /certs/A000000333/3.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIHNMA0GCSqGSIb3DQEBAQUAA4G7ADCBtwKBsQCwYn3uh4ZPnBjBO5ofAlRIvxPF 3 | g4DJH0zrqfm8shT/hBTptZ1quhD5QcczF2j0eyEnkH2Ff6Oar4zgIEXdAWGdaJ7n 4 | McVRFZvn6y1Ro3L/VrVW5csv3jbiMHOkTKIV1sJspohHs4jjlSDgAm5iKUtVfWRw 5 | RAygrvyUOMkjrsmyCY1tOhr16LHeNvS1MEAQnYm3fK+vcMJsYBq99Z7sD9yKmQiR 6 | QM0ugX4zUXWwO3qjPQIBAw== 7 | -----END PUBLIC KEY----- 8 | -------------------------------------------------------------------------------- /certs/A000000333/9.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIHNMA0GCSqGSIb3DQEBAQUAA4G7ADCBtwKBsQDrN038Wpa3HShjh17aLq+5axtD 3 | nT7OCxgmomcu7vp5kChndvi9mJoVFBp1w4TfwU/vkkOqsycHZZvp5Hl6JHwvC22Z 4 | Ny84SvYv4jvFS83FeprNHVWFwwPyAe9Oi4Bq+4CdsaPbHNESrIhPFkpnuZx9blqK 5 | bfHTyubX7T1b5yWy3kreI/pnm/TrFak9im4px/+hpw3i5U9ZPZCKO/nrvXYLv9yN 6 | uLVEl+bFvg5KTawp5QIBAw== 7 | -----END PUBLIC KEY----- 8 | -------------------------------------------------------------------------------- /certs/a000000004/5.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIHNMA0GCSqGSIb3DQEBAQUAA4G7ADCBtwKBsQC4BIq8MMkNl2M2VD4/1wkcj+SA 3 | Dfgg7VXn6UgT7QBVW1c/7KPYSvYTGmUdZs/0KE+xO2Ne3Q7kAXbYvwS3/Rx7rPms 4 | cyffqoqnLRDbO45wst3YEctBllJeo4aswzwNnUV1kWRpxOT1Po4ckSzGGMsi3efD 5 | Vo6QAi5runcCAuRSKi3WI9GA4hW9HRUH/j3JDKMQ0ns+/M2Pg94wUsrR5Ik4xo0J 6 | WqyRtfN+KLtJ7H7VlwIBAw== 7 | -----END PUBLIC KEY----- 8 | -------------------------------------------------------------------------------- /certs/A000000003/146.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIHNMA0GCSqGSIb3DQEBAQUAA4G7ADCBtwKBsQCZavVvVpGH0JKTwUgQRQ7Y7jNX 3 | OXsYokWO+qkto7bfZRTsBgGVMY/UO+m48Mxmnj+EQFfL3fi9oZG7ZEc7yNyacw24 4 | 9rTt45JBhv/ZuMdzV4nCOja6C4r2U3LrV+pdiefRTpx7a1V0YPEIhdoWrJI/Fa83 5 | WPDwPr08XCyUnLowbbROaiwHbF9n4oHX71Z4XcTXWUXkkfAZGIAKni3Gb2AIBWbO 6 | Da+NF+rUatjjCiR8nwIBAw== 7 | -----END PUBLIC KEY----- 8 | -------------------------------------------------------------------------------- /certs/A000000025/103.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIHNMA0GCSqGSIb3DQEBAQUAA4G7ADCBtwKBsQDGh63M89V9M2CxdORx7aaTqlVd 3 | /cbIzTlMdLolzN+Oq/0fHOrfviKAyegfegWJmNwit/Ildv6EcT0L3T00z80S/NDS 4 | aQG6dBA9B1xmTavMr1e/eJSUBRxewwOi4deEMG09s+tmXNNgpVj0C3wFyRmy8Cgv 5 | 4e2b9iYaqBRkj7wmOxQhRJHeQm0kLWXNH/8Pvk1Nr/XPrLKtxxMcmxR+55GVZVEH 6 | YnBpa3X9lzc/H9eATwIBAw== 7 | -----END PUBLIC KEY----- 8 | -------------------------------------------------------------------------------- /certs/A000000025/152.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIHNMA0GCSqGSIb3DQEBAQUAA4G7ADCBtwKBsQDTGnCU+yIcumZg+5dar+qA23u3 3 | 6v1zUedIgnq2LUruzPwXh/1HoEaZoC2wDXw4LoDoBLNcWUNMYCOJ1pG5zNUe0Gvm 4 | eidhGcTBDi5A/E7d+d85ubC97o0HbioBLoopKvjv4YVTRwY5waAyJS4OV0iyWj+b 5 | pM/O4HMDiwYYN/KsGwTCeWQPW9EQqdxmXtL6aCi9XQ/oEKiS3uaw50zohjveCP1f 6 | 1hoPEfoNFJeNjO190wIBAw== 7 | -----END PUBLIC KEY----- 8 | -------------------------------------------------------------------------------- /certs/A000000025/194.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIHNMA0GCSqGSIb3DQEBAQUAA4G7ADCBtwKBsQC4dQAvOLom1hFnxdRANnYErTjf 3 | LpPY7o2g6NnAz0zFeI0R3qaJ5fQdI6PaPgsfpYda4lYg9aa8zuCYwbNcaRiJ19Dv 4 | Zw64MS5xI/zF3H0vBxnMgOGpMBf5RNCXMw7flFdi/uYrewugNIIo2/ONQhblpnp+ 5 | 909dMRHESqMTIPYjyzxT5glm1pIAZ8nggrdGEX5I5PAOEQlQylTaPjjlRTvVVE46 6 | Z2DjpqQnZq0ihODJrwIBAw== 7 | -----END PUBLIC KEY----- 8 | -------------------------------------------------------------------------------- /certs/A000000025/201.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIHNMA0GCSqGSIb3DQEBAQUAA4G7ADCBtwKBsQCzYttXM8Fbh5e47O5Vyxo3H3YO 3 | C+3TcVuycEJP1OomBiw4w/Sqo3Mqg9NuqOlgL2aD7sxrr/Y90tSQFL3k1tYDzXRC 4 | BrBbS60MZMY6s5drXIyq+FOVSfWSHAtwDVsPg8Tn6UYGi6qrVGNUTbGMY4ARGPIY 5 | LvzIoeheU8KnroOaXGo8q+c3YrcNFwq2SvxspIKUSQJhH7AGHgmmest35JPZmKDM 6 | +T2BpPbA3Gt98i5i2wIBAw== 7 | -----END PUBLIC KEY----- 8 | -------------------------------------------------------------------------------- /certs/A000000029/103.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIHNMA0GCSqGSIb3DQEBAQUAA4G7ADCBtwKBsQDGh63M89V9M2CxdORx7aaTqlVd 3 | /cbIzTlMdLolzN+Oq/0fHOrfviKAyegfegWJmNwit/Ildv6EcT0L3T00z80S/NDS 4 | aQG6dBA9B1xmTavMr1e/eJSUBRxewwOi4deEMG09s+tmXNNgpVj0C3wFyRmy8Cgv 5 | 4e2b9iYaqBRkj7wmOxQhRJHeQm0kLWXNH/8Pvk1Nr/XPrLKtxxMcmxR+55GVZVEH 6 | YnBpa3X9lzc/H9eATwIBAw== 7 | -----END PUBLIC KEY----- 8 | -------------------------------------------------------------------------------- /certs/A000000029/146.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIHNMA0GCSqGSIb3DQEBAQUAA4G7ADCBtwKBsQCZavVvVpGH0JKTwUgQRQ7Y7jNX 3 | OXsYokWO+qkto7bfZRTsBgGVMY/UO+m48Mxmnj+EQFfL3fi9oZG7ZEc7yNyacw24 4 | 9rTt45JBhv/ZuMdzV4nCOja6C4r2U3LrV+pdiefRTpx7a1V0YPEIhdoWrJI/Fa83 5 | WPDwPr08XCyUnLowbbROaiwHbF9n4oHX71Z4XcTXWUXkkfAZGIAKni3Gb2AIBWbO 6 | Da+NF+rUatjjCiR8nwIBAw== 7 | -----END PUBLIC KEY----- 8 | -------------------------------------------------------------------------------- /certs/A000000065/235.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIHNMA0GCSqGSIb3DQEBAQUAA4G7ADCBtwKBsQCpppan48asFCHk3ok277bWbOlg 3 | 6vpupeA9Bm8pYoSmHaKJCm0NhpuoyangHk7/O74zHs4s4UKcBm3YhXgeKtq8hs/9 4 | doVPufG82u3Oa1RyfZwsAclkLpzRv8TPJKai5JwVQbAuvAU0dESBzIkiBzoh+ODX 5 | K8iZi9UpxphWeofxZFDfuWmWGkGGq0zGSKTUGxSePdITk6mTgz1e7uv8vODHd7Uk 6 | R+07gW46KYSTDAfAIQIBAw== 7 | -----END PUBLIC KEY----- 8 | -------------------------------------------------------------------------------- /certs/A000000384/194.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIHNMA0GCSqGSIb3DQEBAQUAA4G7ADCBtwKBsQCL/XD8BUVnGLcALxuIkEB4AInZ 3 | WWnzFgo5mbTgVtLO/AB9MDOwKGhnDJ7+SGJAlsL9D6f9r9y7SmOkzXEGqXvdjOP3 4 | HyFor8tCMPLDNJJGemwYK0v6du5gWy/sS0UZtaknZ98jgF7IcImA4YywicBl0Dat 5 | V9GW6IrBVSFI/Dtit3G2sUTSjfWu50/DFSG2lokJpGPqAYQmHddRJ4oQt8dGaFIL 6 | JTtqhg5UBl0rVnenUwIBAw== 7 | -----END PUBLIC KEY----- 8 | -------------------------------------------------------------------------------- /certs/A000000524/108.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIHNMA0GCSqGSIb3DQEBAQUAA4G7ADCBtwKBsQDHYln/eFq9X/YTIjwB9b2g82+T 3 | Qs8za2bDLUss1QluCU2OBN+hGpsuO8eNpjtcEBSNjteeumhdXQ7+HFiz+SnYYbQP 4 | 86qjtScUjQwkkh7kLaBI4B449qOknfpn3RzV3SCRQS3TbTJp+vfS4P+xo+Aolpy2 5 | ulqTA6b/ZVQPQhsGmjG1UzmO5SXvpcLOJry4HFNFAY1ePptxMPcvWYwOqkaC1Nov 6 | IgRRh4CoEI+C3cnPHwIBAw== 7 | -----END PUBLIC KEY----- 8 | -------------------------------------------------------------------------------- /certs/a000000004/241.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIHNMA0GCSqGSIb3DQEBAQUAA4G7ADCBtwKBsQCg3PS94Zw1RrS28EFNF03eKUqr 3 | u4KMWoNNc6rifJmwsFOpAngAcjm2RZ/wu817S5xsUKwCzpE2jaG9Iarq28ZTRzN9 4 | ibaPXJmgnQW+At0fjFuiDi8T+yonxB0/hcrVz2Zo51hR7Gbtv5iFH9TkLETB1Z9Z 5 | hHA7J9W58huPoNkyefu/aeCQZCkJyeon+JiVlUGqZ1f19iQQT24dOpUy8qblFRWu 6 | rRtDs9eDUIii+vp75wIBAw== 7 | -----END PUBLIC KEY----- 8 | -------------------------------------------------------------------------------- /certs/B012345678/2.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIHdMA0GCSqGSIb3DQEBAQUAA4HLADCBxwKBwQCpmm0+BxiJ7Z46DDkcabC4BPwW 3 | CytL3VcMkt1aD0X1PoYh98lsQCJCZnNeHuGzwGI4rjUEYyD9joH4zrP4tMl7lAkw 4 | o6xeeQCG2tQaak9RF7oc4kOKUawFPrACrthm0sRY/XM1kCGhICmgwEMEXBFmT+Ah 5 | nsY8EL8hVbsnhGCaEGQh1FFjeZc4wcMJCbtsb+Uru3Y5e5dAzgZKYT/4QRGF8IhC 6 | pCPq0g7f+/8c1sP+DJghR5GZwm2FcsyK//CHqcMCAQM= 7 | -----END PUBLIC KEY----- 8 | -------------------------------------------------------------------------------- /emv/proprietarytemplate.go: -------------------------------------------------------------------------------- 1 | package emv 2 | 3 | type ProprietaryTemplate struct { 4 | Sfi int `tlv:"88"` 5 | Label string `tlv:"50"` 6 | Priority int `tlv:"87"` 7 | LanguagePreference string `tlv:"5f2d"` 8 | ProcessingObjects DataObjectList `tlv:"9F38"` 9 | DiscretionaryData []byte `tlv:"bf0c"` 10 | } 11 | -------------------------------------------------------------------------------- /certs/B012345678/248.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIHdMA0GCSqGSIb3DQEBAQUAA4HLADCBxwKBwQCpmm0+BxiJ7Z46DDkcabC4BPwW 3 | CytL3VcMkt1aD0X1PoYh98lsQCJCZnNeHuGzwGI4rjUEYyD9joH4zrP4tMl7lAkw 4 | o6xeeQCG2tQaak9RF7oc4kOKUawFPrACrthm0sRY/XM1kCGhICmgwEMEXBFmT+Ah 5 | nsY8EL8hVbsnhGCaEGQh1FFjeZc4wcMJCbtsb+Uru3Y5e5dAzgZKYT/4QRGF8IhC 6 | pCPq0g7f+/8c1sP+DJghR5GZwm2FcsyK//CHqcMCAQM= 7 | -----END PUBLIC KEY----- 8 | -------------------------------------------------------------------------------- /certs/a000000004/249.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIHdMA0GCSqGSIb3DQEBAQUAA4HLADCBxwKBwQCpmm0+BxiJ7Z46DDkcabC4BPwW 3 | CytL3VcMkt1aD0X1PoYh98lsQCJCZnNeHuGzwGI4rjUEYyD9joH4zrP4tMl7lAkw 4 | o6xeeQCG2tQaak9RF7oc4kOKUawFPrACrthm0sRY/XM1kCGhICmgwEMEXBFmT+Ah 5 | nsY8EL8hVbsnhGCaEGQh1FFjeZc4wcMJCbtsb+Uru3Y5e5dAzgZKYT/4QRGF8IhC 6 | pCPq0g7f+/8c1sP+DJghR5GZwm2FcsyK//CHqcMCAQM= 7 | -----END PUBLIC KEY----- 8 | -------------------------------------------------------------------------------- /certs/A000000003/88.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIHnMA0GCSqGSIb3DQEBAQUAA4HVADCB0QKByQCZVSxKHs1ooCYBV/xBUbWZKDdE 3 | XT/Fc2XKVpLIe+NYzc3yyS+2g3UihCpI6xHN/+L9kXcMciHkr2IHwt5ABMfe4bYn 4 | bcYtUqh9LNAfvy3EBl21KCTSohZ6BtGeag94EHHNst0xTLlEQdjcDpNjF7d78G9R 5 | d/bFq6OjvGqjAgnJcmC3oa06GSybjNHRU1cK/Mh8PNaB0T6Zf+M7OWOgoceXcqz5 6 | kQM+G4OXrQNBUA5IokdwvEy+GdLM9BlQT9vwOJvC8v3NTUTmHwIDAQAB 7 | -----END PUBLIC KEY----- 8 | -------------------------------------------------------------------------------- /certs/B012345678/245.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIH9MA0GCSqGSIb3DQEBAQUAA4HrADCB5wKB4QCiWmvXg6Xva4+2+DBVwmD1+Z6h 3 | ZnjzuQU+D2SY6Cw/XR6MOPE1iAF+KxKz2P9vUBZ/RkQpEHKenk0bNznlBnwKx6H0 4 | SH419nW8FuIzMVFlyxQr/bJeMBpjKlSjNx66tlct7rrzcPM38Ffuc7SuRtGovE2o 5 | U+w8wSyMvC2hgyLWhTDHCyK9rDUd02BorjIeEavyZPTTVpu3EhRUUAVVjeJgg8c1 6 | 23djaBcv6ML1yF6LW4kMxoKRHS3nH6YmuIF/zMCJIrcDhp87rqwUWdd82FN2vDYY 7 | L0I4MU1sQhL73X8j0wIBAw== 8 | -----END PUBLIC KEY----- 9 | -------------------------------------------------------------------------------- /certs/a000000004/246.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIH9MA0GCSqGSIb3DQEBAQUAA4HrADCB5wKB4QCiWmvXg6Xva4+2+DBVwmD1+Z6h 3 | ZnjzuQU+D2SY6Cw/XR6MOPE1iAF+KxKz2P9vUBZ/RkQpEHKenk0bNznlBnwKx6H0 4 | SH419nW8FuIzMVFlyxQr/bJeMBpjKlSjNx66tlct7rrzcPM38Ffuc7SuRtGovE2o 5 | U+w8wSyMvC2hgyLWhTDHCyK9rDUd02BorjIeEavyZPTTVpu3EhRUUAVVjeJgg8c1 6 | 23djaBcv6ML1yF6LW4kMxoKRHS3nH6YmuIF/zMCJIrcDhp87rqwUWdd82FN2vDYY 7 | L0I4MU1sQhL73X8j0wIBAw== 8 | -----END PUBLIC KEY----- 9 | -------------------------------------------------------------------------------- /applicationsorter.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "github.com/greenboxal/emv-kernel/emv" 4 | 5 | type ApplicationSorter []*emv.ApplicationInformation 6 | 7 | func (s ApplicationSorter) Len() int { 8 | return len(s) 9 | } 10 | 11 | func (s ApplicationSorter) Swap(i, j int) { 12 | s[i], s[j] = s[j], s[i] 13 | } 14 | 15 | func (s ApplicationSorter) Less(i, j int) bool { 16 | p1 := s[i].Priority & 0xF 17 | p2 := s[j].Priority & 0xF 18 | 19 | return p1 < p2 20 | } 21 | -------------------------------------------------------------------------------- /certs/A000000003/9.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBFjANBgkqhkiG9w0BAQEFAAOCAQMAMIH/AoH5AJ2RIkjeCk45wafd4/bSWImS 3 | waQJWvvRgk0bp0hH8rxJJtLv2QS0tUlUzRiaVMXRF5ZU+Pmw0qtfA1frZC/tqV05 4 | EsZXaUX6uJfnBiyqRKSqBrj+bj26GK9q43OOMEKe6b4DQnydZPaV+oyrS/43aFPq 5 | NK0ddr/K0VkIwHf/5txVIezvXSeKluJvVzWf+u2hlDS5N/GtmZ3FxB6xGTW0TBgQ 6 | DoV/QxpKWmu2URTxdMLXtZ/fI31rsd0JFuZE1wne1WSBR3x12VzdaCVGFfd0DsB/ 7 | MwrF1nvNdb8j0ooUCCbAJtvelxo3zT75uN9kSsOFAQUB78ZQnXpBAgED 8 | -----END PUBLIC KEY----- 9 | -------------------------------------------------------------------------------- /certs/A000000029/9.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBFjANBgkqhkiG9w0BAQEFAAOCAQMAMIH/AoH5AJ2RIkjeCk45wafd4/bSWImS 3 | waQJWvvRgk0bp0hH8rxJJtLv2QS0tUlUzRiaVMXRF5ZU+Pmw0qtfA1frZC/tqV05 4 | EsZXaUX6uJfnBiyqRKSqBrj+bj26GK9q43OOMEKe6b4DQnydZPaV+oyrS/43aFPq 5 | NK0ddr/K0VkIwHf/5txVIezvXSeKluJvVzWf+u2hlDS5N/GtmZ3FxB6xGTW0TBgQ 6 | DoV/QxpKWmu2URTxdMLXtZ/fI31rsd0JFuZE1wne1WSBR3x12VzdaCVGFfd0DsB/ 7 | MwrF1nvNdb8j0ooUCCbAJtvelxo3zT75uN9kSsOFAQUB78ZQnXpBAgED 8 | -----END PUBLIC KEY----- 9 | -------------------------------------------------------------------------------- /certs/A000000141/4.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBFjANBgkqhkiG9w0BAQEFAAOCAQMAMIH/AoH5AOftyp2BDzeS3E7xocnzgD/T 3 | kEAAr5w+Mit1Fs1BpiMalinArVpM359AdQ+lHS2p3MHj9bNvAyqAhsWJMP3BCyg5 4 | kJsZucojJlpidkqTLDfGVm0TkvA0hsYmqfbCBOEmYGlgLewPMdiljPOU/ZaTmx4U 5 | 4r6RuBjEkszRumP0EOXzMe1IAT8emRFjKjs6WuJGKcVEUHy+rea1zi/3fCzU35Id 6 | aTQj6oiuoARXFGH6spMuRsBunqY9JKBWZt/ZG1f8WJWcJLkEFiT9wzoz8C4QmVXh 7 | 8WUk8yQWH72jVAxhQfv2cCPFJjv1+8XIO0767oImVbap7Kv6AYmpAgED 8 | -----END PUBLIC KEY----- 9 | -------------------------------------------------------------------------------- /certs/A000000333/4.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBFjANBgkqhkiG9w0BAQEFAAOCAQMAMIH/AoH5ALyFPmtTZeiefukxfJSwLQq7 3 | Db2RwFoiSiVUqintn8udhuucy7MipXgR+GGIqsc1HHK9nvGWxaAazvek6w0q1j2e 4 | asLng2VHyxWVxovLr9D2codg86fKe5cwG34CIBhO/E9lMAjZPOCYwNk7RSAQltGt 5 | /0zx+fwCr3WdonzW39bXibCZ8W83i2EAM05j89NfMlGl7HhpNzH1IzUZzbOA9auM 6 | DwJyjpHUaavQ6uDZOxzGbOEnspx9d0QaSdCfyl1tl2L8dMMbtQbIuuPHmtbCV4d1 7 | uVlWtTcNHQUZ43kGs4RzYjMlHo8JrXnfvixqv62sjk2GJDGMJ9rxAgED 8 | -----END PUBLIC KEY----- 9 | -------------------------------------------------------------------------------- /certs/A000000003/148.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBFjANBgkqhkiG9w0BAQEFAAOCAQMAMIH/AoH5AKzSsSMC7mRPP4NavR/HpvYs 3 | zkj/7GIqqO8GK+9vuLqLxou/arWHDu1Xm8OXPhITA9NIQaeW1ty8Qdv55SxGCXlc 4 | DM9+6G+h1csEEHHtLFHSIC9j8RVsWKktOLxgvfQk4XduK8lkgHigOzb7VUN1/FPV 5 | fHP1Fg6lnzr8U5jse2d1jWXJv/eCi2uC1L4SSkFqtzAZFDEepGLBn3cfMbO1czYA 6 | Df9zLTuD3gcFLXMDVNKXvscocdzPDhk/Fxq6J+5GTGqXaQlD1Zvauyon63HO69r6 7 | EXYEZHj9Yv7EUtXKOTKWUwqj9Bknrf5DSi3yrjBU+IQGV6JuD8YXAgED 8 | -----END PUBLIC KEY----- 9 | -------------------------------------------------------------------------------- /certs/A000000003/83.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBFjANBgkqhkiG9w0BAQEFAAOCAQMAMIH/AoH5ALzYNyG+UszMS2RXMh8ip9x2 3 | n1TrgCWRO+gE2eq7+hmz18XTymWNdoyvVwZ+7IPH5un4HQWGcD7Z3drdIGddY0JJ 4 | gLEOs2ToHrN9tA7RADRMkoiG/0zMNyA+5hBtW1nRrBAuLNLXrBf02Ww5jl/Zk+y0 5 | /995sXVH/5+iqo7v1svaEky7F6D4UoFGOHE14iawBaR0uQYv8mTS/476NoFKopUA 6 | ZbGwTAoa6bL2nUpKqXnWzpX+6Uhe0KA67pvZU+gc/R726BTf08LON676OMH5h3Nx 7 | 6R1qXrWf3t910zJfo8pmzfug5XFGzHiYGP8Gvl/MUKvTYq5LgJltAgED 8 | -----END PUBLIC KEY----- 9 | -------------------------------------------------------------------------------- /certs/A000000025/104.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBFjANBgkqhkiG9w0BAQEFAAOCAQMAMIH/AoH5APTRmPLwzxQOTS2Bt2XrTiTO 3 | 1MCDSCJ2mFTQ6X6AZsvkZQKbP0EONQ9iljgaJTvnGku6u9UWYl2uZ9Bz0AETqrnq 4 | Tc7KKfO7el1GwNi5g+JILCrXWXNaWrmqrvsx0+cYuMpmwBnsoKi+MS4kPrR6YjAG 5 | IL1RzxaakZTBekLlGzTYN3WpjoCy1m9PmAhKRI/gUH6ifJBa7nK2KoopQ4tqRID/ 6 | 9y+TKAQypV/dZIrZPYK57PASdcCRS62Os6r0axKfh0n+pCWi3N1+gToI/AynhB7d 7 | SZhc2LxtXVbxernGfOxQukIkQFY+zOIWmeQ1yGgrYmY5NnLGk9i3AgED 8 | -----END PUBLIC KEY----- 9 | -------------------------------------------------------------------------------- /certs/A000000025/153.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBFjANBgkqhkiG9w0BAQEFAAOCAQMAMIH/AoH5AOF0AHQin6DSKKliNYHXoyKQ 3 | P7ibp2hnEuYB+oqySpeJGG8VtwzLvnQhscsRDUU2FogTX/0NsVo/UWuykdShI+v1 4 | oG+/fh7mMRtzfauyiVcKeVnVMrJfHaZ1jITdzK3ASbx2TAU5Gr0sre/6fiQtXdBu 5 | VgAfDmgVHjOIB0vZMw1q+lfL8zlG9THlHg1JAu4jXHVqkF+3M5QObsiXtJRKXtx2 6 | VwXirPdseOrXjdmwZt8LLIh1C4ruAMm01AkfpzOESdqS2/yQj6B4HAEoxJLbmTyI 7 | uou3yt/iONR38lF+Dn49KxF5agMYzirU2h245Uqw2U8QnbnK7vvvAgED 8 | -----END PUBLIC KEY----- 9 | -------------------------------------------------------------------------------- /certs/A000000025/16.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBFjANBgkqhkiG9w0BAQEFAAOCAQMAMIH/AoH5AM+Y3+2z03J5Ze53l3IzVeB1 3 | HIHS099NGOurn7nUnzjIxKgmuZ3J3qPwEEPUvyKsNVDilipZY5sTMhVkIveIucFt 4 | QBNe/RupQUd1BXXmNrbrxhhzTJHB0b8+3CpGpDkBZo4P/BNndAgOiIBE9qHmXcmq 5 | qJKNrL6w21XqNRRobGpzLO9V7ifPh38RBlJpSg40hMhV2IKuGRZ04lwpYgW7tZlF 6 | UXb917vFSfJ7pf41M29+KeaNeDlzGZQ2Yzxn7lpoDwUWDtEtFmXsg9GZfxD9Bbvb 7 | +UM+j3l67j6fAqNCKKzpJ6vmK4uSga0I099cc3loUEXXul/N5YY3AgED 8 | -----END PUBLIC KEY----- 9 | -------------------------------------------------------------------------------- /certs/A000000025/195.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBFjANBgkqhkiG9w0BAQEFAAOCAQMAMIH/AoH5ALkxgqvjQ9+/OIxxxNZ0fc3s 3 | YDZ/5jz6qULX0yPmiNCDKDZUi/Dt/x7e64gsdQmf+BqT+lJcMkJbNgI+oCqImbm/ 4 | fXk06G+ZeJGCMAbOqpMJGnPB/eGKvU+HoiMIZAwGTIwCdoXxstt7dBtnqw3gXocE 5 | gcX5clCMF/V+T4M9YyIPbqLPu4eHKKpYh95AfRDGuPWNRneezsHiFVSH1Sx4pcA4 6 | l/K7WA4KK73o6i4cGPaq8+s9BMNHfeq4jxUMiBD9HvjrBZaGYzb+LB+8a+witP5d 7 | iFZHcm21lwmlBfdcSeDY1xv1HkGBISviFCqyoejA07cTbNe3cI5NAgED 8 | -----END PUBLIC KEY----- 9 | -------------------------------------------------------------------------------- /certs/A000000025/202.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBFjANBgkqhkiG9w0BAQEFAAOCAQMAMIH/AoH5AMI+y9cRn0ecLuVGwSOlhdaX 3 | p9ELVcLSi+8NKZwB3GVCCgP+Uifs3suAJfvIbuvBk1KYwXU6uEmTZ0lxlZF1jDFf 4 | oVBAB4m7FPrdbq4q1hfaOBYxmdG61dP49qeiCu9CCt/iQE0wshk1nGpJUlZczKbx 5 | HsW+VktJsOpb9bPcjFxkASCNACnDlXqMWSLL3jnTpWTG3rtr0q75H8J7s9OJK+uW 6 | Rtzi4e+Fge/6cSFYquxUHAu7Sz4nnX2lTkWgrMNXDnEsn3zfmFz6/Tgq4To7IUqe 7 | jh5xqx6nB4lREqvDqX0Pywri7lyFSSts/VSIXN1jN+iVzHD7MlXjAgED 8 | -----END PUBLIC KEY----- 9 | -------------------------------------------------------------------------------- /certs/A000000029/148.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBFjANBgkqhkiG9w0BAQEFAAOCAQMAMIH/AoH5AKzSsSMC7mRPP4NavR/HpvYs 3 | zkj/7GIqqO8GK+9vuLqLxou/arWHDu1Xm8OXPhITA9NIQaeW1ty8Qdv55SxGCXlc 4 | DM9+6G+h1csEEHHtLFHSIC9j8RVsWKktOLxgvfQk4XduK8lkgHigOzb7VUN1/FPV 5 | fHP1Fg6lnzr8U5jse2d1jWXJv/eCi2uC1L4SSkFqtzAZFDEepGLBn3cfMbO1czYA 6 | Df9zLTuD3gcFLXMDVNKXvscocdzPDhk/Fxq6J+5GTGqXaQlD1Zvauyon63HO69r6 7 | EXYEZHj9Yv7EUtXKOTKWUwqj9Bknrf5DSi3yrjBU+IQGV6JuD8YXAgED 8 | -----END PUBLIC KEY----- 9 | -------------------------------------------------------------------------------- /certs/A000000065/14.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBFjANBgkqhkiG9w0BAQEFAAOCAQMAMIH/AoH5AK7tVbnuAOHs6wRfYdLammar 3 | Y3tD+1zb2yKi+7Jb4GHpN+OCRO5RMvUwFEo/JokH2P1kiGP1qW/tfkIInpNFetwO 4 | G8icWKDbcmdfvEf+6f8zwWrebTQZNrBram9e9vZqTt2YHfddqDmcMFP0MOyjQkN8 5 | I69COiEayfWOrwmw+DfenYbHEJ2xZGVhqlrwKJr1UUrGS8LZ02oXm7inlx4r+gOp 6 | 5LhH/T1jUk1DoOgANUe5Sop15RnfMXfQpgvAtLqx6lmiy7TS1iNU6Sbpx9O+QYHo 7 | G6YPgoWoltF9qMMkJIG2xAV2mjnVR8dO2f+Vpwp5YEa17/NmgtwpAgED 8 | -----END PUBLIC KEY----- 9 | -------------------------------------------------------------------------------- /certs/A000000065/20.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBFjANBgkqhkiG9w0BAQEFAAOCAQMAMIH/AoH5AK7tVbnuAOHs6wRfYdLammar 3 | Y3tD+1zb2yKi+7Jb4GHpN+OCRO5RMvUwFEo/JokH2P1kiGP1qW/tfkIInpNFetwO 4 | G8icWKDbcmdfvEf+6f8zwWrebTQZNrBram9e9vZqTt2YHfddqDmcMFP0MOyjQkN8 5 | I69COiEayfWOrwmw+DfenYbHEJ2xZGVhqlrwKJr1UUrGS8LZ02oXm7inlx4r+gOp 6 | 5LhH/T1jUk1DoOgANUe5Sop15RnfMXfQpgvAtLqx6lmiy7TS1iNU6Sbpx9O+QYHo 7 | G6YPgoWoltF9qMMkJIG2xAV2mjnVR8dO2f+Vpwp5YEa17/NmgtwpAgED 8 | -----END PUBLIC KEY----- 9 | -------------------------------------------------------------------------------- /certs/A000000065/236.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBFjANBgkqhkiG9w0BAQEFAAOCAQMAMIH/AoH5AKnt/cWAKafsAD0T8i9q7VYi 3 | eG1F98NlFqPb/k11v84A9M9lZnDNB6ZqmafNNdL1Ioyy15S5XEkw/drRf4ySkxZK 4 | /sh21WRN0xq/6Gt6pRLFjVxxMQ+zbo18z/TJWGacAELf8Ej1LkErUww7t3VVtvmz 5 | XiwPGxemGA0D2UkUtJcKQjCfJZ2zfsd/9roEus9rF/97EMGgQnLQjAQ6HI6JUWgd 6 | 5BvjD05C0+0/4zKL1MYyexnREKLoXZ3Ew0IlovDKdoT/XAXB8BE1/FHXMx46QTrt 7 | CULIu9uXUQThcbCO58KziOxOpJO+X8sMQW3yqdu836XRI0TsMFdrAgED 8 | -----END PUBLIC KEY----- 9 | -------------------------------------------------------------------------------- /certs/A000000333/11.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBFjANBgkqhkiG9w0BAQEFAAOCAQMAMIH/AoH5AM+f30azVjeOmvMRsPmBshof 3 | IvJQ+xH1XJWHCePHJBkYKTSDKJ6uaIoJTALDROKZnzFacoQfSJ4ksboAVs+rO0ed 4 | DoJkUjddzbtn6X7Cqmb0YB13T+rvd1rMxiG/62X7AFP8XzkqpeHUxBpN6f/f3xMn 5 | xLuHTx9jpZnuOQL+lecp/XjUI03H5s8aurqj9tspt/BdHZAdLnamBqjL///svZGP 6 | otJ4vbQ7BDT11FE0vhwngdFX1QH/Q+XxxHCWfNV85Ttk2Cl0yCdZN8XYUCoSUqil 7 | 1giKJZtpT5hkjZryyw79nZQ8afiW1J+jlwIWKsta8puQut4AW8FXAgED 8 | -----END PUBLIC KEY----- 9 | -------------------------------------------------------------------------------- /certs/A000000384/195.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBFjANBgkqhkiG9w0BAQEFAAOCAQMAMIH/AoH5AKGmK2oDk95O9NnVNoTBTq7U 3 | qIGibuZNvUVQ6zWB4AMoGkEX97+eVkj9XjiCvEq0awpfSM31wtVsfRSkzWnTN4AA 4 | UMCZSXQjdijvjXUeH6u6rXPtcPYEhpMLVaXzxK67K7Gtqq46N00C8ZQgvVKKsZyd 5 | CfxBu4FAxARDrixaJFk8IW6WBL4Nxpu7HR+YynYhLV0bWdu5BzkUXF+Yx97+y+kd 6 | pMWftA8VmiYKCwWIYaJdC4jQs//YfO5S3SjHsf/lCkm2YRZhXcRWlrSmHlY7PN02 7 | 4/Ktz/tQ28PoKAQSdp0AZikXCWiTscMZ6BM6BD3fBa6CpV+u/sHfAgED 8 | -----END PUBLIC KEY----- 9 | -------------------------------------------------------------------------------- /certs/A000000524/109.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBFjANBgkqhkiG9w0BAQEFAAOCAQMAMIH/AoH5ALdH6Ms2FejSYjE1VIjzx2xH 3 | Rve7HDgebG5qvwptfNk8/GssMQKIyovn7hcw3mIaWdG7LYwCyRSPoG5dH15nLu/O 4 | iuy61KHBjzF18b6hrvU5N2WSNmtGpQROMuWbPzX1DoX4Q7oBhR5Thrfr4nNn09SD 5 | xUctMCCvQhFt3aMjQVV+ursEPrxgBrmaZSAJBFv6UMUnAoWG4FlC4dWUIjtJ/oVm 6 | kxwx++jJA6vU8oPh+rA9dYJH7EtyioWpiXYBt1MpMmOtvRC+mI0MUv4AkcJyHcAs 7 | UTD8dmPpVzmnDuL4Tf0uUMiKGiZYfvfMBH/KLQPCzwzktSS07D8HAgED 8 | -----END PUBLIC KEY----- 9 | -------------------------------------------------------------------------------- /certs/a000000004/239.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBFjANBgkqhkiG9w0BAQEFAAOCAQMAMIH/AoH5AKGRy4dHPyk0m11gqIs+ruCX 3 | OqbxoILzWNhJ/d/5wJH4me2peSyvCe8o9dIkBLiKIpPuu8GUnEO+pNYM/YeaFTlU 4 | Tgng8J9g8GWyvyoT7McF89RoudM653rZ0/GcpA8j3PXrfATcj2nrpWWx68tGhs0n 5 | R4VTD/b26e5DqkP9sCzgDa7BXHuP1qmzlLq6QZ0/bcheFlab6OdpiWiO/qLfIv99 6 | NcBDM43qqYKgK4Zt5TKFGeu81vA83Whmc4R/hNtlGrhsKM8UYlYsV3uFNWSikMhV 7 | bYGFMSaNJcyYpMxqC9//2i3Mo6lMmYVZ4wf935FQBtmph7B92us7AgED 8 | -----END PUBLIC KEY----- 9 | -------------------------------------------------------------------------------- /certs/B012345678/249.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBGTANBgkqhkiG9w0BAQEFAAOCAQYAMIIBAQKB+QCm5vtyF5UG+GDMyown+Zzs 3 | 2Ux9TzGR0wO77jdIHHqhXyM7p1Xp5DdjRammfnmUvcHGgLs1ItjJPrDMyRrTGtRQ 4 | 2jDTN2YtGawD4rTvX27BgoLUkeGXZ9eyRULf3v9vYhhVA1MgabuzaeO7n7GaxvHD 5 | C5fSSe7nZOC6yX8lyHPZc5U+UVOkIGS7+r/Qaku0hoYL9mN0Bsn8NoE6SnX3XDHM 6 | qfafjeWa3s72vefgeAD8vgNdMXavhHPiPpqj3+4iEZbRFIMCZ3xyDP4lRKA9tVPn 7 | 8bhCe6HMcrDymxLf70wIHQdtNT5xiAqt/zhjUq8Kt7KO1J4eZy0R+QIDAQAB 8 | -----END PUBLIC KEY----- 9 | -------------------------------------------------------------------------------- /certs/a000000004/245.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBGTANBgkqhkiG9w0BAQEFAAOCAQYAMIIBAQKB+QCm5vtyF5UG+GDMyown+Zzs 3 | 2Ux9TzGR0wO77jdIHHqhXyM7p1Xp5DdjRammfnmUvcHGgLs1ItjJPrDMyRrTGtRQ 4 | 2jDTN2YtGawD4rTvX27BgoLUkeGXZ9eyRULf3v9vYhhVA1MgabuzaeO7n7GaxvHD 5 | C5fSSe7nZOC6yX8lyHPZc5U+UVOkIGS7+r/Qaku0hoYL9mN0Bsn8NoE6SnX3XDHM 6 | qfafjeWa3s72vefgeAD8vgNdMXavhHPiPpqj3+4iEZbRFIMCZ3xyDP4lRKA9tVPn 7 | 8bhCe6HMcrDymxLf70wIHQdtNT5xiAqt/zhjUq8Kt7KO1J4eZy0R+QIDAQAB 8 | -----END PUBLIC KEY----- 9 | -------------------------------------------------------------------------------- /certs/a000000004/6.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEA0kwk0tf7VQnVsm69QHfO 3 | dFFqK4nkBi2D3B9+J9XlqmZX83bavdtrQlHzI0JuYh9d/B36B8BgNZCLft9nTL61 4 | mPWfnMtcVUEFIcFZXnvYatccQsMo/NnYLJ3WjfHm0/GJwy9Xi340h+hNZC7S2j9o 5 | mqGIwqHzfhOVcy4YcpVP/rGdXEBFFefD9jfkueD4iYh8DEMZSUKzqS1DsKsJHFUQ 6 | +zwkoSZHZMvuuv7Aqsym+Uj8lzyJUN+TQUC334fncZO5VBk+s7deYLu4F8T+6qVC 7 | zjiHgohbhGDEyUQpN+z9uAj9i4l55TaOuFnJBo09DqkWeNY7wCyHuJ2z6+bPHY9r 8 | 5gIBAw== 9 | -----END PUBLIC KEY----- 10 | -------------------------------------------------------------------------------- /emv/taglist.go: -------------------------------------------------------------------------------- 1 | package emv 2 | 3 | import "github.com/greenboxal/emv-kernel/tlv" 4 | 5 | type TagList []int 6 | 7 | func (tlPointer *TagList) DecodeTlv(data []byte) error { 8 | if *tlPointer == nil { 9 | *tlPointer = make(TagList, 0) 10 | } 11 | 12 | tl := *tlPointer 13 | 14 | for i := 0; i < len(data); { 15 | tag, tagLength, err := tlv.DecodeTag(data[i:]) 16 | 17 | if err != nil { 18 | return err 19 | } 20 | 21 | i += tagLength 22 | 23 | tl = append(tl, tag) 24 | } 25 | 26 | *tlPointer = tl 27 | 28 | return nil 29 | } 30 | -------------------------------------------------------------------------------- /tlv/tlv_test.go: -------------------------------------------------------------------------------- 1 | package tlv 2 | 3 | import ( 4 | "encoding/hex" 5 | "github.com/stretchr/testify/assert" 6 | "testing" 7 | ) 8 | 9 | func TestTlv(t *testing.T) { 10 | tlv, err := hex.DecodeString("9f2701009f360200419f2608c74d18b08248fefc9f10120110201009248400000000000000000029ff") 11 | 12 | assert.Nil(t, err) 13 | 14 | decoded, err := DecodeTlv(tlv) 15 | 16 | assert.Nil(t, err) 17 | 18 | encoded := EncodeTlv(decoded) 19 | 20 | decoded2, err := DecodeTlv(encoded) 21 | 22 | assert.Nil(t, err) 23 | assert.Equal(t, decoded, decoded2) 24 | } 25 | -------------------------------------------------------------------------------- /emv/applicationfilelist.go: -------------------------------------------------------------------------------- 1 | package emv 2 | 3 | import "errors" 4 | 5 | type ApplicationFileList []ApplicationFile 6 | 7 | func (afl *ApplicationFileList) DecodeTlv(data []byte) error { 8 | if len(data)%4 != 0 { 9 | return errors.New("len must be multiple of 4") 10 | } 11 | 12 | *afl = make(ApplicationFileList, len(data)/4) 13 | 14 | for i := 0; i < len(data); i += 4 { 15 | entry := &(*afl)[i/4] 16 | 17 | entry.Sfi = int(data[i] >> 3) 18 | entry.Start = int(data[i+1]) 19 | entry.End = int(data[i+2]) 20 | entry.SdaCount = int(data[i+3]) 21 | } 22 | 23 | return nil 24 | } 25 | -------------------------------------------------------------------------------- /emv/publickey.go: -------------------------------------------------------------------------------- 1 | package emv 2 | 3 | import "math/big" 4 | 5 | type PublicKey struct { 6 | exponent *big.Int 7 | modulus *big.Int 8 | } 9 | 10 | func NewPublicKey(e, m *big.Int) *PublicKey { 11 | return &PublicKey{ 12 | exponent: e, 13 | modulus: m, 14 | } 15 | } 16 | 17 | func (pk *PublicKey) Decrypt(data []byte) ([]byte, error) { 18 | num := big.NewInt(0) 19 | num.SetBytes(data) 20 | 21 | result := big.NewInt(0) 22 | result.Exp(num, pk.exponent, pk.modulus) 23 | 24 | return result.Bytes(), nil 25 | } 26 | 27 | func (pk *PublicKey) Modulus() []byte { 28 | return pk.modulus.Bytes() 29 | } 30 | -------------------------------------------------------------------------------- /emv/dataobjectlist.go: -------------------------------------------------------------------------------- 1 | package emv 2 | 3 | import "github.com/greenboxal/emv-kernel/tlv" 4 | 5 | type DataObjectList map[int]int 6 | 7 | func (dolPointer *DataObjectList) DecodeTlv(data []byte) error { 8 | if *dolPointer == nil { 9 | *dolPointer = make(DataObjectList) 10 | } 11 | 12 | dol := *dolPointer 13 | 14 | for i := 0; i < len(data); { 15 | tag, tagLength, err := tlv.DecodeTag(data[i:]) 16 | 17 | if err != nil { 18 | return err 19 | } 20 | 21 | i += tagLength 22 | 23 | length, lengthLength, err := tlv.DecodeLength(data[i:]) 24 | 25 | if err != nil { 26 | return err 27 | } 28 | 29 | i += lengthLength 30 | 31 | dol[int(tag)] = int(length) 32 | } 33 | 34 | return nil 35 | } 36 | -------------------------------------------------------------------------------- /emv/cardinformation.go: -------------------------------------------------------------------------------- 1 | package emv 2 | 3 | import "github.com/greenboxal/emv-kernel/tlv" 4 | 5 | type CardInformation struct { 6 | Pan string `tlv:"5A,hex"` 7 | SequenceNumber int `tlv:"5F34"` 8 | ExpiracyDate string `tlv:"5F24,hex"` 9 | HolderName string `tlv:"5F20"` 10 | Track2 string `tlv:"57,hex"` 11 | 12 | RiskManagementData DataObjectList `tlv:"8C"` 13 | 14 | SchemePublicKeyIndex int `tlv:"8F"` 15 | 16 | IssuerPublicKeyCertificate []byte `tlv:"90"` 17 | IssuerPublicKeyRemainder []byte `tlv:"92"` 18 | IssuerPublicKeyExponent []byte `tlv:"9F32"` 19 | 20 | IccPublicKeyCertificate []byte `tlv:"9F46"` 21 | IccPublicKeyRemainder []byte `tlv:"9F48"` 22 | 23 | SignedStaticApplicationData []byte `tlv:"93"` 24 | SdaTags TagList `tlv:"9F4A"` 25 | 26 | Raw tlv.Tlv `tlv:"other"` 27 | } 28 | -------------------------------------------------------------------------------- /filecertificatemanager.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rsa" 5 | "crypto/x509" 6 | "encoding/hex" 7 | "encoding/pem" 8 | "errors" 9 | "io/ioutil" 10 | "math/big" 11 | "path" 12 | "strconv" 13 | 14 | "github.com/greenboxal/emv-kernel/emv" 15 | ) 16 | 17 | type fileCertificateManager struct { 18 | BasePath string 19 | } 20 | 21 | func (fcm *fileCertificateManager) GetSchemePublicKey(rid []byte, index int) (*emv.PublicKey, error) { 22 | fullPath := path.Join(fcm.BasePath, hex.EncodeToString(rid), strconv.Itoa(index)) + ".pem" 23 | 24 | data, err := ioutil.ReadFile(fullPath) 25 | 26 | if err != nil { 27 | return nil, err 28 | } 29 | 30 | block, _ := pem.Decode(data) 31 | 32 | if block == nil { 33 | return nil, errors.New("error parsing pem file") 34 | } 35 | 36 | pub, err := x509.ParsePKIXPublicKey(block.Bytes) 37 | 38 | if err != nil { 39 | return nil, err 40 | } 41 | 42 | rsaPub, ok := pub.(*rsa.PublicKey) 43 | 44 | if !ok { 45 | return nil, errors.New("invalid public key") 46 | } 47 | 48 | return emv.NewPublicKey(big.NewInt(int64(rsaPub.E)), rsaPub.N), nil 49 | } 50 | -------------------------------------------------------------------------------- /emv/consts.go: -------------------------------------------------------------------------------- 1 | package emv 2 | 3 | const ( 4 | _ uint64 = 0 5 | 6 | AipSdaSupported = 1 << 14 7 | AipDdaSupported = 1 << 13 8 | AipCvmSupported = 1 << 12 9 | AipTerminalRiskManagement = 1 << 11 10 | AipIssuerAuthentication = 1 << 10 11 | AipCdaSupported = 1 << 8 12 | 13 | TvrCdaFailed = 1 << 2 14 | TvrDdaFailed = 1 << 3 15 | TvrHotlist = 1 << 4 16 | TvrIccDataMissing = 1 << 5 17 | TvrSdaFailed = 1 << 6 18 | TvrOfflineNotPerformed = 1 << 7 19 | TvrNewCard = 1 << 11 20 | TvrNotProductAllowed = 1 << 12 21 | TvrNotYetEffective = 1 << 13 22 | TvrExpiredApplication = 1 << 14 23 | TvrDifferentVersions = 1 << 15 24 | TvrOnlinePinEntered = 1 << 18 25 | TvrPinNotEntered = 1 << 19 26 | TvrNoPinpad = 1 << 20 27 | TvrPinTryLimit = 1 << 21 28 | TvrUnrecognizedCvm = 1 << 22 29 | TvrCvmFailed = 1 << 23 30 | TvrForcedOnline = 1 << 27 31 | TvrRandomOnline = 1 << 28 32 | TvrOfflineUpperLimit = 1 << 29 33 | TvrOfflineLowerLimit = 1 << 30 34 | TvrFloorLimit = 1 << 31 35 | TvrScriptFailedAfterAC = 1 << 36 36 | TvrScriptFailedBeforeAC = 1 << 37 37 | TvrIssuerAuthFailed = 1 << 38 38 | TvrDefaulDdol = 1 << 39 39 | 40 | AcAac = 0 41 | AcTc = 1 << 6 42 | AcArqc = 1 << 7 43 | AcCdaRequested = 1 << 4 44 | ) 45 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/ebfe/scard" 6 | "github.com/greenboxal/emv-kernel/emv" 7 | ) 8 | 9 | var hints = []emv.ApplicationHint{ 10 | emv.ApplicationHint{ 11 | Name: []byte{0xA0, 0x00, 0x00, 0x00, 0x04, 0x10, 0x10}, 12 | Partial: false, 13 | }, 14 | emv.ApplicationHint{ 15 | Name: []byte{0xA0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10}, 16 | Partial: false, 17 | }, 18 | emv.ApplicationHint{ 19 | Name: []byte{0xA0, 0x00, 0x00, 0x00, 0x25, 0x01}, 20 | Partial: true, 21 | }, 22 | emv.ApplicationHint{ 23 | Name: []byte{0xA0, 0x00}, 24 | Partial: true, 25 | }, 26 | } 27 | 28 | func getCard() (*scard.Card, error) { 29 | ctx, err := scard.EstablishContext() 30 | 31 | if err != nil { 32 | return nil, err 33 | } 34 | 35 | readers, err := ctx.ListReaders() 36 | 37 | if err != nil { 38 | return nil, err 39 | } 40 | 41 | fmt.Printf("Available readers:\n") 42 | for i, r := range readers { 43 | fmt.Printf("\t%d: %s\n", i, r) 44 | } 45 | 46 | selected := -1 47 | 48 | if len(readers) == 1 { 49 | selected = 0 50 | } 51 | 52 | if selected == -1 { 53 | return nil, err 54 | } 55 | 56 | return ctx.Connect(readers[selected], scard.ShareExclusive, scard.ProtocolAny) 57 | } 58 | 59 | func main() { 60 | rawCard, err := getCard() 61 | 62 | if err != nil { 63 | fmt.Printf("Error: %v\n", err) 64 | return 65 | } 66 | 67 | card := emv.NewCard(rawCard) 68 | 69 | processor := NewTransactionProcessor(card) 70 | 71 | err = processor.Initialize() 72 | 73 | if err != nil { 74 | fmt.Printf("Error: %v\n", err) 75 | return 76 | } 77 | 78 | err = processor.Process() 79 | 80 | if err != nil { 81 | fmt.Printf("Error: %v\n", err) 82 | return 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # emv-kernel 2 | 3 | Proof of concept EMV kernel written in Go. 4 | 5 | Should be compatible with EMV 4.3 and any card brand which implements the standard correctly (MasterCard, Visa, Amex, etc). 6 | 7 | ## EMV 8 | 9 | EMV stands for Europay, MasterCard and Visa. You can read more about it [here](https://en.wikipedia.org/wiki/EMV#Versions). 10 | 11 | This technology is used to authenticate genuine transactions in modern credit and debit cards. 12 | 13 | ## Whats an EMV Kernel? 14 | 15 | An EMV Kernel is a piece of software capable of talking with an EMV ICC (the card chip) and processing a transaction correctly. 16 | 17 | This includes implementing the EMV protocol, verifying chip authenticity, performing risk management and asking for the Application Cryptogram (AC), which is a cryptographic proof of the transaction used in the authorization process. 18 | 19 | ## Can I use it? 20 | 21 | ### No 22 | Do not expect to use this in production, I can't guarantee that this will pass in any certification process. 23 | 24 | Without certification (even with TBH), no acquirer will permit a transaction to be processed in its network. Also, typical EMV kernels are implemented by Point of Sale manufacturers and always run on secure hardware (as per the EMV Book and PCI PTS). 25 | 26 | ### Yes 27 | This should work for Offline-Pin transactions which don't need to send the PIN enciphered with the acquirer key. 28 | 29 | ## How to use it 30 | 31 | Just plug any PC/SC smart card reader with any compatible card inside. 32 | 33 | ## References 34 | 35 | * http://www.openscdp.org/scripts/tutorial/emv/index.html 36 | * https://www.emvco.com/specifications.aspx?id=223 37 | * https://en.wikipedia.org/wiki/EMV 38 | * The internet 39 | 40 | ## License 41 | 42 | MIT. 43 | 44 | -------------------------------------------------------------------------------- /tools/modexp2pubkey.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | // cheating, .. ignoring deprecation warnings 8 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 9 | 10 | unsigned char *base64_decode(const char* base64data, int* len) { 11 | BIO *b64, *bmem; 12 | size_t length = strlen(base64data); 13 | unsigned char *buffer = (unsigned char *)malloc(length); 14 | b64 = BIO_new(BIO_f_base64()); 15 | BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); 16 | bmem = BIO_new_mem_buf((void*)base64data, length); 17 | bmem = BIO_push(b64, bmem); 18 | *len = BIO_read(bmem, buffer, length); 19 | BIO_free_all(bmem); 20 | return buffer; 21 | } 22 | 23 | BIGNUM* bignum_base64_decode(const char* base64bignum) { 24 | BIGNUM* bn = NULL; 25 | int len; 26 | unsigned char* data = base64_decode(base64bignum, &len); 27 | if (len) { 28 | bn = BN_bin2bn(data, len, NULL); 29 | } 30 | free(data); 31 | return bn; 32 | } 33 | 34 | EVP_PKEY* RSA_fromBase64(const char* modulus_b64, const char* exp_b64) { 35 | BIGNUM *n = bignum_base64_decode(modulus_b64); 36 | BIGNUM *e = bignum_base64_decode(exp_b64); 37 | 38 | if (!n) printf("Invalid encoding for modulus\n"); 39 | if (!e) printf("Invalid encoding for public exponent\n"); 40 | 41 | if (e && n) { 42 | EVP_PKEY* pRsaKey = EVP_PKEY_new(); 43 | RSA* rsa = RSA_new(); 44 | rsa->e = e; 45 | rsa->n = n; 46 | EVP_PKEY_assign_RSA(pRsaKey, rsa); 47 | return pRsaKey; 48 | } else { 49 | if (n) BN_free(n); 50 | if (e) BN_free(e); 51 | return NULL; 52 | } 53 | } 54 | 55 | void assert_syntax(int argc, char** argv) { 56 | if (argc != 4) { 57 | fprintf(stderr, "Description: %s takes a RSA public key modulus and exponent in base64 encoding and produces a public key file in PEM format.\n", argv[0]); 58 | fprintf(stderr, "syntax: %s \n", argv[0]); 59 | exit(1); 60 | } 61 | } 62 | 63 | int main(int argc, char** argv) { 64 | assert_syntax(argc, argv); 65 | 66 | const char* modulus = argv[1]; 67 | const char* exp = argv[2]; 68 | const char* filename = argv[3]; 69 | 70 | EVP_PKEY* pkey = RSA_fromBase64(modulus, exp); 71 | 72 | if (pkey == NULL) { 73 | fprintf(stderr, "an error occurred :(\n"); 74 | return 2; 75 | } else { 76 | printf("success decoded into RSA public key\n"); 77 | FILE* file = fopen(filename, "w"); 78 | PEM_write_PUBKEY(file, pkey); 79 | fflush(file); 80 | fclose(file); 81 | printf("written to file: %s\n", filename); 82 | } 83 | 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /transactionprocessor.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/greenboxal/emv-kernel/emv" 6 | "sort" 7 | ) 8 | 9 | type terminalPinAsker struct{} 10 | 11 | func (t *terminalPinAsker) RetrievePin() (string, error) { 12 | pin := "" 13 | 14 | fmt.Printf("Enter the card PIN\n") 15 | fmt.Printf("Please note that this COULD block your card\n") 16 | fmt.Printf("PIN: ") 17 | fmt.Scanf("%s\n", &pin) 18 | 19 | return pin, nil 20 | } 21 | 22 | type TransactionProcessor struct { 23 | card *emv.Card 24 | ctx *emv.Context 25 | } 26 | 27 | func NewTransactionProcessor(card *emv.Card) *TransactionProcessor { 28 | return &TransactionProcessor{ 29 | card: card, 30 | } 31 | } 32 | 33 | func (t *TransactionProcessor) Initialize() error { 34 | t.ctx = emv.NewContext(t.card, &emv.ContextConfig{ 35 | Terminal: emv.Terminal{ 36 | CountryCode: []byte{0x00, 0x76}, 37 | }, 38 | }, &fileCertificateManager{"./certs"}) 39 | 40 | err := t.ctx.Initialize() 41 | 42 | if err != nil { 43 | return err 44 | } 45 | 46 | info, err := t.selectApplication() 47 | 48 | if err != nil { 49 | return err 50 | } 51 | 52 | _, err = t.ctx.SelectApplication(info.Name) 53 | 54 | if err != nil { 55 | return err 56 | } 57 | 58 | raw, _ := t.ctx.CardInformation.Raw.EncodeTlv() 59 | fmt.Printf("%x\n", raw) 60 | 61 | _, err = t.ctx.Authenticate() 62 | 63 | if err != nil { 64 | return err 65 | } 66 | 67 | return nil 68 | } 69 | 70 | func (t *TransactionProcessor) selectApplication() (*emv.ApplicationInformation, error) { 71 | applications, err := t.ctx.ListApplications(false, hints) 72 | 73 | if err != nil { 74 | return nil, err 75 | } 76 | 77 | sort.Sort(ApplicationSorter(applications)) 78 | 79 | if len(applications) == 0 { 80 | return nil, fmt.Errorf("no application available") 81 | } 82 | 83 | selected := 0 84 | 85 | if len(applications) == 1 && applications[0].Priority&0x80 == 0 { 86 | selected = 1 87 | } else { 88 | fmt.Printf("Available applications:\n") 89 | fmt.Printf("\t00: Cancel\n") 90 | for i, app := range applications { 91 | fmt.Printf("\t%02d: %s (%10x)\n", i+1, app.Label, app.Name) 92 | } 93 | fmt.Printf("\n") 94 | 95 | fmt.Printf("Enter the wanted application: ") 96 | fmt.Scanf("%d\n", &selected) 97 | } 98 | 99 | if selected == 0 { 100 | return nil, fmt.Errorf("operation was cancelled") 101 | } 102 | 103 | if selected > len(applications) { 104 | return nil, fmt.Errorf("invalid application selected") 105 | } 106 | 107 | app := applications[selected-1] 108 | 109 | fmt.Printf("Selected %s (%10x)\n", app.Label, app.Name) 110 | 111 | return app, nil 112 | } 113 | 114 | func (t *TransactionProcessor) Process() error { 115 | return nil 116 | } 117 | -------------------------------------------------------------------------------- /tlv/ber.go: -------------------------------------------------------------------------------- 1 | package tlv 2 | 3 | import "fmt" 4 | 5 | // Taken from: https://github.com/cdevr/WapSNMP 6 | 7 | func EncodeTag(tag int) []byte { 8 | if (tag>>8)&0x1F == 0 { 9 | return []byte{byte(tag)} 10 | } 11 | 12 | return []byte{byte(tag >> 8), byte(tag & 0xff)} 13 | } 14 | 15 | func DecodeTag(toparse []byte) (int, int, error) { 16 | if toparse[0]&0x1F != 0x1F { 17 | return int(toparse[0]), 1, nil 18 | } 19 | 20 | return (int(toparse[0]) << 8) | int(toparse[1]), 2, nil 21 | } 22 | 23 | // EncodeLength encodes an integer value as a BER compliant length value. 24 | func EncodeLength(length uint64) []byte { 25 | // The first bit is used to indicate whether this is the final byte 26 | // encoding the length. So, if the first bit is 0, just return a one 27 | // byte response containing the byte-encoded length. 28 | if length <= 0x7f { 29 | return []byte{byte(length)} 30 | } 31 | 32 | // If the length is bigger the format is, first bit 1 + the rest of the 33 | // bits in the first byte encode the length of the length, then follows 34 | // the actual length. 35 | 36 | // Technically the SNMP spec allows for packet lengths longer than can be 37 | // specified in a 127-byte encoded integer, however, going out on a limb 38 | // here, I don't think I'm going to support a use case that insane. 39 | 40 | r := EncodeUInt(length) 41 | numOctets := len(r) 42 | result := make([]byte, 1+numOctets) 43 | result[0] = 0x80 | byte(numOctets) 44 | for i, b := range r { 45 | result[1+i] = b 46 | } 47 | return result 48 | } 49 | 50 | // DecodeLength returns the length and the length of the length or an error. 51 | // 52 | // Caveats: Does not support indefinite length. Couldn't find any 53 | // SNMP packet dump actually using that. 54 | func DecodeLength(toparse []byte) (uint64, int, error) { 55 | // If the first bit is zero, the rest of the first byte indicates the length. Values up to 127 are encoded this way (unless you're using indefinite length, but we don't support that) 56 | 57 | if toparse[0] == 0x80 { 58 | return 0, 0, fmt.Errorf("we don't support indefinite length encoding") 59 | } 60 | if toparse[0]&0x80 == 0 { 61 | return uint64(toparse[0]), 1, nil 62 | } 63 | 64 | // If the first bit is one, the rest of the first byte encodes the length of then encoded length. So read how many bytes are part of the length. 65 | numOctets := int(toparse[0] & 0x7f) 66 | if len(toparse) < 1+numOctets { 67 | return 0, 0, fmt.Errorf("invalid length") 68 | } 69 | 70 | // Decode the specified number of bytes as a BER Integer encoded 71 | // value. 72 | val, err := DecodeUInt(toparse[1 : numOctets+1]) 73 | if err != nil { 74 | return 0, 0, err 75 | } 76 | 77 | return val, 1 + numOctets, nil 78 | } 79 | 80 | // DecodeInteger decodes an integer. 81 | // 82 | // Will error out if it's longer than 64 bits. 83 | func DecodeInteger(toparse []byte) (int64, error) { 84 | if len(toparse) > 8 { 85 | return 0, fmt.Errorf("don't support more than 64 bits") 86 | } 87 | var val int64 88 | for _, b := range toparse { 89 | val = val<<8 | int64(b) 90 | } 91 | // Extend sign if necessary. 92 | val <<= 64 - uint8(len(toparse))*8 93 | val >>= 64 - uint8(len(toparse))*8 94 | return val, nil 95 | } 96 | 97 | // DecodeUInt decodes an unsigned int. 98 | // 99 | // Will error out if it's longer than 64 bits. 100 | func DecodeUInt(toparse []byte) (uint64, error) { 101 | if len(toparse) > 8 { 102 | return 0, fmt.Errorf("don't support more than 64 bits") 103 | } 104 | var val uint64 105 | for _, b := range toparse { 106 | val = val<<8 | uint64(b) 107 | } 108 | return val, nil 109 | } 110 | 111 | // EncodeInteger encodes an integer to BER format. 112 | func EncodeInteger(toEncode int64) []byte { 113 | // Calculate the length we'll need for the encoded value. 114 | var l int64 = 1 115 | if toEncode > 0 { 116 | for i := toEncode; i > 255; i >>= 8 { 117 | l++ 118 | } 119 | } else { 120 | for i := -toEncode; i > 255; i >>= 8 { 121 | l++ 122 | } 123 | // Ensure room for the sign if necessary. 124 | if toEncode < 0 { 125 | l++ 126 | } 127 | } 128 | 129 | // Now create a byte array of the correct length and copy the value into it. 130 | result := make([]byte, l) 131 | for i := int64(0); i < l; i++ { 132 | result[i] = byte(toEncode >> uint(8*(l-i-1))) 133 | } 134 | if result[0] > 127 && toEncode > 0 { 135 | result = append([]byte{0}, result...) 136 | } 137 | /* 138 | // Chop off superfluous 0xff's. 139 | s := 0 140 | for ; s+1 < len(result) && result[s] == 0xff && result[s+1] == 0xff; s++ { 141 | } 142 | return result[s:]*/ 143 | return result 144 | } 145 | 146 | // EncodeUInt encodes an unsigned integer to BER format. 147 | func EncodeUInt(toEncode uint64) []byte { 148 | // Calculate the length we'll need for the encoded value. 149 | var l int64 = 1 150 | for i := toEncode; i > 255; i >>= 8 { 151 | l++ 152 | } 153 | 154 | // Now create a byte array of the correct length and copy the value into it. 155 | result := make([]byte, l) 156 | for i := int64(0); i < l; i++ { 157 | result[i] = byte(toEncode >> uint(8*(l-i-1))) 158 | } 159 | return result 160 | } 161 | -------------------------------------------------------------------------------- /emv/card.go: -------------------------------------------------------------------------------- 1 | package emv 2 | 3 | import ( 4 | "encoding/hex" 5 | "fmt" 6 | "github.com/ebfe/scard" 7 | "github.com/greenboxal/emv-kernel/tlv" 8 | ) 9 | 10 | type Card struct { 11 | *scard.Card 12 | } 13 | 14 | func NewCard(card *scard.Card) *Card { 15 | return &Card{card} 16 | } 17 | 18 | func (c *Card) SendRawApdu(apdu *Apdu) (*ApduResponse, error) { 19 | dataLength := byte(0) 20 | fixed := 5 21 | 22 | if apdu.Data != nil { 23 | fixed = 6 24 | dataLength = byte(len(apdu.Data)) 25 | } 26 | 27 | req := make([]byte, fixed+len(apdu.Data)) 28 | 29 | req[0] = apdu.Class 30 | req[1] = apdu.Instruction 31 | req[2] = apdu.P1 32 | req[3] = apdu.P2 33 | 34 | if apdu.Data != nil { 35 | req[4] = dataLength 36 | copy(req[5:], apdu.Data) 37 | req[5+dataLength] = apdu.Expected 38 | } else { 39 | req[4] = apdu.Expected 40 | } 41 | 42 | fmt.Printf("SENT %s\n", hex.EncodeToString(req)) 43 | 44 | res, err := c.Transmit(req) 45 | 46 | if err != nil { 47 | return nil, err 48 | } 49 | 50 | fmt.Printf("RECV %s\n", hex.EncodeToString(res)) 51 | 52 | return &ApduResponse{ 53 | res[:len(res)-2], 54 | res[len(res)-2], 55 | res[len(res)-1], 56 | }, nil 57 | } 58 | 59 | func (c *Card) SendApdu(apdu *Apdu) (*ApduResponse, error) { 60 | res, err := c.SendRawApdu(apdu) 61 | 62 | if err != nil { 63 | return nil, err 64 | } 65 | 66 | if res.SW1 == 0x61 { 67 | return c.SendRawApdu(&Apdu{ 68 | Class: 0x00, 69 | Instruction: 0xC0, 70 | P1: 0x00, 71 | P2: 0x00, 72 | Expected: res.SW2, 73 | }) 74 | } else if res.SW1 == 0x6C { 75 | return c.SendRawApdu(&Apdu{ 76 | Class: apdu.Class, 77 | Instruction: apdu.Instruction, 78 | P1: apdu.P1, 79 | P2: apdu.P2, 80 | Data: apdu.Data, 81 | Expected: res.SW2, 82 | }) 83 | } 84 | 85 | return res, nil 86 | } 87 | 88 | func (c *Card) Select(name []byte, first bool) (*ApduResponse, error) { 89 | var p2 byte 90 | 91 | if first { 92 | p2 = 0 93 | } else { 94 | p2 = 2 95 | } 96 | 97 | return c.SendApdu(&Apdu{ 98 | Class: 0x00, 99 | Instruction: 0xA4, 100 | P1: 0x04, 101 | P2: p2, 102 | Data: []byte(name), 103 | Expected: 0, 104 | }) 105 | } 106 | 107 | func (c *Card) ReadRecord(sfi, record int) (*ApduResponse, error) { 108 | return c.SendApdu(&Apdu{ 109 | Class: 0x00, 110 | Instruction: 0xB2, 111 | P1: byte(record), 112 | P2: (byte(sfi) << 3) | 0x4, 113 | Data: nil, 114 | Expected: 0, 115 | }) 116 | } 117 | 118 | func (c *Card) SelectApplication(name []byte, first bool) (*Application, bool, error) { 119 | app := &Application{} 120 | res, err := c.Select(name, first) 121 | 122 | if err != nil { 123 | return nil, false, err 124 | } 125 | 126 | if res.SW1 == 0x6a && res.SW2 == 0x82 { 127 | return nil, false, nil 128 | } 129 | 130 | if res.SW1 != 0x90 || res.SW2 != 0x00 { 131 | return nil, false, fmt.Errorf("Error selecting application") 132 | } 133 | 134 | body, err := tlv.DecodeTlv(res.Body) 135 | 136 | if err != nil { 137 | return nil, true, err 138 | } 139 | 140 | found, err := body.UnmarshalValue(0x6f, app) 141 | 142 | if err != nil { 143 | return nil, true, err 144 | } 145 | 146 | if !found { 147 | return nil, true, fmt.Errorf("Error decoding application") 148 | } 149 | 150 | return app, true, nil 151 | } 152 | 153 | func (c *Card) GetProcessingOptions(pdol tlv.Tlv) (*ProcessingOptions, error) { 154 | pdolData, err := pdol.EncodeTlv() 155 | 156 | if err != nil { 157 | return nil, err 158 | } 159 | 160 | res, err := c.SendApdu(&Apdu{ 161 | Class: 0x80, 162 | Instruction: 0xA8, 163 | P1: 0x00, 164 | P2: 0x00, 165 | Data: pdolData, 166 | Expected: 0, 167 | }) 168 | 169 | if err != nil { 170 | return nil, err 171 | } 172 | 173 | body, err := tlv.DecodeTlv(res.Body) 174 | 175 | if err != nil { 176 | return nil, err 177 | } 178 | 179 | po := &ProcessingOptions{} 180 | 181 | found, err := body.UnmarshalValue(0x77, po) 182 | 183 | if err != nil { 184 | return nil, err 185 | } 186 | 187 | if !found { 188 | raw, found, err := body.Bytes(0x80) 189 | 190 | if err != nil { 191 | return nil, err 192 | } 193 | 194 | if !found { 195 | return nil, fmt.Errorf("Invalid message") 196 | } 197 | 198 | aip, err := tlv.DecodeInteger(raw[0:2]) 199 | 200 | if err != nil { 201 | return nil, err 202 | } 203 | 204 | po.ApplicationInterchangeProfile = int(aip) 205 | po.ApplicationFileList.DecodeTlv(raw[2:]) 206 | } 207 | 208 | fmt.Printf("%#+v\n", po) 209 | 210 | return po, nil 211 | } 212 | 213 | func (c *Card) VerifyPin(pin string) (bool, error) { 214 | pinBlock := make([]byte, 8) 215 | 216 | if len(pin) < 4 || len(pin) > 12 { 217 | return false, fmt.Errorf("wrong pin size") 218 | } 219 | 220 | pinBlock[0] = byte((1 << 5) | len(pin)) 221 | 222 | for i := 0; i < 12; i++ { 223 | digit := byte(0) 224 | 225 | if i < len(pin) { 226 | digit = byte(pin[i] - '0') 227 | } else { 228 | digit = 0xF 229 | } 230 | 231 | offset := i / 2 232 | nibble := 1 - (i % 2) 233 | shift := nibble * 4 234 | 235 | pinBlock[1+offset] |= digit << uint(shift) 236 | } 237 | 238 | pinBlock[7] = 0xFF 239 | 240 | res, err := c.SendApdu(&Apdu{ 241 | Class: 0x00, 242 | Instruction: 0x20, 243 | P1: 0x00, 244 | P2: 1 << 7, 245 | Data: pinBlock, 246 | Expected: 0, 247 | }) 248 | 249 | if err != nil { 250 | return false, err 251 | } 252 | 253 | return res.SW1 == 0x90 && res.SW2 == 0x00, nil 254 | } 255 | 256 | func (c *Card) GenerateAC(kind int, dol tlv.Tlv) (*GeneratedAC, error) { 257 | data, err := dol.EncodeTlv() 258 | 259 | if err != nil { 260 | return nil, err 261 | } 262 | 263 | res, err := c.SendApdu(&Apdu{ 264 | Class: 0x80, 265 | Instruction: 0xAE, 266 | P1: byte(kind), 267 | P2: 0x00, 268 | Data: data, 269 | Expected: 0, 270 | }) 271 | 272 | if res.SW1 != 0x90 && res.SW2 != 0x00 { 273 | return nil, fmt.Errorf("an error ocurred processing command") 274 | } 275 | 276 | body, err := tlv.DecodeTlv(res.Body) 277 | 278 | if err != nil { 279 | return nil, err 280 | } 281 | 282 | ac := &GeneratedAC{} 283 | 284 | found, err := body.UnmarshalValue(0x77, ac) 285 | 286 | if err != nil { 287 | return nil, err 288 | } 289 | 290 | if !found { 291 | return nil, fmt.Errorf("an error ocurred processing command") 292 | } 293 | 294 | return ac, nil 295 | } 296 | -------------------------------------------------------------------------------- /tlv/tlv.go: -------------------------------------------------------------------------------- 1 | package tlv 2 | 3 | import ( 4 | "encoding/hex" 5 | "fmt" 6 | "reflect" 7 | "strconv" 8 | "strings" 9 | ) 10 | 11 | type Tlv map[int][]byte 12 | 13 | func Pick(tag int, tlvs ...Tlv) (Tlv, bool) { 14 | for _, t := range tlvs { 15 | _, found := t[tag] 16 | 17 | if found { 18 | return t, true 19 | } 20 | } 21 | 22 | return nil, false 23 | } 24 | 25 | func (tlv Tlv) CopyFrom(other Tlv) { 26 | for k, v := range other { 27 | tlv[k] = v 28 | } 29 | } 30 | 31 | func (tlv Tlv) DecodeTlv(data []byte) error { 32 | for i := 0; i < len(data); { 33 | tag, tagLength, err := DecodeTag(data[i:]) 34 | 35 | if err != nil { 36 | return err 37 | } 38 | 39 | i += tagLength 40 | 41 | if tag == 0 { 42 | continue 43 | } 44 | 45 | length, lengthLength, err := DecodeLength(data[i:]) 46 | 47 | if err != nil { 48 | return err 49 | } 50 | 51 | i += lengthLength 52 | 53 | value := make([]byte, int(length)) 54 | copy(value, data[i:i+int(length)]) 55 | i += int(length) 56 | 57 | tlv[tag] = value 58 | } 59 | 60 | return nil 61 | } 62 | 63 | func (tlv Tlv) EncodeTlv() ([]byte, error) { 64 | data := make([]byte, 0) 65 | 66 | for k, v := range tlv { 67 | data = append(data, EncodeTag(k)...) 68 | data = append(data, EncodeLength(uint64(len(v)))...) 69 | data = append(data, v...) 70 | } 71 | 72 | return data, nil 73 | } 74 | 75 | func (t Tlv) Marshal(obj interface{}) error { 76 | value := reflect.ValueOf(obj) 77 | 78 | switch value.Kind() { 79 | case reflect.Ptr, reflect.Interface: 80 | value = value.Elem() 81 | } 82 | 83 | typ := value.Type() 84 | 85 | for i := 0; i < typ.NumField(); i++ { 86 | field := value.Field(i) 87 | fieldDef := typ.Field(i) 88 | 89 | structTag, ok := fieldDef.Tag.Lookup("tlv") 90 | opts := strings.Split(structTag, ",") 91 | 92 | if !ok { 93 | continue 94 | } 95 | 96 | if optsContains(opts, "other") { 97 | if !field.IsNil() { 98 | other := field.Interface().(Tlv) 99 | 100 | t.CopyFrom(other) 101 | } 102 | } else { 103 | tag, err := strconv.ParseUint(opts[0], 16, 64) 104 | 105 | if err != nil { 106 | return err 107 | } 108 | 109 | err = t.MarshalValueWithOptions(int(tag), field.Interface(), opts) 110 | 111 | if err != nil { 112 | return err 113 | } 114 | } 115 | } 116 | 117 | return nil 118 | } 119 | 120 | func (t Tlv) Unmarshal(obj interface{}) error { 121 | value := reflect.ValueOf(obj) 122 | 123 | switch value.Kind() { 124 | case reflect.Ptr, reflect.Interface: 125 | value = value.Elem() 126 | } 127 | 128 | if !value.CanSet() { 129 | return fmt.Errorf("go type '%s' is read-only", value.Type()) 130 | } 131 | 132 | typ := value.Type() 133 | 134 | for i := 0; i < typ.NumField(); i++ { 135 | field := value.Field(i) 136 | fieldDef := typ.Field(i) 137 | 138 | structTag, ok := fieldDef.Tag.Lookup("tlv") 139 | opts := strings.Split(structTag, ",") 140 | 141 | if !ok { 142 | continue 143 | } 144 | 145 | if optsContains(opts, "other") { 146 | if field.IsNil() { 147 | field.Set(reflect.ValueOf(t)) 148 | } else { 149 | other := field.Interface().(Tlv) 150 | 151 | other.CopyFrom(t) 152 | } 153 | } else { 154 | tag, err := strconv.ParseUint(opts[0], 16, 64) 155 | 156 | if err != nil { 157 | return err 158 | } 159 | 160 | _, err = t.UnmarshalValueWithOptions(int(tag), field.Addr().Interface(), opts) 161 | 162 | if err != nil { 163 | return err 164 | } 165 | } 166 | } 167 | 168 | return nil 169 | } 170 | 171 | func (t Tlv) MarshalValue(tag int, value interface{}) error { 172 | return t.MarshalValueWithOptions(tag, value, []string{}) 173 | } 174 | 175 | func (t Tlv) MarshalValueWithOptions(tag int, value interface{}, options []string) error { 176 | reflectedValue := reflect.ValueOf(value) 177 | 178 | switch reflectedValue.Kind() { 179 | case reflect.Ptr, reflect.Interface: 180 | reflectedValue = reflectedValue.Elem() 181 | } 182 | 183 | typ := reflectedValue.Type() 184 | 185 | encoder, ok := value.(TlvEncoder) 186 | 187 | if ok { 188 | data, err := encoder.EncodeTlv() 189 | 190 | if err != nil { 191 | return err 192 | } 193 | 194 | t[tag] = data 195 | 196 | return nil 197 | } 198 | 199 | switch typ.Kind() { 200 | case reflect.Struct: 201 | tlv := make(Tlv) 202 | 203 | err := tlv.Marshal(value) 204 | 205 | if err != nil { 206 | return err 207 | } 208 | 209 | data, err := tlv.EncodeTlv() 210 | 211 | if err != nil { 212 | return err 213 | } 214 | 215 | t[tag] = data 216 | default: 217 | switch v := value.(type) { 218 | case []byte: 219 | t[tag] = v 220 | case int: 221 | t[tag] = EncodeInteger(int64(v)) 222 | case int64: 223 | t[tag] = EncodeInteger(v) 224 | case uint64: 225 | t[tag] = EncodeUInt(v) 226 | case uint: 227 | t[tag] = EncodeUInt(uint64(v)) 228 | case string: 229 | if optsContains(options, "hex") { 230 | data, err := hex.DecodeString(v) 231 | 232 | if err != nil { 233 | return err 234 | } 235 | 236 | t[tag] = data 237 | } else { 238 | t[tag] = []byte(v) 239 | } 240 | case bool: 241 | i := 0 242 | 243 | if v { 244 | i = 1 245 | } 246 | 247 | t[tag] = EncodeUInt(uint64(i)) 248 | default: 249 | return fmt.Errorf("go type %s can't be encoded", typ.Name()) 250 | } 251 | } 252 | 253 | return nil 254 | } 255 | 256 | func (t Tlv) UnmarshalValue(tag int, value interface{}) (bool, error) { 257 | return t.UnmarshalValueWithOptions(tag, value, []string{}) 258 | } 259 | 260 | func (t Tlv) UnmarshalValueWithOptions(tag int, value interface{}, options []string) (bool, error) { 261 | data, found := t[tag] 262 | 263 | if !found { 264 | return false, nil 265 | } 266 | 267 | reflectedValue := reflect.ValueOf(value) 268 | 269 | switch reflectedValue.Kind() { 270 | case reflect.Ptr, reflect.Interface: 271 | reflectedValue = reflectedValue.Elem() 272 | } 273 | 274 | if !reflectedValue.CanSet() { 275 | return true, fmt.Errorf("go type '%s' is read-only", reflectedValue.Type()) 276 | } 277 | 278 | typ := reflectedValue.Type() 279 | 280 | decoder, ok := value.(TlvDecoder) 281 | 282 | if ok { 283 | return true, decoder.DecodeTlv(data) 284 | } 285 | 286 | switch typ.Kind() { 287 | case reflect.Struct: 288 | result, err := DecodeTlv(data) 289 | 290 | if err != nil { 291 | return true, err 292 | } 293 | 294 | err = result.Unmarshal(value) 295 | 296 | if err != nil { 297 | return true, err 298 | } 299 | default: 300 | switch v := value.(type) { 301 | case *[]byte: 302 | *v = data 303 | case *int: 304 | result, err := DecodeInteger(data) 305 | 306 | if err != nil { 307 | return true, err 308 | } 309 | 310 | *v = int(result) 311 | case *int64: 312 | result, err := DecodeInteger(data) 313 | 314 | if err != nil { 315 | return true, err 316 | } 317 | 318 | *v = result 319 | case *uint64: 320 | result, err := DecodeUInt(data) 321 | 322 | if err != nil { 323 | return true, err 324 | } 325 | 326 | *v = result 327 | case *uint: 328 | result, err := DecodeUInt(data) 329 | 330 | if err != nil { 331 | return true, err 332 | } 333 | 334 | *v = uint(result) 335 | case *string: 336 | if optsContains(options, "hex") { 337 | *v = hex.EncodeToString(data) 338 | } else { 339 | *v = string(data) 340 | } 341 | case *bool: 342 | result, err := DecodeUInt(data) 343 | 344 | if err != nil { 345 | return true, err 346 | } 347 | 348 | *v = result != 0 349 | default: 350 | return true, fmt.Errorf("go type %s can't be decoded", typ.Name()) 351 | } 352 | } 353 | 354 | return true, nil 355 | } 356 | 357 | func (t Tlv) Tlv(tag int) (Tlv, bool, error) { 358 | result := make(Tlv) 359 | found, err := t.UnmarshalValue(tag, &result) 360 | 361 | if !found || err != nil { 362 | return nil, found, err 363 | } 364 | 365 | return result, true, nil 366 | } 367 | 368 | func (t Tlv) Uint(tag int) (uint64, bool, error) { 369 | result := uint64(0) 370 | found, err := t.UnmarshalValue(tag, &result) 371 | 372 | if !found || err != nil { 373 | return 0, found, err 374 | } 375 | 376 | return result, true, nil 377 | } 378 | 379 | func (t Tlv) Int(tag int) (int64, bool, error) { 380 | result := int64(0) 381 | found, err := t.UnmarshalValue(tag, &result) 382 | 383 | if !found || err != nil { 384 | return 0, found, err 385 | } 386 | 387 | return result, true, nil 388 | } 389 | 390 | func (t Tlv) String(tag int) (string, bool, error) { 391 | result := "" 392 | found, err := t.UnmarshalValue(tag, &result) 393 | 394 | if !found || err != nil { 395 | return "", found, err 396 | } 397 | 398 | return result, true, nil 399 | } 400 | 401 | func (t Tlv) Bytes(tag int) ([]byte, bool, error) { 402 | result := []byte{} 403 | found, err := t.UnmarshalValue(tag, &result) 404 | 405 | if !found || err != nil { 406 | return nil, found, err 407 | } 408 | 409 | return result, true, nil 410 | } 411 | 412 | func DecodeTlv(data []byte) (Tlv, error) { 413 | tlv := make(Tlv) 414 | 415 | return tlv, tlv.DecodeTlv(data) 416 | } 417 | 418 | func optsContains(s []string, e string) bool { 419 | for _, a := range s { 420 | if a == e { 421 | return true 422 | } 423 | } 424 | return false 425 | } 426 | -------------------------------------------------------------------------------- /emv/context.go: -------------------------------------------------------------------------------- 1 | package emv 2 | 3 | import ( 4 | "bytes" 5 | "crypto/rand" 6 | "crypto/sha1" 7 | "fmt" 8 | "github.com/ebfe/scard" 9 | "github.com/greenboxal/emv-kernel/tlv" 10 | "math/big" 11 | ) 12 | 13 | type Context struct { 14 | card *Card 15 | config *ContextConfig 16 | cm CertificateManager 17 | 18 | Application *Application 19 | ProcessingOptions *ProcessingOptions 20 | CardInformation *CardInformation 21 | 22 | tvr uint64 23 | cvr uint64 24 | 25 | sdaData []byte 26 | dataAuthenticationCode []byte 27 | } 28 | 29 | func NewContext(card *Card, config *ContextConfig, cm CertificateManager) *Context { 30 | return &Context{ 31 | config: config, 32 | card: card, 33 | cm: cm, 34 | CardInformation: &CardInformation{}, 35 | sdaData: []byte{}, 36 | } 37 | } 38 | 39 | func (c *Context) Initialize() error { 40 | return c.card.Reconnect(scard.ShareExclusive, scard.ProtocolAny, scard.ResetCard) 41 | } 42 | 43 | func (c *Context) ListApplications(contactless bool, hints []ApplicationHint) ([]*ApplicationInformation, error) { 44 | var pseFile []byte 45 | 46 | if contactless { 47 | pseFile = []byte("2PAY.SYS.DDF01") 48 | } else { 49 | pseFile = []byte("1PAY.SYS.DDF01") 50 | } 51 | 52 | result := make([]*ApplicationInformation, 0) 53 | pse, found, err := c.card.SelectApplication(pseFile, true) 54 | 55 | if err != nil { 56 | return nil, err 57 | } 58 | 59 | if found { 60 | record := 1 61 | 62 | for true { 63 | res, err := c.card.ReadRecord(pse.Template.Sfi, record) 64 | 65 | if err != nil { 66 | return nil, err 67 | } 68 | 69 | if len(res.Body) == 0 { 70 | break 71 | } 72 | 73 | tlv, err := tlv.DecodeTlv(res.Body) 74 | 75 | if err != nil { 76 | return nil, err 77 | } 78 | 79 | tlv, found, err = tlv.Tlv(0x70) 80 | 81 | if err != nil { 82 | return nil, err 83 | } 84 | 85 | if !found { 86 | return nil, fmt.Errorf("invalid PSE record") 87 | } 88 | 89 | info := &ApplicationInformation{} 90 | found, err := tlv.UnmarshalValue(0x61, info) 91 | 92 | if err != nil { 93 | return nil, err 94 | } 95 | 96 | if !found { 97 | return nil, fmt.Errorf("invalid PSE record") 98 | } 99 | 100 | result = append(result, info) 101 | record++ 102 | } 103 | } else { 104 | for _, hint := range hints { 105 | first := true 106 | 107 | for true { 108 | app, found, err := c.card.SelectApplication(hint.Name, first) 109 | 110 | if err != nil { 111 | return nil, err 112 | } 113 | 114 | if !found { 115 | break 116 | } 117 | 118 | duplicated := false 119 | 120 | for _, info := range result { 121 | if bytes.Equal(info.Name, app.DedicatedFileName) { 122 | duplicated = true 123 | break 124 | } 125 | } 126 | 127 | if !duplicated { 128 | result = append(result, &ApplicationInformation{ 129 | Name: app.DedicatedFileName, 130 | Label: app.Template.Label, 131 | Priority: app.Template.Priority, 132 | }) 133 | } 134 | 135 | if !hint.Partial { 136 | break 137 | } 138 | 139 | first = false 140 | } 141 | } 142 | } 143 | 144 | return result, nil 145 | } 146 | 147 | func (c *Context) SelectApplication(applicationName []byte) (*Application, error) { 148 | var pdol tlv.Tlv 149 | 150 | app, found, err := c.card.SelectApplication(applicationName, true) 151 | 152 | if err != nil { 153 | return nil, err 154 | } 155 | 156 | if !found { 157 | return nil, fmt.Errorf("application not found") 158 | } 159 | 160 | if app.Template.ProcessingObjects != nil { 161 | pdol, err = c.buildDol(app.Template.ProcessingObjects, nil) 162 | 163 | if err != nil { 164 | return nil, err 165 | } 166 | } else { 167 | pdol = make(tlv.Tlv) 168 | pdol.MarshalValue(0x83, []byte{}) 169 | } 170 | 171 | opts, err := c.card.GetProcessingOptions(pdol) 172 | 173 | if err != nil { 174 | return nil, err 175 | } 176 | 177 | c.Application = app 178 | c.ProcessingOptions = opts 179 | 180 | for _, app := range opts.ApplicationFileList { 181 | sdaCount := app.SdaCount 182 | 183 | for i := app.Start; i <= app.End; i++ { 184 | record, err := c.card.ReadRecord(app.Sfi, i) 185 | 186 | if err != nil { 187 | return nil, err 188 | } 189 | 190 | body, err := tlv.DecodeTlv(record.Body) 191 | 192 | if err != nil { 193 | return nil, err 194 | } 195 | 196 | templateBytes, found, err := body.Bytes(0x70) 197 | 198 | if err != nil { 199 | return nil, err 200 | } 201 | 202 | if !found { 203 | return nil, fmt.Errorf("malformed application file") 204 | } 205 | 206 | // Build SDA data 207 | if sdaCount > 0 { 208 | if app.Sfi <= 10 { 209 | c.sdaData = append(c.sdaData, templateBytes...) 210 | } else { 211 | c.sdaData = append(c.sdaData, record.Body...) 212 | } 213 | 214 | sdaCount-- 215 | } 216 | 217 | template, err := tlv.DecodeTlv(templateBytes) 218 | 219 | if err != nil { 220 | return nil, err 221 | } 222 | 223 | err = template.Unmarshal(c.CardInformation) 224 | 225 | if err != nil { 226 | return nil, err 227 | } 228 | } 229 | } 230 | 231 | return app, nil 232 | } 233 | 234 | func (c *Context) Authenticate() (bool, error) { 235 | success := true 236 | 237 | if c.ProcessingOptions.ApplicationInterchangeProfile&AipDdaSupported != 0 { 238 | ok, err := c.authenticateDda() 239 | 240 | if err != nil { 241 | return false, err 242 | } 243 | 244 | if !ok { 245 | c.tvr |= TvrDdaFailed 246 | } 247 | 248 | success = success && ok 249 | } else if c.ProcessingOptions.ApplicationInterchangeProfile&AipSdaSupported != 0 { 250 | ok, err := c.authenticateSda() 251 | 252 | if err != nil { 253 | return false, err 254 | } 255 | 256 | if !ok { 257 | c.tvr |= TvrSdaFailed 258 | } 259 | 260 | success = success && ok 261 | } else { 262 | c.tvr |= TvrOfflineNotPerformed 263 | } 264 | 265 | return true, nil 266 | } 267 | 268 | func (c *Context) VerifyCardholder(pinAsker PinAsker) (bool, error) { 269 | pin, err := pinAsker.RetrievePin() 270 | 271 | if err != nil { 272 | return false, err 273 | } 274 | 275 | ok, err := c.card.VerifyPin(pin) 276 | 277 | if err != nil { 278 | return false, err 279 | } 280 | 281 | if !ok { 282 | c.tvr |= TvrCvmFailed 283 | } 284 | 285 | return ok, nil 286 | } 287 | 288 | func (c *Context) GenerateCryptogram(tx *Transaction) (*TransactionResult, error) { 289 | return nil, nil 290 | } 291 | 292 | func (c *Context) buildDol(dol DataObjectList, tx *Transaction) (tlv.Tlv, error) { 293 | t := make(tlv.Tlv) 294 | 295 | for tag, length := range dol { 296 | switch tag { 297 | case 0x9F02: 298 | t.MarshalValue(tag, tx.Amount) 299 | case 0x9F03: 300 | t.MarshalValue(tag, tx.AdditionalAmount) 301 | case 0x9F1A: 302 | t.MarshalValue(tag, c.config.Terminal.CountryCode) 303 | case 0x95: 304 | t.MarshalValue(tag, c.tvr) 305 | case 0x5F2A: 306 | t.MarshalValue(tag, c.config.Terminal.CurrencyCode) 307 | case 0x9A: 308 | t.MarshalValue(tag, tx.Date) 309 | case 0x9C: 310 | t.MarshalValue(tag, tx.Type) 311 | case 0x9F37: 312 | number, err := c.generateUnpredictableNumber(length) 313 | 314 | if err != nil { 315 | return nil, err 316 | } 317 | 318 | t.MarshalValue(tag, number) 319 | case 0x9F35: 320 | t.MarshalValue(tag, c.config.Terminal.Type) 321 | case 0x9F45: 322 | t.MarshalValue(tag, c.dataAuthenticationCode) 323 | case 0x9F34: 324 | t.MarshalValue(tag, c.cvr) 325 | default: 326 | t, found := tlv.Pick(tag, c.CardInformation.Raw, c.ProcessingOptions.Raw) 327 | 328 | if found { 329 | value, _, _ := t.Bytes(tag) 330 | 331 | t.MarshalValue(tag, value) 332 | } 333 | } 334 | } 335 | 336 | return t, nil 337 | } 338 | 339 | func (c *Context) authenticateSda() (bool, error) { 340 | pub, err := c.retrieveIssuerPublicKey() 341 | 342 | if err != nil { 343 | return false, err 344 | } 345 | 346 | sad, err := pub.Decrypt(c.CardInformation.SignedStaticApplicationData) 347 | 348 | if err != nil { 349 | return false, err 350 | } 351 | 352 | if sad[len(sad)-1] != 0xBC { 353 | return false, fmt.Errorf("invalid static application data") 354 | } 355 | 356 | if sad[0] != 0x6A { 357 | return false, fmt.Errorf("invalid static application data") 358 | } 359 | 360 | if sad[1] != 0x03 { 361 | return false, fmt.Errorf("invalid static application data") 362 | } 363 | 364 | sdaTags, err := c.buildSdaTags() 365 | 366 | if err != nil { 367 | return false, err 368 | } 369 | 370 | data := sad[1:][:len(sad)-22] 371 | data = append(data, c.sdaData...) 372 | data = append(data, sdaTags...) 373 | 374 | actualHash := sha1.Sum(data) 375 | expectedHash := sad[len(sad)-21:][:20] 376 | 377 | if !bytes.Equal(expectedHash, actualHash[:]) { 378 | fmt.Printf("%x\n%x\n", actualHash, expectedHash) 379 | return false, fmt.Errorf("sda hash doesn't match") 380 | } 381 | 382 | c.dataAuthenticationCode = sad[3:][:2] 383 | 384 | return true, nil 385 | } 386 | 387 | func (c *Context) authenticateDda() (bool, error) { 388 | return false, fmt.Errorf("not implemented") 389 | } 390 | 391 | func (c *Context) buildSdaTags() ([]byte, error) { 392 | result := make([]byte, 0) 393 | 394 | for _, tag := range c.CardInformation.SdaTags { 395 | t, found := tlv.Pick(tag, c.CardInformation.Raw, c.ProcessingOptions.Raw) 396 | 397 | if !found { 398 | return nil, fmt.Errorf("missing SDA tag") 399 | } 400 | 401 | value, _, err := t.Bytes(tag) 402 | 403 | if err != nil { 404 | return nil, err 405 | } 406 | 407 | result = append(result, value...) 408 | } 409 | 410 | return result, nil 411 | } 412 | 413 | func (c *Context) retrieveIssuerPublicKey() (*PublicKey, error) { 414 | rid := c.Application.DedicatedFileName[0:5] 415 | index := c.CardInformation.SchemePublicKeyIndex 416 | 417 | pub, err := c.cm.GetSchemePublicKey(rid, index) 418 | 419 | if err != nil { 420 | return nil, err 421 | } 422 | 423 | cert, err := pub.Decrypt(c.CardInformation.IssuerPublicKeyCertificate) 424 | 425 | if err != nil { 426 | return nil, err 427 | } 428 | 429 | if cert[0] != 0x6A { 430 | return nil, fmt.Errorf("invalid issuer public key") 431 | } 432 | 433 | if cert[1] != 0x02 { 434 | return nil, fmt.Errorf("invalid issuer public key") 435 | } 436 | 437 | if cert[len(cert)-1] != 0xBC { 438 | return nil, fmt.Errorf("invalid issuer public key") 439 | } 440 | 441 | schemeModulus := pub.Modulus() 442 | 443 | keycheck := cert[1:][:14+len(schemeModulus)-36] 444 | keycheck = append(keycheck, c.CardInformation.IssuerPublicKeyRemainder...) 445 | keycheck = append(keycheck, c.CardInformation.IssuerPublicKeyExponent...) 446 | 447 | expectedKeycheckHash := cert[15+len(schemeModulus)-36:][:20] 448 | actualKeycheckHash := sha1.Sum(keycheck) 449 | 450 | if !bytes.Equal(expectedKeycheckHash, actualKeycheckHash[:]) { 451 | fmt.Printf("%x\n%x\n", expectedKeycheckHash, actualKeycheckHash) 452 | return nil, fmt.Errorf("hash doesn't match") 453 | } 454 | 455 | modulus := cert[15 : 15+len(schemeModulus)-36] 456 | modulus = append(modulus, c.CardInformation.IssuerPublicKeyRemainder...) 457 | 458 | e := big.NewInt(0) 459 | e.SetBytes(c.CardInformation.IssuerPublicKeyExponent) 460 | 461 | m := big.NewInt(0) 462 | m.SetBytes(modulus) 463 | 464 | return NewPublicKey(e, m), nil 465 | } 466 | 467 | func (c *Context) generateUnpredictableNumber(size int) ([]byte, error) { 468 | data := make([]byte, size) 469 | 470 | _, err := rand.Read(data) 471 | 472 | if err != nil { 473 | return nil, err 474 | } 475 | 476 | return data, nil 477 | } 478 | --------------------------------------------------------------------------------