├── .circleci └── config.yml ├── .gitignore ├── .golangci.yml ├── CODE_OF_CONDUCT.md ├── LICENSE ├── Makefile ├── README.md ├── algorithms.go ├── cbor.go ├── cbor_test.go ├── common_headers.go ├── common_headers_test.go ├── core.go ├── core_test.go ├── errors.go ├── example ├── sign.go └── verify.go ├── fuzz.go ├── go.mod ├── go.sum ├── helpers_test.go ├── samples ├── CWT_A_3.json.cose ├── CWT_A_4.json.cose ├── CWT_A_5.json.cose ├── CWT_A_6.json.cose ├── CWT_A_7.json.cose ├── RFC8152_Appendix_B.json.cose ├── RFC8152_Appendix_C_1_1.json.cose ├── RFC8152_Appendix_C_1_2.json.cose ├── RFC8152_Appendix_C_1_3.json.cose ├── RFC8152_Appendix_C_1_4.json.cose ├── RFC8152_Appendix_C_2_1.json.cose ├── RFC8152_Appendix_C_3_1.json.cose ├── RFC8152_Appendix_C_3_2.json.cose ├── RFC8152_Appendix_C_3_3.json.cose ├── RFC8152_Appendix_C_3_4.json.cose ├── RFC8152_Appendix_C_4_1.json.cose ├── RFC8152_Appendix_C_4_2.json.cose ├── RFC8152_Appendix_C_5_1.json.cose ├── RFC8152_Appendix_C_5_2.json.cose ├── RFC8152_Appendix_C_5_3.json.cose ├── RFC8152_Appendix_C_5_4.json.cose ├── RFC8152_Appendix_C_6_1.json.cose ├── X25519-tests_x25519-hkdf-256-direct.json.cose ├── X25519-tests_x25519-ss-hkdf-256-direct.json.cose ├── aes-ccm-examples_aes-ccm-01.json.cose ├── aes-ccm-examples_aes-ccm-02.json.cose ├── aes-ccm-examples_aes-ccm-03.json.cose ├── aes-ccm-examples_aes-ccm-04.json.cose ├── aes-ccm-examples_aes-ccm-05.json.cose ├── aes-ccm-examples_aes-ccm-06.json.cose ├── aes-ccm-examples_aes-ccm-07.json.cose ├── aes-ccm-examples_aes-ccm-08.json.cose ├── aes-ccm-examples_aes-ccm-enc-01.json.cose ├── aes-ccm-examples_aes-ccm-enc-02.json.cose ├── aes-ccm-examples_aes-ccm-enc-03.json.cose ├── aes-ccm-examples_aes-ccm-enc-04.json.cose ├── aes-ccm-examples_aes-ccm-enc-05.json.cose ├── aes-ccm-examples_aes-ccm-enc-06.json.cose ├── aes-ccm-examples_aes-ccm-enc-07.json.cose ├── aes-ccm-examples_aes-ccm-enc-08.json.cose ├── aes-gcm-examples_aes-gcm-01.json.cose ├── aes-gcm-examples_aes-gcm-02.json.cose ├── aes-gcm-examples_aes-gcm-03.json.cose ├── aes-gcm-examples_aes-gcm-04.json.cose ├── aes-gcm-examples_aes-gcm-05.json.cose ├── aes-gcm-examples_aes-gcm-enc-01.json.cose ├── aes-gcm-examples_aes-gcm-enc-02.json.cose ├── aes-gcm-examples_aes-gcm-enc-03.json.cose ├── aes-gcm-examples_aes-gcm-enc-04.json.cose ├── aes-wrap-examples_aes-wrap-128-01.json.cose ├── aes-wrap-examples_aes-wrap-128-02.json.cose ├── aes-wrap-examples_aes-wrap-128-03.json.cose ├── aes-wrap-examples_aes-wrap-128-04.json.cose ├── aes-wrap-examples_aes-wrap-128-05.json.cose ├── aes-wrap-examples_aes-wrap-192-01.json.cose ├── aes-wrap-examples_aes-wrap-192-02.json.cose ├── aes-wrap-examples_aes-wrap-192-03.json.cose ├── aes-wrap-examples_aes-wrap-192-04.json.cose ├── aes-wrap-examples_aes-wrap-192-05.json.cose ├── aes-wrap-examples_aes-wrap-256-01.json.cose ├── aes-wrap-examples_aes-wrap-256-02.json.cose ├── aes-wrap-examples_aes-wrap-256-03.json.cose ├── aes-wrap-examples_aes-wrap-256-04.json.cose ├── aes-wrap-examples_aes-wrap-256-05.json.cose ├── cbc-mac-examples_cbc-mac-01.json.cose ├── cbc-mac-examples_cbc-mac-02.json.cose ├── cbc-mac-examples_cbc-mac-03.json.cose ├── cbc-mac-examples_cbc-mac-04.json.cose ├── cbc-mac-examples_cbc-mac-enc-01.json.cose ├── cbc-mac-examples_cbc-mac-enc-02.json.cose ├── cbc-mac-examples_cbc-mac-enc-03.json.cose ├── cbc-mac-examples_cbc-mac-enc-04.json.cose ├── chacha-poly-examples_chacha-poly-01.json.cose ├── chacha-poly-examples_chacha-poly-enc-01.json.cose ├── ecdh-direct-examples_p256-hkdf-256-01.json.cose ├── ecdh-direct-examples_p256-hkdf-256-02.json.cose ├── ecdh-direct-examples_p256-hkdf-256-03.json.cose ├── ecdh-direct-examples_p256-hkdf-512-01.json.cose ├── ecdh-direct-examples_p256-hkdf-512-02.json.cose ├── ecdh-direct-examples_p256-hkdf-512-03.json.cose ├── ecdh-direct-examples_p256-ss-hkdf-256-01.json.cose ├── ecdh-direct-examples_p256-ss-hkdf-256-02.json.cose ├── ecdh-direct-examples_p256-ss-hkdf-256-03.json.cose ├── ecdh-direct-examples_p256-ss-hkdf-512-01.json.cose ├── ecdh-direct-examples_p256-ss-hkdf-512-02.json.cose ├── ecdh-direct-examples_p256-ss-hkdf-512-03.json.cose ├── ecdh-direct-examples_p521-hkdf-256-01.json.cose ├── ecdh-direct-examples_p521-hkdf-256-02.json.cose ├── ecdh-direct-examples_p521-hkdf-256-03.json.cose ├── ecdh-direct-examples_p521-hkdf-512-01.json.cose ├── ecdh-direct-examples_p521-hkdf-512-02.json.cose ├── ecdh-direct-examples_p521-hkdf-512-03.json.cose ├── ecdh-direct-examples_p521-ss-hkdf-256-01.json.cose ├── ecdh-direct-examples_p521-ss-hkdf-256-02.json.cose ├── ecdh-direct-examples_p521-ss-hkdf-256-03.json.cose ├── ecdh-direct-examples_p521-ss-hkdf-512-01.json.cose ├── ecdh-direct-examples_p521-ss-hkdf-512-02.json.cose ├── ecdh-direct-examples_p521-ss-hkdf-512-03.json.cose ├── ecdh-wrap-examples_p256-ss-wrap-128-01.json.cose ├── ecdh-wrap-examples_p256-ss-wrap-128-02.json.cose ├── ecdh-wrap-examples_p256-ss-wrap-128-03.json.cose ├── ecdh-wrap-examples_p256-ss-wrap-192-01.json.cose ├── ecdh-wrap-examples_p256-ss-wrap-192-02.json.cose ├── ecdh-wrap-examples_p256-ss-wrap-192-03.json.cose ├── ecdh-wrap-examples_p256-ss-wrap-256-01.json.cose ├── ecdh-wrap-examples_p256-ss-wrap-256-02.json.cose ├── ecdh-wrap-examples_p256-ss-wrap-256-03.json.cose ├── ecdh-wrap-examples_p256-wrap-128-01.json.cose ├── ecdh-wrap-examples_p256-wrap-128-02.json.cose ├── ecdh-wrap-examples_p256-wrap-128-03.json.cose ├── ecdh-wrap-examples_p256-wrap-192-01.json.cose ├── ecdh-wrap-examples_p256-wrap-192-02.json.cose ├── ecdh-wrap-examples_p256-wrap-192-03.json.cose ├── ecdh-wrap-examples_p256-wrap-256-01.json.cose ├── ecdh-wrap-examples_p256-wrap-256-02.json.cose ├── ecdh-wrap-examples_p256-wrap-256-03.json.cose ├── ecdh-wrap-examples_p521-ss-wrap-128-01.json.cose ├── ecdh-wrap-examples_p521-ss-wrap-128-02.json.cose ├── ecdh-wrap-examples_p521-ss-wrap-128-03.json.cose ├── ecdh-wrap-examples_p521-ss-wrap-192-01.json.cose ├── ecdh-wrap-examples_p521-ss-wrap-192-02.json.cose ├── ecdh-wrap-examples_p521-ss-wrap-192-03.json.cose ├── ecdh-wrap-examples_p521-ss-wrap-256-01.json.cose ├── ecdh-wrap-examples_p521-ss-wrap-256-02.json.cose ├── ecdh-wrap-examples_p521-ss-wrap-256-03.json.cose ├── ecdh-wrap-examples_p521-wrap-128-01.json.cose ├── ecdh-wrap-examples_p521-wrap-128-02.json.cose ├── ecdh-wrap-examples_p521-wrap-128-03.json.cose ├── ecdh-wrap-examples_p521-wrap-192-01.json.cose ├── ecdh-wrap-examples_p521-wrap-192-02.json.cose ├── ecdh-wrap-examples_p521-wrap-192-03.json.cose ├── ecdh-wrap-examples_p521-wrap-256-01.json.cose ├── ecdh-wrap-examples_p521-wrap-256-02.json.cose ├── ecdh-wrap-examples_p521-wrap-256-03.json.cose ├── ecdsa-examples_ecdsa-01.json.cose ├── ecdsa-examples_ecdsa-02.json.cose ├── ecdsa-examples_ecdsa-03.json.cose ├── ecdsa-examples_ecdsa-04.json.cose ├── ecdsa-examples_ecdsa-sig-01.json.cose ├── ecdsa-examples_ecdsa-sig-02.json.cose ├── ecdsa-examples_ecdsa-sig-03.json.cose ├── ecdsa-examples_ecdsa-sig-04.json.cose ├── eddsa-examples_eddsa-01.json.cose ├── eddsa-examples_eddsa-02.json.cose ├── eddsa-examples_eddsa-sig-01.json.cose ├── eddsa-examples_eddsa-sig-02.json.cose ├── encrypted-tests_aes-gcm-01.json.cose ├── encrypted-tests_enc-fail-01.json.cose ├── encrypted-tests_enc-fail-02.json.cose ├── encrypted-tests_enc-fail-03.json.cose ├── encrypted-tests_enc-fail-04.json.cose ├── encrypted-tests_enc-fail-06.json.cose ├── encrypted-tests_enc-fail-07.json.cose ├── encrypted-tests_enc-pass-01.json.cose ├── encrypted-tests_enc-pass-02.json.cose ├── encrypted-tests_enc-pass-03.json.cose ├── enveloped-tests_aes-gcm-01.json.cose ├── enveloped-tests_env-fail-01.json.cose ├── enveloped-tests_env-fail-02.json.cose ├── enveloped-tests_env-fail-03.json.cose ├── enveloped-tests_env-fail-04.json.cose ├── enveloped-tests_env-fail-06.json.cose ├── enveloped-tests_env-fail-07.json.cose ├── enveloped-tests_env-pass-01.json.cose ├── enveloped-tests_env-pass-02.json.cose ├── enveloped-tests_env-pass-03.json.cose ├── hkdf-aes-examples_hmac-aes-128-01.json.cose ├── hkdf-aes-examples_hmac-aes-128-02.json.cose ├── hkdf-aes-examples_hmac-aes-128-03.json.cose ├── hkdf-aes-examples_hmac-aes-128-04.json.cose ├── hkdf-aes-examples_hmac-aes-128-05.json.cose ├── hkdf-aes-examples_hmac-aes-128-06.json.cose ├── hkdf-aes-examples_hmac-aes-128-07.json.cose ├── hkdf-aes-examples_hmac-aes-128-08.json.cose ├── hkdf-aes-examples_hmac-aes-128-09.json.cose ├── hkdf-aes-examples_hmac-aes-128-10.json.cose ├── hkdf-aes-examples_hmac-aes-128-11.json.cose ├── hkdf-aes-examples_hmac-aes-128-12.json.cose ├── hkdf-aes-examples_hmac-aes-128-13.json.cose ├── hkdf-aes-examples_hmac-aes-128-14.json.cose ├── hkdf-aes-examples_hmac-aes-256-01.json.cose ├── hkdf-aes-examples_hmac-aes-256-02.json.cose ├── hkdf-aes-examples_hmac-aes-256-03.json.cose ├── hkdf-aes-examples_hmac-aes-256-04.json.cose ├── hkdf-aes-examples_hmac-aes-256-05.json.cose ├── hkdf-aes-examples_hmac-aes-256-06.json.cose ├── hkdf-aes-examples_hmac-aes-256-07.json.cose ├── hkdf-aes-examples_hmac-aes-256-08.json.cose ├── hkdf-aes-examples_hmac-aes-256-09.json.cose ├── hkdf-aes-examples_hmac-aes-256-10.json.cose ├── hkdf-aes-examples_hmac-aes-256-11.json.cose ├── hkdf-aes-examples_hmac-aes-256-12.json.cose ├── hkdf-aes-examples_hmac-aes-256-13.json.cose ├── hkdf-aes-examples_hmac-aes-256-14.json.cose ├── hkdf-hmac-sha-examples_hmac-sha-256-01.json.cose ├── hkdf-hmac-sha-examples_hmac-sha-256-02.json.cose ├── hkdf-hmac-sha-examples_hmac-sha-256-03.json.cose ├── hkdf-hmac-sha-examples_hmac-sha-256-04.json.cose ├── hkdf-hmac-sha-examples_hmac-sha-256-05.json.cose ├── hkdf-hmac-sha-examples_hmac-sha-256-06.json.cose ├── hkdf-hmac-sha-examples_hmac-sha-256-07.json.cose ├── hkdf-hmac-sha-examples_hmac-sha-256-08.json.cose ├── hkdf-hmac-sha-examples_hmac-sha-256-09.json.cose ├── hkdf-hmac-sha-examples_hmac-sha-256-10.json.cose ├── hkdf-hmac-sha-examples_hmac-sha-256-11.json.cose ├── hkdf-hmac-sha-examples_hmac-sha-256-12.json.cose ├── hkdf-hmac-sha-examples_hmac-sha-256-13.json.cose ├── hkdf-hmac-sha-examples_hmac-sha-256-14.json.cose ├── hkdf-hmac-sha-examples_hmac-sha-512-01.json.cose ├── hkdf-hmac-sha-examples_hmac-sha-512-02.json.cose ├── hkdf-hmac-sha-examples_hmac-sha-512-03.json.cose ├── hkdf-hmac-sha-examples_hmac-sha-512-04.json.cose ├── hkdf-hmac-sha-examples_hmac-sha-512-05.json.cose ├── hkdf-hmac-sha-examples_hmac-sha-512-06.json.cose ├── hkdf-hmac-sha-examples_hmac-sha-512-07.json.cose ├── hkdf-hmac-sha-examples_hmac-sha-512-08.json.cose ├── hkdf-hmac-sha-examples_hmac-sha-512-09.json.cose ├── hkdf-hmac-sha-examples_hmac-sha-512-10.json.cose ├── hkdf-hmac-sha-examples_hmac-sha-512-11.json.cose ├── hkdf-hmac-sha-examples_hmac-sha-512-12.json.cose ├── hkdf-hmac-sha-examples_hmac-sha-512-13.json.cose ├── hkdf-hmac-sha-examples_hmac-sha-512-14.json.cose ├── hmac-examples_HMac-01.json.cose ├── hmac-examples_HMac-02.json.cose ├── hmac-examples_HMac-03.json.cose ├── hmac-examples_HMac-04.json.cose ├── hmac-examples_HMac-05.json.cose ├── hmac-examples_HMac-enc-01.json.cose ├── hmac-examples_HMac-enc-02.json.cose ├── hmac-examples_HMac-enc-03.json.cose ├── hmac-examples_HMac-enc-04.json.cose ├── hmac-examples_HMac-enc-05.json.cose ├── mac-tests_HMac-01.json.cose ├── mac-tests_mac-fail-01.json.cose ├── mac-tests_mac-fail-02.json.cose ├── mac-tests_mac-fail-03.json.cose ├── mac-tests_mac-fail-04.json.cose ├── mac-tests_mac-fail-06.json.cose ├── mac-tests_mac-fail-07.json.cose ├── mac-tests_mac-pass-01.json.cose ├── mac-tests_mac-pass-02.json.cose ├── mac-tests_mac-pass-03.json.cose ├── mac0-tests_HMac-01.json.cose ├── mac0-tests_mac-fail-01.json.cose ├── mac0-tests_mac-fail-02.json.cose ├── mac0-tests_mac-fail-03.json.cose ├── mac0-tests_mac-fail-04.json.cose ├── mac0-tests_mac-fail-06.json.cose ├── mac0-tests_mac-fail-07.json.cose ├── mac0-tests_mac-pass-01.json.cose ├── mac0-tests_mac-pass-02.json.cose ├── mac0-tests_mac-pass-03.json.cose ├── sign-tests_ecdsa-01.json.cose ├── sign-tests_sign-fail-01.json.cose ├── sign-tests_sign-fail-02.json.cose ├── sign-tests_sign-fail-03.json.cose ├── sign-tests_sign-fail-04.json.cose ├── sign-tests_sign-fail-06.json.cose ├── sign-tests_sign-fail-07.json.cose ├── sign-tests_sign-pass-01.json.cose ├── sign-tests_sign-pass-02.json.cose ├── sign-tests_sign-pass-03.json.cose ├── sign1-tests_sign-fail-01.json.cose ├── sign1-tests_sign-fail-02.json.cose ├── sign1-tests_sign-fail-03.json.cose ├── sign1-tests_sign-fail-04.json.cose ├── sign1-tests_sign-fail-06.json.cose ├── sign1-tests_sign-fail-07.json.cose ├── sign1-tests_sign-pass-01.json.cose ├── sign1-tests_sign-pass-02.json.cose └── sign1-tests_sign-pass-03.json.cose ├── sign_verify.go ├── sign_verify_cose_rust_cli_test.go ├── sign_verify_cose_wg_examples_test.go └── sign_verify_test.go /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | "golang-1.14": 4 | docker: 5 | - image: circleci/golang:1.14 6 | working_directory: /go/src/go.mozilla.org/cose/ 7 | environment: 8 | - GO111MODULE: "on" # yaml sees an unquoted on value as "true" but go checks for "on" 9 | steps: 10 | - checkout 11 | - run: 12 | name: install rust and cargo 13 | command: | 14 | sudo apt-get install libnss3-dev 15 | curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain stable 16 | source $HOME/.cargo/env 17 | echo $PATH 18 | which cargo 19 | - run: 20 | name: print rust and cargo version information 21 | command: | 22 | source $HOME/.cargo/env 23 | rustc --version 24 | cargo --version 25 | - run: 26 | name: run tests 27 | command: | 28 | source $HOME/.cargo/env 29 | make ci 30 | "golang-1.15": 31 | docker: 32 | - image: circleci/golang:1.15 33 | working_directory: /go/src/go.mozilla.org/cose/ 34 | environment: 35 | - GO111MODULE: "on" # yaml sees an unquoted on value as "true" but go checks for "on" 36 | steps: 37 | - checkout 38 | - run: 39 | name: install rust and cargo 40 | command: | 41 | sudo apt-get install libnss3-dev 42 | curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain stable 43 | source $HOME/.cargo/env 44 | echo $PATH 45 | which cargo 46 | - run: 47 | name: print rust and cargo version information 48 | command: | 49 | source $HOME/.cargo/env 50 | rustc --version 51 | cargo --version 52 | - run: 53 | name: run tests 54 | command: | 55 | source $HOME/.cargo/env 56 | make ci 57 | "lint": 58 | docker: 59 | - image: circleci/golang:1.15 60 | working_directory: /go/src/go.mozilla.org/cose/ 61 | environment: 62 | - GO111MODULE: "on" # yaml sees an unquoted on value as "true" but go checks for "on" 63 | steps: 64 | - checkout 65 | - run: 66 | name: install golangci-lint 67 | command: | 68 | GO111MODULE=on go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.26.0 69 | - run: 70 | name: print debugging info about go env 71 | command: go env GOPATH 72 | - run: 73 | name: print debugging info about golangci-lint 74 | command: which golangci-lint 75 | - run: 76 | name: Run required linters in .golangci.yml plus hard-coded ones here 77 | command: $(go env GOPATH)/bin/golangci-lint run --timeout=3m 78 | - run: 79 | name: Run optional linters (not required to pass) 80 | command : $(go env GOPATH)/bin/golangci-lint run --timeout=3m --issues-exit-code=0 -E dupl -E gocritic -E gosimple -E lll -E prealloc 81 | 82 | workflows: 83 | version: 2 84 | build: 85 | jobs: 86 | - "lint" 87 | - "golang-1.14" 88 | - "golang-1.15" 89 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.dll 4 | *.so 5 | *.dylib 6 | 7 | # Test binary, build with `go test -c` 8 | *.test 9 | 10 | # Output of the go coverage tool, specifically when used with LiteIDE 11 | *.out 12 | 13 | # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 14 | .glide/ 15 | 16 | # test deps 17 | test/cose-rust/ 18 | test/cose-wg-examples/ 19 | 20 | # go deps 21 | vendor/ 22 | 23 | # OSX fs files 24 | .DS_Store 25 | /cose-fuzz.zip 26 | /workdir/ 27 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | # Do not delete linter settings. Linters like gocritic can be enabled on the command line. 2 | 3 | linters-settings: 4 | dupl: 5 | threshold: 100 6 | funlen: 7 | lines: 100 8 | statements: 50 9 | goconst: 10 | min-len: 2 11 | min-occurrences: 3 12 | gocritic: 13 | enabled-tags: 14 | - diagnostic 15 | - experimental 16 | - opinionated 17 | - performance 18 | - style 19 | disabled-checks: 20 | - dupImport # https://github.com/go-critic/go-critic/issues/845 21 | - ifElseChain 22 | - octalLiteral 23 | - paramTypeCombine 24 | - whyNoLint 25 | - wrapperFunc 26 | gofmt: 27 | simplify: false 28 | goimports: 29 | local-prefixes: github.com/fxamacker/cbor 30 | golint: 31 | min-confidence: 0 32 | govet: 33 | check-shadowing: true 34 | lll: 35 | line-length: 140 36 | maligned: 37 | suggest-new: true 38 | misspell: 39 | locale: US 40 | 41 | linters: 42 | disable-all: true 43 | enable: 44 | - deadcode 45 | - errcheck 46 | - goconst 47 | - gocyclo 48 | - gofmt 49 | - goimports 50 | - golint 51 | - gosec 52 | - govet 53 | - ineffassign 54 | - maligned 55 | - misspell 56 | - staticcheck 57 | - structcheck 58 | - typecheck 59 | - unconvert 60 | - unused 61 | - varcheck 62 | 63 | 64 | issues: 65 | # max-issues-per-linter default is 50. Set to 0 to disable limit. 66 | max-issues-per-linter: 0 67 | # max-same-issues default is 3. Set to 0 to disable limit. 68 | max-same-issues: 0 69 | # Excluding configuration per-path, per-linter, per-text and per-source 70 | exclude-rules: 71 | - path: _test\.go 72 | linters: 73 | - goconst 74 | - dupl 75 | - gomnd 76 | - lll 77 | - path: doc\.go 78 | linters: 79 | - goimports 80 | - gomnd 81 | - lll 82 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Community Participation Guidelines 2 | 3 | This repository is governed by Mozilla's code of conduct and etiquette guidelines. 4 | For more details, please read the 5 | [Mozilla Community Participation Guidelines](https://www.mozilla.org/about/governance/policies/participation/). 6 | 7 | ## How to Report 8 | For more information on how to report violations of the Community Participation Guidelines, please read our '[How to Report](https://www.mozilla.org/about/governance/policies/participation/reporting/)' page. 9 | 10 | 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. 374 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | install: 3 | # dev requirements 4 | go get -u github.com/stretchr/testify/assert 5 | 6 | mkdir -p test 7 | cd test && git clone https://github.com/cose-wg/Examples.git cose-wg-examples || true 8 | cd test && git clone https://github.com/g-k/cose-rust.git || true 9 | cd test/cose-rust && git checkout test-verify-cli 10 | 11 | 12 | install-go-fuzz: 13 | # dev requirement 14 | go get -u github.com/dvyukov/go-fuzz/... 15 | 16 | # sample generated with: 17 | # for file in $(find . -name *.json); do jq '.output.cbor' < $file | tr -d \" | base64 --decode > $(echo $file | sed s/..// | tr '/' '_').cose; done 18 | fuzz: install-go-fuzz 19 | mkdir -p workdir/corpus 20 | cp samples/*.cose workdir/corpus 21 | go-fuzz-build go.mozilla.org/cose 22 | go-fuzz -bin=./cose-fuzz.zip -workdir=workdir 23 | 24 | lint: 25 | golint 26 | 27 | vet: 28 | go vet 29 | 30 | coverage: 31 | go test -v -cover -race -coverprofile=coverage.out && go tool cover -html=coverage.out 32 | 33 | what-todo: 34 | rg -g '**/*.go' -i TODO 35 | 36 | install-golint: 37 | go get -u golang.org/x/lint/golint 38 | 39 | goveralls: 40 | go get -u github.com/mattn/goveralls 41 | 42 | smoketest-examples: 43 | go run example/sign.go 44 | go run example/verify.go 45 | 46 | ci: install-golint goveralls install coverage lint vet 47 | goveralls -coverprofile=coverage.out -service=circle-ci -repotoken=$(COVERALLS_TOKEN) 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # go-cose 2 | 3 | [![CircleCI](https://circleci.com/gh/mozilla-services/go-cose.svg?style=svg)](https://circleci.com/gh/mozilla-services/go-cose) 4 | [![Coverage Status](https://coveralls.io/repos/github/mozilla-services/go-cose/badge.svg)](https://coveralls.io/github/mozilla-services/go-cose) 5 | 6 | ## Caution 7 | > :warning: Please note that the repository is no longer actively maintained. No further development of any go-cose features will take place here. Please use [veraison-go-cose](https://github.com/veraison/go-cose) if you need go-cose library for your project or wish to participate in go-cose development. 8 | 9 | ## DANGER 10 | > :biohazard: This repository does not properly verify certain COSE signatures. While this does not affect Mozilla's internal use of the code, others are advised to use the [veraison-go-cose](https://github.com/veraison/go-cose) implementation. 11 | 12 | ---- 13 | A [COSE](https://tools.ietf.org/html/rfc8152) library for go. 14 | 15 | It currently supports signing and verifying the SignMessage type with the ES{256,384,512} and PS256 algorithms. 16 | 17 | [API docs](https://godoc.org/go.mozilla.org/cose) 18 | 19 | ## Usage 20 | 21 | ### Install 22 | 23 | ```console 24 | go get -u go.mozilla.org/cose 25 | ``` 26 | 27 | ### Signing a message 28 | 29 | See [example/sign.go](example/sign.go) and run it with: 30 | 31 | ```console 32 | $ go run example/sign.go 33 | Bit lengths of integers r and s (256 and 256) do not match the key length 255 34 | Message signature (ES256): 043685f99421f9e80c7c3c50d0fc8266161d3d614aaa3b63d2cdf581713fca62bb5d2e34d2352dbe41424b31d0b4a11d6b2d4764c18e2af04f4520fbe494d51c 35 | ``` 36 | 37 | ### Verifying a message 38 | 39 | See [example/verify.go](example/verify.go) and run it with: 40 | 41 | ```console 42 | $ go run example/verify.go 43 | Bit lengths of integers r and s (256 and 254) do not match the key length 254 44 | Message signature (ES256): 9411dc5200c1cb67ccd76424ade09ce89c4a8d8d2b66f2bbf70edf63beb2dc3cbde83250773e659b635d3715442a1efaa6b0c030ee8a2523c3e37a22ddb055fa 45 | Message signature verified 46 | ``` 47 | 48 | ## Development 49 | 50 | Running tests: 51 | 52 | 1. Install [rust and cargo](https://www.rustup.rs/) 53 | 54 | 1. On OSX: `brew install nss` [nss](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS) then in `sign_verify_cose_rust_cli_test.go` add `NSS_LIB_DIR` to `cmd` or `-L /usr/local/opt/nss/lib` to RUSTFLAGS e.g. `cmd.Env = append(os.Environ(), "NSS_LIB_DIR=/usr/local/opt/nss/lib", "RUSTFLAGS=-A dead_code -A unused_imports")` 55 | 56 | 1. If you already have `dep` and `golint` commands installed, run `make install-godep install-golint` 57 | 58 | 1. Run `go test` 59 | -------------------------------------------------------------------------------- /algorithms.go: -------------------------------------------------------------------------------- 1 | // COSE Algorithms 2 | // 3 | 4 | package cose 5 | 6 | import ( 7 | "crypto" 8 | "crypto/elliptic" 9 | ) 10 | 11 | // KeyType is the type to use in keyOptions to tell MakeDEREndEntity 12 | // which type of crypto.PrivateKey to generate 13 | type KeyType int 14 | const ( 15 | // KeyTypeUnsupported is the type to not generate a key 16 | KeyTypeUnsupported KeyType = iota 17 | 18 | // KeyTypeRSA is the type to generate an rsa.PrivateKey 19 | KeyTypeRSA KeyType = iota 20 | 21 | // KeyTypeECDSA is the type to generate an ecdsa.PrivateKey 22 | KeyTypeECDSA KeyType = iota 23 | ) 24 | 25 | // Algorithm represents an IANA algorithm's parameters (Name, 26 | // Value/ID, and optional extra data) 27 | // 28 | // From the spec: 29 | // 30 | // NOTE: The assignment of algorithm identifiers in this document was 31 | // done so that positive numbers were used for the first layer objects 32 | // (COSE_Sign, COSE_Sign1, COSE_Encrypt, COSE_Encrypt0, COSE_Mac, and 33 | // COSE_Mac0). Negative numbers were used for second layer objects 34 | // (COSE_Signature and COSE_recipient). 35 | // 36 | // https://www.iana.org/assignments/cose/cose.xhtml#header-algorithm-parameters 37 | // 38 | // https://tools.ietf.org/html/rfc8152#section-16.4 39 | // 40 | type Algorithm struct { 41 | Name string 42 | Value int 43 | 44 | // optional fields 45 | HashFunc crypto.Hash // hash function for SignMessages 46 | privateKeyType KeyType // private key type to generate for new Signers 47 | 48 | minRSAKeyBitLen int // minimimum RSA key size to generate in bits 49 | 50 | privateKeyECDSACurve elliptic.Curve // ecdsa private key curve type 51 | } 52 | 53 | // algorithms is an array/slice of IANA algorithms 54 | var algorithms = []Algorithm{ 55 | Algorithm{ 56 | Name: "RSAES-OAEP w/ SHA-512", // RSAES-OAEP w/ SHA-512 from [RFC8230] 57 | Value: -42, 58 | }, 59 | Algorithm{ 60 | Name: "RSAES-OAEP w/ SHA-256", // RSAES-OAEP w/ SHA-256 from [RFC8230] 61 | Value: -41, 62 | }, 63 | Algorithm{ 64 | Name: "RSAES-OAEP w/ RFC 8017 default parameters", // RSAES-OAEP w/ SHA-1 from [RFC8230] 65 | Value: -40, 66 | }, 67 | Algorithm{ 68 | Name: "PS512", // RSASSA-PSS w/ SHA-512 from [RFC8230] 69 | Value: -39, 70 | }, 71 | Algorithm{ 72 | Name: "PS384", // RSASSA-PSS w/ SHA-384 from [RFC8230] 73 | Value: -38, 74 | }, 75 | Algorithm{ 76 | Name: "PS256", // RSASSA-PSS w/ SHA-256 from [RFC8230] 77 | Value: -37, 78 | HashFunc: crypto.SHA256, 79 | privateKeyType: KeyTypeRSA, 80 | minRSAKeyBitLen: 2048, 81 | }, 82 | Algorithm{ 83 | Name: "ES512", // ECDSA w/ SHA-512 from [RFC8152] 84 | Value: -36, 85 | HashFunc: crypto.SHA512, 86 | privateKeyType: KeyTypeECDSA, 87 | privateKeyECDSACurve: elliptic.P521(), 88 | }, 89 | Algorithm{ 90 | Name: "ES384", // ECDSA w/ SHA-384 from [RFC8152] 91 | Value: -35, 92 | HashFunc: crypto.SHA384, 93 | privateKeyType: KeyTypeECDSA, 94 | privateKeyECDSACurve: elliptic.P384(), 95 | }, 96 | Algorithm{ 97 | Name: "ECDH-SS + A256KW", // ECDH SS w/ Concat KDF and AES Key Wrap w/ 256-bit key from [RFC8152] 98 | Value: -34, 99 | }, 100 | Algorithm{ 101 | Name: "ECDH-SS + A192KW", // ECDH SS w/ Concat KDF and AES Key Wrap w/ 192-bit key from [RFC8152] 102 | Value: -33, 103 | }, 104 | Algorithm{ 105 | Name: "ECDH-SS + A128KW", // ECDH SS w/ Concat KDF and AES Key Wrap w/ 128-bit key from [RFC8152] 106 | Value: -32, 107 | }, 108 | Algorithm{ 109 | Name: "ECDH-ES + A256KW", // ECDH ES w/ Concat KDF and AES Key Wrap w/ 256-bit key from [RFC8152] 110 | Value: -31, 111 | }, 112 | Algorithm{ 113 | Name: "ECDH-ES + A192KW", // ECDH ES w/ Concat KDF and AES Key Wrap w/ 192-bit key from [RFC8152] 114 | Value: -30, 115 | }, 116 | Algorithm{ 117 | Name: "ECDH-ES + A128KW", // ECDH ES w/ Concat KDF and AES Key Wrap w/ 128-bit key from [RFC8152] 118 | Value: -29, 119 | }, 120 | Algorithm{ 121 | Name: "ECDH-SS + HKDF-512", // ECDH SS w/ HKDF - generate key directly from [RFC8152] 122 | Value: -28, 123 | }, 124 | Algorithm{ 125 | Name: "ECDH-SS + HKDF-256", // ECDH SS w/ HKDF - generate key directly from [RFC8152] 126 | Value: -27, 127 | }, 128 | Algorithm{ 129 | Name: "ECDH-ES + HKDF-512", // ECDH ES w/ HKDF - generate key directly from [RFC8152] 130 | Value: -26, 131 | }, 132 | Algorithm{ 133 | Name: "ECDH-ES + HKDF-256", // ECDH ES w/ HKDF - generate key directly from [RFC8152] 134 | Value: -25, 135 | }, 136 | Algorithm{ 137 | Name: "direct+HKDF-AES-256", // Shared secret w/ AES-MAC 256-bit key from [RFC8152] 138 | Value: -13, 139 | }, 140 | Algorithm{ 141 | Name: "direct+HKDF-AES-128", // Shared secret w/ AES-MAC 128-bit key from [RFC8152] 142 | Value: -12, 143 | }, 144 | Algorithm{ 145 | Name: "direct+HKDF-SHA-512", // Shared secret w/ HKDF and SHA-512 from [RFC8152] 146 | Value: -11, 147 | }, 148 | Algorithm{ 149 | Name: "direct+HKDF-SHA-256", // Shared secret w/ HKDF and SHA-256 from [RFC8152] 150 | Value: -10, 151 | }, 152 | Algorithm{ 153 | Name: "EdDSA", // EdDSA from [RFC8152] 154 | Value: -8, 155 | }, 156 | Algorithm{ 157 | Name: "ES256", // ECDSA w/ SHA-256 from [RFC8152] 158 | Value: -7, 159 | HashFunc: crypto.SHA256, 160 | privateKeyType: KeyTypeECDSA, 161 | privateKeyECDSACurve: elliptic.P256(), 162 | }, 163 | Algorithm{ 164 | Name: "direct", // Direct use of CEK from [RFC8152] 165 | Value: -6, 166 | }, 167 | Algorithm{ 168 | Name: "A256KW", // AES Key Wrap w/ 256-bit key from [RFC8152] 169 | Value: -5, 170 | }, 171 | Algorithm{ 172 | Name: "A192KW", // AES Key Wrap w/ 192-bit key from [RFC8152] 173 | Value: -4, 174 | }, 175 | Algorithm{ 176 | Name: "A128KW", // AES Key Wrap w/ 128-bit key from [RFC8152] 177 | Value: -3, 178 | }, 179 | Algorithm{ 180 | Name: "A128GCM", // AES-GCM mode w/ 128-bit key, 128-bit tag from [RFC8152] 181 | Value: 1, 182 | }, 183 | Algorithm{ 184 | Name: "A192GCM", // AES-GCM mode w/ 192-bit key, 128-bit tag from [RFC8152] 185 | Value: 2, 186 | }, 187 | Algorithm{ 188 | Name: "A256GCM", // AES-GCM mode w/ 256-bit key, 128-bit tag from [RFC8152] 189 | Value: 3, 190 | }, 191 | Algorithm{ 192 | Name: "HMAC 256/64", // HMAC w/ SHA-256 truncated to 64 bits from [RFC8152] 193 | Value: 4, 194 | }, 195 | Algorithm{ 196 | Name: "HMAC 256/256", // HMAC w/ SHA-256 from [RFC8152] 197 | Value: 5, 198 | }, 199 | Algorithm{ 200 | Name: "HMAC 384/384", // HMAC w/ SHA-384 from [RFC8152] 201 | Value: 6, 202 | }, 203 | Algorithm{ 204 | Name: "HMAC 512/512", // HMAC w/ SHA-512 from [RFC8152] 205 | Value: 7, 206 | }, 207 | Algorithm{ 208 | Name: "AES-CCM-16-64-128", // AES-CCM mode 128-bit key, 64-bit tag, 13-byte nonce from [RFC8152] 209 | Value: 10, 210 | }, 211 | Algorithm{ 212 | Name: "AES-CCM-16-64-256", // AES-CCM mode 256-bit key, 64-bit tag, 13-byte nonce from [RFC8152] 213 | Value: 11, 214 | }, 215 | Algorithm{ 216 | Name: "AES-CCM-64-64-128", // AES-CCM mode 128-bit key, 64-bit tag, 7-byte nonce from [RFC8152] 217 | Value: 12, 218 | }, 219 | Algorithm{ 220 | Name: "AES-CCM-64-64-256", // AES-CCM mode 256-bit key, 64-bit tag, 7-byte nonce from [RFC8152] 221 | Value: 13, 222 | }, 223 | Algorithm{ 224 | Name: "AES-MAC 128/64", // AES-MAC 128-bit key, 64-bit tag from [RFC8152] 225 | Value: 14, 226 | }, 227 | Algorithm{ 228 | Name: "AES-MAC 256/64", // AES-MAC 256-bit key, 64-bit tag from [RFC8152] 229 | Value: 15, 230 | }, 231 | Algorithm{ 232 | Name: "ChaCha20/Poly1305", // ChaCha20/Poly1305 w/ 256-bit key, 128-bit tag from [RFC8152] 233 | Value: 24, 234 | }, 235 | Algorithm{ 236 | Name: "AES-MAC 128/128", // AES-MAC 128-bit key, 128-bit tag from [RFC8152] 237 | Value: 25, 238 | }, 239 | Algorithm{ 240 | Name: "AES-MAC 256/128", // AES-MAC 256-bit key, 128-bit tag from [RFC8152] 241 | Value: 26, 242 | }, 243 | Algorithm{ 244 | Name: "AES-CCM-16-128-128", // AES-CCM mode 128-bit key, 128-bit tag, 13-byte nonce from [RFC8152] 245 | Value: 30, 246 | }, 247 | Algorithm{ 248 | Name: "AES-CCM-16-128-256", // AES-CCM mode 256-bit key, 128-bit tag, 13-byte nonce from [RFC8152] 249 | Value: 31, 250 | }, 251 | Algorithm{ 252 | Name: "AES-CCM-64-128-128", // AES-CCM mode 128-bit key, 128-bit tag, 7-byte nonce from [RFC8152] 253 | Value: 32, 254 | }, 255 | Algorithm{ 256 | Name: "AES-CCM-64-128-256", // AES-CCM mode 256-bit key, 128-bit tag, 7-byte nonce from [RFC8152] 257 | Value: 33, 258 | }, 259 | } 260 | -------------------------------------------------------------------------------- /cbor.go: -------------------------------------------------------------------------------- 1 | package cose 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "reflect" 7 | 8 | "github.com/fxamacker/cbor/v2" 9 | "github.com/pkg/errors" 10 | ) 11 | 12 | // SignMessageCBORTag is the CBOR tag for a COSE SignMessage 13 | // from https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml#tags 14 | const SignMessageCBORTag = 98 15 | 16 | var signMessagePrefix = []byte{ 17 | // 0b110_11000 major type 6 (tag) with additional information 18 | // length 24 bits / 3 bytes (since tags are always uints) 19 | // 20 | // per https://tools.ietf.org/html/rfc7049#section-2.4 21 | '\xd8', 22 | 23 | // uint8_t with the tag value 24 | SignMessageCBORTag, 25 | 26 | // 0b100_00100 major type 4 (array) with additional 27 | // information 4 for a 4-item array representing a COSE_Sign 28 | // message 29 | '\x84', 30 | } 31 | 32 | // IsSignMessage checks whether the prefix is 0xd8 0x62 for a COSE 33 | // SignMessage 34 | func IsSignMessage(data []byte) bool { 35 | return bytes.HasPrefix(data, signMessagePrefix) 36 | } 37 | 38 | // Readonly CBOR encoding and decoding modes. 39 | var ( 40 | encMode, encModeError = initCBOREncMode() 41 | decMode, decModeError = initCBORDecMode() 42 | ) 43 | 44 | func initCBOREncMode() (en cbor.EncMode, err error) { 45 | encOpt := cbor.EncOptions{ 46 | IndefLength: cbor.IndefLengthForbidden, // no streaming 47 | Sort: cbor.SortCanonical, // sort map keys 48 | } 49 | return encOpt.EncMode() 50 | } 51 | 52 | func initCBORDecMode() (dm cbor.DecMode, err error) { 53 | // Create a tag with SignMessage and tag number 98. 54 | // When decoding CBOR data with tag number 98 to interface{}, cbor library returns SignMessage. 55 | tags := cbor.NewTagSet() 56 | err = tags.Add( 57 | cbor.TagOptions{EncTag: cbor.EncTagRequired, DecTag: cbor.DecTagRequired}, 58 | reflect.TypeOf(SignMessage{}), 59 | SignMessageCBORTag, 60 | ) 61 | if err != nil { 62 | return nil, err 63 | } 64 | 65 | decOpt := cbor.DecOptions{ 66 | IndefLength: cbor.IndefLengthForbidden, // no streaming 67 | IntDec: cbor.IntDecConvertSigned, // decode CBOR uint/int to Go int64 68 | } 69 | return decOpt.DecModeWithTags(tags) 70 | } 71 | 72 | func init() { 73 | if encModeError != nil { 74 | panic(encModeError) 75 | } 76 | if decModeError != nil { 77 | panic(decModeError) 78 | } 79 | } 80 | 81 | // Marshal returns the CBOR []byte encoding of param o 82 | func Marshal(o interface{}) (b []byte, err error) { 83 | defer func() { 84 | // Need to recover from panic because Headers.EncodeUnprotected() 85 | // and Headers.EncodeProtected() can panic. 86 | if r := recover(); r != nil { 87 | b = nil 88 | switch x := r.(type) { 89 | case error: 90 | err = fmt.Errorf("cbor: %s", x.Error()) 91 | default: 92 | err = fmt.Errorf("cbor: %v", x) 93 | } 94 | } 95 | }() 96 | 97 | return encMode.Marshal(o) 98 | } 99 | 100 | // Unmarshal returns the CBOR decoding of a []byte into param o 101 | func Unmarshal(b []byte) (o interface{}, err error) { 102 | err = decMode.Unmarshal(b, &o) 103 | return o, err 104 | } 105 | 106 | type signature struct { 107 | _ struct{} `cbor:",toarray"` 108 | Protected []byte 109 | Unprotected map[interface{}]interface{} 110 | SignatureBytes []byte 111 | } 112 | 113 | type signMessage struct { 114 | _ struct{} `cbor:",toarray"` 115 | Protected []byte 116 | Unprotected map[interface{}]interface{} 117 | Payload []byte 118 | Signatures []signature 119 | } 120 | 121 | // MarshalCBOR encodes SignMessage. 122 | func (message *SignMessage) MarshalCBOR() ([]byte, error) { 123 | // Verify SignMessage headers. 124 | if message.Headers == nil { 125 | return nil, errors.New("cbor: SignMessage has nil Headers") 126 | } 127 | dup := FindDuplicateHeader(message.Headers) 128 | if dup != nil { 129 | return nil, fmt.Errorf("cbor: Duplicate header %+v found", dup) 130 | } 131 | 132 | // Convert Signature to signature. 133 | sigs := make([]signature, len(message.Signatures)) 134 | for i, s := range message.Signatures { 135 | dup := FindDuplicateHeader(s.Headers) 136 | if dup != nil { 137 | return nil, fmt.Errorf("cbor: Duplicate signature header %+v found", dup) 138 | } 139 | 140 | sigs[i] = signature{ 141 | Protected: s.Headers.EncodeProtected(), 142 | Unprotected: s.Headers.EncodeUnprotected(), 143 | SignatureBytes: s.SignatureBytes, 144 | } 145 | } 146 | 147 | // Convert SignMessage to signMessage. 148 | m := signMessage{ 149 | Protected: message.Headers.EncodeProtected(), 150 | Unprotected: message.Headers.EncodeUnprotected(), 151 | Payload: message.Payload, 152 | Signatures: sigs, 153 | } 154 | 155 | // Marshal signMessage with tag number 98. 156 | return encMode.Marshal(cbor.Tag{Number: SignMessageCBORTag, Content: m}) 157 | } 158 | 159 | // UnmarshalCBOR decodes data into SignMessage. 160 | // 161 | // Unpacks a SignMessage described by CDDL fragments: 162 | // 163 | // COSE_Sign = [ 164 | // Headers, 165 | // payload : bstr / nil, 166 | // signatures : [+ COSE_Signature] 167 | // ] 168 | // 169 | // COSE_Signature = [ 170 | // Headers, 171 | // signature : bstr 172 | // ] 173 | // 174 | // Headers = ( 175 | // protected : empty_or_serialized_map, 176 | // unprotected : header_map 177 | // ) 178 | // 179 | // header_map = { 180 | // Generic_Headers, 181 | // * label => values 182 | // } 183 | // 184 | // empty_or_serialized_map = bstr .cbor header_map / bstr .size 0 185 | // 186 | // Generic_Headers = ( 187 | // ? 1 => int / tstr, ; algorithm identifier 188 | // ? 2 => [+label], ; criticality 189 | // ? 3 => tstr / int, ; content type 190 | // ? 4 => bstr, ; key identifier 191 | // ? 5 => bstr, ; IV 192 | // ? 6 => bstr, ; Partial IV 193 | // ? 7 => COSE_Signature / [+COSE_Signature] ; Counter signature 194 | // ) 195 | // 196 | func (message *SignMessage) UnmarshalCBOR(data []byte) (err error) { 197 | if message == nil { 198 | return errors.New("cbor: UnmarshalCBOR on nil SignMessage pointer") 199 | } 200 | 201 | // Decode to cbor.RawTag to extract tag number and tag content as []byte. 202 | var raw cbor.RawTag 203 | err = decMode.Unmarshal(data, &raw) 204 | if err != nil { 205 | return err 206 | } 207 | 208 | // Verify tag number. 209 | if raw.Number != SignMessageCBORTag { 210 | return fmt.Errorf("cbor: wrong tag number %d", raw.Number) 211 | } 212 | 213 | // Decode tag content to signMessage. 214 | var m signMessage 215 | err = decMode.Unmarshal(raw.Content, &m) 216 | if err != nil { 217 | return err 218 | } 219 | 220 | // Create Headers from signMessage. 221 | msgHeaders := &Headers{} 222 | err = msgHeaders.Decode([]interface{}{m.Protected, m.Unprotected}) 223 | if err != nil { 224 | return fmt.Errorf("cbor: %s", err.Error()) 225 | } 226 | 227 | // Create Signature from signMessage. 228 | var sigs []Signature 229 | for _, s := range m.Signatures { 230 | sh := &Headers{} 231 | err = sh.Decode([]interface{}{s.Protected, s.Unprotected}) 232 | if err != nil { 233 | return fmt.Errorf("cbor: %s", err.Error()) 234 | } 235 | 236 | sigs = append(sigs, Signature{ 237 | Headers: sh, 238 | SignatureBytes: s.SignatureBytes, 239 | }) 240 | } 241 | 242 | *message = SignMessage{ 243 | Headers: msgHeaders, 244 | Payload: m.Payload, 245 | Signatures: sigs, 246 | } 247 | return nil 248 | } 249 | -------------------------------------------------------------------------------- /cbor_test.go: -------------------------------------------------------------------------------- 1 | package cose 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | 7 | "github.com/fxamacker/cbor/v2" 8 | "github.com/stretchr/testify/assert" 9 | 10 | "testing" 11 | ) 12 | 13 | // Tests for encoding and decoding go-cose objects to and from CBOR 14 | 15 | type CBORTestCase struct { 16 | name string 17 | obj interface{} 18 | bytes []byte 19 | } 20 | 21 | var CBORTestCases = []CBORTestCase{ 22 | // golang data structures 23 | { 24 | "empty bstr", 25 | []byte(""), 26 | []byte("\x40"), // bytes(0) i.e. "" 27 | }, 28 | { 29 | "generic interface map", 30 | map[interface{}]interface{}{1: -7}, 31 | []byte("\xA1\x01\x26"), 32 | }, 33 | 34 | // SignMessage Headers 35 | { 36 | "sign message with empty headers", 37 | SignMessage{ 38 | Headers: &Headers{ 39 | Protected: map[interface{}]interface{}{}, 40 | Unprotected: map[interface{}]interface{}{}, 41 | }, 42 | Payload: nil, 43 | Signatures: nil, 44 | }, 45 | // D8 62 # tag(98) COSE SignMessage tag 46 | // 84 # array(4) 47 | // 40 # bytes(0) empty protected headers 48 | // # "" 49 | // A0 # map(0) empty unprotectd headers 50 | // F6 # primitive(22) nil / null payload 51 | // 80 # array(0) no signatures 52 | []byte("\xd8\x62\x84\x40\xa0\xf6\x80"), 53 | }, 54 | { 55 | "sign message with alg in protected header", 56 | SignMessage{ 57 | Headers: &Headers{ 58 | Protected: map[interface{}]interface{}{"alg": "ES256"}, 59 | Unprotected: map[interface{}]interface{}{}, 60 | }, 61 | Payload: nil, 62 | Signatures: nil, 63 | }, 64 | // D8 62 # tag(98) COSE SignMessage tag 65 | // 84 # array(4) 66 | // 43 # bytes(3) bstr protected header 67 | // A10126 # "\xA1\x01&" 68 | // A0 # map(0) empty unprotected headers 69 | // F6 # primitive(22) nil / null payload 70 | // 80 # array(0) no signatures 71 | // 72 | // where bstr h'A10126' is: 73 | // A1 # map(1) 74 | // 01 # unsigned(1) common header ID for alg 75 | // 26 # negative(7) ES256 alg ID 76 | []byte("\xd8\x62\x84\x43\xa1\x01\x26\xa0\xf6\x80"), 77 | }, 78 | { 79 | "sign message with alg in unprotected header", 80 | SignMessage{ 81 | Headers: &Headers{ 82 | Protected: map[interface{}]interface{}{}, 83 | Unprotected: map[interface{}]interface{}{"alg": "ES256"}, 84 | }, 85 | Payload: nil, 86 | Signatures: nil, 87 | }, 88 | // D8 62 # tag(98) COSE SignMessage tag 89 | // 84 # array(4) 90 | // 40 # bytes(0) empty protected headers 91 | // # "" 92 | // A1 # map(1) unprotected headers 93 | // 01 # unsigned(1) common header ID for alg 94 | // 26 # negative(7) ES256 alg ID 95 | // F6 # primitive(22) nil / null payload 96 | // 80 # array(0) no signatures 97 | []byte("\xd8\x62\x84\x40\xa1\x01\x26\xf6\x80"), 98 | }, 99 | } 100 | 101 | func MarshalsToExpectedBytes(t *testing.T, testCase CBORTestCase) { 102 | assert := assert.New(t) 103 | 104 | bytes, err := Marshal(testCase.obj) 105 | assert.Nil(err) 106 | 107 | assert.Equal(testCase.bytes, bytes) 108 | } 109 | 110 | func UnmarshalsWithoutErr(t *testing.T, testCase CBORTestCase) { 111 | assert := assert.New(t) 112 | 113 | _, err := Unmarshal(testCase.bytes) 114 | assert.Nil(err) 115 | } 116 | 117 | func RoundtripsToExpectedBytes(t *testing.T, testCase CBORTestCase) { 118 | assert := assert.New(t) 119 | 120 | obj, err := Unmarshal(testCase.bytes) 121 | assert.Nil(err) 122 | 123 | bytes, err := Marshal(obj) 124 | assert.Nil(err) 125 | 126 | assert.Equal(testCase.bytes, bytes) 127 | } 128 | 129 | func TestCBOREncoding(t *testing.T) { 130 | for _, testCase := range CBORTestCases { 131 | t.Run(fmt.Sprintf("%s: MarshalsToExpectedBytes", testCase.name), func(t *testing.T) { 132 | MarshalsToExpectedBytes(t, testCase) 133 | }) 134 | 135 | t.Run(fmt.Sprintf("%s: UnmarshalsToExpectedInterface", testCase.name), func(t *testing.T) { 136 | UnmarshalsWithoutErr(t, testCase) 137 | }) 138 | 139 | t.Run(fmt.Sprintf("%s: RoundtripsToExpectedBytes", testCase.name), func(t *testing.T) { 140 | RoundtripsToExpectedBytes(t, testCase) 141 | }) 142 | } 143 | } 144 | 145 | func TestCBORMarshalSignMessageWithNilHeadersErrors(t *testing.T) { 146 | assert := assert.New(t) 147 | 148 | msg := NewSignMessage() 149 | msg.Payload = nil 150 | msg.Headers = nil 151 | _, err := Marshal(msg) 152 | assert.Equal("cbor: SignMessage has nil Headers", err.Error()) 153 | } 154 | 155 | func TestCBORMarshalDuplicateKeysErrs(t *testing.T) { 156 | assert := assert.New(t) 157 | 158 | // NB: golang does not allow duplicate keys in a map literal 159 | // so we don't test Marshalling duplicate entries both in 160 | // Protected or Unprotected 161 | 162 | // uncompressed one in each 163 | msg := NewSignMessage() 164 | msg.Payload = nil 165 | msg.Headers = &Headers{ 166 | Protected: map[interface{}]interface{}{ 167 | "alg": "ES256", 168 | }, 169 | Unprotected: map[interface{}]interface{}{ 170 | "alg": "PS256", 171 | }, 172 | } 173 | _, err := Marshal(msg) 174 | assert.Equal(errors.New("cbor: Duplicate header 1 found"), err) 175 | 176 | // compressed one in each 177 | msg.Headers = &Headers{ 178 | Protected: map[interface{}]interface{}{ 179 | 1: -7, 180 | }, 181 | Unprotected: map[interface{}]interface{}{ 182 | 1: -37, 183 | }, 184 | } 185 | _, err = Marshal(msg) 186 | assert.Equal(errors.New("cbor: Duplicate header 1 found"), err) 187 | 188 | // compressed and uncompressed both in Protected 189 | msg.Headers = &Headers{ 190 | Protected: map[interface{}]interface{}{ 191 | "alg": "ES256", 192 | 1: -37, 193 | }, 194 | Unprotected: map[interface{}]interface{}{}, 195 | } 196 | _, err = Marshal(msg) 197 | assert.Equal(errors.New("cbor: Duplicate compressed and uncompressed common header 1 found in headers"), err) 198 | 199 | // compressed and uncompressed both in Unprotected 200 | msg.Headers = &Headers{ 201 | Protected: map[interface{}]interface{}{}, 202 | Unprotected: map[interface{}]interface{}{ 203 | "alg": "ES256", 204 | 1: -37, 205 | }, 206 | } 207 | _, err = Marshal(msg) 208 | assert.Equal(errors.New("cbor: Duplicate compressed and uncompressed common header 1 found in headers"), err) 209 | 210 | // compressed and uncompressed one in each 211 | msg.Headers = &Headers{ 212 | Protected: map[interface{}]interface{}{ 213 | "alg": "ES256", 214 | }, 215 | Unprotected: map[interface{}]interface{}{ 216 | 1: -37, 217 | }, 218 | } 219 | _, err = Marshal(msg) 220 | assert.Equal(errors.New("cbor: Duplicate header 1 found"), err) 221 | 222 | msg.Headers = &Headers{ 223 | Protected: map[interface{}]interface{}{ 224 | 1: -37, 225 | }, 226 | Unprotected: map[interface{}]interface{}{ 227 | "alg": "ES256", 228 | }, 229 | } 230 | _, err = Marshal(msg) 231 | assert.Equal(errors.New("cbor: Duplicate header 1 found"), err) 232 | 233 | // duplicate headers in a SignMessage Signature 234 | msg.Headers = &Headers{ 235 | Protected: map[interface{}]interface{}{}, 236 | Unprotected: map[interface{}]interface{}{}, 237 | } 238 | msg.AddSignature(&Signature{ 239 | Headers: &Headers{ 240 | Protected: map[interface{}]interface{}{ 241 | 1: -37, 242 | }, 243 | Unprotected: map[interface{}]interface{}{ 244 | "alg": "ES256", 245 | }, 246 | }, 247 | SignatureBytes: []byte(""), 248 | }) 249 | _, err = Marshal(msg) 250 | assert.Equal("cbor: Duplicate signature header 1 found", err.Error()) 251 | } 252 | 253 | func TestCBORDecodeNilSignMessagePayload(t *testing.T) { 254 | assert := assert.New(t) 255 | 256 | msg := NewSignMessage() 257 | msg.Payload = nil 258 | 259 | // tag(98) + array(4) [ bytes(0), map(0), nil/null, array(0) ] 260 | b := HexToBytesOrDie("D862" + "84" + "40" + "A0" + "F6" + "80") 261 | 262 | result, err := Unmarshal(b) 263 | assert.Nil(err) 264 | assert.Equal(result, *msg) 265 | 266 | bytes, err := Marshal(result) 267 | assert.Nil(err) 268 | assert.Equal(bytes, b) 269 | } 270 | 271 | func TestCBORDecodingDuplicateKeys(t *testing.T) { 272 | assert := assert.New(t) 273 | 274 | type DecodeTestCase struct { 275 | bytes []byte 276 | result SignMessage 277 | } 278 | var cases = []DecodeTestCase{ 279 | { 280 | // duplicate compressed key in protected 281 | // tag(98) + array(4) [ bytes(5), map(0), bytes(0), array(0) ] 282 | // 283 | // where our bytes(5) is A201260128 or 284 | // A2 # map(2) 285 | // 01 # unsigned(1) 286 | // 26 # negative(6) 287 | // 01 # unsigned(1) 288 | // 29 # negative(10) 289 | // 290 | // and decodes to map[1:-10] so last/rightmost value wins 291 | HexToBytesOrDie("D862" + "84" + "45A201260129" + "A0" + "40" + "80"), 292 | SignMessage{ 293 | Headers: &Headers{ 294 | Protected: map[interface{}]interface{}{1: -10}, 295 | Unprotected: map[interface{}]interface{}{}, 296 | }, 297 | Payload: []byte(""), 298 | Signatures: nil, 299 | }, 300 | }, 301 | { 302 | // duplicate compressed key in unprotected 303 | // tag(98) + array(4) [ bytes(0), map(2), bytes(0), array(0) ] 304 | // 305 | // where our map(2) is 306 | // 01 # unsigned(1) 307 | // 26 # negative(6) 308 | // 01 # unsigned(1) 309 | // 29 # negative(10) 310 | // 311 | // and decodes to map[1:-10] so last/rightmost value wins 312 | HexToBytesOrDie("D862" + "84" + "40" + "A201260129" + "40" + "80"), 313 | SignMessage{ 314 | Headers: &Headers{ 315 | Protected: map[interface{}]interface{}{}, 316 | Unprotected: map[interface{}]interface{}{1: -10}, 317 | }, 318 | Payload: []byte(""), 319 | Signatures: nil, 320 | }, 321 | }, 322 | { 323 | // duplicate uncompressed key in protected 324 | // tag(98) + array(4) [ bytes(21), map(0), bytes(0), array(0) ] 325 | // 326 | // see next test for what bytes(21) represents 327 | HexToBytesOrDie("D862" + "84" + "55" + "A2" + "63" + "616C67" + "65" + "4553323536" + "63" + "616C67" + "65" + "5053323536" + "A0" + "40" + "80"), 328 | SignMessage{ 329 | Headers: &Headers{ 330 | Protected: map[interface{}]interface{}{ 331 | 1: -37, // decoding compresses to check for duplicate keys 332 | }, 333 | Unprotected: map[interface{}]interface{}{}, 334 | }, 335 | Payload: []byte(""), 336 | Signatures: nil, 337 | }, 338 | }, 339 | { 340 | // duplicate uncompressed key in unprotected 341 | // tag(98) + array(4) [ bytes(0), map(2), bytes(0), array(0) ] 342 | // 343 | // where our map(2) is 344 | // 345 | // A2 # map(2) 346 | // 63 # text(3) 347 | // 616C67 # "alg" 348 | // 65 # text(5) 349 | // 4553323536 # "ES256" 350 | // 63 # text(3) 351 | // 616C67 # "alg" 352 | // 65 # text(5) 353 | // 5053323536 # "PS256" 354 | // 355 | HexToBytesOrDie("D862" + "84" + "40" + "A2" + "63" + "616C67" + "65" + "4553323536" + "63" + "616C67" + "65" + "5053323536" + "40" + "80"), 356 | SignMessage{ 357 | Headers: &Headers{ 358 | Protected: map[interface{}]interface{}{}, 359 | Unprotected: map[interface{}]interface{}{ 360 | 1: -37, // decoding compresses to check for duplicate keys 361 | }, 362 | }, 363 | Payload: []byte(""), 364 | Signatures: nil, 365 | }, 366 | }, 367 | } 368 | 369 | for _, testCase := range cases { 370 | result, err := Unmarshal(testCase.bytes) 371 | assert.Nil(err) 372 | assert.Equal(testCase.result, result) 373 | } 374 | } 375 | 376 | func TestCBORDecodingErrors(t *testing.T) { 377 | assert := assert.New(t) 378 | 379 | type DecodeErrorTestCase struct { 380 | bytes []byte 381 | errorMessage string 382 | } 383 | var cases = []DecodeErrorTestCase{ 384 | { 385 | HexToBytesOrDie("D862" + "60"), // tag(98) + text(0) 386 | "cbor: cannot unmarshal UTF-8 text string into Go value of type cose.signMessage", 387 | }, 388 | { 389 | HexToBytesOrDie("D862" + "80"), // tag(98) + array(0) 390 | "cbor: cannot unmarshal array into Go value of type cose.signMessage (cannot decode CBOR array to struct with different number of elements)", 391 | }, 392 | { 393 | // tag(98) + array(4) [ 4 * text(0) ] 394 | HexToBytesOrDie("D862" + "84" + "60" + "60" + "60" + "60"), 395 | "cbor: cannot unmarshal UTF-8 text string into Go struct field cose.signMessage.Protected of type []uint8", 396 | }, 397 | { 398 | // tag(98) + array(4) [ bytes(0), map(0), 2 * text(0) ] 399 | HexToBytesOrDie("D862" + "84" + "40" + "A0" + "60" + "60"), 400 | "cbor: cannot unmarshal UTF-8 text string into Go struct field cose.signMessage.Payload of type []uint8", 401 | }, 402 | { 403 | // tag(98) + array(4) [ bytes(0), map(0), bytes(0), text(0) ] 404 | HexToBytesOrDie("D862" + "84" + "40" + "A0" + "40" + "60"), 405 | "cbor: cannot unmarshal UTF-8 text string into Go struct field cose.signMessage.Signatures of type []cose.signature", 406 | }, 407 | { 408 | // wrong # of protected header bytes 409 | // tag(98) + array(4) [ bytes(2) (but actually 1), map(0), bytes(0), text(0) ] 410 | HexToBytesOrDie("D862" + "84" + "4263" + "A0" + "40" + "60"), 411 | "unexpected EOF", 412 | }, 413 | { 414 | // protected header is serialized array 415 | // tag(98) + array(4) [ bytes(3), map(2), bytes(0), array(0) ] 416 | // protected header is bytes(3) is [2, -7] 417 | HexToBytesOrDie("D862" + "84" + "43820226" + "A10224" + "40" + "80"), 418 | "cbor: error casting protected to map; got []interface {}", 419 | }, 420 | { 421 | // duplicate compressed key in protected and unprotected 422 | // tag(98) + array(4) [ bytes(3), map(2), bytes(0), array(0) ] 423 | // bytes(3) is protected {2: -7} 424 | // map(1) is {2: -5} 425 | HexToBytesOrDie("D862" + "84" + "43A10226" + "A10224" + "40" + "80"), 426 | "cbor: Duplicate header 2 found", 427 | }, 428 | { 429 | // duplicate uncompressed key in protected and unprotected 430 | // tag(98) + array(4) [ bytes(11), map(1), bytes(0), array(0) ] 431 | // bytes(11) is protected {"alg": "ES256"} 432 | // map(1) is unprotected {"alg": "ES256"} 433 | HexToBytesOrDie("D862" + "84" + "4B" + "A1" + "63" + "616C67" + "65" + "4553323536" + "A1" + "63" + "616C67" + "65" + "4553323536" + "40" + "80"), 434 | "cbor: Duplicate header 1 found", 435 | }, 436 | { 437 | // duplicate key compressed in protected and uncompressed in unprotected 438 | // tag(98) + array(4) [ bytes(3), map(1), bytes(0), array(0) ] 439 | // bytes(3) is protected {1: -7} 440 | // map(1) is unprotected {"alg": "PS256"} 441 | HexToBytesOrDie("D862" + "84" + "43" + "A10126" + "A1" + "63" + "616C67" + "65" + "4553323536" + "40" + "80"), 442 | "cbor: Duplicate header 1 found", 443 | }, 444 | { 445 | // duplicate key uncompressed in protected and compressed in unprotected 446 | // tag(98) + array(4) [ bytes(11), map(1), bytes(0), array(0) ] 447 | // bytes(11) is protected {"alg": "ES256"} 448 | // map(1) is unprotected {1: -7} 449 | HexToBytesOrDie("D862" + "84" + "4B" + "A1" + "63" + "616C67" + "65" + "4553323536" + "A10126" + "40" + "80"), 450 | "cbor: Duplicate header 1 found", 451 | }, 452 | { 453 | // Signature's protected header is serialized array 454 | // tag(98) + array(4) [ bytes(0), map(0), bytes(0), array(1) ] 455 | // Signature is array(3) [ bytes(3), map(0), bytes(0)] 456 | // Signature protected header is bytes(3) is [2, -7] 457 | HexToBytesOrDie("D862" + "84" + "40" + "A0" + "40" + "81" + "83" + "43820226" + "A0" + "40"), 458 | "cbor: error casting protected to map; got []interface {}", 459 | }, 460 | { 461 | // Signature duplicate compressed key in protected and unprotected 462 | // tag(98) + array(4) [ bytes(0), map(0), bytes(0), array(1) ] 463 | // Signature is array(3) [ bytes(3), map(1), bytes(0)] 464 | // Signature bytes(3) is protected {2: -7} 465 | // Signature map(1) is {2: -5} 466 | HexToBytesOrDie("D862" + "84" + "40" + "A0" + "40" + "81" + "83" + "43A10226" + "A10224" + "40"), 467 | "cbor: Duplicate header 2 found", 468 | }, 469 | { 470 | // Signature duplicate uncompressed key in protected and unprotected 471 | // tag(98) + array(4) [ bytes(0), map(0), bytes(0), array(1) ] 472 | // Signature is array(3) [ bytes(11), map(1), bytes(0)] 473 | // Signature bytes(11) is protected {"alg": "ES256"} 474 | // Signature map(1) is unprotected {"alg": "ES256"} 475 | //HexToBytesOrDie("D862" + "84" + "4B" + "A1" + "63" + "616C67" + "65" + "4553323536" + "A1" + "63" + "616C67" + "65" + "4553323536" + "40" + "80"), 476 | HexToBytesOrDie("D862" + "84" + "40" + "A0" + "40" + "81" + "83" + "4B" + "A1" + "63" + "616C67" + "65" + "4553323536" + "A1" + "63" + "616C67" + "65" + "4553323536" + "40"), 477 | "cbor: Duplicate header 1 found", 478 | }, 479 | { 480 | // Signature duplicate key compressed in protected and uncompressed in unprotected 481 | // tag(98) + array(4) [ bytes(0), map(0), bytes(0), array(1) ] 482 | // Signature is array(3) [ bytes(3), map(1), bytes(0)] 483 | // Signature bytes(3) is protected {1: -7} 484 | // Signature map(1) is unprotected {"alg": "PS256"} 485 | //HexToBytesOrDie("D862" + "84" + "43" + "A10126" + "A1" + "63" + "616C67" + "65" + "4553323536" + "40" + "80"), 486 | HexToBytesOrDie("D862" + "84" + "40" + "A0" + "40" + "81" + "83" + "43" + "A10126" + "A1" + "63" + "616C67" + "65" + "4553323536" + "40"), 487 | "cbor: Duplicate header 1 found", 488 | }, 489 | { 490 | // Signature duplicate key uncompressed in protected and compressed in unprotected 491 | // tag(98) + array(4) [ bytes(0), map(0), bytes(0), array(1) ] 492 | // Signature is array(3) [ bytes(11), map(1), bytes(0)] 493 | // Signature bytes(11) is protected {"alg": "ES256"} 494 | // Signature map(1) is unprotected {1: -7} 495 | //HexToBytesOrDie("D862" + "84" + "4B" + "A1" + "63" + "616C67" + "65" + "4553323536" + "A10126" + "40" + "80"), 496 | HexToBytesOrDie("D862" + "84" + "40" + "A0" + "40" + "81" + "83" + "4B" + "A1" + "63" + "616C67" + "65" + "4553323536" + "A10126" + "40"), 497 | "cbor: Duplicate header 1 found", 498 | }, 499 | } 500 | 501 | for _, testCase := range cases { 502 | result, err := Unmarshal(testCase.bytes) 503 | assert.Nil(result) 504 | assert.Equal(testCase.errorMessage, err.Error()) 505 | } 506 | } 507 | 508 | // TestCBORDecodingToSignMessageErrors tests unmarshaling COSE data to SignMessage, 509 | // while TestCBORDecodingErrors tests unmarshaling COSE data to interface{}. 510 | func TestCBORDecodingToSignMessageErrors(t *testing.T) { 511 | assert := assert.New(t) 512 | 513 | type DecodeErrorTestCase struct { 514 | name string 515 | bytes []byte 516 | errorMessage string 517 | } 518 | var cases = []DecodeErrorTestCase{ 519 | { 520 | "missing tag number", 521 | HexToBytesOrDie("8440A0F680"), // array(4) [ bytes(0), map(0), nil, array(0)] 522 | "cbor: cannot unmarshal array into Go value of type cbor.RawTag", 523 | }, 524 | { 525 | "wrong tag number", 526 | HexToBytesOrDie("D8638440A0F680"), // tag(99) + array(4) [ bytes(0), map(0), nil, array(0)] 527 | "cbor: wrong tag number 99", 528 | }, 529 | } 530 | 531 | for _, testCase := range cases { 532 | var msg SignMessage 533 | err := cbor.Unmarshal(testCase.bytes, &msg) 534 | assert.Equal(testCase.errorMessage, err.Error()) 535 | } 536 | } 537 | 538 | func TestIsSignMessage(t *testing.T) { 539 | assert := assert.New(t) 540 | 541 | assert.Equal(IsSignMessage([]byte("deadbeef")), false) 542 | 543 | msgBytes, err := Marshal(NewSignMessage()) 544 | assert.Nil(err) 545 | assert.Equal(IsSignMessage(msgBytes), true) 546 | } 547 | 548 | func TestUnmarshalToNilSignMessage(t *testing.T) { 549 | assert := assert.New(t) 550 | 551 | b := []byte("\xd8\x62\x84\x40\xa0\xf6\x80") 552 | var msg *SignMessage 553 | err := msg.UnmarshalCBOR(b) 554 | assert.Equal("cbor: UnmarshalCBOR on nil SignMessage pointer", err.Error()) 555 | } 556 | -------------------------------------------------------------------------------- /common_headers.go: -------------------------------------------------------------------------------- 1 | package cose 2 | 3 | import ( 4 | "fmt" 5 | "github.com/pkg/errors" 6 | ) 7 | 8 | // Headers represents "two buckets of information that are not 9 | // considered to be part of the payload itself, but are used for 10 | // holding information about content, algorithms, keys, or evaluation 11 | // hints for the processing of the layer." 12 | // 13 | // https://tools.ietf.org/html/rfc8152#section-3 14 | // 15 | // It is represented by CDDL fragments: 16 | // 17 | // Headers = ( 18 | // protected : empty_or_serialized_map, 19 | // unprotected : header_map 20 | // ) 21 | // 22 | // header_map = { 23 | // Generic_Headers, 24 | // * label => values 25 | // } 26 | // 27 | // empty_or_serialized_map = bstr .cbor header_map / bstr .size 0 28 | // 29 | type Headers struct { 30 | Protected map[interface{}]interface{} 31 | Unprotected map[interface{}]interface{} 32 | } 33 | 34 | // EncodeUnprotected returns compressed unprotected headers 35 | func (h *Headers) EncodeUnprotected() (encoded map[interface{}]interface{}) { 36 | return CompressHeaders(h.Unprotected) 37 | } 38 | 39 | // EncodeProtected compresses and Marshals protected headers to bytes 40 | // to encode as a CBOR bstr 41 | func (h *Headers) EncodeProtected() (bstr []byte) { 42 | if h == nil { 43 | panic("Cannot encode nil Headers") 44 | } 45 | 46 | if h.Protected == nil || len(h.Protected) < 1 { 47 | return []byte("") 48 | } 49 | 50 | encoded, err := Marshal(CompressHeaders(h.Protected)) 51 | if err != nil { 52 | panic(fmt.Sprintf("Marshal error of protected headers %s", err)) 53 | } 54 | return encoded 55 | } 56 | 57 | // DecodeProtected Unmarshals and sets Headers.protected from an interface{} 58 | func (h *Headers) DecodeProtected(o interface{}) (err error) { 59 | if h == nil { 60 | return errors.New("error decoding protected headers on nil headers") 61 | } 62 | 63 | b, ok := o.([]byte) 64 | if !ok { 65 | return errors.Errorf("error casting protected header bytes; got %T", o) 66 | } 67 | if len(b) <= 0 { 68 | return nil 69 | } 70 | 71 | protected, err := Unmarshal(b) 72 | if err != nil { 73 | return errors.Errorf("error CBOR decoding protected header bytes; got %T", protected) 74 | } 75 | protectedMap, ok := protected.(map[interface{}]interface{}) 76 | if !ok { 77 | return errors.Errorf("error casting protected to map; got %T", protected) 78 | } 79 | h.Protected = protectedMap 80 | return nil 81 | } 82 | 83 | // DecodeUnprotected Unmarshals and sets Headers.unprotected from an interface{} 84 | func (h *Headers) DecodeUnprotected(o interface{}) (err error) { 85 | msgHeadersUnprotected, ok := o.(map[interface{}]interface{}) 86 | if !ok { 87 | return errors.Errorf("error decoding unprotected header as map[interface {}]interface {}; got %T", o) 88 | } 89 | h.Unprotected = msgHeadersUnprotected 90 | return nil 91 | } 92 | 93 | // Decode loads a two element interface{} slice into Headers.protected 94 | // and unprotected respectively 95 | func (h *Headers) Decode(o []interface{}) (err error) { 96 | if len(o) != 2 { 97 | return errors.Errorf("can only decode headers from 2-item array; got %d", len(o)) 98 | } 99 | err = h.DecodeProtected(o[0]) 100 | if err != nil { 101 | return err 102 | } 103 | err = h.DecodeUnprotected(o[1]) 104 | if err != nil { 105 | return err 106 | } 107 | dup := FindDuplicateHeader(h) 108 | if dup != nil { 109 | return errors.Errorf("Duplicate header %+v found", dup) 110 | } 111 | return nil 112 | } 113 | 114 | // GetCommonHeaderTag returns the CBOR tag for the map label 115 | // 116 | // using Common COSE Headers Parameters Table 2 117 | // https://tools.ietf.org/html/rfc8152#section-3.1 118 | func GetCommonHeaderTag(label string) (tag int, err error) { 119 | switch label { 120 | case "alg": 121 | return 1, nil 122 | case "crit": 123 | return 2, nil 124 | case "content type": 125 | return 3, nil 126 | case "kid": 127 | return 4, nil 128 | case "IV": 129 | return 5, nil 130 | case "Partial IV": 131 | return 6, nil 132 | case "counter signature": 133 | return 7, nil 134 | default: 135 | return 0, ErrMissingCOSETagForLabel 136 | } 137 | } 138 | 139 | // GetCommonHeaderTagOrPanic returns the CBOR label for a string. Is 140 | // the inverse of GetCommonHeaderLabel. 141 | func GetCommonHeaderTagOrPanic(label string) (tag int) { 142 | tag, err := GetCommonHeaderTag(label) 143 | if err != nil { 144 | panic(fmt.Sprintf("Failed to find a tag for label %s", label)) 145 | } 146 | return tag 147 | } 148 | 149 | // GetCommonHeaderLabel returns the CBOR label for the map tag. Is 150 | // the inverse of GetCommonHeaderTag. 151 | func GetCommonHeaderLabel(tag int) (label string, err error) { 152 | switch tag { 153 | case 1: 154 | return "alg", nil 155 | case 2: 156 | return "crit", nil 157 | case 3: 158 | return "content type", nil 159 | case 4: 160 | return "kid", nil 161 | case 5: 162 | return "IV", nil 163 | case 6: 164 | return "Partial IV", nil 165 | case 7: 166 | return "counter signature", nil 167 | default: 168 | return "", ErrMissingCOSETagForTag 169 | } 170 | } 171 | 172 | // getAlgByName returns a Algorithm for an IANA name 173 | func getAlgByName(name string) (alg *Algorithm, err error) { 174 | for _, alg := range algorithms { 175 | if alg.Name == name { 176 | return &alg, nil 177 | } 178 | } 179 | return nil, errors.Errorf("Algorithm named %s not found", name) 180 | } 181 | 182 | // getAlgByNameOrPanic returns a Algorithm for an IANA name and panics otherwise 183 | func getAlgByNameOrPanic(name string) (alg *Algorithm) { 184 | alg, err := getAlgByName(name) 185 | if err != nil { 186 | panic(fmt.Sprintf("Unable to get algorithm named %s", name)) 187 | } 188 | return alg 189 | } 190 | 191 | // getAlgByValue returns a Algorithm for an IANA value 192 | func getAlgByValue(value int) (alg *Algorithm, err error) { 193 | for _, alg := range algorithms { 194 | if alg.Value == value { 195 | return &alg, nil 196 | } 197 | } 198 | return nil, errors.Errorf("Algorithm with value %v not found", value) 199 | } 200 | 201 | func compressHeader(k, v interface{}) (compressedK, compressedV interface{}) { 202 | var keyIsAlg = false 203 | 204 | compressedK = k 205 | compressedV = v 206 | 207 | switch key := k.(type) { 208 | case string: 209 | if key == "alg" { 210 | keyIsAlg = true 211 | } 212 | tag, err := GetCommonHeaderTag(key) 213 | if err == nil { 214 | compressedK = tag 215 | } 216 | case int64: 217 | compressedK = int(key) 218 | } 219 | 220 | switch val := v.(type) { 221 | case string: 222 | if keyIsAlg { 223 | alg, err := getAlgByName(val) 224 | if err == nil { 225 | compressedV = alg.Value 226 | } 227 | } 228 | case int64: 229 | compressedV = int(val) 230 | } 231 | return 232 | } 233 | 234 | func decompressHeader(k, v interface{}) (decompressedK, decompressedV interface{}) { 235 | var keyIsAlg = false 236 | 237 | decompressedK = k 238 | decompressedV = v 239 | 240 | switch key := k.(type) { 241 | case int: 242 | label, err := GetCommonHeaderLabel(key) 243 | if err == nil { 244 | decompressedK = label 245 | } 246 | if label == "alg" { 247 | keyIsAlg = true 248 | } 249 | } 250 | 251 | switch val := v.(type) { 252 | case int: 253 | if keyIsAlg { 254 | alg, err := getAlgByValue(val) 255 | if err == nil { 256 | decompressedV = alg.Name 257 | } 258 | } 259 | } 260 | return 261 | } 262 | 263 | // CompressHeaders replaces string tags with their int values and alg 264 | // tags with their IANA int values. 265 | // 266 | // panics when a compressed header tag already exists (e.g. alg and 1) 267 | // casts int64 keys to int to make looking up common header IDs easier 268 | func CompressHeaders(headers map[interface{}]interface{}) (compressed map[interface{}]interface{}) { 269 | compressed = map[interface{}]interface{}{} 270 | for k, v := range headers { 271 | compressedK, compressedV := compressHeader(k, v) 272 | if _, ok := compressed[compressedK]; ok { 273 | panic(fmt.Sprintf("Duplicate compressed and uncompressed common header %v found in headers", compressedK)) 274 | } else { 275 | compressed[compressedK] = compressedV 276 | } 277 | } 278 | return compressed 279 | } 280 | 281 | // DecompressHeaders replaces int values with string tags and alg int 282 | // values with their IANA labels. Is the inverse of CompressHeaders. 283 | func DecompressHeaders(headers map[interface{}]interface{}) (decompressed map[interface{}]interface{}) { 284 | decompressed = map[interface{}]interface{}{} 285 | 286 | for k, v := range headers { 287 | k, v = decompressHeader(k, v) 288 | decompressed[k] = v 289 | } 290 | 291 | return decompressed 292 | } 293 | 294 | // FindDuplicateHeader compresses the headers and returns the first 295 | // duplicate header or nil for none found 296 | func FindDuplicateHeader(headers *Headers) interface{} { 297 | if headers == nil { 298 | return nil 299 | } 300 | headers.Protected = CompressHeaders(headers.Protected) 301 | headers.Unprotected = CompressHeaders(headers.Unprotected) 302 | for k, _ := range headers.Protected { 303 | _, ok := headers.Unprotected[k] 304 | if ok { 305 | return k 306 | } 307 | } 308 | return nil 309 | } 310 | 311 | // getAlg returns the alg by label or int 312 | // alg should only be in Protected headers so it does not check Unprotected headers 313 | func getAlg(h *Headers) (alg *Algorithm, err error) { 314 | if h == nil { 315 | err = errors.New("Cannot getAlg on nil Headers") 316 | return 317 | } 318 | 319 | if tmp, ok := h.Protected["alg"]; ok { 320 | if algName, ok := tmp.(string); ok { 321 | alg, err = getAlgByName(algName) 322 | if err != nil { 323 | return nil, err 324 | } 325 | return alg, nil 326 | } 327 | } else if tmp, ok := h.Protected[int(1)]; ok { 328 | if algValue, ok := tmp.(int); ok { 329 | alg, err = getAlgByValue(algValue) 330 | if err != nil { 331 | return nil, err 332 | } 333 | return alg, nil 334 | } 335 | } 336 | return nil, ErrAlgNotFound 337 | } 338 | -------------------------------------------------------------------------------- /common_headers_test.go: -------------------------------------------------------------------------------- 1 | package cose 2 | 3 | import ( 4 | "fmt" 5 | "github.com/stretchr/testify/assert" 6 | "testing" 7 | ) 8 | 9 | var CompressionTestCases = []struct { 10 | name string 11 | input map[interface{}]interface{} 12 | intermediate map[interface{}]interface{} 13 | roundtrip map[interface{}]interface{} 14 | }{ 15 | { 16 | "all empty", 17 | map[interface{}]interface{}{}, 18 | map[interface{}]interface{}{}, 19 | map[interface{}]interface{}{}, 20 | }, 21 | { 22 | "all keys", 23 | map[interface{}]interface{}{ 24 | "counter signature": []int{1, 2, -3}, 25 | "Partial IV": "foo", 26 | "alg": true, 27 | "IV": nil, 28 | "content type": false, 29 | "kid": -1, 30 | "crit": true, 31 | }, 32 | map[interface{}]interface{}{ 33 | 3: false, 34 | 1: true, 35 | 2: true, 36 | 4: -1, 37 | 5: nil, 38 | 6: "foo", 39 | 7: []int{1, 2, -3}, 40 | }, 41 | map[interface{}]interface{}{ 42 | "counter signature": []int{1, 2, -3}, 43 | "Partial IV": "foo", 44 | "alg": true, 45 | "IV": nil, 46 | "content type": false, 47 | "kid": -1, 48 | "crit": true, 49 | }, 50 | }, 51 | { 52 | "unknown key", 53 | map[interface{}]interface{}{ 54 | "unknown": -1, 55 | }, 56 | map[interface{}]interface{}{ 57 | "unknown": -1, 58 | }, 59 | map[interface{}]interface{}{ 60 | "unknown": -1, 61 | }, 62 | }, 63 | { 64 | "known key wrong case \"ALG\"", 65 | map[interface{}]interface{}{ 66 | "ALG": 1, 67 | }, 68 | map[interface{}]interface{}{ 69 | "ALG": 1, 70 | }, 71 | map[interface{}]interface{}{ 72 | "ALG": 1, 73 | }, 74 | }, 75 | { 76 | "supported alg value \"ES256\" compressed", 77 | map[interface{}]interface{}{ 78 | "alg": "ES256", 79 | }, 80 | map[interface{}]interface{}{ 81 | 1: -7, 82 | }, 83 | map[interface{}]interface{}{ 84 | "alg": "ES256", 85 | }, 86 | }, 87 | { 88 | "supported alg value \"PS256\" compressed", 89 | map[interface{}]interface{}{ 90 | "alg": "PS256", 91 | }, 92 | map[interface{}]interface{}{ 93 | 1: -37, 94 | }, 95 | map[interface{}]interface{}{ 96 | "alg": "PS256", 97 | }, 98 | }, 99 | { 100 | "converts int64 to int", 101 | map[interface{}]interface{}{ 102 | int64(1): int64(-37), 103 | }, 104 | map[interface{}]interface{}{ 105 | 1: -37, 106 | }, 107 | map[interface{}]interface{}{ 108 | "alg": "PS256", 109 | }, 110 | }, 111 | } 112 | 113 | func TestHeaderCompressionRoundTrip(t *testing.T) { 114 | for _, testCase := range CompressionTestCases { 115 | assert := assert.New(t) 116 | 117 | compressed := CompressHeaders(testCase.input) 118 | assert.Equal( 119 | testCase.intermediate, 120 | compressed, 121 | fmt.Sprintf("%s: header compression failed", testCase.name)) 122 | 123 | assert.Equal( 124 | testCase.roundtrip, 125 | DecompressHeaders(compressed), 126 | fmt.Sprintf("%s: header compression-decompression roundtrip failed", testCase.name)) 127 | } 128 | } 129 | 130 | func TestHeaderCompressionDoesNotDecompressUnknownTag(t *testing.T) { 131 | assert := assert.New(t) 132 | 133 | compressed := map[interface{}]interface{}{ 134 | 777: 1, 135 | } 136 | assert.Equal( 137 | compressed, 138 | DecompressHeaders(compressed), 139 | "header decompression modifies unknown tag") 140 | } 141 | 142 | func TestGetAlgPanics(t *testing.T) { 143 | assert := assert.New(t) 144 | 145 | var algName = "FOOOO" 146 | assert.Panics(func () { getAlgByNameOrPanic(algName) }) 147 | } 148 | 149 | func TestGetCommonHeaderTagOrPanicPanics(t *testing.T) { 150 | assert := assert.New(t) 151 | 152 | var label = "FOOOO" 153 | assert.Panics(func () { GetCommonHeaderTagOrPanic(label) }) 154 | } 155 | 156 | func TestGetAlgWithString(t *testing.T) { 157 | assert := assert.New(t) 158 | 159 | var h *Headers = nil 160 | alg, err := getAlg(h) 161 | assert.Nil(alg) 162 | assert.NotNil(err) 163 | assert.Equal("Cannot getAlg on nil Headers", err.Error()) 164 | 165 | h = &Headers{} 166 | h.Protected = map[interface{}]interface{}{ 167 | "alg": "ROT13", 168 | } 169 | alg, err = getAlg(h) 170 | assert.Nil(alg) 171 | assert.NotNil(err) 172 | assert.Equal(err.Error(), "Algorithm named ROT13 not found") 173 | 174 | h.Protected["alg"] = "ES256" 175 | alg, err = getAlg(h) 176 | assert.NotNil(alg) 177 | assert.Nil(err) 178 | assert.Equal(alg.Name, "ES256") 179 | } 180 | 181 | func TestFindDuplicateHeaderWithNilHeaders(t *testing.T) { 182 | assert := assert.New(t) 183 | 184 | var h *Headers = nil 185 | assert.Nil(FindDuplicateHeader(h)) 186 | } 187 | 188 | func TestHeaderEncodeErrors(t *testing.T) { 189 | assert := assert.New(t) 190 | 191 | var h *Headers = nil 192 | assert.Panics(func () { h.EncodeProtected() }) 193 | 194 | h = &Headers{ 195 | Protected: map[interface{}]interface{}{ 196 | "alg": -3, 197 | 1: -7, 198 | }, 199 | } 200 | assert.Panics(func () { h.EncodeProtected() }) 201 | } 202 | 203 | func TestHeaderDecodeErrors(t *testing.T) { 204 | assert := assert.New(t) 205 | 206 | var ( 207 | h *Headers = &Headers{ 208 | Protected: nil, 209 | Unprotected: nil, 210 | } 211 | v []interface{} 212 | err error 213 | ) 214 | err = h.Decode(v) 215 | assert.NotNil(err) 216 | assert.Equal(err.Error(), "can only decode headers from 2-item array; got 0") 217 | 218 | v = []interface{}{[]byte("\x90"), map[interface{}]interface{}{}} 219 | err = h.Decode(v) 220 | assert.NotNil(err) 221 | assert.Equal(err.Error(), "error CBOR decoding protected header bytes; got ") 222 | 223 | v = []interface{}{[]byte("\x60"), map[interface{}]interface{}{}} 224 | err = h.Decode(v) 225 | assert.NotNil(err) 226 | assert.Equal(err.Error(), "error casting protected to map; got string") 227 | 228 | v = []interface{}{[]byte("\xA1\x02\x26"), -1} 229 | err = h.Decode(v) 230 | assert.NotNil(err) 231 | assert.Equal(err.Error(), "error decoding unprotected header as map[interface {}]interface {}; got int") 232 | } 233 | -------------------------------------------------------------------------------- /core.go: -------------------------------------------------------------------------------- 1 | package cose 2 | 3 | import ( 4 | "crypto" 5 | "crypto/ecdsa" 6 | "crypto/elliptic" 7 | "crypto/rand" 8 | "crypto/rsa" 9 | "crypto/subtle" 10 | "encoding/base64" 11 | "github.com/pkg/errors" 12 | "io" 13 | "math/big" 14 | ) 15 | 16 | // ContextSignature identifies the context of the signature as a 17 | // COSE_Signature structure per 18 | // https://tools.ietf.org/html/rfc8152#section-4.4 19 | const ContextSignature = "Signature" 20 | 21 | // Supported Algorithms 22 | var ( 23 | // PS256 is RSASSA-PSS w/ SHA-256 from [RFC8230] 24 | PS256 = getAlgByNameOrPanic("PS256") 25 | 26 | // ES256 is ECDSA w/ SHA-256 from [RFC8152] 27 | ES256 = getAlgByNameOrPanic("ES256") 28 | 29 | // ES384 is ECDSA w/ SHA-384 from [RFC8152] 30 | ES384 = getAlgByNameOrPanic("ES384") 31 | 32 | // ES512 is ECDSA w/ SHA-512 from [RFC8152] 33 | ES512 = getAlgByNameOrPanic("ES512") 34 | ) 35 | 36 | // ByteSigner take a signature digest and returns COSE signature bytes 37 | type ByteSigner interface { 38 | // Sign returns the COSE signature as a byte slice 39 | Sign(rand io.Reader, digest []byte) (signature []byte, err error) 40 | } 41 | 42 | // ByteVerifier checks COSE signatures 43 | type ByteVerifier interface { 44 | // Verify returns nil for a successfully verified signature or an error 45 | Verify(digest []byte, signature []byte) (err error) 46 | } 47 | 48 | // Signer holds a COSE Algorithm and private key for signing messages 49 | type Signer struct { 50 | PrivateKey crypto.PrivateKey 51 | alg *Algorithm 52 | } 53 | 54 | // RSAOptions are options for NewSigner currently just the RSA Key 55 | // size 56 | type RSAOptions struct { 57 | Size int 58 | } 59 | 60 | // NewSigner returns a Signer with a generated key 61 | func NewSigner(alg *Algorithm, options interface{}) (signer *Signer, err error) { 62 | var privateKey crypto.PrivateKey 63 | 64 | if alg.privateKeyType == KeyTypeECDSA { 65 | if alg.privateKeyECDSACurve == nil { 66 | err = errors.Errorf("No ECDSA curve found for algorithm") 67 | return nil, err 68 | } 69 | 70 | privateKey, err = ecdsa.GenerateKey(alg.privateKeyECDSACurve, rand.Reader) 71 | if err != nil { 72 | err = errors.Wrapf(err, "error generating ecdsa signer private key") 73 | return nil, err 74 | } 75 | } else if alg.privateKeyType == KeyTypeRSA { 76 | var keyBitLen int = alg.minRSAKeyBitLen 77 | 78 | if opts, ok := options.(RSAOptions); ok { 79 | if opts.Size > alg.minRSAKeyBitLen { 80 | keyBitLen = opts.Size 81 | } else { 82 | err = errors.Errorf("error generating rsa signer private key RSA key size must be at least %d", alg.minRSAKeyBitLen) 83 | return nil, err 84 | } 85 | } 86 | privateKey, err = rsa.GenerateKey(rand.Reader, keyBitLen) 87 | if err != nil { 88 | err = errors.Wrapf(err, "error generating rsa signer private key") 89 | return nil, err 90 | } 91 | } else { 92 | return nil, ErrUnknownPrivateKeyType 93 | } 94 | 95 | return &Signer{ 96 | PrivateKey: privateKey, 97 | alg: alg, 98 | }, nil 99 | } 100 | 101 | // NewSignerFromKey checks whether the privateKey is supported and 102 | // returns a Signer using the provided key 103 | func NewSignerFromKey(alg *Algorithm, privateKey crypto.PrivateKey) (signer *Signer, err error) { 104 | switch privateKey.(type) { 105 | case *rsa.PrivateKey: 106 | case *ecdsa.PrivateKey: 107 | default: 108 | return nil, ErrUnknownPrivateKeyType 109 | } 110 | return &Signer{ 111 | PrivateKey: privateKey, 112 | alg: alg, 113 | }, nil 114 | } 115 | 116 | // Public returns the crypto.PublicKey for the Signer's privateKey 117 | func (s *Signer) Public() (publicKey crypto.PublicKey) { 118 | switch key := s.PrivateKey.(type) { 119 | case *rsa.PrivateKey: 120 | return key.Public() 121 | case *ecdsa.PrivateKey: 122 | return key.Public() 123 | default: 124 | panic("Could not return public key for Unrecognized private key type.") 125 | } 126 | } 127 | 128 | // Sign returns the COSE signature as a byte slice 129 | func (s *Signer) Sign(rand io.Reader, digest []byte) (signature []byte, err error) { 130 | switch key := s.PrivateKey.(type) { 131 | case *rsa.PrivateKey: 132 | if s.alg.privateKeyType != KeyTypeRSA { 133 | return nil, errors.Errorf("Key type must be RSA") 134 | } 135 | if key.N.BitLen() < s.alg.minRSAKeyBitLen { 136 | return nil, errors.Errorf("RSA key must be at least %d bits long", s.alg.minRSAKeyBitLen) 137 | } 138 | 139 | sig, err := rsa.SignPSS(rand, key, s.alg.HashFunc, digest, &rsa.PSSOptions{ 140 | SaltLength: rsa.PSSSaltLengthEqualsHash, 141 | Hash: s.alg.HashFunc, 142 | }) 143 | if err != nil { 144 | return nil, errors.Errorf("rsa.SignPSS error %s", err) 145 | } 146 | return sig, nil 147 | case *ecdsa.PrivateKey: 148 | if s.alg.privateKeyType != KeyTypeECDSA { 149 | return nil, errors.Errorf("Key type must be ECDSA") 150 | } 151 | 152 | // https://tools.ietf.org/html/rfc8152#section-8.1 153 | r, s, err := ecdsa.Sign(rand, key, digest) 154 | if err != nil { 155 | return nil, errors.Errorf("ecdsa.Sign error %s", err) 156 | } 157 | 158 | // These integers (r and s) will be the same length as 159 | // the length of the key used for the signature 160 | // process. 161 | const tolerance = uint(1) 162 | rByteLen, sByteLen, dByteLen := len(s.Bits()), len(r.Bits()), len(key.D.Bits()) 163 | if !(approxEqual(sByteLen, rByteLen, tolerance) && approxEqual(sByteLen, dByteLen, tolerance) && approxEqual(dByteLen, rByteLen, tolerance)) { 164 | return nil, errors.Errorf("Byte lengths of integers r and s (%d and %d) do not match the key length %d±%d\n", sByteLen, rByteLen, dByteLen, tolerance) 165 | } 166 | 167 | // The signature is encoded by converting the integers 168 | // into byte strings of the same length as the key 169 | // size. The length is rounded up to the nearest byte 170 | // and is left padded with zero bits to get to the 171 | // correct length. The two integers are then 172 | // concatenated together to form a byte string that is 173 | // the resulting signature. 174 | n := ecdsaCurveKeyBytesSize(key.Curve) 175 | sig := make([]byte, 0) 176 | sig = append(sig, I2OSP(r, n)...) 177 | sig = append(sig, I2OSP(s, n)...) 178 | 179 | return sig, nil 180 | default: 181 | return nil, ErrUnknownPrivateKeyType 182 | } 183 | } 184 | 185 | // Verifier returns a Verifier using the Signer's public key and 186 | // Algorithm 187 | func (s *Signer) Verifier() (verifier *Verifier) { 188 | return &Verifier{ 189 | PublicKey: s.Public(), 190 | Alg: s.alg, 191 | } 192 | } 193 | 194 | // Verifier holds a PublicKey and Algorithm to verify signatures 195 | type Verifier struct { 196 | PublicKey crypto.PublicKey 197 | Alg *Algorithm 198 | } 199 | 200 | // Verify verifies a signature returning nil for success or an error 201 | func (v *Verifier) Verify(digest []byte, signature []byte) (err error) { 202 | if v.Alg.Value > -1 { // Negative numbers are used for second layer objects (COSE_Signature and COSE_recipient) 203 | return ErrInvalidAlg 204 | } 205 | 206 | switch key := v.PublicKey.(type) { 207 | case *rsa.PublicKey: 208 | hashFunc := v.Alg.HashFunc 209 | 210 | err = rsa.VerifyPSS(key, hashFunc, digest, signature, &rsa.PSSOptions{ 211 | SaltLength: rsa.PSSSaltLengthEqualsHash, 212 | Hash: hashFunc, 213 | }) 214 | if err != nil { 215 | return errors.Errorf("verification failed rsa.VerifyPSS err %s", err) 216 | } 217 | return nil 218 | case *ecdsa.PublicKey: 219 | if v.Alg.privateKeyECDSACurve == nil { 220 | return errors.Errorf("Could not find an elliptic curve for the ecdsa algorithm") 221 | } 222 | 223 | algCurveBitSize := v.Alg.privateKeyECDSACurve.Params().BitSize 224 | keyCurveBitSize := key.Curve.Params().BitSize 225 | 226 | if algCurveBitSize != keyCurveBitSize { 227 | return errors.Errorf("Expected %d bit key, got %d bits instead", algCurveBitSize, keyCurveBitSize) 228 | } 229 | 230 | algKeyBytesSize := ecdsaCurveKeyBytesSize(v.Alg.privateKeyECDSACurve) 231 | 232 | // signature bytes is the keys with padding r and s 233 | if len(signature) != 2*algKeyBytesSize { 234 | return errors.Errorf("invalid signature length: %d", len(signature)) 235 | } 236 | 237 | r := big.NewInt(0).SetBytes(signature[:algKeyBytesSize]) 238 | s := big.NewInt(0).SetBytes(signature[algKeyBytesSize:]) 239 | 240 | ok := ecdsa.Verify(key, digest, r, s) 241 | if ok { 242 | return nil 243 | } 244 | return ErrECDSAVerification 245 | default: 246 | return ErrUnknownPublicKeyType 247 | } 248 | } 249 | 250 | // buildAndMarshalSigStructure creates a Sig_structure, populates it 251 | // with the appropriate fields, and marshals it to CBOR bytes 252 | func buildAndMarshalSigStructure(bodyProtected, signProtected, external, payload []byte) (ToBeSigned []byte, err error) { 253 | // 1. Create a Sig_structure and populate it with the appropriate fields. 254 | // 255 | // Sig_structure = [ 256 | // context : "Signature" / "Signature1" / "CounterSignature", 257 | // body_protected : empty_or_serialized_map, 258 | // ? sign_protected : empty_or_serialized_map, 259 | // external_aad : bstr, 260 | // payload : bstr 261 | // ] 262 | sigStructure := []interface{}{ 263 | ContextSignature, 264 | bodyProtected, // message.headers.EncodeProtected(), 265 | signProtected, // message.signatures[0].headers.EncodeProtected(), 266 | external, 267 | payload, 268 | } 269 | 270 | // 2. Create the value ToBeSigned by encoding the Sig_structure to a 271 | // byte string, using the encoding described in Section 14. 272 | ToBeSigned, err = Marshal(sigStructure) 273 | if err != nil { 274 | return nil, errors.Errorf("Error marshaling Sig_structure: %s", err) 275 | } 276 | return ToBeSigned, nil 277 | } 278 | 279 | // hashSigStructure computes the crypto.Hash digest of a byte slice 280 | func hashSigStructure(ToBeSigned []byte, hash crypto.Hash) (digest []byte, err error) { 281 | if !hash.Available() { 282 | return []byte(""), ErrUnavailableHashFunc 283 | } 284 | hasher := hash.New() 285 | _, _ = hasher.Write(ToBeSigned) // Write() on hash never fails 286 | digest = hasher.Sum(nil) 287 | return digest, nil 288 | } 289 | 290 | // ecdsaCurveKeyBytesSize returns the ECDSA key size in bytes with padding 291 | func ecdsaCurveKeyBytesSize(curve elliptic.Curve) (keyBytesSize int) { 292 | curveBits := curve.Params().BitSize 293 | keyBytesSize = curveBits / 8 294 | 295 | // add a byte of padding for curves like P521 296 | if curveBits%8 > 0 { 297 | keyBytesSize++ 298 | } 299 | return 300 | } 301 | 302 | // I2OSP "Integer-to-Octet-String" converts a nonnegative integer to 303 | // an octet string of a specified length 304 | // 305 | // https://tools.ietf.org/html/rfc8017#section-4.1 306 | func I2OSP(b *big.Int, n int) []byte { 307 | var ( 308 | octetString = b.Bytes() 309 | octetStringSize = len(octetString) 310 | result = make([]byte, n) 311 | ) 312 | if !(b.Sign() == 0 || b.Sign() == 1) { 313 | panic("I2OSP error: integer must be zero or positive") 314 | } 315 | if n == 0 || octetStringSize > n { 316 | panic("I2OSP error: integer too large") 317 | } 318 | 319 | subtle.ConstantTimeCopy(1, result[:n-octetStringSize], result[:n-octetStringSize]) 320 | subtle.ConstantTimeCopy(1, result[n-octetStringSize:], octetString) 321 | return result 322 | } 323 | 324 | // FromBase64Int decodes a base64-encoded string into a big.Int or panics 325 | // 326 | // from https://github.com/square/go-jose/blob/789a4c4bd4c118f7564954f441b29c153ccd6a96/utils_test.go#L45 327 | // Apache License 2.0 328 | func FromBase64Int(data string) *big.Int { 329 | val, err := base64.RawURLEncoding.DecodeString(data) 330 | if err != nil { 331 | panic("Invalid test data") 332 | } 333 | return new(big.Int).SetBytes(val) 334 | } 335 | 336 | // Sign returns the SignatureBytes for each Signer in the same order 337 | // on the digest or the error from the first failing Signer 338 | func Sign(rand io.Reader, digest []byte, signers []ByteSigner) (signatures [][]byte, err error) { 339 | var signatureBytes []byte 340 | 341 | for _, signer := range signers { 342 | signatureBytes, err = signer.Sign(rand, digest) 343 | if err != nil { 344 | return 345 | } 346 | signatures = append(signatures, signatureBytes) 347 | } 348 | return 349 | } 350 | 351 | // Verify returns nil if all Verifier verify the SignatureBytes or the 352 | // error from the first failing Verifier 353 | func Verify(digest []byte, signatures [][]byte, verifiers []ByteVerifier) (err error) { 354 | if len(signatures) != len(verifiers) { 355 | return errors.Errorf("Wrong number of signatures %d and verifiers %d", len(signatures), len(verifiers)) 356 | } 357 | for i, verifier := range verifiers { 358 | err = verifier.Verify(digest, signatures[i]) 359 | if err != nil { 360 | return 361 | } 362 | } 363 | return nil 364 | } 365 | 366 | // approxEquals returns a bool of whether x and y are equal to within 367 | // a given tolerance 368 | func approxEqual(x, y int, tolerance uint) bool { 369 | var ( 370 | larger, smaller int 371 | ) 372 | if x > y { 373 | larger = x 374 | smaller = y 375 | } else { 376 | larger = y 377 | smaller = x 378 | } 379 | return uint(larger-smaller) <= tolerance 380 | } 381 | -------------------------------------------------------------------------------- /core_test.go: -------------------------------------------------------------------------------- 1 | package cose 2 | 3 | import ( 4 | "crypto/dsa" 5 | "crypto/ecdsa" 6 | "crypto/elliptic" 7 | "crypto/rand" 8 | "crypto/rsa" 9 | "fmt" 10 | "github.com/stretchr/testify/assert" 11 | "math/big" 12 | "os" 13 | "testing" 14 | "time" 15 | ) 16 | 17 | var ( 18 | dsaPrivateKey = dsa.PrivateKey{ 19 | PublicKey: dsa.PublicKey{ 20 | Parameters: dsa.Parameters{ 21 | P: FromBase64Int("A9B5B793FB4785793D246BAE77E8FF63CA52F442DA763C440259919FE1BC1D6065A9350637A04F75A2F039401D49F08E066C4D275A5A65DA5684BC563C14289D7AB8A67163BFBF79D85972619AD2CFF55AB0EE77A9002B0EF96293BDD0F42685EBB2C66C327079F6C98000FBCB79AACDE1BC6F9D5C7B1A97E3D9D54ED7951FEF"), 22 | Q: FromBase64Int("E1D3391245933D68A0714ED34BBCB7A1F422B9C1"), 23 | G: FromBase64Int("634364FC25248933D01D1993ECABD0657CC0CB2CEED7ED2E3E8AECDFCDC4A25C3B15E9E3B163ACA2984B5539181F3EFF1A5E8903D71D5B95DA4F27202B77D2C44B430BB53741A8D59A8F86887525C9F2A6A5980A195EAA7F2FF910064301DEF89D3AA213E1FAC7768D89365318E370AF54A112EFBA9246D9158386BA1B4EEFDA"), 24 | }, 25 | Y: FromBase64Int("32969E5780CFE1C849A1C276D7AEB4F38A23B591739AA2FE197349AEEBD31366AEE5EB7E6C6DDB7C57D02432B30DB5AA66D9884299FAA72568944E4EEDC92EA3FBC6F39F53412FBCC563208F7C15B737AC8910DBC2D9C9B8C001E72FDC40EB694AB1F06A5A2DBD18D9E36C66F31F566742F11EC0A52E9F7B89355C02FB5D32D2"), 26 | }, 27 | X: FromBase64Int("5078D4D29795CBE76D3AACFE48C9AF0BCDBEE91A"), 28 | } 29 | ecdsaPrivateKey = ecdsa.PrivateKey{ 30 | PublicKey: ecdsa.PublicKey{ 31 | Curve: elliptic.P256(), 32 | X: FromBase64Int("usWxHK2PmfnHKwXPS54m0kTcGJ90UiglWiGahtagnv8"), 33 | Y: FromBase64Int("IBOL-C3BttVivg-lSreASjpkttcsz-1rb7btKLv8EX4"), 34 | }, 35 | D: FromBase64Int("V8kgd2ZBRuh2dgyVINBUqpPDr7BOMGcF22CQMIUHtNM"), 36 | } 37 | rsaPrivateKey = rsa.PrivateKey{ 38 | PublicKey: rsa.PublicKey{ 39 | N: fromBase10("14314132931241006650998084889274020608918049032671858325988396851334124245188214251956198731333464217832226406088020736932173064754214329009979944037640912127943488972644697423190955557435910767690712778463524983667852819010259499695177313115447116110358524558307947613422897787329221478860907963827160223559690523660574329011927531289655711860504630573766609239332569210831325633840174683944553667352219670930408593321661375473885147973879086994006440025257225431977751512374815915392249179976902953721486040787792801849818254465486633791826766873076617116727073077821584676715609985777563958286637185868165868520557"), 40 | E: 3, 41 | }, 42 | D: fromBase10("9542755287494004433998723259516013739278699355114572217325597900889416163458809501304132487555642811888150937392013824621448709836142886006653296025093941418628992648429798282127303704957273845127141852309016655778568546006839666463451542076964744073572349705538631742281931858219480985907271975884773482372966847639853897890615456605598071088189838676728836833012254065983259638538107719766738032720239892094196108713378822882383694456030043492571063441943847195939549773271694647657549658603365629458610273821292232646334717612674519997533901052790334279661754176490593041941863932308687197618671528035670452762731"), 43 | Primes: []*big.Int{ 44 | fromBase10("130903255182996722426771613606077755295583329135067340152947172868415809027537376306193179624298874215608270802054347609836776473930072411958753044562214537013874103802006369634761074377213995983876788718033850153719421695468704276694983032644416930879093914927146648402139231293035971427838068945045019075433"), 45 | fromBase10("109348945610485453577574767652527472924289229538286649661240938988020367005475727988253438647560958573506159449538793540472829815903949343191091817779240101054552748665267574271163617694640513549693841337820602726596756351006149518830932261246698766355347898158548465400674856021497190430791824869615170301029"), 46 | }, 47 | } 48 | ) 49 | 50 | func fromBase10(base10 string) *big.Int { 51 | i, ok := new(big.Int).SetString(base10, 10) 52 | 53 | if !ok { 54 | panic("bad number: " + base10) 55 | } 56 | 57 | return i 58 | } 59 | 60 | func TestNewSigner(t *testing.T) { 61 | assert := assert.New(t) 62 | 63 | _, err := NewSigner(ES256, nil) 64 | assert.Nil(err) 65 | 66 | _, err = NewSigner(PS256, nil) 67 | assert.Nil(err) 68 | 69 | edDSA := getAlgByNameOrPanic("EdDSA") 70 | 71 | signer, err := NewSigner(edDSA, nil) 72 | assert.NotNil(err) 73 | assert.Equal(err.Error(), ErrUnknownPrivateKeyType.Error()) 74 | 75 | edDSA.privateKeyType = KeyTypeECDSA 76 | signer, err = NewSigner(edDSA, nil) 77 | assert.NotNil(err) 78 | assert.Equal(err.Error(), "No ECDSA curve found for algorithm") 79 | 80 | signer, err = NewSigner(PS256, RSAOptions{Size: 2050}) 81 | assert.Nil(err) 82 | rkey := signer.PrivateKey.(*rsa.PrivateKey) 83 | keySize := rkey.D.BitLen() 84 | bitSizeDiff := 2050 - keySize 85 | assert.True(bitSizeDiff <= 8, fmt.Sprintf("generated key size %d not within 8 bits of expected size 2050", keySize)) 86 | 87 | _, err = NewSigner(PS256, RSAOptions{Size: 128}) 88 | assert.NotNil(err) 89 | assert.Equal(err.Error(), "error generating rsa signer private key RSA key size must be at least 2048") 90 | 91 | _, err = NewSignerFromKey(ES256, &ecdsaPrivateKey) 92 | assert.Nil(err, "Error creating signer with ecdsaPrivateKey") 93 | 94 | _, err = NewSignerFromKey(ES256, &rsaPrivateKey) 95 | assert.Nil(err, "Error creating signer with rsaPrivateKey") 96 | 97 | _, err = NewSignerFromKey(ES256, &dsaPrivateKey) 98 | assert.Equal(ErrUnknownPrivateKeyType, err, "Did not error creating signer with unsupported dsaPrivateKey") 99 | } 100 | 101 | func TestSignerPublic(t *testing.T) { 102 | assert := assert.New(t) 103 | 104 | ecdsaSigner, err := NewSignerFromKey(ES256, &ecdsaPrivateKey) 105 | assert.Nil(err, "Error creating signer with ecdsaPrivateKey") 106 | 107 | rsaSigner, err := NewSignerFromKey(ES256, &rsaPrivateKey) 108 | assert.Nil(err, "Error creating signer with rsaPrivateKey") 109 | 110 | ecdsaSigner.Public() 111 | rsaSigner.Public() 112 | 113 | ecdsaSigner.PrivateKey = dsaPrivateKey 114 | assert.Panics(func() { ecdsaSigner.Public() }) 115 | } 116 | 117 | func TestSignerSignErrors(t *testing.T) { 118 | assert := assert.New(t) 119 | 120 | signer, err := NewSigner(ES256, nil) 121 | assert.Nil(err, "Error creating ES256 signer") 122 | 123 | hasher := signer.alg.HashFunc.New() 124 | _, _ = hasher.Write([]byte("ahoy")) // Write() on hash never fails 125 | digest := hasher.Sum(nil) 126 | 127 | signer.alg.privateKeyType = KeyTypeUnsupported 128 | _, err = signer.Sign(rand.Reader, digest) 129 | assert.NotNil(err) 130 | assert.Equal(err.Error(), "Key type must be ECDSA") 131 | signer.alg.privateKeyType = KeyTypeECDSA 132 | 133 | signer, err = NewSigner(PS256, nil) 134 | assert.Nil(err, "Error creating PS256 signer") 135 | 136 | signer.alg.privateKeyType = KeyTypeUnsupported 137 | _, err = signer.Sign(rand.Reader, digest) 138 | assert.NotNil(err) 139 | assert.Equal(err.Error(), "Key type must be RSA") 140 | signer.alg.privateKeyType = KeyTypeRSA 141 | 142 | weakKey, err := rsa.GenerateKey(rand.Reader, 128) 143 | assert.Nil(err, "Error creating weak RSA key") 144 | signer.PrivateKey = weakKey 145 | _, err = signer.Sign(rand.Reader, digest) 146 | assert.NotNil(err) 147 | assert.Equal(err.Error(), "RSA key must be at least 2048 bits long") 148 | } 149 | 150 | func TestVerifyRSASuccess(t *testing.T) { 151 | assert := assert.New(t) 152 | 153 | signer, err := NewSigner(PS256, nil) 154 | assert.Nil(err, "Error creating signer") 155 | 156 | hasher := signer.alg.HashFunc.New() 157 | _, _ = hasher.Write([]byte("ahoy")) // Write() on hash never fails 158 | digest := hasher.Sum(nil) 159 | 160 | signatureBytes, err := signer.Sign(rand.Reader, digest) 161 | assert.Nil(err) 162 | 163 | verifier := signer.Verifier() 164 | err = verifier.Verify(digest, signatureBytes) 165 | assert.Nil(err) 166 | } 167 | 168 | func TestVerifyInvalidAlgErrors(t *testing.T) { 169 | assert := assert.New(t) 170 | 171 | signer, err := NewSignerFromKey(ES256, &ecdsaPrivateKey) 172 | assert.Nil(err, "Error creating signer") 173 | 174 | verifier := signer.Verifier() 175 | 176 | verifier.Alg.Value = 20 177 | err = verifier.Verify([]byte(""), []byte("")) 178 | assert.Equal(ErrInvalidAlg, err) 179 | 180 | verifier.Alg.Value = -7 181 | 182 | verifier.PublicKey = rsaPrivateKey.Public() 183 | verifier.Alg = PS256 184 | err = verifier.Verify([]byte(""), []byte("")) 185 | assert.NotNil(err) 186 | assert.Equal("verification failed rsa.VerifyPSS err crypto/rsa: verification error", err.Error()) 187 | 188 | verifier.PublicKey = dsaPrivateKey.PublicKey 189 | verifier.Alg = ES256 190 | err = verifier.Verify([]byte(""), []byte("")) 191 | assert.NotNil(err) 192 | assert.Equal("Unrecognized public key type", err.Error()) 193 | 194 | verifier.PublicKey = ecdsaPrivateKey.Public() 195 | verifier.Alg = ES256 196 | verifier.Alg.privateKeyECDSACurve = nil 197 | err = verifier.Verify([]byte(""), []byte("")) 198 | assert.NotNil(err) 199 | assert.Equal("Could not find an elliptic curve for the ecdsa algorithm", err.Error()) 200 | 201 | verifier.Alg.privateKeyECDSACurve = elliptic.P256() 202 | } 203 | 204 | func TestFromBase64IntErrors(t *testing.T) { 205 | assert := assert.New(t) 206 | assert.Panics(func() { FromBase64Int("z") }) 207 | } 208 | 209 | func TestSignVerifyWithoutMessage(t *testing.T) { 210 | assert := assert.New(t) 211 | 212 | signer, err := NewSigner(ES256, nil) 213 | assert.Nil(err, "Error creating ES256 signer") 214 | 215 | verifier := signer.Verifier() 216 | 217 | hasher := signer.alg.HashFunc.New() 218 | _, _ = hasher.Write([]byte("ahoy")) // Write() on hash never fails 219 | digest := hasher.Sum(nil) 220 | 221 | sigs, err := Sign(rand.Reader, digest, []ByteSigner{signer}) 222 | assert.Nil(err) 223 | 224 | err = Verify(digest, sigs, []ByteVerifier{verifier}) 225 | assert.Nil(err) 226 | 227 | err = Verify(digest, sigs, []ByteVerifier{}) 228 | assert.NotNil(err) 229 | assert.Equal(err.Error(), "Wrong number of signatures 1 and verifiers 0") 230 | } 231 | 232 | func TestI2OSPCorrectness(t *testing.T) { 233 | assert := assert.New(t) 234 | 235 | // negative int 236 | assert.Panics(func() { I2OSP(big.NewInt(int64(-1)), 2) }) 237 | 238 | // not enough bytes in output / "integer too large" 239 | assert.Panics(func() { I2OSP(big.NewInt(int64(0)), 0) }) 240 | assert.Panics(func() { I2OSP(big.NewInt(int64(1)), 0) }) 241 | assert.Panics(func() { I2OSP(big.NewInt(int64(256)), 1) }) 242 | 243 | assert.Equal(I2OSP(big.NewInt(int64(0)), 2), []byte("\x00\x00")) 244 | assert.Equal(I2OSP(big.NewInt(int64(1)), 2), []byte("\x00\x01")) 245 | assert.Equal(I2OSP(big.NewInt(int64(255)), 2), []byte("\x00\xFF")) 246 | assert.Equal(I2OSP(big.NewInt(int64(256)), 2), []byte("\x01\x00")) 247 | assert.Equal(I2OSP(big.NewInt(int64(65535)), 2), []byte("\xFF\xFF")) 248 | 249 | } 250 | 251 | func TestI2OSPTiming(t *testing.T) { 252 | assert := assert.New(t) 253 | 254 | var ( 255 | toleranceNS = int64(500) // i.e. 0.5 microseconds 256 | zero = big.NewInt(int64(0)) 257 | biggerN = rsaPrivateKey.Primes[0] 258 | biggerNSize = len(biggerN.Bytes()) 259 | call_args = []struct { 260 | N *big.Int 261 | Size int 262 | }{ 263 | {zero, biggerNSize}, 264 | {biggerN, biggerNSize}, 265 | } 266 | elapsed_times []time.Duration 267 | ) 268 | if os.Getenv("CI") == "true" { 269 | toleranceNS = int64(50000) // i.e. 50 microseconds 270 | fmt.Printf("I2OSPTiming using larger timing diff in CI of %s", time.Duration(toleranceNS)) 271 | } 272 | 273 | for _, args := range call_args { 274 | start := time.Now() 275 | I2OSP(args.N, args.Size) 276 | elapsed_times = append(elapsed_times, time.Since(start)) 277 | } 278 | assert.Equal(len(call_args), len(elapsed_times)) 279 | 280 | diff := int64(elapsed_times[0]) - int64(elapsed_times[1]) 281 | if diff < 0 { 282 | diff = -diff 283 | } 284 | fmt.Printf("I2OSPTiming timing diff is %s", time.Duration(diff)) 285 | assert.True(diff < toleranceNS) 286 | } 287 | 288 | func TestApproxEqual(t *testing.T) { 289 | assert := assert.New(t) 290 | 291 | assert.True(approxEqual(1, 1, 0)) 292 | assert.True(approxEqual(8, 9, 1)) 293 | assert.True(approxEqual(9, 8, 1)) 294 | assert.True(approxEqual(10, 5, 5)) 295 | assert.True(approxEqual(-1, 0, 1)) 296 | 297 | assert.False(approxEqual(10, 5, 1)) 298 | assert.False(approxEqual(6, 5, 0)) 299 | } 300 | -------------------------------------------------------------------------------- /errors.go: -------------------------------------------------------------------------------- 1 | package cose 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | var ( 8 | ErrInvalidAlg = errors.New("Invalid algorithm") 9 | ErrAlgNotFound = errors.New("Error fetching alg") 10 | ErrECDSAVerification = errors.New("verification failed ecdsa.Verify") 11 | ErrRSAPSSVerification = errors.New("verification failed rsa.VerifyPSS err crypto/rsa: verification error") 12 | ErrMissingCOSETagForLabel = errors.New("No common COSE tag for label") 13 | ErrMissingCOSETagForTag = errors.New("No common COSE label for tag") 14 | ErrNilSigHeader = errors.New("Signature.headers is nil") 15 | ErrNilSigProtectedHeaders = errors.New("Signature.headers.protected is nil") 16 | ErrNilSignatures = errors.New("SignMessage.signatures is nil. Use AddSignature to add one") 17 | ErrNoSignatures = errors.New("No signatures to sign the message. Use AddSignature to add them") 18 | ErrNoSignerFound = errors.New("No signer found") 19 | ErrNoVerifierFound = errors.New("No verifier found") 20 | ErrUnavailableHashFunc = errors.New("hash function is not available") 21 | ErrUnknownPrivateKeyType = errors.New("Unrecognized private key type") 22 | ErrUnknownPublicKeyType = errors.New("Unrecognized public key type") 23 | ) 24 | -------------------------------------------------------------------------------- /example/sign.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | cose "go.mozilla.org/cose" 7 | ) 8 | 9 | func main() { 10 | // create a signer with a new private key 11 | signer, err := cose.NewSigner(cose.ES256, nil) 12 | if err != nil { 13 | panic(fmt.Sprintf(fmt.Sprintf("Error creating signer %s", err))) 14 | } 15 | 16 | // create a signature 17 | sig := cose.NewSignature() 18 | sig.Headers.Unprotected["kid"] = 1 19 | sig.Headers.Protected["alg"] = "ES256" 20 | 21 | // create a message 22 | external := []byte("") // optional external data see https://tools.ietf.org/html/rfc8152#section-4.3 23 | 24 | msg := cose.NewSignMessage() 25 | msg.Payload = []byte("payload to sign") 26 | msg.AddSignature(sig) 27 | 28 | err = msg.Sign(rand.Reader, external, []cose.Signer{*signer}) 29 | if err == nil { 30 | fmt.Println(fmt.Sprintf("Message signature (ES256): %x", msg.Signatures[0].SignatureBytes)) 31 | } else { 32 | panic(fmt.Sprintf("Error signing the message %+v", err)) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /example/verify.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | cose "go.mozilla.org/cose" 7 | ) 8 | 9 | func main() { 10 | // create a signer with a new private key 11 | signer, err := cose.NewSigner(cose.ES256, nil) 12 | if err != nil { 13 | panic(fmt.Sprintf(fmt.Sprintf("Error creating signer %s", err))) 14 | } 15 | 16 | // create a signature 17 | sig := cose.NewSignature() 18 | sig.Headers.Unprotected["kid"] = 1 19 | sig.Headers.Protected["alg"] = "ES256" 20 | 21 | // create a message 22 | external := []byte("") // optional external data see https://tools.ietf.org/html/rfc8152#section-4.3 23 | 24 | msg := cose.NewSignMessage() 25 | msg.Payload = []byte("payload to sign") 26 | msg.AddSignature(sig) 27 | 28 | err = msg.Sign(rand.Reader, external, []cose.Signer{*signer}) 29 | if err == nil { 30 | fmt.Println(fmt.Sprintf("Message signature (ES256): %x", msg.Signatures[0].SignatureBytes)) 31 | } else { 32 | panic(fmt.Sprintf("Error signing the message %+v", err)) 33 | } 34 | 35 | // derive a verifier using the signer's public key and COSE algorithm 36 | verifier := signer.Verifier() 37 | 38 | // Verify 39 | err = msg.Verify(external, []cose.Verifier{*verifier}) 40 | if err == nil { 41 | fmt.Println("Message signature verified") 42 | } else { 43 | fmt.Println(fmt.Sprintf("Error verifying the message %+v", err)) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /fuzz.go: -------------------------------------------------------------------------------- 1 | // +build gofuzz 2 | 3 | package cose 4 | 5 | func Fuzz(data []byte) int { 6 | if _, err := Unmarshal(data); err != nil { 7 | return 0 8 | } 9 | return 1 10 | } 11 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module go.mozilla.org/cose 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/davecgh/go-spew v1.1.0 // indirect 7 | github.com/fxamacker/cbor/v2 v2.2.1-0.20200429214022-fc263b46c618 8 | github.com/pkg/errors v0.8.0 9 | github.com/pmezard/go-difflib v1.0.0 // indirect 10 | github.com/stretchr/testify v1.2.1 11 | ) 12 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 2 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/fxamacker/cbor/v2 v2.2.1-0.20200429214022-fc263b46c618 h1:RIQZGQ00xy1acO7H7mjL8N5ZDyI0soZG7X8akiXwSTo= 4 | github.com/fxamacker/cbor/v2 v2.2.1-0.20200429214022-fc263b46c618/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= 5 | github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= 6 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 7 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 8 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 9 | github.com/stretchr/testify v1.2.1 h1:52QO5WkIUcHGIR7EnGagH88x1bUzqGXTC5/1bDTUQ7U= 10 | github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 11 | github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= 12 | github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= 13 | -------------------------------------------------------------------------------- /samples/CWT_A_3.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/CWT_A_3.json.cose -------------------------------------------------------------------------------- /samples/CWT_A_4.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/CWT_A_4.json.cose -------------------------------------------------------------------------------- /samples/CWT_A_5.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/CWT_A_5.json.cose -------------------------------------------------------------------------------- /samples/CWT_A_6.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/CWT_A_6.json.cose -------------------------------------------------------------------------------- /samples/CWT_A_7.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/CWT_A_7.json.cose -------------------------------------------------------------------------------- /samples/RFC8152_Appendix_B.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/RFC8152_Appendix_B.json.cose -------------------------------------------------------------------------------- /samples/RFC8152_Appendix_C_1_1.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/RFC8152_Appendix_C_1_1.json.cose -------------------------------------------------------------------------------- /samples/RFC8152_Appendix_C_1_2.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/RFC8152_Appendix_C_1_2.json.cose -------------------------------------------------------------------------------- /samples/RFC8152_Appendix_C_1_3.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/RFC8152_Appendix_C_1_3.json.cose -------------------------------------------------------------------------------- /samples/RFC8152_Appendix_C_1_4.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/RFC8152_Appendix_C_1_4.json.cose -------------------------------------------------------------------------------- /samples/RFC8152_Appendix_C_2_1.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/RFC8152_Appendix_C_2_1.json.cose -------------------------------------------------------------------------------- /samples/RFC8152_Appendix_C_3_1.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/RFC8152_Appendix_C_3_1.json.cose -------------------------------------------------------------------------------- /samples/RFC8152_Appendix_C_3_2.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/RFC8152_Appendix_C_3_2.json.cose -------------------------------------------------------------------------------- /samples/RFC8152_Appendix_C_3_3.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/RFC8152_Appendix_C_3_3.json.cose -------------------------------------------------------------------------------- /samples/RFC8152_Appendix_C_3_4.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/RFC8152_Appendix_C_3_4.json.cose -------------------------------------------------------------------------------- /samples/RFC8152_Appendix_C_4_1.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/RFC8152_Appendix_C_4_1.json.cose -------------------------------------------------------------------------------- /samples/RFC8152_Appendix_C_4_2.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/RFC8152_Appendix_C_4_2.json.cose -------------------------------------------------------------------------------- /samples/RFC8152_Appendix_C_5_1.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/RFC8152_Appendix_C_5_1.json.cose -------------------------------------------------------------------------------- /samples/RFC8152_Appendix_C_5_2.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/RFC8152_Appendix_C_5_2.json.cose -------------------------------------------------------------------------------- /samples/RFC8152_Appendix_C_5_3.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/RFC8152_Appendix_C_5_3.json.cose -------------------------------------------------------------------------------- /samples/RFC8152_Appendix_C_5_4.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/RFC8152_Appendix_C_5_4.json.cose -------------------------------------------------------------------------------- /samples/RFC8152_Appendix_C_6_1.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/RFC8152_Appendix_C_6_1.json.cose -------------------------------------------------------------------------------- /samples/X25519-tests_x25519-hkdf-256-direct.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/X25519-tests_x25519-hkdf-256-direct.json.cose -------------------------------------------------------------------------------- /samples/X25519-tests_x25519-ss-hkdf-256-direct.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/X25519-tests_x25519-ss-hkdf-256-direct.json.cose -------------------------------------------------------------------------------- /samples/aes-ccm-examples_aes-ccm-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-ccm-examples_aes-ccm-01.json.cose -------------------------------------------------------------------------------- /samples/aes-ccm-examples_aes-ccm-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-ccm-examples_aes-ccm-02.json.cose -------------------------------------------------------------------------------- /samples/aes-ccm-examples_aes-ccm-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-ccm-examples_aes-ccm-03.json.cose -------------------------------------------------------------------------------- /samples/aes-ccm-examples_aes-ccm-04.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-ccm-examples_aes-ccm-04.json.cose -------------------------------------------------------------------------------- /samples/aes-ccm-examples_aes-ccm-05.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-ccm-examples_aes-ccm-05.json.cose -------------------------------------------------------------------------------- /samples/aes-ccm-examples_aes-ccm-06.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-ccm-examples_aes-ccm-06.json.cose -------------------------------------------------------------------------------- /samples/aes-ccm-examples_aes-ccm-07.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-ccm-examples_aes-ccm-07.json.cose -------------------------------------------------------------------------------- /samples/aes-ccm-examples_aes-ccm-08.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-ccm-examples_aes-ccm-08.json.cose -------------------------------------------------------------------------------- /samples/aes-ccm-examples_aes-ccm-enc-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-ccm-examples_aes-ccm-enc-01.json.cose -------------------------------------------------------------------------------- /samples/aes-ccm-examples_aes-ccm-enc-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-ccm-examples_aes-ccm-enc-02.json.cose -------------------------------------------------------------------------------- /samples/aes-ccm-examples_aes-ccm-enc-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-ccm-examples_aes-ccm-enc-03.json.cose -------------------------------------------------------------------------------- /samples/aes-ccm-examples_aes-ccm-enc-04.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-ccm-examples_aes-ccm-enc-04.json.cose -------------------------------------------------------------------------------- /samples/aes-ccm-examples_aes-ccm-enc-05.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-ccm-examples_aes-ccm-enc-05.json.cose -------------------------------------------------------------------------------- /samples/aes-ccm-examples_aes-ccm-enc-06.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-ccm-examples_aes-ccm-enc-06.json.cose -------------------------------------------------------------------------------- /samples/aes-ccm-examples_aes-ccm-enc-07.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-ccm-examples_aes-ccm-enc-07.json.cose -------------------------------------------------------------------------------- /samples/aes-ccm-examples_aes-ccm-enc-08.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-ccm-examples_aes-ccm-enc-08.json.cose -------------------------------------------------------------------------------- /samples/aes-gcm-examples_aes-gcm-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-gcm-examples_aes-gcm-01.json.cose -------------------------------------------------------------------------------- /samples/aes-gcm-examples_aes-gcm-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-gcm-examples_aes-gcm-02.json.cose -------------------------------------------------------------------------------- /samples/aes-gcm-examples_aes-gcm-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-gcm-examples_aes-gcm-03.json.cose -------------------------------------------------------------------------------- /samples/aes-gcm-examples_aes-gcm-04.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-gcm-examples_aes-gcm-04.json.cose -------------------------------------------------------------------------------- /samples/aes-gcm-examples_aes-gcm-05.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-gcm-examples_aes-gcm-05.json.cose -------------------------------------------------------------------------------- /samples/aes-gcm-examples_aes-gcm-enc-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-gcm-examples_aes-gcm-enc-01.json.cose -------------------------------------------------------------------------------- /samples/aes-gcm-examples_aes-gcm-enc-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-gcm-examples_aes-gcm-enc-02.json.cose -------------------------------------------------------------------------------- /samples/aes-gcm-examples_aes-gcm-enc-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-gcm-examples_aes-gcm-enc-03.json.cose -------------------------------------------------------------------------------- /samples/aes-gcm-examples_aes-gcm-enc-04.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-gcm-examples_aes-gcm-enc-04.json.cose -------------------------------------------------------------------------------- /samples/aes-wrap-examples_aes-wrap-128-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-wrap-examples_aes-wrap-128-01.json.cose -------------------------------------------------------------------------------- /samples/aes-wrap-examples_aes-wrap-128-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-wrap-examples_aes-wrap-128-02.json.cose -------------------------------------------------------------------------------- /samples/aes-wrap-examples_aes-wrap-128-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-wrap-examples_aes-wrap-128-03.json.cose -------------------------------------------------------------------------------- /samples/aes-wrap-examples_aes-wrap-128-04.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-wrap-examples_aes-wrap-128-04.json.cose -------------------------------------------------------------------------------- /samples/aes-wrap-examples_aes-wrap-128-05.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-wrap-examples_aes-wrap-128-05.json.cose -------------------------------------------------------------------------------- /samples/aes-wrap-examples_aes-wrap-192-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-wrap-examples_aes-wrap-192-01.json.cose -------------------------------------------------------------------------------- /samples/aes-wrap-examples_aes-wrap-192-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-wrap-examples_aes-wrap-192-02.json.cose -------------------------------------------------------------------------------- /samples/aes-wrap-examples_aes-wrap-192-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-wrap-examples_aes-wrap-192-03.json.cose -------------------------------------------------------------------------------- /samples/aes-wrap-examples_aes-wrap-192-04.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-wrap-examples_aes-wrap-192-04.json.cose -------------------------------------------------------------------------------- /samples/aes-wrap-examples_aes-wrap-192-05.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-wrap-examples_aes-wrap-192-05.json.cose -------------------------------------------------------------------------------- /samples/aes-wrap-examples_aes-wrap-256-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-wrap-examples_aes-wrap-256-01.json.cose -------------------------------------------------------------------------------- /samples/aes-wrap-examples_aes-wrap-256-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-wrap-examples_aes-wrap-256-02.json.cose -------------------------------------------------------------------------------- /samples/aes-wrap-examples_aes-wrap-256-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-wrap-examples_aes-wrap-256-03.json.cose -------------------------------------------------------------------------------- /samples/aes-wrap-examples_aes-wrap-256-04.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-wrap-examples_aes-wrap-256-04.json.cose -------------------------------------------------------------------------------- /samples/aes-wrap-examples_aes-wrap-256-05.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/aes-wrap-examples_aes-wrap-256-05.json.cose -------------------------------------------------------------------------------- /samples/cbc-mac-examples_cbc-mac-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/cbc-mac-examples_cbc-mac-01.json.cose -------------------------------------------------------------------------------- /samples/cbc-mac-examples_cbc-mac-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/cbc-mac-examples_cbc-mac-02.json.cose -------------------------------------------------------------------------------- /samples/cbc-mac-examples_cbc-mac-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/cbc-mac-examples_cbc-mac-03.json.cose -------------------------------------------------------------------------------- /samples/cbc-mac-examples_cbc-mac-04.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/cbc-mac-examples_cbc-mac-04.json.cose -------------------------------------------------------------------------------- /samples/cbc-mac-examples_cbc-mac-enc-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/cbc-mac-examples_cbc-mac-enc-01.json.cose -------------------------------------------------------------------------------- /samples/cbc-mac-examples_cbc-mac-enc-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/cbc-mac-examples_cbc-mac-enc-02.json.cose -------------------------------------------------------------------------------- /samples/cbc-mac-examples_cbc-mac-enc-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/cbc-mac-examples_cbc-mac-enc-03.json.cose -------------------------------------------------------------------------------- /samples/cbc-mac-examples_cbc-mac-enc-04.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/cbc-mac-examples_cbc-mac-enc-04.json.cose -------------------------------------------------------------------------------- /samples/chacha-poly-examples_chacha-poly-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/chacha-poly-examples_chacha-poly-01.json.cose -------------------------------------------------------------------------------- /samples/chacha-poly-examples_chacha-poly-enc-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/chacha-poly-examples_chacha-poly-enc-01.json.cose -------------------------------------------------------------------------------- /samples/ecdh-direct-examples_p256-hkdf-256-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-direct-examples_p256-hkdf-256-01.json.cose -------------------------------------------------------------------------------- /samples/ecdh-direct-examples_p256-hkdf-256-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-direct-examples_p256-hkdf-256-02.json.cose -------------------------------------------------------------------------------- /samples/ecdh-direct-examples_p256-hkdf-256-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-direct-examples_p256-hkdf-256-03.json.cose -------------------------------------------------------------------------------- /samples/ecdh-direct-examples_p256-hkdf-512-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-direct-examples_p256-hkdf-512-01.json.cose -------------------------------------------------------------------------------- /samples/ecdh-direct-examples_p256-hkdf-512-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-direct-examples_p256-hkdf-512-02.json.cose -------------------------------------------------------------------------------- /samples/ecdh-direct-examples_p256-hkdf-512-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-direct-examples_p256-hkdf-512-03.json.cose -------------------------------------------------------------------------------- /samples/ecdh-direct-examples_p256-ss-hkdf-256-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-direct-examples_p256-ss-hkdf-256-01.json.cose -------------------------------------------------------------------------------- /samples/ecdh-direct-examples_p256-ss-hkdf-256-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-direct-examples_p256-ss-hkdf-256-02.json.cose -------------------------------------------------------------------------------- /samples/ecdh-direct-examples_p256-ss-hkdf-256-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-direct-examples_p256-ss-hkdf-256-03.json.cose -------------------------------------------------------------------------------- /samples/ecdh-direct-examples_p256-ss-hkdf-512-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-direct-examples_p256-ss-hkdf-512-01.json.cose -------------------------------------------------------------------------------- /samples/ecdh-direct-examples_p256-ss-hkdf-512-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-direct-examples_p256-ss-hkdf-512-02.json.cose -------------------------------------------------------------------------------- /samples/ecdh-direct-examples_p256-ss-hkdf-512-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-direct-examples_p256-ss-hkdf-512-03.json.cose -------------------------------------------------------------------------------- /samples/ecdh-direct-examples_p521-hkdf-256-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-direct-examples_p521-hkdf-256-01.json.cose -------------------------------------------------------------------------------- /samples/ecdh-direct-examples_p521-hkdf-256-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-direct-examples_p521-hkdf-256-02.json.cose -------------------------------------------------------------------------------- /samples/ecdh-direct-examples_p521-hkdf-256-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-direct-examples_p521-hkdf-256-03.json.cose -------------------------------------------------------------------------------- /samples/ecdh-direct-examples_p521-hkdf-512-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-direct-examples_p521-hkdf-512-01.json.cose -------------------------------------------------------------------------------- /samples/ecdh-direct-examples_p521-hkdf-512-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-direct-examples_p521-hkdf-512-02.json.cose -------------------------------------------------------------------------------- /samples/ecdh-direct-examples_p521-hkdf-512-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-direct-examples_p521-hkdf-512-03.json.cose -------------------------------------------------------------------------------- /samples/ecdh-direct-examples_p521-ss-hkdf-256-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-direct-examples_p521-ss-hkdf-256-01.json.cose -------------------------------------------------------------------------------- /samples/ecdh-direct-examples_p521-ss-hkdf-256-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-direct-examples_p521-ss-hkdf-256-02.json.cose -------------------------------------------------------------------------------- /samples/ecdh-direct-examples_p521-ss-hkdf-256-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-direct-examples_p521-ss-hkdf-256-03.json.cose -------------------------------------------------------------------------------- /samples/ecdh-direct-examples_p521-ss-hkdf-512-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-direct-examples_p521-ss-hkdf-512-01.json.cose -------------------------------------------------------------------------------- /samples/ecdh-direct-examples_p521-ss-hkdf-512-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-direct-examples_p521-ss-hkdf-512-02.json.cose -------------------------------------------------------------------------------- /samples/ecdh-direct-examples_p521-ss-hkdf-512-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-direct-examples_p521-ss-hkdf-512-03.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p256-ss-wrap-128-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p256-ss-wrap-128-01.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p256-ss-wrap-128-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p256-ss-wrap-128-02.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p256-ss-wrap-128-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p256-ss-wrap-128-03.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p256-ss-wrap-192-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p256-ss-wrap-192-01.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p256-ss-wrap-192-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p256-ss-wrap-192-02.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p256-ss-wrap-192-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p256-ss-wrap-192-03.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p256-ss-wrap-256-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p256-ss-wrap-256-01.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p256-ss-wrap-256-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p256-ss-wrap-256-02.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p256-ss-wrap-256-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p256-ss-wrap-256-03.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p256-wrap-128-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p256-wrap-128-01.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p256-wrap-128-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p256-wrap-128-02.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p256-wrap-128-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p256-wrap-128-03.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p256-wrap-192-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p256-wrap-192-01.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p256-wrap-192-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p256-wrap-192-02.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p256-wrap-192-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p256-wrap-192-03.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p256-wrap-256-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p256-wrap-256-01.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p256-wrap-256-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p256-wrap-256-02.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p256-wrap-256-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p256-wrap-256-03.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p521-ss-wrap-128-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p521-ss-wrap-128-01.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p521-ss-wrap-128-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p521-ss-wrap-128-02.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p521-ss-wrap-128-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p521-ss-wrap-128-03.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p521-ss-wrap-192-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p521-ss-wrap-192-01.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p521-ss-wrap-192-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p521-ss-wrap-192-02.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p521-ss-wrap-192-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p521-ss-wrap-192-03.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p521-ss-wrap-256-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p521-ss-wrap-256-01.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p521-ss-wrap-256-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p521-ss-wrap-256-02.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p521-ss-wrap-256-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p521-ss-wrap-256-03.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p521-wrap-128-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p521-wrap-128-01.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p521-wrap-128-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p521-wrap-128-02.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p521-wrap-128-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p521-wrap-128-03.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p521-wrap-192-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p521-wrap-192-01.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p521-wrap-192-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p521-wrap-192-02.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p521-wrap-192-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p521-wrap-192-03.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p521-wrap-256-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p521-wrap-256-01.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p521-wrap-256-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p521-wrap-256-02.json.cose -------------------------------------------------------------------------------- /samples/ecdh-wrap-examples_p521-wrap-256-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdh-wrap-examples_p521-wrap-256-03.json.cose -------------------------------------------------------------------------------- /samples/ecdsa-examples_ecdsa-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdsa-examples_ecdsa-01.json.cose -------------------------------------------------------------------------------- /samples/ecdsa-examples_ecdsa-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdsa-examples_ecdsa-02.json.cose -------------------------------------------------------------------------------- /samples/ecdsa-examples_ecdsa-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdsa-examples_ecdsa-03.json.cose -------------------------------------------------------------------------------- /samples/ecdsa-examples_ecdsa-04.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdsa-examples_ecdsa-04.json.cose -------------------------------------------------------------------------------- /samples/ecdsa-examples_ecdsa-sig-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdsa-examples_ecdsa-sig-01.json.cose -------------------------------------------------------------------------------- /samples/ecdsa-examples_ecdsa-sig-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdsa-examples_ecdsa-sig-02.json.cose -------------------------------------------------------------------------------- /samples/ecdsa-examples_ecdsa-sig-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdsa-examples_ecdsa-sig-03.json.cose -------------------------------------------------------------------------------- /samples/ecdsa-examples_ecdsa-sig-04.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/ecdsa-examples_ecdsa-sig-04.json.cose -------------------------------------------------------------------------------- /samples/eddsa-examples_eddsa-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/eddsa-examples_eddsa-01.json.cose -------------------------------------------------------------------------------- /samples/eddsa-examples_eddsa-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/eddsa-examples_eddsa-02.json.cose -------------------------------------------------------------------------------- /samples/eddsa-examples_eddsa-sig-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/eddsa-examples_eddsa-sig-01.json.cose -------------------------------------------------------------------------------- /samples/eddsa-examples_eddsa-sig-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/eddsa-examples_eddsa-sig-02.json.cose -------------------------------------------------------------------------------- /samples/encrypted-tests_aes-gcm-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/encrypted-tests_aes-gcm-01.json.cose -------------------------------------------------------------------------------- /samples/encrypted-tests_enc-fail-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/encrypted-tests_enc-fail-01.json.cose -------------------------------------------------------------------------------- /samples/encrypted-tests_enc-fail-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/encrypted-tests_enc-fail-02.json.cose -------------------------------------------------------------------------------- /samples/encrypted-tests_enc-fail-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/encrypted-tests_enc-fail-03.json.cose -------------------------------------------------------------------------------- /samples/encrypted-tests_enc-fail-04.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/encrypted-tests_enc-fail-04.json.cose -------------------------------------------------------------------------------- /samples/encrypted-tests_enc-fail-06.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/encrypted-tests_enc-fail-06.json.cose -------------------------------------------------------------------------------- /samples/encrypted-tests_enc-fail-07.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/encrypted-tests_enc-fail-07.json.cose -------------------------------------------------------------------------------- /samples/encrypted-tests_enc-pass-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/encrypted-tests_enc-pass-01.json.cose -------------------------------------------------------------------------------- /samples/encrypted-tests_enc-pass-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/encrypted-tests_enc-pass-02.json.cose -------------------------------------------------------------------------------- /samples/encrypted-tests_enc-pass-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/encrypted-tests_enc-pass-03.json.cose -------------------------------------------------------------------------------- /samples/enveloped-tests_aes-gcm-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/enveloped-tests_aes-gcm-01.json.cose -------------------------------------------------------------------------------- /samples/enveloped-tests_env-fail-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/enveloped-tests_env-fail-01.json.cose -------------------------------------------------------------------------------- /samples/enveloped-tests_env-fail-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/enveloped-tests_env-fail-02.json.cose -------------------------------------------------------------------------------- /samples/enveloped-tests_env-fail-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/enveloped-tests_env-fail-03.json.cose -------------------------------------------------------------------------------- /samples/enveloped-tests_env-fail-04.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/enveloped-tests_env-fail-04.json.cose -------------------------------------------------------------------------------- /samples/enveloped-tests_env-fail-06.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/enveloped-tests_env-fail-06.json.cose -------------------------------------------------------------------------------- /samples/enveloped-tests_env-fail-07.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/enveloped-tests_env-fail-07.json.cose -------------------------------------------------------------------------------- /samples/enveloped-tests_env-pass-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/enveloped-tests_env-pass-01.json.cose -------------------------------------------------------------------------------- /samples/enveloped-tests_env-pass-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/enveloped-tests_env-pass-02.json.cose -------------------------------------------------------------------------------- /samples/enveloped-tests_env-pass-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/enveloped-tests_env-pass-03.json.cose -------------------------------------------------------------------------------- /samples/hkdf-aes-examples_hmac-aes-128-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-aes-examples_hmac-aes-128-01.json.cose -------------------------------------------------------------------------------- /samples/hkdf-aes-examples_hmac-aes-128-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-aes-examples_hmac-aes-128-02.json.cose -------------------------------------------------------------------------------- /samples/hkdf-aes-examples_hmac-aes-128-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-aes-examples_hmac-aes-128-03.json.cose -------------------------------------------------------------------------------- /samples/hkdf-aes-examples_hmac-aes-128-04.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-aes-examples_hmac-aes-128-04.json.cose -------------------------------------------------------------------------------- /samples/hkdf-aes-examples_hmac-aes-128-05.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-aes-examples_hmac-aes-128-05.json.cose -------------------------------------------------------------------------------- /samples/hkdf-aes-examples_hmac-aes-128-06.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-aes-examples_hmac-aes-128-06.json.cose -------------------------------------------------------------------------------- /samples/hkdf-aes-examples_hmac-aes-128-07.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-aes-examples_hmac-aes-128-07.json.cose -------------------------------------------------------------------------------- /samples/hkdf-aes-examples_hmac-aes-128-08.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-aes-examples_hmac-aes-128-08.json.cose -------------------------------------------------------------------------------- /samples/hkdf-aes-examples_hmac-aes-128-09.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-aes-examples_hmac-aes-128-09.json.cose -------------------------------------------------------------------------------- /samples/hkdf-aes-examples_hmac-aes-128-10.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-aes-examples_hmac-aes-128-10.json.cose -------------------------------------------------------------------------------- /samples/hkdf-aes-examples_hmac-aes-128-11.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-aes-examples_hmac-aes-128-11.json.cose -------------------------------------------------------------------------------- /samples/hkdf-aes-examples_hmac-aes-128-12.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-aes-examples_hmac-aes-128-12.json.cose -------------------------------------------------------------------------------- /samples/hkdf-aes-examples_hmac-aes-128-13.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-aes-examples_hmac-aes-128-13.json.cose -------------------------------------------------------------------------------- /samples/hkdf-aes-examples_hmac-aes-128-14.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-aes-examples_hmac-aes-128-14.json.cose -------------------------------------------------------------------------------- /samples/hkdf-aes-examples_hmac-aes-256-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-aes-examples_hmac-aes-256-01.json.cose -------------------------------------------------------------------------------- /samples/hkdf-aes-examples_hmac-aes-256-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-aes-examples_hmac-aes-256-02.json.cose -------------------------------------------------------------------------------- /samples/hkdf-aes-examples_hmac-aes-256-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-aes-examples_hmac-aes-256-03.json.cose -------------------------------------------------------------------------------- /samples/hkdf-aes-examples_hmac-aes-256-04.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-aes-examples_hmac-aes-256-04.json.cose -------------------------------------------------------------------------------- /samples/hkdf-aes-examples_hmac-aes-256-05.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-aes-examples_hmac-aes-256-05.json.cose -------------------------------------------------------------------------------- /samples/hkdf-aes-examples_hmac-aes-256-06.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-aes-examples_hmac-aes-256-06.json.cose -------------------------------------------------------------------------------- /samples/hkdf-aes-examples_hmac-aes-256-07.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-aes-examples_hmac-aes-256-07.json.cose -------------------------------------------------------------------------------- /samples/hkdf-aes-examples_hmac-aes-256-08.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-aes-examples_hmac-aes-256-08.json.cose -------------------------------------------------------------------------------- /samples/hkdf-aes-examples_hmac-aes-256-09.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-aes-examples_hmac-aes-256-09.json.cose -------------------------------------------------------------------------------- /samples/hkdf-aes-examples_hmac-aes-256-10.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-aes-examples_hmac-aes-256-10.json.cose -------------------------------------------------------------------------------- /samples/hkdf-aes-examples_hmac-aes-256-11.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-aes-examples_hmac-aes-256-11.json.cose -------------------------------------------------------------------------------- /samples/hkdf-aes-examples_hmac-aes-256-12.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-aes-examples_hmac-aes-256-12.json.cose -------------------------------------------------------------------------------- /samples/hkdf-aes-examples_hmac-aes-256-13.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-aes-examples_hmac-aes-256-13.json.cose -------------------------------------------------------------------------------- /samples/hkdf-aes-examples_hmac-aes-256-14.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-aes-examples_hmac-aes-256-14.json.cose -------------------------------------------------------------------------------- /samples/hkdf-hmac-sha-examples_hmac-sha-256-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-hmac-sha-examples_hmac-sha-256-01.json.cose -------------------------------------------------------------------------------- /samples/hkdf-hmac-sha-examples_hmac-sha-256-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-hmac-sha-examples_hmac-sha-256-02.json.cose -------------------------------------------------------------------------------- /samples/hkdf-hmac-sha-examples_hmac-sha-256-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-hmac-sha-examples_hmac-sha-256-03.json.cose -------------------------------------------------------------------------------- /samples/hkdf-hmac-sha-examples_hmac-sha-256-04.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-hmac-sha-examples_hmac-sha-256-04.json.cose -------------------------------------------------------------------------------- /samples/hkdf-hmac-sha-examples_hmac-sha-256-05.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-hmac-sha-examples_hmac-sha-256-05.json.cose -------------------------------------------------------------------------------- /samples/hkdf-hmac-sha-examples_hmac-sha-256-06.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-hmac-sha-examples_hmac-sha-256-06.json.cose -------------------------------------------------------------------------------- /samples/hkdf-hmac-sha-examples_hmac-sha-256-07.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-hmac-sha-examples_hmac-sha-256-07.json.cose -------------------------------------------------------------------------------- /samples/hkdf-hmac-sha-examples_hmac-sha-256-08.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-hmac-sha-examples_hmac-sha-256-08.json.cose -------------------------------------------------------------------------------- /samples/hkdf-hmac-sha-examples_hmac-sha-256-09.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-hmac-sha-examples_hmac-sha-256-09.json.cose -------------------------------------------------------------------------------- /samples/hkdf-hmac-sha-examples_hmac-sha-256-10.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-hmac-sha-examples_hmac-sha-256-10.json.cose -------------------------------------------------------------------------------- /samples/hkdf-hmac-sha-examples_hmac-sha-256-11.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-hmac-sha-examples_hmac-sha-256-11.json.cose -------------------------------------------------------------------------------- /samples/hkdf-hmac-sha-examples_hmac-sha-256-12.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-hmac-sha-examples_hmac-sha-256-12.json.cose -------------------------------------------------------------------------------- /samples/hkdf-hmac-sha-examples_hmac-sha-256-13.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-hmac-sha-examples_hmac-sha-256-13.json.cose -------------------------------------------------------------------------------- /samples/hkdf-hmac-sha-examples_hmac-sha-256-14.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-hmac-sha-examples_hmac-sha-256-14.json.cose -------------------------------------------------------------------------------- /samples/hkdf-hmac-sha-examples_hmac-sha-512-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-hmac-sha-examples_hmac-sha-512-01.json.cose -------------------------------------------------------------------------------- /samples/hkdf-hmac-sha-examples_hmac-sha-512-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-hmac-sha-examples_hmac-sha-512-02.json.cose -------------------------------------------------------------------------------- /samples/hkdf-hmac-sha-examples_hmac-sha-512-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-hmac-sha-examples_hmac-sha-512-03.json.cose -------------------------------------------------------------------------------- /samples/hkdf-hmac-sha-examples_hmac-sha-512-04.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-hmac-sha-examples_hmac-sha-512-04.json.cose -------------------------------------------------------------------------------- /samples/hkdf-hmac-sha-examples_hmac-sha-512-05.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-hmac-sha-examples_hmac-sha-512-05.json.cose -------------------------------------------------------------------------------- /samples/hkdf-hmac-sha-examples_hmac-sha-512-06.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-hmac-sha-examples_hmac-sha-512-06.json.cose -------------------------------------------------------------------------------- /samples/hkdf-hmac-sha-examples_hmac-sha-512-07.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-hmac-sha-examples_hmac-sha-512-07.json.cose -------------------------------------------------------------------------------- /samples/hkdf-hmac-sha-examples_hmac-sha-512-08.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-hmac-sha-examples_hmac-sha-512-08.json.cose -------------------------------------------------------------------------------- /samples/hkdf-hmac-sha-examples_hmac-sha-512-09.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-hmac-sha-examples_hmac-sha-512-09.json.cose -------------------------------------------------------------------------------- /samples/hkdf-hmac-sha-examples_hmac-sha-512-10.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-hmac-sha-examples_hmac-sha-512-10.json.cose -------------------------------------------------------------------------------- /samples/hkdf-hmac-sha-examples_hmac-sha-512-11.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-hmac-sha-examples_hmac-sha-512-11.json.cose -------------------------------------------------------------------------------- /samples/hkdf-hmac-sha-examples_hmac-sha-512-12.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-hmac-sha-examples_hmac-sha-512-12.json.cose -------------------------------------------------------------------------------- /samples/hkdf-hmac-sha-examples_hmac-sha-512-13.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-hmac-sha-examples_hmac-sha-512-13.json.cose -------------------------------------------------------------------------------- /samples/hkdf-hmac-sha-examples_hmac-sha-512-14.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hkdf-hmac-sha-examples_hmac-sha-512-14.json.cose -------------------------------------------------------------------------------- /samples/hmac-examples_HMac-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hmac-examples_HMac-01.json.cose -------------------------------------------------------------------------------- /samples/hmac-examples_HMac-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hmac-examples_HMac-02.json.cose -------------------------------------------------------------------------------- /samples/hmac-examples_HMac-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hmac-examples_HMac-03.json.cose -------------------------------------------------------------------------------- /samples/hmac-examples_HMac-04.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hmac-examples_HMac-04.json.cose -------------------------------------------------------------------------------- /samples/hmac-examples_HMac-05.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hmac-examples_HMac-05.json.cose -------------------------------------------------------------------------------- /samples/hmac-examples_HMac-enc-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hmac-examples_HMac-enc-01.json.cose -------------------------------------------------------------------------------- /samples/hmac-examples_HMac-enc-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hmac-examples_HMac-enc-02.json.cose -------------------------------------------------------------------------------- /samples/hmac-examples_HMac-enc-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hmac-examples_HMac-enc-03.json.cose -------------------------------------------------------------------------------- /samples/hmac-examples_HMac-enc-04.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hmac-examples_HMac-enc-04.json.cose -------------------------------------------------------------------------------- /samples/hmac-examples_HMac-enc-05.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/hmac-examples_HMac-enc-05.json.cose -------------------------------------------------------------------------------- /samples/mac-tests_HMac-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/mac-tests_HMac-01.json.cose -------------------------------------------------------------------------------- /samples/mac-tests_mac-fail-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/mac-tests_mac-fail-01.json.cose -------------------------------------------------------------------------------- /samples/mac-tests_mac-fail-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/mac-tests_mac-fail-02.json.cose -------------------------------------------------------------------------------- /samples/mac-tests_mac-fail-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/mac-tests_mac-fail-03.json.cose -------------------------------------------------------------------------------- /samples/mac-tests_mac-fail-04.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/mac-tests_mac-fail-04.json.cose -------------------------------------------------------------------------------- /samples/mac-tests_mac-fail-06.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/mac-tests_mac-fail-06.json.cose -------------------------------------------------------------------------------- /samples/mac-tests_mac-fail-07.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/mac-tests_mac-fail-07.json.cose -------------------------------------------------------------------------------- /samples/mac-tests_mac-pass-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/mac-tests_mac-pass-01.json.cose -------------------------------------------------------------------------------- /samples/mac-tests_mac-pass-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/mac-tests_mac-pass-02.json.cose -------------------------------------------------------------------------------- /samples/mac-tests_mac-pass-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/mac-tests_mac-pass-03.json.cose -------------------------------------------------------------------------------- /samples/mac0-tests_HMac-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/mac0-tests_HMac-01.json.cose -------------------------------------------------------------------------------- /samples/mac0-tests_mac-fail-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/mac0-tests_mac-fail-01.json.cose -------------------------------------------------------------------------------- /samples/mac0-tests_mac-fail-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/mac0-tests_mac-fail-02.json.cose -------------------------------------------------------------------------------- /samples/mac0-tests_mac-fail-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/mac0-tests_mac-fail-03.json.cose -------------------------------------------------------------------------------- /samples/mac0-tests_mac-fail-04.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/mac0-tests_mac-fail-04.json.cose -------------------------------------------------------------------------------- /samples/mac0-tests_mac-fail-06.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/mac0-tests_mac-fail-06.json.cose -------------------------------------------------------------------------------- /samples/mac0-tests_mac-fail-07.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/mac0-tests_mac-fail-07.json.cose -------------------------------------------------------------------------------- /samples/mac0-tests_mac-pass-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/mac0-tests_mac-pass-01.json.cose -------------------------------------------------------------------------------- /samples/mac0-tests_mac-pass-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/mac0-tests_mac-pass-02.json.cose -------------------------------------------------------------------------------- /samples/mac0-tests_mac-pass-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/mac0-tests_mac-pass-03.json.cose -------------------------------------------------------------------------------- /samples/sign-tests_ecdsa-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/sign-tests_ecdsa-01.json.cose -------------------------------------------------------------------------------- /samples/sign-tests_sign-fail-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/sign-tests_sign-fail-01.json.cose -------------------------------------------------------------------------------- /samples/sign-tests_sign-fail-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/sign-tests_sign-fail-02.json.cose -------------------------------------------------------------------------------- /samples/sign-tests_sign-fail-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/sign-tests_sign-fail-03.json.cose -------------------------------------------------------------------------------- /samples/sign-tests_sign-fail-04.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/sign-tests_sign-fail-04.json.cose -------------------------------------------------------------------------------- /samples/sign-tests_sign-fail-06.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/sign-tests_sign-fail-06.json.cose -------------------------------------------------------------------------------- /samples/sign-tests_sign-fail-07.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/sign-tests_sign-fail-07.json.cose -------------------------------------------------------------------------------- /samples/sign-tests_sign-pass-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/sign-tests_sign-pass-01.json.cose -------------------------------------------------------------------------------- /samples/sign-tests_sign-pass-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/sign-tests_sign-pass-02.json.cose -------------------------------------------------------------------------------- /samples/sign-tests_sign-pass-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/sign-tests_sign-pass-03.json.cose -------------------------------------------------------------------------------- /samples/sign1-tests_sign-fail-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/sign1-tests_sign-fail-01.json.cose -------------------------------------------------------------------------------- /samples/sign1-tests_sign-fail-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/sign1-tests_sign-fail-02.json.cose -------------------------------------------------------------------------------- /samples/sign1-tests_sign-fail-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/sign1-tests_sign-fail-03.json.cose -------------------------------------------------------------------------------- /samples/sign1-tests_sign-fail-04.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/sign1-tests_sign-fail-04.json.cose -------------------------------------------------------------------------------- /samples/sign1-tests_sign-fail-06.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/sign1-tests_sign-fail-06.json.cose -------------------------------------------------------------------------------- /samples/sign1-tests_sign-fail-07.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/sign1-tests_sign-fail-07.json.cose -------------------------------------------------------------------------------- /samples/sign1-tests_sign-pass-01.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/sign1-tests_sign-pass-01.json.cose -------------------------------------------------------------------------------- /samples/sign1-tests_sign-pass-02.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/sign1-tests_sign-pass-02.json.cose -------------------------------------------------------------------------------- /samples/sign1-tests_sign-pass-03.json.cose: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mozilla-services/go-cose/18d34e90336ddbe7bb992f6b434b0343092ecaba/samples/sign1-tests_sign-pass-03.json.cose -------------------------------------------------------------------------------- /sign_verify.go: -------------------------------------------------------------------------------- 1 | package cose 2 | 3 | import ( 4 | "bytes" 5 | "crypto" 6 | "fmt" 7 | "io" 8 | "github.com/pkg/errors" 9 | ) 10 | 11 | // Signature represents a COSE signature with CDDL fragment: 12 | // 13 | // COSE_Signature = [ 14 | // Headers, 15 | // signature : bstr 16 | // ] 17 | // 18 | // https://tools.ietf.org/html/rfc8152#section-4.1 19 | type Signature struct { 20 | Headers *Headers 21 | SignatureBytes []byte 22 | } 23 | 24 | // NewSignature returns a new COSE Signature with empty headers and 25 | // nil signature bytes 26 | func NewSignature() (s *Signature) { 27 | return &Signature{ 28 | Headers: &Headers{ 29 | Protected: map[interface{}]interface{}{}, 30 | Unprotected: map[interface{}]interface{}{}, 31 | }, 32 | SignatureBytes: nil, 33 | } 34 | } 35 | 36 | func (s *Signature) Equal(other *Signature) bool { 37 | if s == nil && other == nil { 38 | return true 39 | } 40 | return bytes.Equal(s.SignatureBytes, other.SignatureBytes) && s.Headers == other.Headers 41 | } 42 | 43 | // Decode updates the signature inplace from its COSE serialization 44 | func (s *Signature) Decode(o interface{}) { 45 | if s == nil { 46 | panic("error decoding on nil Signature") 47 | } 48 | 49 | array, ok := o.([]interface{}) 50 | if !ok { 51 | panic(fmt.Sprintf("error decoding signature Array; got %T", array)) 52 | } 53 | if len(array) != 3 { 54 | panic(fmt.Sprintf("can only decode Signature with 3 items; got %d", len(array))) 55 | } 56 | 57 | err := s.Headers.Decode(array[0:2]) 58 | if err != nil { 59 | panic(fmt.Sprintf("error decoding signature header: %+v", err)) 60 | } 61 | 62 | signatureBytes, ok := array[2].([]byte) 63 | if !ok { 64 | panic(fmt.Sprintf("unable to decode COSE signature expecting decode from interface{}; got %T", array[2])) 65 | } 66 | s.SignatureBytes = signatureBytes 67 | } 68 | 69 | // SignMessage represents a COSESignMessage with CDDL fragment: 70 | // 71 | // COSE_Sign = [ 72 | // Headers, 73 | // payload : bstr / nil, 74 | // signatures : [+ COSE_Signature] 75 | // ] 76 | // 77 | // https://tools.ietf.org/html/rfc8152#section-4.1 78 | type SignMessage struct { 79 | Headers *Headers 80 | Payload []byte 81 | Signatures []Signature 82 | } 83 | 84 | // NewSignMessage takes a []byte payload and returns a new pointer to 85 | // a SignMessage with empty headers and signatures 86 | func NewSignMessage() *SignMessage { 87 | return &SignMessage{ 88 | Headers: &Headers{ 89 | Protected: map[interface{}]interface{}{}, 90 | Unprotected: map[interface{}]interface{}{}, 91 | }, 92 | Payload: nil, 93 | Signatures: nil, 94 | } 95 | } 96 | 97 | // AddSignature adds a signature to the message signatures creating an 98 | // empty []Signature if necessary 99 | func (m *SignMessage) AddSignature(s *Signature) { 100 | if m.Signatures == nil { 101 | m.Signatures = []Signature{} 102 | } 103 | m.Signatures = append(m.Signatures, *s) 104 | } 105 | 106 | // SigStructure returns the byte slice to be signed 107 | func (m *SignMessage) SigStructure(external []byte, signature *Signature) (ToBeSigned []byte, err error) { 108 | // 1. Create a Sig_structure and populate it with the appropriate fields. 109 | // 110 | // 2. Create the value ToBeSigned by encoding the Sig_structure to a 111 | // byte string, using the encoding described in Section 14. 112 | ToBeSigned, err = buildAndMarshalSigStructure( 113 | m.Headers.EncodeProtected(), 114 | signature.Headers.EncodeProtected(), 115 | external, 116 | m.Payload) 117 | return 118 | } 119 | 120 | // signatureDigest takes an extra external byte slice and a Signature 121 | // and returns the SigStructure (i.e. ToBeSigned) hashed using the 122 | // algorithm from the signature parameter 123 | func (m *SignMessage) signatureDigest(external []byte, signature *Signature, hashFunc crypto.Hash) (digest []byte, err error) { 124 | if m == nil { 125 | err = errors.Errorf("Cannot compute signatureDigest on nil SignMessage") 126 | return 127 | } 128 | if m.Signatures == nil { 129 | err = errors.Errorf("Cannot compute signatureDigest on nil SignMessage.Signatures") 130 | return 131 | } 132 | signatureInMessage := false 133 | for _, msgSig := range m.Signatures { 134 | if msgSig.Equal(signature) { 135 | signatureInMessage = true 136 | } 137 | } 138 | if !signatureInMessage { 139 | err = errors.Errorf("SignMessage.Signatures does not include the signature to digest") 140 | return 141 | } 142 | 143 | ToBeSigned, err := m.SigStructure(external, signature) 144 | if err != nil { 145 | return nil, err 146 | } 147 | 148 | digest, err = hashSigStructure(ToBeSigned, hashFunc) 149 | if err != nil { 150 | return nil, err 151 | } 152 | 153 | return digest, err 154 | } 155 | 156 | // Signing and Verification Process 157 | // https://tools.ietf.org/html/rfc8152#section-4.4 158 | 159 | // Sign signs a SignMessage i.e. it populates 160 | // signatures[].SignatureBytes using the provided array of Signers 161 | func (m *SignMessage) Sign(rand io.Reader, external []byte, signers []Signer) (err error) { 162 | if m.Signatures == nil { 163 | return ErrNilSignatures 164 | } else if len(m.Signatures) < 1 { 165 | return ErrNoSignatures 166 | } else if len(m.Signatures) != len(signers) { 167 | return errors.Errorf("%d signers for %d signatures", len(signers), len(m.Signatures)) 168 | } 169 | 170 | for i, signature := range m.Signatures { 171 | if signature.Headers == nil { 172 | return ErrNilSigHeader 173 | } else if signature.Headers.Protected == nil { 174 | return ErrNilSigProtectedHeaders 175 | } else if signature.SignatureBytes != nil || len(signature.SignatureBytes) > 0 { 176 | return errors.Errorf("SignMessage signature %d already has signature bytes", i) 177 | } 178 | 179 | alg, err := getAlg(signature.Headers) 180 | if err != nil { 181 | return err 182 | } 183 | if alg.Value > -1 { // Negative numbers are used for second layer objects (COSE_Signature and COSE_recipient) 184 | return ErrInvalidAlg 185 | } 186 | 187 | digest, err := m.signatureDigest(external, &signature, alg.HashFunc) 188 | if err != nil { 189 | return err 190 | } 191 | 192 | signer := signers[i] 193 | if alg.Value != signer.alg.Value { 194 | return errors.Errorf("Signer of type %s cannot generate a signature of type %s", signer.alg.Name, alg.Name) 195 | } 196 | 197 | // 3. Call the signature creation algorithm passing in K (the key to 198 | // sign with), alg (the algorithm to sign with), and ToBeSigned (the 199 | // value to sign). 200 | signatureBytes, err := signer.Sign(rand, digest) 201 | if err != nil { 202 | return err 203 | } 204 | 205 | // 4. Place the resulting signature value in the 'signature' field of the array. 206 | m.Signatures[i].SignatureBytes = signatureBytes 207 | } 208 | return nil 209 | } 210 | 211 | // Verify verifies all signatures on the SignMessage returning nil for 212 | // success or an error from the first failed verification 213 | func (m *SignMessage) Verify(external []byte, verifiers []Verifier) (err error) { 214 | if m == nil || m.Signatures == nil || len(m.Signatures) < 1 { 215 | return nil 216 | } 217 | if len(m.Signatures) != len(verifiers) { 218 | return errors.Errorf("Wrong number of signatures %d and verifiers %d", len(m.Signatures), len(verifiers)) 219 | } 220 | 221 | for i, signature := range m.Signatures { 222 | if signature.Headers == nil { 223 | return ErrNilSigHeader 224 | } else if signature.Headers.Protected == nil { 225 | return ErrNilSigProtectedHeaders 226 | } else if signature.SignatureBytes == nil || len(signature.SignatureBytes) < 1 { 227 | return errors.Errorf("SignMessage signature %d missing signature bytes to verify", i) 228 | } 229 | 230 | alg, err := getAlg(signature.Headers) 231 | if err != nil { 232 | return err 233 | } 234 | if alg.Value > -1 { // Negative numbers are used for second layer objects (COSE_Signature and COSE_recipient) 235 | return ErrInvalidAlg 236 | } 237 | 238 | digest, err := m.signatureDigest(external, &signature, alg.HashFunc) 239 | if err != nil { 240 | return err 241 | } 242 | 243 | verifier := verifiers[i] 244 | 245 | // 3. Call the signature creation algorithm passing in K (the key to 246 | // sign with), alg (the algorithm to sign with), and ToBeSigned (the 247 | // value to sign). 248 | err = verifier.Verify(digest, signature.SignatureBytes) 249 | if err != nil { 250 | return err 251 | } 252 | } 253 | return 254 | } 255 | -------------------------------------------------------------------------------- /sign_verify_cose_rust_cli_test.go: -------------------------------------------------------------------------------- 1 | package cose 2 | 3 | import ( 4 | "crypto/rand" 5 | "crypto/x509" 6 | "encoding/hex" 7 | "fmt" 8 | "os" 9 | "os/exec" 10 | "testing" 11 | 12 | "github.com/stretchr/testify/assert" 13 | ) 14 | 15 | // signing tests for Firefox Addon COSE Signatures 16 | // 17 | 18 | func RustCoseVerifiesGoCoseSignatures(t *testing.T, testCase RustTestCase) { 19 | fmt.Println(fmt.Sprintf("%s", testCase.Title)) 20 | 21 | assert := assert.New(t) 22 | assert.True(len(testCase.Params) > 0, "No signature params!") 23 | 24 | signers := []Signer{} 25 | verifiers := []Verifier{} 26 | 27 | message := NewSignMessage() 28 | msgHeaders := &Headers{ 29 | Protected: map[interface{}]interface{}{}, 30 | Unprotected: map[interface{}]interface{}{}, 31 | } 32 | msgHeaders.Protected[kidTag] = testCase.Certs 33 | message.Headers = msgHeaders 34 | message.Payload = []byte(testCase.SignPayload) 35 | 36 | for _, param := range testCase.Params { 37 | key, err := x509.ParsePKCS8PrivateKey(param.pkcs8) 38 | assert.Nil(err) 39 | 40 | signer, err := NewSignerFromKey(param.algorithm, key) 41 | assert.Nil(err, fmt.Sprintf("%s: Error creating signer %s", testCase.Title, err)) 42 | signers = append(signers, *signer) 43 | verifiers = append(verifiers, *signer.Verifier()) 44 | 45 | sig := NewSignature() 46 | sig.Headers.Protected[algTag] = param.algorithm.Value 47 | sig.Headers.Protected[kidTag] = param.certificate 48 | 49 | message.AddSignature(sig) 50 | } 51 | assert.True(len(message.Signatures) > 0) 52 | assert.Equal(len(message.Signatures), len(signers)) 53 | 54 | var external []byte 55 | 56 | err := message.Sign(rand.Reader, external, signers) 57 | assert.Nil(err, fmt.Sprintf("%s: signing failed with err %s", testCase.Title, err)) 58 | 59 | if testCase.ModifySignature { 60 | // tamper with the COSE signature. 61 | sig1 := message.Signatures[0].SignatureBytes 62 | sig1[len(sig1)-5] ^= 1 63 | } 64 | if testCase.ModifyPayload { 65 | message.Payload[0] ^= 1 66 | } 67 | 68 | message.Payload = nil 69 | 70 | // Verify our signature with cose-rust 71 | 72 | // encode message and signature 73 | msgBytes, err := Marshal(message) 74 | assert.Nil(err, fmt.Sprintf("%s: Error marshaling signed message to bytes %s", testCase.Title, err)) 75 | 76 | // Make sure cose-rust can verify our signature too 77 | cmd := exec.Command("cargo", "run", "--quiet", "--color", "never", "--example", "sign_verify", 78 | "--", 79 | "verify", 80 | hex.EncodeToString([]byte(testCase.SignPayload)), 81 | hex.EncodeToString(msgBytes)) 82 | 83 | cmd.Dir = "./test/cose-rust" 84 | cmd.Env = append(os.Environ(), "RUSTFLAGS=-A dead_code -A unused_imports") 85 | cmd.Stdout = os.Stdout 86 | cmd.Stderr = os.Stderr 87 | err = cmd.Run() 88 | 89 | if testCase.ModifySignature || testCase.ModifyPayload { 90 | assert.NotNil(err, fmt.Sprintf("%s: verifying signature with cose-rust did not fail %s", testCase.Title, err)) 91 | } else { 92 | assert.Nil(err, fmt.Sprintf("%s: error verifying signature with cose-rust %s", testCase.Title, err)) 93 | } 94 | } 95 | 96 | func TestRustCoseCli(t *testing.T) { 97 | for _, testCase := range RustTestCases { 98 | t.Run(testCase.Title, func(t *testing.T) { 99 | RustCoseVerifiesGoCoseSignatures(t, testCase) 100 | }) 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /sign_verify_cose_wg_examples_test.go: -------------------------------------------------------------------------------- 1 | package cose 2 | 3 | import ( 4 | "crypto/rand" 5 | "encoding/hex" 6 | "fmt" 7 | "github.com/stretchr/testify/assert" 8 | "strings" 9 | "testing" 10 | ) 11 | 12 | func WGExampleSignsAndVerifies(t *testing.T, example WGExample) { 13 | assert := assert.New(t) 14 | privateKey := LoadPrivateKey(&example) 15 | 16 | // testcases only include one signature 17 | assert.Equal(len(example.Input.Sign.Signers), 1) 18 | 19 | signerInput := example.Input.Sign.Signers[0] 20 | alg := getAlgByNameOrPanic(signerInput.Protected.Alg) 21 | external := HexToBytesOrDie(signerInput.External) 22 | 23 | decoded, err := Unmarshal(HexToBytesOrDie(example.Output.Cbor)) 24 | assert.Nil(err, fmt.Sprintf("%s: Error decoding example CBOR", example.Title)) 25 | 26 | if ExpectCastToFail(example.Title) { 27 | return 28 | } 29 | 30 | message, ok := decoded.(SignMessage) 31 | assert.True(ok, fmt.Sprintf("%s: Error casting example CBOR to SignMessage", example.Title)) 32 | 33 | signer, err := NewSignerFromKey(alg, &privateKey) 34 | assert.Nil(err, fmt.Sprintf("%s: Error creating signer %s", example.Title, err)) 35 | 36 | verifier := signer.Verifier() 37 | 38 | // Test Verify - signatures CBOR decoded from example 39 | assert.NotNil(message.Signatures[0].SignatureBytes) 40 | err = message.Verify(external, []Verifier{*verifier}) 41 | if example.Fail { 42 | assert.NotNil(err, fmt.Sprintf("%s: verifying signature did not fail. Got nil instead of error from signature verification failure", example.Title)) 43 | 44 | // signing should not necessarily fail and the 45 | // intermediates are wrong for fail test cases 46 | return 47 | } 48 | assert.Nil(err, fmt.Sprintf("%s: error verifying signature %+v", example.Title, err)) 49 | 50 | // Test Sign 51 | 52 | // clear the signature 53 | message.Signatures[0].SignatureBytes = nil 54 | 55 | err = message.Sign(rand.Reader, external, []Signer{*signer}) 56 | assert.Nil(err, fmt.Sprintf("%s: signing failed with err %s", example.Title, err)) 57 | 58 | // check intermediate 59 | ToBeSigned, err := message.SigStructure(external, &message.Signatures[0]) 60 | assert.Nil(err, fmt.Sprintf("%s: signing failed with err %s", example.Title, err)) 61 | assert.Equal(example.Intermediates.Signers[0].ToBeSignHex, 62 | strings.ToUpper(hex.EncodeToString(ToBeSigned)), 63 | fmt.Sprintf("%s: signing wrong Hex Intermediate", example.Title)) 64 | 65 | // Verify our signature (round trip) 66 | digest, err := hashSigStructure(ToBeSigned, alg.HashFunc) 67 | assert.Nil(err, fmt.Sprintf("%s: round trip failed to hash signature %s", example.Title, err)) 68 | 69 | err = verifier.Verify(digest, message.Signatures[0].SignatureBytes) 70 | assert.Nil(err, fmt.Sprintf("%s: round trip signature verification failed with err %s", example.Title, err)) 71 | } 72 | 73 | var SkipExampleTitles = map[string]bool{ 74 | "ECDSA-01: ECDSA - P-256": false, // ecdsa-01.json 75 | "ECDSA-02: ECDSA - P-384": false, // ecdsa-02.json 76 | 77 | "ECDSA-03: ECDSA - P-512": false, // ecdsa-03.json 78 | 79 | // not recommended "SHA-256 be used only with curve P-256, 80 | // SHA-384 be used only with curve P-384, and SHA-512 be used 81 | // with curve P-521" 82 | "ECDSA-01: ECDSA - P-256 w/ SHA-512": true, // ecdsa-04.json 83 | 84 | // unsupported message types 85 | "ECDSA-01: ECDSA - P-256 - sign0": true, // ecdsa-sig-01.json 86 | "ECDSA-sig-02: ECDSA - P-384 - sign1": true, // ecdsa-sig-02.json 87 | "ECDSA-03: ECDSA - P-512 - sign0": true, // ecdsa-sig-03.json 88 | "ECDSA-sig-01: ECDSA - P-256 w/ SHA-512 - implicit": true, // ecdsa-sig-04.json 89 | } 90 | 91 | func ExpectCastToFail(title string) (shouldFail bool) { 92 | // (g-k) these decode but not to SignMessages since I 93 | // haven't found a way to get ugorji/go/codec to use our 94 | // extension to decode without the right CBOR tag 95 | return title == "sign-pass-03: Remove CBOR Tag" || title == "sign-fail-01: Wrong CBOR Tag" 96 | } 97 | 98 | func TestWGExamples(t *testing.T) { 99 | examples := append( 100 | LoadExamples("./test/cose-wg-examples/sign-tests"), 101 | LoadExamples("./test/cose-wg-examples/ecdsa-examples")..., 102 | ) 103 | 104 | for _, example := range examples { 105 | t.Run(fmt.Sprintf("Example: %s %v", example.Title, example.Fail), func(t *testing.T) { 106 | if v, ok := SkipExampleTitles[example.Title]; ok && v { 107 | return 108 | } 109 | WGExampleSignsAndVerifies(t, example) 110 | }) 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /sign_verify_test.go: -------------------------------------------------------------------------------- 1 | package cose 2 | 3 | import ( 4 | "crypto" 5 | "crypto/ecdsa" 6 | "crypto/elliptic" 7 | "crypto/rand" 8 | "fmt" 9 | "github.com/stretchr/testify/assert" 10 | "testing" 11 | ) 12 | 13 | func TestSignErrors(t *testing.T) { 14 | assert := assert.New(t) 15 | 16 | msg := NewSignMessage() 17 | msg.Payload = []byte("payload to sign") 18 | 19 | signer, err := NewSigner(ES256, nil) 20 | assert.Nil(err, fmt.Sprintf("Error creating signer %s", err)) 21 | 22 | sig := NewSignature() 23 | sig.Headers.Protected[algTag] = -41 // RSAES-OAEP w/ SHA-256 from [RFC8230] 24 | sig.Headers.Protected[kidTag] = 1 25 | 26 | msg.Signatures = []Signature{} 27 | err = msg.Sign(rand.Reader, []byte(""), []Signer{*signer}) 28 | assert.Equal(ErrNoSignatures, err) 29 | 30 | msg.Signatures = nil 31 | err = msg.Sign(rand.Reader, []byte(""), []Signer{*signer}) 32 | assert.Equal(ErrNilSignatures, err) 33 | 34 | // check that it creates the signatures array from nil 35 | msg.AddSignature(sig) 36 | assert.Equal(len(msg.Signatures), 1) 37 | 38 | msg.Signatures[0].Headers = nil 39 | err = msg.Sign(rand.Reader, []byte(""), []Signer{*signer}) 40 | assert.Equal(ErrNilSigHeader, err) 41 | 42 | msg.Signatures = nil 43 | msg.AddSignature(sig) 44 | msg.Signatures[0].Headers.Protected = nil 45 | err = msg.Sign(rand.Reader, []byte(""), []Signer{*signer}) 46 | assert.Equal(ErrNilSigProtectedHeaders, err) 47 | 48 | msg.Signatures = nil 49 | sig.Headers.Protected = map[interface{}]interface{}{} 50 | sig.Headers.Protected[algTag] = -41 // RSAES-OAEP w/ SHA-256 from [RFC8230] 51 | sig.Headers.Protected[kidTag] = 1 52 | sig.SignatureBytes = []byte("already signed") 53 | 54 | msg.AddSignature(sig) 55 | assert.Equal(len(msg.Signatures), 1) 56 | assert.NotNil(msg.Signatures[0].Headers) 57 | 58 | err = msg.Sign(rand.Reader, []byte(""), []Signer{}) 59 | assert.Equal("0 signers for 1 signatures", err.Error()) 60 | 61 | err = msg.Sign(rand.Reader, []byte(""), []Signer{*signer}) 62 | assert.Equal("SignMessage signature 0 already has signature bytes", err.Error()) 63 | 64 | msg.Signatures[0].SignatureBytes = nil 65 | err = msg.Sign(rand.Reader, []byte(""), []Signer{*signer}) 66 | assert.Equal(ErrUnavailableHashFunc, err) 67 | 68 | msg.Signatures[0].Headers.Protected[algTag] = ES256.Value 69 | signer.alg = ES256 70 | signer.PrivateKey = dsaPrivateKey 71 | err = msg.Sign(rand.Reader, []byte(""), []Signer{*signer}) 72 | assert.Equal(ErrUnknownPrivateKeyType, err) 73 | 74 | signer.alg = PS256 75 | err = msg.Sign(rand.Reader, []byte(""), []Signer{*signer}) 76 | assert.Equal("Signer of type PS256 cannot generate a signature of type ES256", err.Error()) 77 | 78 | msg.Signatures[0].Headers.Protected[algTag] = -9000 79 | err = msg.Sign(rand.Reader, []byte(""), []Signer{*signer}) 80 | assert.Equal("Algorithm with value -9000 not found", err.Error()) 81 | 82 | msg.Signatures[0].Headers.Protected[algTag] = 1 83 | err = msg.Sign(rand.Reader, []byte(""), []Signer{*signer}) 84 | assert.Equal(ErrInvalidAlg, err) 85 | 86 | delete(msg.Signatures[0].Headers.Protected, algTag) 87 | err = msg.Sign(rand.Reader, []byte(""), []Signer{*signer}) 88 | assert.Equal(ErrAlgNotFound, err) 89 | } 90 | 91 | func TestSignatureEqual(t *testing.T) { 92 | assert := assert.New(t) 93 | 94 | var s1, s2 *Signature = nil, nil 95 | assert.Equal(s1.Equal(s2), true) 96 | 97 | s1 = &Signature{} 98 | s2 = s1 99 | assert.Equal(s1.Equal(s2), true) 100 | 101 | s1.SignatureBytes = []byte("123") 102 | assert.Equal(s1.Equal(s2), true) 103 | 104 | s2 = &Signature{SignatureBytes: []byte("000")} 105 | assert.Equal(s1.Equal(s2), false) 106 | 107 | s2.SignatureBytes = s1.SignatureBytes 108 | assert.Equal(s1.Equal(s2), true) 109 | 110 | s1.Headers = &Headers{ 111 | Protected: map[interface{}]interface{}{algTag: -41}, // RSAES-OAEP w/ SHA-256 from [RFC8230] 112 | } 113 | assert.Equal(s1.Equal(s2), false) 114 | 115 | s2.Headers = s1.Headers 116 | assert.Equal(s1.Equal(s2), true) 117 | } 118 | 119 | func TestSignatureDecodeErrors(t *testing.T) { 120 | assert := assert.New(t) 121 | 122 | var ( 123 | s *Signature = nil 124 | result interface{} 125 | ) 126 | assert.Panics(func () { s.Decode(result) }) 127 | 128 | s = &Signature{} 129 | result = 5 130 | assert.Panics(func () { s.Decode(result) }) 131 | 132 | s = &Signature{} 133 | result = []interface{}{1, 2} 134 | assert.Panics(func () { s.Decode(result) }) 135 | 136 | s = &Signature{} 137 | result = []interface{}{ 138 | []byte("\xA0"), 139 | map[interface{}]interface{}{}, 140 | []byte(""), 141 | } 142 | assert.Panics(func () { s.Decode(result) }) 143 | 144 | s.Headers = &Headers{} 145 | result = []interface{}{ 146 | []byte("\xA0"), 147 | map[interface{}]interface{}{}, 148 | -1, 149 | } 150 | assert.Panics(func () { s.Decode(result) }) 151 | } 152 | 153 | func TestSignMessageSignatureDigest(t *testing.T) { 154 | assert := assert.New(t) 155 | 156 | var ( 157 | external = []byte("") 158 | hashFunc = crypto.SHA256 159 | signature *Signature = nil 160 | msg *SignMessage = nil 161 | digest []byte 162 | err error 163 | ) 164 | 165 | digest, err = msg.signatureDigest(external, signature, hashFunc) 166 | assert.Equal(err.Error(), "Cannot compute signatureDigest on nil SignMessage") 167 | assert.Equal(len(digest), 0) 168 | 169 | msg = &SignMessage{} 170 | digest, err = msg.signatureDigest(external, signature, hashFunc) 171 | assert.Equal(err.Error(), "Cannot compute signatureDigest on nil SignMessage.Signatures") 172 | assert.Equal(len(digest), 0) 173 | 174 | msg.AddSignature(&Signature{ 175 | Headers: nil, 176 | SignatureBytes: []byte("123"), 177 | }) 178 | signature = &Signature{ 179 | Headers: nil, 180 | SignatureBytes: nil, 181 | } 182 | digest, err = msg.signatureDigest(external, signature, hashFunc) 183 | assert.Equal(err.Error(), "SignMessage.Signatures does not include the signature to digest") 184 | assert.Equal(len(digest), 0) 185 | 186 | msg = NewSignMessage() 187 | signature = NewSignature() 188 | signature.Headers.Protected[algTag] = ES256 189 | msg.Signatures = []Signature{*signature} 190 | digest, err = msg.signatureDigest(nil, signature, hashFunc) 191 | assert.Equal(err, nil, "signatureDigest does not accept nil external") 192 | } 193 | 194 | func TestVerifyErrors(t *testing.T) { 195 | assert := assert.New(t) 196 | 197 | msg := NewSignMessage() 198 | msg.Payload = []byte("payload to sign") 199 | 200 | 201 | sig := NewSignature() 202 | sig.Headers.Protected[algTag] = -41 // RSAES-OAEP w/ SHA-256 from [RFC8230] 203 | sig.Headers.Protected[kidTag] = 1 204 | 205 | signer, err := NewSigner(ES256, nil) 206 | assert.Nil(err, "Error creating signer") 207 | 208 | verifier := signer.Verifier() 209 | 210 | verifiers := []Verifier{*verifier} 211 | payload := []byte("") 212 | 213 | msg.Signatures = []Signature{} 214 | assert.Nil(msg.Verify(payload, verifiers)) 215 | 216 | msg.Signatures = nil 217 | assert.Nil(msg.Verify(payload, verifiers)) 218 | 219 | msg.AddSignature(sig) 220 | msg.Signatures[0].Headers.Protected = nil 221 | assert.Equal(ErrNilSigProtectedHeaders, msg.Verify(payload, verifiers)) 222 | 223 | msg.Signatures[0].Headers = nil 224 | assert.Equal(ErrNilSigHeader, msg.Verify(payload, verifiers)) 225 | 226 | sig = NewSignature() 227 | sig.Headers.Protected[algTag] = -41 // RSAES-OAEP w/ SHA-256 from [RFC8230] 228 | sig.Headers.Protected[kidTag] = 1 229 | msg.Signatures[0] = *sig 230 | assert.Equal("SignMessage signature 0 missing signature bytes to verify", msg.Verify(payload, verifiers).Error()) 231 | 232 | msg.Signatures[0].Headers.Protected[algTag] = -41 // RSAES-OAEP w/ SHA-256 from [RFC8230] 233 | msg.Signatures[0].Headers.Protected[kidTag] = 1 234 | msg.Signatures[0].SignatureBytes = []byte("already signed") 235 | assert.Equal(ErrUnavailableHashFunc, msg.Verify(payload, verifiers)) 236 | 237 | msg.Signatures[0].Headers.Protected[algTag] = 1 238 | assert.Equal(ErrInvalidAlg, msg.Verify(payload, verifiers)) 239 | 240 | msg.Signatures[0].Headers.Protected[algTag] = -7 // ECDSA w/ SHA-256 from [RFC8152] 241 | assert.Equal("Wrong number of signatures 1 and verifiers 0", msg.Verify(payload, []Verifier{}).Error()) 242 | 243 | verifiers = []Verifier{ 244 | Verifier{ 245 | PublicKey: &ecdsa.PublicKey{ 246 | Curve: elliptic.P384(), 247 | X: FromBase64Int("usWxHK2PmfnHKwXPS54m0kTcGJ90UiglWiGahtagnv8"), 248 | Y: FromBase64Int("IBOL-C3BttVivg-lSreASjpkttcsz-1rb7btKLv8EX4"), 249 | }, 250 | Alg: ES256, 251 | }, 252 | } 253 | assert.Equal("Expected 256 bit key, got 384 bits instead", msg.Verify(payload, verifiers).Error()) 254 | 255 | verifiers = []Verifier{ 256 | Verifier{ 257 | PublicKey: ecdsaPrivateKey.Public(), 258 | Alg: ES256, 259 | }, 260 | } 261 | assert.Equal("invalid signature length: 14", msg.Verify(payload, verifiers).Error()) 262 | } 263 | --------------------------------------------------------------------------------