diff --git a/.github/_ISSUE_TEMPLATE/bug-report.md b/.github/_ISSUE_TEMPLATE/bug-report.md deleted file mode 100644 index 8c37af0..0000000 --- a/.github/_ISSUE_TEMPLATE/bug-report.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -name: πŸ› Bug Report -about: Thank you for taking the time, please report a reproducible bug -title: "[Bug] " -labels: bug -assignees: add codeowner's @name here - ---- - -**Describe the bug** -*A clear and concise description of what the bug is.* - -**To Reproduce:** -*Steps to reproduce the behavior:* - -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -**Expected behavior:** -*A clear and concise description of what you expected to happen.* - -**Supporting Material** -*If applicable, add screenshots, output log and/or other documentation to help explain your problem.* - -**Environment (please complete the following information):** - -- OS: [ex: iOS] -- Version - -**Additional context** -Add any other context that you feel is relevant about the problem here. diff --git a/.github/_ISSUE_TEMPLATE/config.yml b/.github/_ISSUE_TEMPLATE/config.yml deleted file mode 100644 index ce71f10..0000000 --- a/.github/_ISSUE_TEMPLATE/config.yml +++ /dev/null @@ -1,4 +0,0 @@ -contact_links: - - name: ❓ Questions and Help πŸ€” - url: https://discord.gg/tbd (/add your discord channel if applicable) - about: This issue tracker is not for support questions. Please refer to the community for more help. diff --git a/.github/workflows/build-report.yaml b/.github/workflows/build-report.yaml deleted file mode 100644 index b0254e7..0000000 --- a/.github/workflows/build-report.yaml +++ /dev/null @@ -1,31 +0,0 @@ -name: build html report - -on: - push: - workflow_dispatch: - -jobs: - build-report: - runs-on: ubuntu-latest - permissions: - id-token: write - contents: read - pages: write - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-go@v4 - - name: build html - run: | - cd reports - go run ./cmd/build-html - mv _site ../ - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - CICD_ROBOT_GITHUB_APP_NAME: ${{ secrets.CICD_ROBOT_GITHUB_APP_NAME }} - CICD_ROBOT_GITHUB_APP_PRIVATE_KEY: ${{ secrets.CICD_ROBOT_GITHUB_APP_PRIVATE_KEY }} - CICD_ROBOT_GITHUB_APP_ID: ${{ secrets.CICD_ROBOT_GITHUB_APP_ID }} - CICD_ROBOT_GITHUB_APP_INSTALLATION_ID: ${{ secrets.CICD_ROBOT_GITHUB_APP_INSTALLATION_ID }} - - uses: actions/upload-pages-artifact@v2 - - name: deploy GitHub Pages - uses: actions/deploy-pages@v3 - if: github.ref == 'refs/heads/main' \ No newline at end of file diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml deleted file mode 100644 index 61fdcc2..0000000 --- a/.github/workflows/lint.yaml +++ /dev/null @@ -1,13 +0,0 @@ -name: Lint - -on: [push, pull_request] - -jobs: - lint: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - uses: DavidAnson/markdownlint-cli2-action@v13 - with: - globs: "**/*.md" diff --git a/.github/workflows/sync-vectors.yaml b/.github/workflows/sync-vectors.yaml deleted file mode 100644 index d02b6bd..0000000 --- a/.github/workflows/sync-vectors.yaml +++ /dev/null @@ -1,23 +0,0 @@ -name: sync vectors - -on: - push: - branches: [main] - paths: - - 'web5-test-vectors/**/*.json' - workflow_dispatch: - -jobs: - build-report: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-go@v4 - - name: sync vectors - run: cd reports && go run ./cmd/sync-vectors - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - CICD_ROBOT_GITHUB_APP_NAME: ${{ secrets.CICD_ROBOT_GITHUB_APP_NAME }} - CICD_ROBOT_GITHUB_APP_PRIVATE_KEY: ${{ secrets.CICD_ROBOT_GITHUB_APP_PRIVATE_KEY }} - CICD_ROBOT_GITHUB_APP_ID: ${{ secrets.CICD_ROBOT_GITHUB_APP_ID }} - CICD_ROBOT_GITHUB_APP_INSTALLATION_ID: ${{ secrets.CICD_ROBOT_GITHUB_APP_INSTALLATION_ID }} \ No newline at end of file diff --git a/.github/workflows/validate-test-vectors.yaml b/.github/workflows/validate-test-vectors.yaml index 4f2f5c3..5b14f16 100644 --- a/.github/workflows/validate-test-vectors.yaml +++ b/.github/workflows/validate-test-vectors.yaml @@ -3,7 +3,7 @@ name: Validate Test Vectors on: push: paths: - - 'web5-test-vectors/**' + - 'test-vectors/**' - 'scripts/test-vector-validation/**' jobs: diff --git a/.gitignore b/.gitignore index ca35be0..4efacd2 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ _site +.idea diff --git a/.markdownlint-cli2.yaml b/.markdownlint-cli2.yaml deleted file mode 100644 index cb6053b..0000000 --- a/.markdownlint-cli2.yaml +++ /dev/null @@ -1,4 +0,0 @@ -config: - line-length: false - no-duplicate-heading: - siblings_only: true diff --git a/README.md b/README.md index 7087de1..5fdd028 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,8 @@ -# SDK Development +# Web5-Spec - [Purpose](#purpose) -- [Known Unknowns](#known-unknowns) - [Requirements](#requirements) - [Feature Tracking](#feature-tracking) - - [Labels](#labels) - - [Milestones](#milestones) - [Feature Acceptance](#feature-acceptance) - [Work Prioritization](#work-prioritization) - [Implementation Criteria](#implementation-criteria) @@ -16,10 +13,8 @@ - [Publishing API Reference Documentation](#publishing-api-reference-documentation) - [Example Feature Usage](#example-feature-usage) - [Test Vectors](#test-vectors) - - [Usage](#usage) - - [Local Dev](#local-dev) - - [Adding/Updating Vectors](#addingupdating-vectors) - - [Feature Completeness By SDK](#feature-completeness-by-sdk) + - [Adding/Updating Vectors](#addingupdating-vectors) + - [Feature Completeness By SDK](#feature-completeness-by-sdk) - [Web5 SDK Features](#web5-sdk-features) - [Cryptographic Digital Signature Algorithms (DSA)](#cryptographic-digital-signature-algorithms-dsa) - [Key Management](#key-management) @@ -38,28 +33,14 @@ ## Purpose -This repo sets forth the development process and requirements for the following SDKs: +This repo sets forth the development process, requirements, and the desired feature for the following SDKs: -- [tbdex-js](https://github.com/TBD54566975/tbdex-js) -- [tbdex-kt](https://github.com/TBD54566975/tbdex-kt) -- [tbdex-rs](https://github.com/TBD54566975/tbdex-rs) - [web5-js](https://github.com/TBD54566975/web5-js) - [web5-kt](https://github.com/TBD54566975/web5-kt) +- [web5-go](https://github.com/TBD54566975/web5-go) - [web5-rs](https://github.com/TBD54566975/web5-rs) +- [web5-swift](https://github.com/TBD54566975/web5-swift) -It contains the desired feature set for: - -- [web5-js](https://github.com/TBD54566975/web5-js) -- [web5-kt](https://github.com/TBD54566975/web5-kt) -- [web5-rs](https://github.com/TBD54566975/web5-rs) - -Github Issues and PRs created in this repo address topics that impact / span all SDKs we have in development. See section on [Feature Acceptance](#feature-acceptance) for information on submitting proposals for new features across all of our SDKs (e.g. implement Presentation Exchange v9) - -## Known Unknowns - -- We don't yet have a cemented path for supporting Android. It could either be through our pre-existing Kotlin SDK or bindings exposed via Rust - -- We're not yet in a place where we can confidently state that a rust core can support a broad surface area of target languages. We're confident in pursuing rust development for the purposes of surfacing swift bindings. ## Requirements @@ -67,79 +48,6 @@ Github Issues and PRs created in this repo address topics that impact / span all Feature tracking will take place entirely on GitHub through Github Issues and the [SDK development Github project](https://github.com/orgs/TBD54566975/projects/29). ---- - -Work items that impact all SDKs should be created as issues in _this_ Github Repo. e.g. "produce test vectors for `did:web` - ---- - -Work items that are specific to an individual SDK should be created as an issue in the respective sdk's Github Repo - -> [!IMPORTANT] -> Each individual SDK's DRI will be responsible for creating all of the relevant github issues in their respective repo by using the tables below. After all issues are created for a given feature, create a PR for this repo to delete the relevant table. - ---- - -All relevant Github Issues will be tracked in the [SDK Development](https://github.com/orgs/TBD54566975/projects/29) Project. Issues can be associated to the project through the sidebar on an individual issue page. If a new issue is created in any of the SDK repos with one of the below feature labels, it will _automatically_ be added to the project board via GH project workflows. _New_ features lables should be added to the [workflows](https://github.com/orgs/TBD54566975/projects/29/workflows). - ---- - -Work item progress is tracked using the `Status` attribute on a GH issue. This should automatically be reflected on the kanban view on the GH project. PRs should be linked to their respective issue via the PR description. - ---- - -#### Labels - -> [!IMPORTANT] -> A label should be created for each feature, in each respective repo. - -The following labels should exist in all relevant repos - -| Label | Color Hex | Description | -| -------------------- | --------- | ------------------------------------------ | -| `dsa` | `#7FDBFF` | Cryptographic Digital Signature Algorithms | -| `key-mgmt` | `#0074D9` | Key Management | -| `did:web` | `#2ECC40` | did:web | -| `did:jwk` | `#FFDC00` | did:jwk | -| `did:dht` | `#FF851B` | did:dht | -| `did:key` | `#F012BE` | did:key | -| `did:ion` | `#B10DC9` | did:ion | -| `did-doc-validation` | `#3D9970` | DID Document & Resolution Validation | -| `w3c-vc-dm-1.1` | `#39CCCC` | W3C Verifiable Credential Data Model 1.1 | -| `w3c-vc-dm-2.0` | `#01FF70` | W3C Verifiable Credential Data Model 2.0 | -| `sd-jwt` | `#85144B` | SD-JWT / SD-JWT-VC | -| `pd-v2` | `#F9A602` | Presentation Definition V2 | -| `vc-json-schema` | `#C86F42` | VC JSON Schema | -| `tbdex-message` | `#70DB93` | tbDEX Message | -| `tbdex-resource` | `#5B2C6F` | tbDEX Resource | -| `tbdex-offering` | `#E59866` | tbDEX Offering Resource | -| `tbdex-rfq` | `#1F618D` | tbDEX RFQ Message | -| `tbdex-quote` | `#186A3B` | tbDEX Quote Message | -| `tbdex-order` | `#28B463` | tbDEX Order Message | -| `tbdex-orderstatus` | `#D68910` | tbDEX Order-Status Message | -| `tbdex-close` | `#34495E` | tbDEX Close Message | -| `tbdex-server` | `#3498DB` | HTTP server for tbDEX PFIs | -| `tbdex-client` | `#E74C3C` | HTTP client for tbDEX wallets | - -> [!NOTE] -> This list will change over time as features are added or removed - ---- - -#### Milestones - -Github Repo Milestones will be used to track work for specific codenamed projects (e.g. Eagle, Pigeon, Black Swan, etc.). - -The following milestones should exist in all relevant repos - -| Milestone | -| --------- | -| `Eagle` | -| `ABC` | - -> [!NOTE] -> This list will change over time as projects are added - ### Feature Acceptance Proposing new features that impact all SDKs will occur by creating a Github Issue in this repo. The Issue should include motivation or rationale in addition to any relevant reading material. New features will be discussed and decided upon during weekly syncs @@ -147,6 +55,8 @@ Proposing new features that impact all SDKs will occur by creating a Github Issu > [!IMPORTANT] > Language agnostic test vectors **must** be produced _prior_ to commencing implementation beyond the first SDK +Test vectors are in the test-vector directory. More info on test vectors can be found there. + ### Work Prioritization Prioritization of features or specific work items will be reflected during weekly sync meetings. @@ -182,17 +92,17 @@ Each SDK will use Github Actions for CI/CD and other automations | Feature | Typescript | Kotlin | Rust | Swift | | ----------------------------- | ---------- | ------ | ---- | ----- | -| OSS License Check | ❌ | ❌ | βœ… | ❌ | -| Security Scanning | ❌ | ❌ | ⛔️ | ❌ | -| Static Analysis Linting/Style | ❌ | ❌ | βœ… | ❌ | +| OSS License Check | βœ… | βœ… | βœ… | ❌ | +| Security Scanning | βœ… | βœ… | ⛔️ | ❌ | +| Static Analysis Linting/Style | βœ… | βœ… | βœ… | ❌ | | Running Unit Tests | βœ… | βœ… | βœ… | ❌ | -| Publishing Tests Reports | ❌ | ❌ | ❌ | ❌ | -| Code Coverage (CodeCov) | ❌ | ❌ | ❌ | ❌ | -| Publishing Artifacts | ❓ | ❌ | ❌ | ❌ | +| Publishing Tests Reports | βœ… | βœ… | ❌ | ❌ | +| Code Coverage (CodeCov) | βœ… | βœ… | ❌ | ❌ | +| Publishing Artifacts | βœ… | βœ… | ❌ | ❌ | | Release Template Checklist | ❌ | ❌ | ❌ | ❌ | | Automated GH Release Tag | ❌ | ❌ | ❌ | ❌ | -| Publishing API Reference Docs | ❌ | βœ… | ❌ | ❌ | -| Publish Example Feature Usage | ❌ | βœ… | ❌ | ❌ | +| Publishing API Reference Docs | βœ… | βœ… | ❌ | ❌ | +| Publish Example Feature Usage | βœ… | βœ… | ❌ | ❌ | > [!CAUTION] > Security scanning via Snyk is currently not supported in Rust @@ -215,6 +125,7 @@ Each SDK will be published to the most widely adopted registry/repository for th | Kotlin | maven central | | Rust | crates.io | | Swift | swift package index | +| Go | tbd | ### Publishing API Reference Documentation @@ -233,6 +144,7 @@ Each SDK will auto generate API reference documentation using the respective lan | Kotlin | KDoc | Dokka | | Rust | Documentation comments | rustdoc | | Swift | Swift Markup | DocC | +| Go | tbd | tbd | > [!IMPORTANT] > Producing API reference documentation is the responsibility of an _implementer_ @@ -245,39 +157,19 @@ Each SDK will **publish** example usage for _each_ implemented feature. This can Test vectors ensure interoporability of features across SDKs and language implementations by providing common test cases with an input and expected output pair. They include both success and failure cases that can be vectorized. -This repo serves as the home for all web5 feature related vectors. They are available in the [web5-test-vectors](./web5-test-vectors/) directory and hosted on [Github Pages](https://tbd54566975.github.io/sdk-development/web5-test-vectors). - -The `tbdex` repo houses tbdex feature related vectors. They are available in the [test-vectors](https://github.com/TBD54566975/tbdex/test-vectors) directory and hosted on [Github Pages](https://tbdex.dev/). - -### Usage - -#### Local Dev - -SDK implementers should import vectors in order to test their implementation. The recommended pathway to consume them is as follows: +This repo serves as the home for all web5 feature related vectors. They are available in the [test-vectors](./test-vectors/) directory -Fetch the vector and read it into a data model representing the vector structure or a JSON object like so: +The `tbdex` repo houses tbdex feature related vectors. They are available in the [test-vectors](https://github.com/TBD54566975/tbdex/test-vectors) directory -```kt -// for web5 vectors -val stream = URL("https://tbd54566975.github.io/sdk-development/web5-test-vectors/did-jwk/resolve.json").openStream() -val vectorsJson = BufferedReader(InputStreamReader(stream)).readText() -return Json.jsonMapper.readTree(vectorsJson) +The `sdk-report-runner` repo consumes the output tests for these test vectors in each repo and generates a report - [report-runner](https://github.com/TBD54566975/sdk-report-runner) -// for tbdex vectors -val stream = URL("https://tbdex.dev/test-vectors/resources/marshal.json").openStream() -val vectorsJson = BufferedReader(InputStreamReader(stream)).readText() -return Json.jsonMapper.readTree(vectorsJson) -``` +### Adding/Updating Vectors -The data model or JSON object can then be used in the implementer's unit testing framework of choice. +New test vectors should follow the standard [vector structure](./test-vectors/). Vectors are automatically validated against the JSON schema via CI. -#### Adding/Updating Vectors +Create a PR in this repo for adding / updating web5 test vectors -New test vectors should follow the standard [vector structure](./web5-test-vectors/vectors.schema.json). Vectors are automatically validated against the JSON schema via CI. - -Create a PR in this repo for web5 vectors, or in [`tbdex`](https://github.com/TBD54566975/tbdex) for tbdex vectors with the proposed changes or additions. - -#### Feature Completeness By SDK +### Feature Completeness By SDK Test vectors are also used to determine feature completeness via our [test harness](./test-harness/README.md). Results of test harness runs can be found [here](https://tbd54566975.github.io/sdk-development/). @@ -369,12 +261,13 @@ Further, the key manager interface **must** be passed as an argument to _all_ pu ### [W3C Verifiable Credential Data Model 1.1](https://www.w3.org/TR/vc-data-model) -| Feature | Typescript | Kotlin | Rust | Swift | -| ------------------- | ---------- | ------ | ---- | ----- | -| Creation | βœ… | βœ… | ❌ | ❌ | -| Signing as `vc-jwt` | βœ… | βœ… | ❌ | ❌ | -| Verification | βœ… | βœ… | ❌ | ❌ | -| Validation | βœ… | βœ… | ❌ | ❌ | +| Feature | Typescript | Kotlin | Rust | Swift | +| ------------------------------------ | ---------- | ------ | ---- | ----- | +| Creation | βœ… | βœ… | ❌ | ❌ | +| Signing as `vc-jwt` | βœ… | βœ… | ❌ | ❌ | +| Verification | βœ… | βœ… | ❌ | ❌ | +| Validation | βœ… | βœ… | ❌ | ❌ | +| Verifiable Presentations as `vp-jwt` | ⚠️ | ⚠️ | ❌ | ❌ | ### [W3C Verifiable Credential Data Model 2.0](https://www.w3.org/TR/vc-data-model-2.0/) @@ -412,8 +305,11 @@ Further, the key manager interface **must** be passed as an argument to _all_ pu ### [Presentation Exchange V2](https://identity.foundation/presentation-exchange/spec/v2.0.0/) -| Feature | Typescript | Kotlin | Rust | Swift | -| --------------------- | ---------- | ------ | ---- | ----- | -| Concrete Type | βœ… | βœ… | ❌ | ❌ | -| Validation | βœ… | ⚠️ | ❌ | ❌ | -| Credential Evaluation | βœ… | ⚠️ | ❌ | ❌ | +| Feature | Typescript | Kotlin | Rust | Swift | +| ---------------------- | ---------- | ------ | ---- | ----- | +| Concrete Type | βœ… | βœ… | ❌ | ❌ | +| Validation | βœ… | βœ… | ❌ | ❌ | +| Credential Evaluation | βœ… | βœ… | ❌ | ❌ | +| [Predicates](https://identity.foundation/presentation-exchange/spec/v2.0.0/#predicate-feature) | βœ… | βœ… | ❌ | ❌ | +| [Relational Constraints](https://identity.foundation/presentation-exchange/spec/v2.0.0/#relational-constraint-feature) | βœ… | ❌ | ❌ | ❌ | +| [Credential Status](https://identity.foundation/presentation-exchange/spec/v2.0.0/#credential-status-constraint-feature) | ❌ | ❌ | ❌ | ❌ | diff --git a/action.yml b/action.yml deleted file mode 100644 index 8f15a3a..0000000 --- a/action.yml +++ /dev/null @@ -1,12 +0,0 @@ -name: Web5 Spec Conformance Test -description: test that this web5 component conforms to the expected spec -runs: - using: composite - steps: - - run: | - spec_test_version="$(basename "${GITHUB_ACTION_PATH}")" - bin="${GITHUB_ACTION_PATH}/web5-test-harness" - wget --quiet -O "${bin}" "https://github.com/TBD54566975/sdk-development/releases/download/${spec_test_version}/web5-test-harness-linux-amd64" - chmod +x "${bin}" - "${bin}" one - shell: bash diff --git a/reports/README.md b/reports/README.md deleted file mode 100644 index f7f25d3..0000000 --- a/reports/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# SDK Feature Report Generator - -This tool reads junit XML reports from different SDKs and generates an HTML report showing which SDKs support which features. - -## Current Status - -`./cmd/build-html` will iterate over the repos listed in `sdk.go` and download the most recent junit artifact. It will read -all junit results from it and produce a report to `_site/index.html` diff --git a/reports/cmd/build-html/main.go b/reports/cmd/build-html/main.go deleted file mode 100644 index 8e68166..0000000 --- a/reports/cmd/build-html/main.go +++ /dev/null @@ -1,30 +0,0 @@ -package main - -import ( - "errors" - "os" - "path/filepath" - - "golang.org/x/exp/slog" - - "github.com/TBD54566975/sdk-development/reports" -) - -func main() { - allReports, err := reports.GetAllReports() - if err != nil { - slog.Error("error downloading/parsing reports") - panic(err) - } - - if err = os.Mkdir("_site", 0755); err != nil && !errors.Is(err, os.ErrExist) { - slog.Error("error making output directory") - panic(err) - } - - err = reports.WriteHTML(allReports, filepath.Join("_site", "index.html")) - if err != nil { - slog.Error("error writing html output") - panic(err) - } -} diff --git a/reports/cmd/sync-vectors/main.go b/reports/cmd/sync-vectors/main.go deleted file mode 100644 index abeedfe..0000000 --- a/reports/cmd/sync-vectors/main.go +++ /dev/null @@ -1,33 +0,0 @@ -package main - -import ( - "os" - - "github.com/TBD54566975/sdk-development/reports" - "golang.org/x/exp/slog" -) - -func main() { - defer reports.CleanupGitAuth() - if err := reports.ConfigureGitAuth(); err != nil { - panic(err) - } - - errs := make(map[string]error) - for _, sdk := range reports.SDKs { - if err := reports.SyncSDK(sdk); err != nil { - errs[sdk.Name] = err - } - } - - if err := reports.CleanupGitAuth(); err != nil { - panic(err) - } - - if len(errs) > 0 { - for sdk, err := range errs { - slog.Error("error", "sdk", sdk, "error", err) - } - os.Exit(1) - } -} diff --git a/reports/github.go b/reports/github.go deleted file mode 100644 index 9065f5c..0000000 --- a/reports/github.go +++ /dev/null @@ -1,56 +0,0 @@ -package reports - -import ( - "context" - "fmt" - "net/http" - "os" - "strconv" - - ghinstallation "github.com/bradleyfalzon/ghinstallation/v2" - "github.com/google/go-github/v57/github" - "golang.org/x/exp/slog" -) - -var ( - ghAppName = os.Getenv("CICD_ROBOT_GITHUB_APP_NAME") - ghAppPrivateKey = os.Getenv("CICD_ROBOT_GITHUB_APP_PRIVATE_KEY") - ghAppIDString = os.Getenv("CICD_ROBOT_GITHUB_APP_ID") - ghAppInstallationIDString = os.Getenv("CICD_ROBOT_GITHUB_APP_INSTALLATION_ID") - - gh *github.Client - ghTransport *ghinstallation.Transport - - ghUserName = fmt.Sprintf("%s[bot]", ghAppName) -) - -func init() { - ghAppID, err := strconv.ParseInt(ghAppIDString, 10, 32) - if err != nil { - slog.Error("invalid or unset app ID. Please set environment variable CICD_ROBOT_GITHUB_APP_ID to a valid integer") - panic(err) - } - - ghInstallationID, err := strconv.ParseInt(ghAppInstallationIDString, 10, 32) - if err != nil { - slog.Error("invalid or unset installation ID. Please set environment variable CICD_ROBOT_GITHUB_APP_INSTALLATION_ID to a valid integer") - panic(err) - } - - ghTransport, err = ghinstallation.New(http.DefaultTransport, ghAppID, ghInstallationID, []byte(ghAppPrivateKey)) - if err != nil { - slog.Error("error initializing github auth transport.") - panic(err) - } - - gh = github.NewClient(&http.Client{Transport: ghTransport}) - - user, _, err := gh.Users.Get(context.Background(), ghUserName) - if err != nil { - slog.Error("error getting own (app) user info") - panic(err) - } - - gitConfig["user.email"] = fmt.Sprintf("%d+%s@users.noreply.github.com", user.GetID(), ghUserName) - gitConfig["user.name"] = ghUserName -} diff --git a/reports/go.mod b/reports/go.mod deleted file mode 100644 index 62b77be..0000000 --- a/reports/go.mod +++ /dev/null @@ -1,17 +0,0 @@ -module github.com/TBD54566975/sdk-development/reports - -go 1.20 - -require ( - github.com/bradleyfalzon/ghinstallation/v2 v2.8.0 - github.com/google/go-github/v57 v57.0.0 - github.com/joshdk/go-junit v1.0.0 - golang.org/x/exp v0.0.0-20231127185646-65229373498e -) - -require ( - github.com/golang-jwt/jwt/v4 v4.5.0 // indirect - github.com/google/go-github/v56 v56.0.0 // indirect - github.com/google/go-querystring v1.1.0 // indirect - github.com/stretchr/testify v1.8.4 // indirect -) diff --git a/reports/go.sum b/reports/go.sum deleted file mode 100644 index 31b35c3..0000000 --- a/reports/go.sum +++ /dev/null @@ -1,29 +0,0 @@ -github.com/bradleyfalzon/ghinstallation/v2 v2.8.0 h1:yUmoVv70H3J4UOqxqsee39+KlXxNEDfTbAp8c/qULKk= -github.com/bradleyfalzon/ghinstallation/v2 v2.8.0/go.mod h1:fmPmvCiBWhJla3zDv9ZTQSZc8AbwyRnGW1yg5ep1Pcs= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= -github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-github/v56 v56.0.0 h1:TysL7dMa/r7wsQi44BjqlwaHvwlFlqkK8CtBWCX3gb4= -github.com/google/go-github/v56 v56.0.0/go.mod h1:D8cdcX98YWJvi7TLo7zM4/h8ZTx6u6fwGEkCdisopo0= -github.com/google/go-github/v57 v57.0.0 h1:L+Y3UPTY8ALM8x+TV0lg+IEBI+upibemtBD8Q9u7zHs= -github.com/google/go-github/v57 v57.0.0/go.mod h1:s0omdnye0hvK/ecLvpsGfJMiRt85PimQh4oygmLIxHw= -github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= -github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= -github.com/joshdk/go-junit v1.0.0 h1:S86cUKIdwBHWwA6xCmFlf3RTLfVXYQfvanM5Uh+K6GE= -github.com/joshdk/go-junit v1.0.0/go.mod h1:TiiV0PqkaNfFXjEiyjWM3XXrhVyCa1K4Zfga6W52ung= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -golang.org/x/exp v0.0.0-20231127185646-65229373498e h1:Gvh4YaCaXNs6dKTlfgismwWZKyjVZXwOPfIyUaqU3No= -golang.org/x/exp v0.0.0-20231127185646-65229373498e/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/reports/html.go b/reports/html.go deleted file mode 100644 index d5f36d6..0000000 --- a/reports/html.go +++ /dev/null @@ -1,62 +0,0 @@ -package reports - -import ( - "fmt" - "os" - "strings" - - "golang.org/x/exp/slog" -) - -func sanatizeHTML(dirty error) string { - clean := strings.ReplaceAll(dirty.Error(), "<", "<") - clean = strings.ReplaceAll(clean, ">", ">") - clean = strings.ReplaceAll(clean, "\n", "\\\\n") - - return clean -} - -type htmlTemplateInput struct { - Reports []Report - Tests map[string][]string -} - -func WriteHTML(reports []Report, filename string) error { - slog.Info("writing html report", "reports", len(reports)) - - testmap := make(map[string]map[string]bool) - for _, report := range reports { - for category, tests := range report.Results { - if _, ok := tests[category]; !ok { - testmap[category] = map[string]bool{} - } - - for test := range tests { - testmap[category][test] = true - } - } - } - - templateInput := htmlTemplateInput{ - Reports: reports, - Tests: make(map[string][]string), - } - - for category, tests := range testmap { - for test := range tests { - templateInput.Tests[category] = append(templateInput.Tests[category], test) - } - } - - f, err := os.Create(filename) - if err != nil { - return fmt.Errorf("error opening %s: %v", filename, err) - } - defer f.Close() - - if err := htmlTemplates.ExecuteTemplate(f, "report-template.html", templateInput); err != nil { - return err - } - - return nil -} diff --git a/reports/junit-reader.go b/reports/junit-reader.go deleted file mode 100644 index 61a7f03..0000000 --- a/reports/junit-reader.go +++ /dev/null @@ -1,51 +0,0 @@ -package reports - -import ( - "archive/zip" - "bytes" - "fmt" - "strings" - - junit "github.com/joshdk/go-junit" - "golang.org/x/exp/slog" -) - -func readArtifactZip(artifact []byte) ([]junit.Suite, error) { - z, err := zip.NewReader(bytes.NewReader(artifact), int64(len(artifact))) - if err != nil { - return nil, err - } - - suites := []junit.Suite{} - for _, f := range z.File { - if !strings.HasSuffix(f.Name, ".xml") { - continue - } - - s, err := readJunit(f) - if err != nil { - return nil, fmt.Errorf("error reading %s: %v", f.Name, err) - } - - slog.Info("read", "suites", len(s), "file", f.Name) - - suites = append(suites, s...) - } - - return suites, nil -} - -func readJunit(f *zip.File) ([]junit.Suite, error) { - r, err := f.Open() - if err != nil { - return []junit.Suite{}, err - } - defer r.Close() - - suites, err := junit.IngestReader(r) - if err != nil { - return []junit.Suite{}, err - } - - return suites, nil -} diff --git a/reports/report-template.html b/reports/report-template.html deleted file mode 100644 index 389ff76..0000000 --- a/reports/report-template.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - web5 spec compliance report - - - - -

web5 spec compliance report

- - {{ range $category, $tests := .Tests }} -

{{ $category }}

- - {{ range $.Reports }}{{ end }} - {{ range $i, $test := $tests }} - - - {{ range $_, $report := $.Reports }} - - {{ end }} - - {{ end }} -
test{{ .SDK.Name }}
{{ $test }} -
- {{ (index (index .Results $category) $test).GetEmoji }} -
    - {{ range (index (index .Results $category) $test).Errors }}
  • {{ . }}
  • {{ end }} -
-
- {{ end }} - - \ No newline at end of file diff --git a/reports/reports.go b/reports/reports.go deleted file mode 100644 index 2ea47d9..0000000 --- a/reports/reports.go +++ /dev/null @@ -1,147 +0,0 @@ -package reports - -import ( - "embed" - "errors" - htmltemplate "html/template" - "regexp" - "time" - - junit "github.com/joshdk/go-junit" - "golang.org/x/exp/slog" -) - -var ( - ErrNotSupported = errors.New("test not supported by this SDK") - - //go:embed report-template.html - templatesFS embed.FS - - htmlTemplates = htmltemplate.New("") - funcmap = map[string]any{ - "sanatizeHTML": sanatizeHTML, - } -) - -func init() { - htmlTemplates.Funcs(funcmap) - if _, err := htmlTemplates.ParseFS(templatesFS, "report-template.html"); err != nil { - panic(err) - } -} - -type SDKMeta struct { - Name string - Repo string - ArtifactName string - FeatureRegex *regexp.Regexp - VectorRegex *regexp.Regexp - VectorPath string -} - -type Report struct { - SDK SDKMeta - Results map[string]map[string]Result -} - -type Result struct { - Exists bool - Errors []error - Time time.Duration -} - -func (r Report) IsPassing() bool { - for _, results := range r.Results { - for _, result := range results { - if result.IsSkipped() { - continue - } - - if len(result.Errors) > 0 { - return false - } - } - - } - - return true -} - -func (r Result) IsSkipped() bool { - return len(r.Errors) == 1 && r.Errors[0] == ErrNotSupported -} - -func (r Result) GetEmoji() string { - if !r.Exists { - return "🚧" - } - - if len(r.Errors) == 0 { - return "βœ…" - } - - return "❌" -} - -func (s SDKMeta) buildReport(suites []junit.Suite) (Report, error) { - results := make(map[string]map[string]Result) - - for feature, vectors := range knownVectors { - results[feature] = make(map[string]Result) - for vector := range vectors { - results[feature][vector] = Result{} - } - } - - for _, suite := range suites { - suiteName := suite.Name - if s.FeatureRegex != nil { - matches := s.FeatureRegex.FindStringSubmatch(suite.Name) - if len(matches) < 2 { - slog.Info("suite did not match feature regex for sdk, skipping", "sdk", s.Name, "suite", suite.Name, "matches", matches) - continue - } - suiteName = matches[1] - slog.Info("regex success for suite", "sdk", s.Name, "before", suite.Name, "after", suiteName) - } - - if knownVectors[suiteName] == nil { - slog.Info("ignoring test suite that does not correspond to known feature", "suite", suiteName) - continue - } - - for _, test := range suite.Tests { - testName := test.Name - if s.VectorRegex != nil { - matches := s.VectorRegex.FindStringSubmatch(test.Name) - if len(matches) < 2 { - slog.Info("test did not match feature regex for sdk, skipping", "sdk", s.Name, "suite", suiteName, "test", test.Name, "matches", matches) - continue - } - testName = matches[1] - slog.Info("regex success for test", "sdk", s.Name, "before", test.Name, "after", testName) - } - - if !knownVectors[suiteName][testName] { - slog.Info("ignoring test that does not correspond to known vector", "suite", suiteName, "test", testName) - continue - } - - errs := []error{} - if test.Error != nil { - errs = append(errs, test.Error) - } - - results[suiteName][testName] = Result{ - Exists: true, - Errors: errs, - Time: test.Duration, - } - } - } - - return Report{ - SDK: s, - Results: results, - }, nil -} diff --git a/reports/sdks.go b/reports/sdks.go deleted file mode 100644 index 6cf0620..0000000 --- a/reports/sdks.go +++ /dev/null @@ -1,104 +0,0 @@ -package reports - -import ( - "context" - "fmt" - "io" - "net/http" - "regexp" - "strings" - - "golang.org/x/exp/slog" -) - -var ( - SDKs = []SDKMeta{ - { - Name: "web5-js", - Repo: "TBD54566975/web5-js", - ArtifactName: "junit-results", - FeatureRegex: regexp.MustCompile(`Web5TestVectors(\w+)`), - VectorRegex: regexp.MustCompile(`\w+ \w+ (\w+)`), - VectorPath: "test-vectors", - }, - { - Name: "web5-kt", - Repo: "TBD54566975/web5-kt", - ArtifactName: "test-results", - FeatureRegex: regexp.MustCompile(`web5\.sdk\.\w+.Web5TestVectors(\w+)`), - VectorRegex: regexp.MustCompile(`(\w+)\(\)`), - VectorPath: "test-vectors", - }, - } -) - -func GetAllReports() ([]Report, error) { - ctx := context.Background() - - var reports []Report - for _, sdk := range SDKs { - artifact, err := downloadArtifact(ctx, sdk) - if err != nil { - return nil, fmt.Errorf("error downloading artifact from %s: %v", sdk.Repo, err) - } - - suites, err := readArtifactZip(artifact) - if err != nil { - return nil, fmt.Errorf("error parsing artifact from %s: %v", sdk.Repo, err) - } - - report, err := sdk.buildReport(suites) - if err != nil { - return nil, fmt.Errorf("error processing data from %s: %v", sdk.Repo, err) - } - - reports = append(reports, report) - } - - return reports, nil -} - -func downloadArtifact(ctx context.Context, sdk SDKMeta) ([]byte, error) { - owner, repo, _ := strings.Cut(sdk.Repo, "/") - artifacts, _, err := gh.Actions.ListArtifacts(ctx, owner, repo, nil) - if err != nil { - slog.Error("error listing artifacts", "") - return nil, fmt.Errorf("error getting artifact list: %v", err) - } - - var artifactURL string - for _, a := range artifacts.Artifacts { - if a.GetWorkflowRun().GetHeadBranch() != "main" { - continue - } - if *a.Name == sdk.ArtifactName { - artifactURL = *a.ArchiveDownloadURL - slog.Info("downloading artifact", "repo", sdk.Repo, "commit", a.GetWorkflowRun().GetHeadSHA()) - break - } - } - - req, err := http.NewRequest(http.MethodGet, artifactURL, nil) - if err != nil { - return nil, err - } - bearer, err := ghTransport.Token(ctx) - if err != nil { - return nil, fmt.Errorf("error getting github token: %v", err) - } - req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", bearer)) - resp, err := http.DefaultClient.Do(req) - if err != nil { - return nil, fmt.Errorf("error making http request to %s: %v", artifactURL, err) - } - defer resp.Body.Close() - - artifact, err := io.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("error reading response body: %v", err) - } - - slog.Info("downloaded artifact", "sdk", sdk.Repo, "size", len(artifact)) - - return artifact, nil -} diff --git a/reports/sync.go b/reports/sync.go deleted file mode 100644 index 388bc9b..0000000 --- a/reports/sync.go +++ /dev/null @@ -1,258 +0,0 @@ -package reports - -import ( - "context" - "errors" - "fmt" - "io" - "io/fs" - "os" - "os/exec" - "path/filepath" - "strings" - - "github.com/google/go-github/v57/github" - "golang.org/x/exp/slog" -) - -const ( - vectorUpdateBranch = "vector-update" - gitConfigCredentialHelper = "credential.helper" - vectorUpdateCommitMessage = "update test vectors" -) - -// these should be consts but the library expects a pointer to a string, which cannot be done with a const -var ( - vectorUpdatePRTitle = "Update Test Vectors - Out of Sync" - vectorUpdatePRBody = "Some test vectors were changed or added to the sdk-development repo, so they need to be updated in this repo. This is an automated PR that keeps the test vectors in sync from the [main test-vectors location](https://github.com/TBD54566975/sdk-development/tree/main/web5-test-vectors)" - vectorUpdatePRBaseBranch = "main" -) - -var gitCredentialStoreFile string - -var gitConfig = make(map[string]string) - -func SyncSDK(sdk SDKMeta) error { - slog.Info("syncing vectors", "repo", sdk.Repo) - - tmpdir, err := os.MkdirTemp("", "vector-update") - if err != nil { - return fmt.Errorf("error making a temp dir: %v", err) - } - defer os.RemoveAll(tmpdir) - - // clone sdk.Repo - // check if a vector update branch already exists. - // If vector update branch exists, check it out + rebase on default branch - // if vector update branch does not exist, make it - err = clone(fmt.Sprintf("https://github.com/%s", sdk.Repo), tmpdir) - if err != nil { - return fmt.Errorf("error cloning repo %s: %v", sdk.Repo, err) - } - - // copy ../../web5-test-vectors/* to sdk.VectorPath - err = copyDir("../web5-test-vectors", filepath.Join(tmpdir, sdk.VectorPath)) - if err != nil { - return fmt.Errorf("error copying current vectors to cloned repo: %v", err) - } - - // check if git says the repo has changed - return if it hasn't - err = git("-C", tmpdir, "diff-index", "--quiet", "HEAD") - if err != nil { - exitError := new(exec.ExitError) - if !errors.As(err, &exitError) { - return fmt.Errorf("error checking if repo changed: %v", err) - } - - slog.Info("repo changed after copying current vectors in") - } else { - slog.Info("repo did not change after copying current vectors in, not taking further action") - return nil - } - - // commit - if err := git("-C", tmpdir, "commit", "-a", "-m", vectorUpdateCommitMessage); err != nil { - return fmt.Errorf("error committing changes: %v", err) - } - - // push - if err := git("-C", tmpdir, "push", "origin", vectorUpdateBranch, "--force"); err != nil { - return fmt.Errorf("error pushing changes: %v", err) - } - - // open a pull request if one isn't already open - if err := openPRIfNeeded(sdk.Repo); err != nil { - return fmt.Errorf("error opening PR: %v", err) - } - return nil -} - -// clone the repo and checkout the correct branch and rebase it on main -func clone(url string, dest string) error { - if err := git("clone", url, dest); err != nil { - return err - } - - if err := git("-C", dest, "checkout", vectorUpdateBranch); err != nil { - exitError := &exec.ExitError{} - if !errors.As(err, &exitError) { - return err - } - - err = git("-C", dest, "checkout", "-b", vectorUpdateBranch) - if err != nil { - return err - } - } - - if err := git("-C", dest, "rebase", "main"); err != nil { - slog.Warn("rebase failed") - return err - } - - return nil -} - -func git(args ...string) error { - cmd := exec.Command("git", args...) - cmd.Stderr = os.Stderr - cmd.Stdout = os.Stdout - cmd.Env = []string{fmt.Sprintf("GIT_CONFIG_COUNT=%d", len(gitConfig))} - i := 0 - for k, v := range gitConfig { - cmd.Env = append(cmd.Env, - fmt.Sprintf("GIT_CONFIG_KEY_%d=%s", i, k), - fmt.Sprintf("GIT_CONFIG_VALUE_%d=%s", i, v), - ) - i = i + 1 - } - - slog.Info("invoking", "git", args) - if err := cmd.Run(); err != nil { - exitError := &exec.ExitError{} - if !errors.As(err, &exitError) { - return err - } - slog.Info("command did not succeed", "exit_code", exitError.ExitCode()) - return err - } - - return nil -} - -func copyDir(src, dest string) error { - return filepath.WalkDir(src, func(path string, _ fs.DirEntry, err error) error { - if err != nil { - slog.Error("error from walkdir") - return err - } - - if !strings.HasSuffix(path, ".json") { - return nil - } - - relativePath, _ := filepath.Rel(src, path) - destPath := filepath.Join(dest, relativePath) - - slog.Info("mkdir", "dir", filepath.Dir(destPath)) - err = os.MkdirAll(filepath.Dir(destPath), 0755) - if err != nil && !errors.Is(err, os.ErrExist) { - slog.Error("error creating dir", "dir", destPath) - return err - } - - s, err := os.Open(path) - if err != nil { - slog.Error("error opening source vector", "file", path) - return err - } - defer s.Close() - - d, err := os.Create(destPath) - if err != nil { - slog.Error("error opening dest vector", "file", destPath) - return err - } - defer d.Close() - - _, err = io.Copy(d, s) - if err != nil { - slog.Error("error copying vector contents", "src", path, "dest", destPath) - return err - } - - if err := git("-C", dest, "add", destPath); err != nil { - slog.Error("error git add'ing vector", "file", destPath) - return err - } - - slog.Info("copied vector", "file", relativePath) - return nil - }) -} - -func ConfigureGitAuth() error { - slog.Info("telling git about our github token") - - f, err := os.CreateTemp("", "git-credentials") - if err != nil { - return err - } - gitCredentialStoreFile = f.Name() - - authToken, err := ghTransport.Token(context.Background()) - if err != nil { - slog.Error("error getting github auth token") - return err - } - - cmd := exec.Command("git", "credential-store", "--file", gitCredentialStoreFile, "store") - cmd.Stdin = strings.NewReader(fmt.Sprintf("protocol=https\nhost=github.com\nusername=%s\npassword=%s", fmt.Sprintf("%s[bot]", ghAppName), authToken)) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - if err := cmd.Run(); err != nil { - return err - } - - gitConfig[gitConfigCredentialHelper] = fmt.Sprintf("store --file %s", gitCredentialStoreFile) - - return nil -} - -func CleanupGitAuth() error { - return os.Remove(gitCredentialStoreFile) -} - -func openPRIfNeeded(repo string) error { - ctx := context.Background() - owner, repo, _ := strings.Cut(repo, "/") - head := fmt.Sprintf("%s:%s", owner, vectorUpdateBranch) - existing, _, err := gh.PullRequests.List(ctx, owner, repo, &github.PullRequestListOptions{ - State: "open", - Head: head, - }) - if err != nil { - slog.Error("error checking for existing PR") - return err - } - - if len(existing) > 0 { - slog.Info("a PR for that branch already exists, not opening a new one", "pr", existing[0].GetURL()) - return nil - } - - pr, _, err := gh.PullRequests.Create(ctx, owner, repo, &github.NewPullRequest{ - Title: &vectorUpdatePRTitle, - Body: &vectorUpdatePRBody, - Head: &head, - Base: &vectorUpdatePRBaseBranch, - }) - if err != nil { - slog.Error("error creating PR") - return err - } - - slog.Info("opened PR", "pr", pr.GetURL()) - - return nil -} diff --git a/reports/vectors.go b/reports/vectors.go deleted file mode 100644 index 8b18f29..0000000 --- a/reports/vectors.go +++ /dev/null @@ -1,48 +0,0 @@ -package reports - -import ( - "io/fs" - "path/filepath" - "strings" -) - -var knownVectors = readKnownVectors() - -func readKnownVectors() map[string]map[string]bool { - knownVectors := make(map[string]map[string]bool) - dir := "../web5-test-vectors" - err := filepath.Walk(dir, func(path string, info fs.FileInfo, err error) error { - if !strings.HasSuffix(path, ".json") || strings.HasSuffix(path, ".schema.json") { - return nil - } - - feature, vector := parseVectorPath(strings.TrimPrefix(path, dir)) - if knownVectors[feature] == nil { - knownVectors[feature] = make(map[string]bool) - } - knownVectors[feature][vector] = true - - return nil - }) - - if err != nil { - panic(err) - } - - return knownVectors -} - -func parseVectorPath(path string) (feature string, vector string) { - feature, vector = filepath.Split(path) - vector = strings.TrimSuffix(vector, ".json") - feature = strings.Trim(feature, "/") - - featureWords := []string{} - for _, word := range strings.Split(feature, "_") { - featureWords = append(featureWords, strings.Title(word)) // TODO: strings.Title is deprecated - } - - feature = strings.Join(featureWords, "") - - return feature, vector -} diff --git a/scripts/github/.env.example b/scripts/github/.env.example deleted file mode 100644 index b27467e..0000000 --- a/scripts/github/.env.example +++ /dev/null @@ -1,4 +0,0 @@ -# environment info -GH_OWNER=TBD54566975 -GH_REPO= -GH_TOKEN= \ No newline at end of file diff --git a/scripts/github/.gitignore b/scripts/github/.gitignore deleted file mode 100644 index 37d7e73..0000000 --- a/scripts/github/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules -.env diff --git a/scripts/github/README.md b/scripts/github/README.md deleted file mode 100644 index 6579b40..0000000 --- a/scripts/github/README.md +++ /dev/null @@ -1,28 +0,0 @@ -# GitHub Repository Scripts - -This directory contains scripts that help with individual SDK repo management. - -## Scripts Description - -| Script Name | Description | -| --------------------------- | ----------------------------------------------------------------------------- | -| `npm run create-labels` | Creates GitHub labels from a predefined list if they don't already exist. | -| `npm run create-milestones` | Creates GitHub milestones from a predefined list if they don't already exist. | - -## Installation and Usage - -To run the scripts, first install the necessary dependencies: - -```bash -npm install -``` - -## Environment Variables - -Before running the scripts, ensure that a `.env` file exists and has the following variables set. You can copy `.env.example`: - -| Environment Variable | Description | -| -------------------- | -------------------------------------------- | -| `GH_TOKEN` | Your GitHub personal access token. | -| `GH_OWNER` | The owner username of the GitHub repository. | -| `GH_REPO` | The name of the GitHub repository. | diff --git a/scripts/github/github-create-labels.js b/scripts/github/github-create-labels.js deleted file mode 100644 index b8c6f7a..0000000 --- a/scripts/github/github-create-labels.js +++ /dev/null @@ -1,81 +0,0 @@ -import 'dotenv/config'; -import { Octokit } from '@octokit/core'; - -const octokit = new Octokit({ - auth: process.env['GH_TOKEN'] // Your GitHub token from environment variable -}); - -const owner = process.env['GH_OWNER']; // Owner of the repository from environment variable -const repo = process.env['GH_REPO']; // Name of the repository from environment variable - -const labelsToCreate = [ - { "name": "dsa", "color": "7FDBFF", "description": "Cryptographic Digital Signature Algorithms" }, - { "name": "key-mgmt", "color": "0074D9", "description": "Key Management" }, - { "name": "did:web", "color": "2ECC40", "description": "did:web" }, - { "name": "did:jwk", "color": "FFDC00", "description": "did:jwk" }, - { "name": "did:dht", "color": "FF851B", "description": "did:dht" }, - { "name": "did:key", "color": "F012BE", "description": "did:key" }, - { "name": "did:ion", "color": "B10DC9", "description": "did:ion" }, - { "name": "did-doc-validation", "color": "3D9970", "description": "DID Document & Resolution Validation" }, - { "name": "w3c-vc-dm-1.1", "color": "39CCCC", "description": "W3C Verifiable Credential Data Model 1.1" }, - { "name": "w3c-vc-dm-2.0", "color": "01FF70", "description": "W3C Verifiable Credential Data Model 2.0" }, - { "name": "sd-jwt", "color": "85144B", "description": "SD-JWT / SD-JWT-VC" }, - { "name": "pd-v2", "color": "F9A602", "description": "Presentation Definition V2" }, - { "name": "tbdex-message", "color": "70DB93", "description": "tbDEX Message" }, - { "name": "tbdex-resource", "color": "5B2C6F", "description": "tbDEX Resource" }, - { "name": "tbdex-offering", "color": "E59866", "description": "tbDEX Offering Resource" }, - { "name": "tbdex-rfq", "color": "1F618D", "description": "tbDEX RFQ Message" }, - { "name": "tbdex-quote", "color": "186A3B", "description": "tbDEX Quote Message" }, - { "name": "tbdex-order", "color": "28B463", "description": "tbDEX Order Message" }, - { "name": "tbdex-orderstatus", "color": "D68910", "description": "tbDEX Order-Status Message" }, - { "name": "tbdex-close", "color": "34495E", "description": "tbDEX Close Message" }, - { "name": "tbdex-server", "color": "3498DB", "description": "HTTP server for tbDEX PFIs " }, - { "name": "tbdex-client", "color": "E74C3C", "description": "HTTP client for tbDEX wallets" } -]; - -async function fetchExistingLabels() { - const response = await octokit.request('GET /repos/{owner}/{repo}/labels', { - owner, - repo, - headers: { - 'X-GitHub-Api-Version': '2022-11-28' - } - }); - - return response.data.map(label => label.name); -} - -async function createLabels() { - const existingLabels = await fetchExistingLabels(); - - for (const label of labelsToCreate) { - // Check if the label already exists - if (existingLabels.includes(label.name)) { - console.log(`Label "${label.name}" already exists.`); - continue; // Skip creating this label - } - - try { - const response = await octokit.request('POST /repos/{owner}/{repo}/labels', { - owner, - repo, - name: label.name, - color: label.color, - description: label.description, - headers: { - 'X-GitHub-Api-Version': '2022-11-28' - } - }); - - if (response.status === 201) { - console.log(`Created label: ${label.name}`); - } else { - console.log(`Failed to create label: ${label.name}. Status: ${response.status}`); - } - } catch (error) { - console.error(`Failed to create label: ${label.name}. Error: ${error.message}`); - } - } -} - -createLabels().catch(console.error); diff --git a/scripts/github/github-create-milestones.js b/scripts/github/github-create-milestones.js deleted file mode 100644 index abbec67..0000000 --- a/scripts/github/github-create-milestones.js +++ /dev/null @@ -1,60 +0,0 @@ -import 'dotenv/config'; -import { Octokit } from '@octokit/core'; - -const octokit = new Octokit({ - auth: process.env['GH_TOKEN'] // Your GitHub token from environment variable -}); - -const owner = process.env['GH_OWNER']; // Owner of the repository from environment variable -const repo = process.env['GH_REPO']; // Name of the repository from environment variable - -const newMilestones = [ - { "title": "Eagle" }, - { "title": "ABC" } - // Add more milestones here if needed -]; - -async function fetchExistingMilestones() { - const response = await octokit.request('GET /repos/{owner}/{repo}/milestones', { - owner, - repo, - headers: { - 'X-GitHub-Api-Version': '2022-11-28' - } - }); - - return response.data.map(milestone => milestone.title); -} - -async function createMilestones() { - const existingMilestones = await fetchExistingMilestones(); - - for (const milestone of newMilestones) { - // Check if the milestone already exists - if (existingMilestones.includes(milestone.title)) { - console.log(`Milestone "${milestone.title}" already exists.`); - continue; // Skip creating this milestone - } - - try { - const response = await octokit.request('POST /repos/{owner}/{repo}/milestones', { - owner, - repo, - title: milestone.title, - headers: { - 'X-GitHub-Api-Version': '2022-11-28' - } - }); - - if (response.status === 201) { - console.log(`Created milestone: ${milestone.title}`); - } else { - console.log(`Failed to create milestone: ${milestone.title}. Status: ${response.status}`); - } - } catch (error) { - console.error(`Failed to create milestone: ${milestone.title}. Error: ${error.message}`); - } - } -} - -createMilestones().catch(console.error); diff --git a/scripts/github/package-lock.json b/scripts/github/package-lock.json deleted file mode 100644 index 6875d28..0000000 --- a/scripts/github/package-lock.json +++ /dev/null @@ -1,152 +0,0 @@ -{ - "name": "github", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "dependencies": { - "@octokit/core": "5.0.1", - "dotenv": "16.3.1" - } - }, - "node_modules/@octokit/auth-token": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", - "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/core": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.0.1.tgz", - "integrity": "sha512-lyeeeZyESFo+ffI801SaBKmCfsvarO+dgV8/0gD8u1d87clbEdWsP5yC+dSj3zLhb2eIf5SJrn6vDz9AheETHw==", - "dependencies": { - "@octokit/auth-token": "^4.0.0", - "@octokit/graphql": "^7.0.0", - "@octokit/request": "^8.0.2", - "@octokit/request-error": "^5.0.0", - "@octokit/types": "^12.0.0", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/endpoint": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.2.tgz", - "integrity": "sha512-qhKW8YLIi+Kmc92FQUFGr++DYtkx/1fBv+Thua6baqnjnOsgBYJDCvWZR1YcINuHGOEQt416WOfE+A/oG60NBQ==", - "dependencies": { - "@octokit/types": "^12.0.0", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/graphql": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.0.2.tgz", - "integrity": "sha512-OJ2iGMtj5Tg3s6RaXH22cJcxXRi7Y3EBqbHTBRq+PQAqfaS8f/236fUrWhfSn8P4jovyzqucxme7/vWSSZBX2Q==", - "dependencies": { - "@octokit/request": "^8.0.1", - "@octokit/types": "^12.0.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/openapi-types": { - "version": "19.0.2", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.2.tgz", - "integrity": "sha512-8li32fUDUeml/ACRp/njCWTsk5t17cfTM1jp9n08pBrqs5cDFJubtjsSnuz56r5Tad6jdEPJld7LxNp9dNcyjQ==" - }, - "node_modules/@octokit/request": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.5.tgz", - "integrity": "sha512-zVKbNbX1xUluD9ZR4/tPs1yuYrK9xeh5fGZUXA6u04XGsTvomg0YO8/ZUC0FqAd49hAOEMFPAVUTh+2lBhOhLA==", - "dependencies": { - "@octokit/endpoint": "^9.0.0", - "@octokit/request-error": "^5.0.0", - "@octokit/types": "^12.0.0", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/request-error": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.1.tgz", - "integrity": "sha512-X7pnyTMV7MgtGmiXBwmO6M5kIPrntOXdyKZLigNfQWSEQzVxR4a4vo49vJjTWX70mPndj8KhfT4Dx+2Ng3vnBQ==", - "dependencies": { - "@octokit/types": "^12.0.0", - "deprecation": "^2.0.0", - "once": "^1.4.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/types": { - "version": "12.2.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.2.0.tgz", - "integrity": "sha512-ZkdHqHJdifVndN7Pha10+qrgAjy3AcG//Vmjr/o5UFuTiYCcMhqDj39Yr9VM9zJ/42KO2xAYhV7cvLnLI9Kvwg==", - "dependencies": { - "@octokit/openapi-types": "^19.0.2" - } - }, - "node_modules/before-after-hook": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", - "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" - }, - "node_modules/deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" - }, - "node_modules/dotenv": { - "version": "16.3.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", - "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/motdotla/dotenv?sponsor=1" - } - }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/universal-user-agent": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", - "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==" - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - } - } -} diff --git a/scripts/github/package.json b/scripts/github/package.json deleted file mode 100644 index ccc50c8..0000000 --- a/scripts/github/package.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "type": "module", - "scripts": { - "create-labels": "node github-create-labels.js", - "create-milestones": "node github-create-milestones.js" - }, - "dependencies": { - "@octokit/core": "5.0.1", - "dotenv": "16.3.1" - } -} \ No newline at end of file diff --git a/scripts/test-vector-validation/main.js b/scripts/test-vector-validation/main.js index 410d072..ef045df 100644 --- a/scripts/test-vector-validation/main.js +++ b/scripts/test-vector-validation/main.js @@ -7,7 +7,7 @@ import { fileURLToPath } from 'node:url' const __filename = fileURLToPath(import.meta.url) const __dirname = path.dirname(__filename) -const vectorsDir = `${__dirname}/../../web5-test-vectors` +const vectorsDir = `${__dirname}/../../test-vectors` let vectorsSchema = fs.readFileSync(`${vectorsDir}/vectors.schema.json`, 'utf8') vectorsSchema = JSON.parse(vectorsSchema) diff --git a/web5-test-vectors/README.md b/test-vectors/README.md similarity index 79% rename from web5-test-vectors/README.md rename to test-vectors/README.md index 21df00b..b23ce5e 100644 --- a/web5-test-vectors/README.md +++ b/test-vectors/README.md @@ -7,7 +7,7 @@ This directory contains test vectors for all features we intend to support accro ```text web5-test-vectors β”œβ”€β”€ README.md -β”œβ”€β”€ did-jwk <--- feature +β”œβ”€β”€ did_jwk <--- feature β”‚Β Β  └── resolve.json <--- sub-feature β”œβ”€β”€ index.html └── vectors.schema.json @@ -49,9 +49,15 @@ Should `errors` be set to `true`, the `output` field may optionally be used to i ## Creating New Test Vector Full Walkthrough -### Step 1: Create New Test Vector +### Step 1: Pull down the sdk repo with submouldes you are working with +1. git clone --recurse-submodules git@github.com:TBD54566975/web5-kt.git -1. Navigate to the GitHub repository: sdk-development[https://github.com/TBD54566975/sdk-development/tree/main/web5-test-vectors] +Or if you already cloned it, and just want to pull down the submodules: +1. git submodule update --init + +### Step 2: Create New Test Vector in submodule folder + +1. Navigate to web5-spec in your local directory 2. Create a new folder and JSON file with the structure example_feature/hello_world.json. @@ -65,19 +71,15 @@ Should `errors` be set to `true`, the `output` field may optionally be used to i "description": "this is an example", "input": "hello world", "output": "hello world", - "errors" : false + "errors": false } ] } ``` -### Step 2: Copy JSON to Local Test-Vectors Directory - -Copy the `hello_world.json` file from `example_feature` directory into your SDK's test-vectors folder. make sure the file -and file name are both identical to that in the sdk-development repo. - -### Step 3: Create Unit Test in web5-kt +### Step 3: Create Unit Test +#### in Web5-kt 1. In the `web5-kt` project, create a new unit test class. 1. Name the class following the given pattern: @@ -94,13 +96,13 @@ and file name are both identical to that in the sdk-development repo. class Web5TestVectorsExampleFeature { @Test fun hello_world() { - val testVectors = mapper.readValue(File("../test-vectors/example_feature/hello_world.json"), typeRef) + val testVectors = mapper.readValue(File("../web5-spec/test-vectors/example_feature/hello_world.json"), typeRef) assertEquals(testVectors.vectors[0].input, testVectors.vectors[0].output) } } ``` -### Step 4: Create Unit Test in web5-js +#### in Web5-js 1. In the `web5-js` project, create a new unit test class. @@ -115,7 +117,7 @@ class Web5TestVectorsExampleFeature { 1. Implement the class and test method as follows: ```javascript - import ExampleFeatureHelloWorldSpecJson from '../../../test-vectors/example_feature/hello_world.json' assert { type: 'json' }; + import ExampleFeatureHelloWorldSpecJson from '../../../web5-spec/test-vectors/example_feature/hello_world.json' assert { type: 'json' }; describe('Web5TestVectorsExampleFeature', () => { it('hello_world', async () => { @@ -125,10 +127,10 @@ class Web5TestVectorsExampleFeature { }); ``` -### Step 5: Completion +### Step 4: Completion -* Once the above steps are completed, the `sdk-development` repository will automatically detect the new test vectors by consuming artifacts generated by a github action (No action by you required) -* Once the new vector merges into the sdk-development repo, PRs will be automatically opened on all SDKs that don't have it yet. -* The system will indicate whether the test passes or fails with a checkmark or an 'x' on the [test vectors dashboard](https://tbd54566975.github.io/sdk-development/). +* Create a pr for the web5-spec submodules if you added new test vectors +* Create a pr for the web5-* sdk to add the test vector new unit tests you created +* The system will indicate whether the test passes or fails with a checkmark or an 'x' on the [sdk-report-runner](https://tbd54566975.github.io/sdk-report-runner/). Your new test vector system is now set up and ready for use! diff --git a/web5-test-vectors/credentials/README.md b/test-vectors/credentials/README.md similarity index 100% rename from web5-test-vectors/credentials/README.md rename to test-vectors/credentials/README.md diff --git a/web5-test-vectors/credentials/create.json b/test-vectors/credentials/create.json similarity index 100% rename from web5-test-vectors/credentials/create.json rename to test-vectors/credentials/create.json diff --git a/web5-test-vectors/credentials/verify.json b/test-vectors/credentials/verify.json similarity index 100% rename from web5-test-vectors/credentials/verify.json rename to test-vectors/credentials/verify.json diff --git a/test-vectors/crypto_ed25519/README.md b/test-vectors/crypto_ed25519/README.md new file mode 100644 index 0000000..7a16443 --- /dev/null +++ b/test-vectors/crypto_ed25519/README.md @@ -0,0 +1,58 @@ +# `Ed25519` Test Vectors + +This directory contains test vectors for the `Ed25519` signature scheme, which is a part of the +Edwards-curve Digital Signature Algorithm (EdDSA) family of signature algorithms as detailed in +[RFC 8032](https://datatracker.ietf.org/doc/html/rfc8032). + +## `sign` + +Sign test vectors are detailed in a [JSON file](./sign.json). It includes cases for testing the +signing operation with the Ed25519 curve. + +### Input + +The `input` for the sign operation is an object with the following properties: + +| Property | Description | +| -------- | -------------------------------------------------------------------- | +| `key` | A JSON Web Key ([JWK][RFC7517]) object representing the private key. | +| `data` | The data to be signed, as a byte array in hexadecimal string format. | + +### Output + +The `output` is a hexadecimal string representing the signature byte array produced by the signing +operation. + +### Reference Implementations + +Reference implementations for the sign operation can be found in the following SDK repositories: + +- TypeScript: [`Ed25519.sign()`](https://github.com/TBD54566975/web5-js/blob/44c38a116dec0b357ca15d807eb513f819341e50/packages/crypto/src/primitives/ed25519.ts#L434-L468) + +## `verify` + +Verify test vectors are outlined in a [JSON file](./verify.json), encompassing both successful and unsuccessful signature verification cases. + +### Input + +The `input` for the verify operation includes: + +| Property | Description | +| ----------- | -------------------------------------------------------------------------------- | +| `key` | An JSON Web Key ([JWK][RFC7517]) object representing the public key. | +| `signature` | The signature to verify, as a byte array in hexadecimal string format. | +| `data` | The original data that was signed, as a byte array in hexadecimal string format. | + +### Output + +The `output` is a boolean value indicating whether the signature verification was successful +(`true`) or not (`false`). + +### Reference Implementations + +Reference implementations for the verify operation can also be found in the following SDK +repositories: + +- TypeScript: [`Ed25519.verify()`](https://github.com/TBD54566975/web5-js/blob/44c38a116dec0b357ca15d807eb513f819341e50/packages/crypto/src/primitives/ed25519.ts#L512-L547) + +[RFC7517]: https://datatracker.ietf.org/doc/html/rfc7517 diff --git a/test-vectors/crypto_ed25519/sign.json b/test-vectors/crypto_ed25519/sign.json new file mode 100644 index 0000000..0cb2200 --- /dev/null +++ b/test-vectors/crypto_ed25519/sign.json @@ -0,0 +1,78 @@ +{ + "description": "Ed25519 sign test vectors", + "vectors": [ + { + "description": "generates the expected signature given the RFC8032 0x9d... key and empty message", + "input": { + "data": "", + "key": { + "crv": "Ed25519", + "d": "nWGxne_9WmC6hEr0kuwsxERJxWl7MmkZcDusAxyuf2A", + "kid": "kPrK_qmxVWaYVA9wwBF6Iuo3vVzz7TxHCTwXBygrS4k", + "kty": "OKP", + "x": "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo" + } + }, + "output": "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b", + "errors": false + }, + { + "description": "generates the expected signature given the RFC8032 0x4c... key and 72 message", + "input": { + "data": "72", + "key": { + "crv": "Ed25519", + "d": "TM0Imyj_ltqdtsNG7BFOD1uKMZ81q6Yk2oz27U-4pvs", + "kid": "FtIu-VbGrfe_KB6CH7GNwODB72MNxj_ml11dEvO-7kk", + "kty": "OKP", + "x": "PUAXw-hDiVqStwqnTRt-vJyYLM8uxJaMwM1V8Sr0Zgw" + } + }, + "output": "92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00", + "errors": false + }, + { + "description": "generates the expected signature given the RFC8032 0x00... key and 5a... message", + "input": { + "data": "5ac1dfc324f43e6cb79a87ab0470fa857b51fb944982e19074ca44b1e40082c1d07b92efa7ea55ad42b7c027e0b9e33756d95a2c1796a7c2066811dc41858377d4b835c1688d638884cd2ad8970b74c1a54aadd27064163928a77988b24403aa85af82ceab6b728e554761af7175aeb99215b7421e4474c04d213e01ff03e3529b11077cdf28964b8c49c5649e3a46fa0a09dcd59dcad58b9b922a83210acd5e65065531400234f5e40cddcf9804968e3e9ac6f5c44af65001e158067fc3a660502d13fa8874fa93332138d9606bc41b4cee7edc39d753dae12a873941bb357f7e92a4498847d6605456cb8c0b425a47d7d3ca37e54e903a41e6450a35ebe5237c6f0c1bbbc1fd71fb7cd893d189850295c199b7d88af26bc8548975fda1099ffefee42a52f3428ddff35e0173d3339562507ac5d2c45bbd2c19cfe89b", + "key": { + "crv": "Ed25519", + "d": "AC_dH3ZBeTqwZLt6qEj3YufsbjMv_CburNoUGuM7F4M", + "kid": "M7TyrCUM12xZUUArpFOvdxvSN0CKasiRsxOIlVcyEaA", + "kty": "OKP", + "x": "d9HY66zRP04vikDijEpjvJzjv7aXFjNLyyijPrE0CGw" + } + }, + "output": "0df3aa0d0999ad3dc580378f52d152700d5b3b057f56a66f92112e441e1cb9123c66f18712c87efe22d2573777296241216904d7cdd7d5ea433928bd2872fa0c", + "errors": false + }, + { + "description": "generates the expected signature given the RFC8032 0xf5... key and long message", + "input": { + "data": "08b8b2b733424243760fe426a4b54908632110a66c2f6591eabd3345e3e4eb98fa6e264bf09efe12ee50f8f54e9f77b1e355f6c50544e23fb1433ddf73be84d879de7c0046dc4996d9e773f4bc9efe5738829adb26c81b37c93a1b270b20329d658675fc6ea534e0810a4432826bf58c941efb65d57a338bbd2e26640f89ffbc1a858efcb8550ee3a5e1998bd177e93a7363c344fe6b199ee5d02e82d522c4feba15452f80288a821a579116ec6dad2b3b310da903401aa62100ab5d1a36553e06203b33890cc9b832f79ef80560ccb9a39ce767967ed628c6ad573cb116dbefefd75499da96bd68a8a97b928a8bbc103b6621fcde2beca1231d206be6cd9ec7aff6f6c94fcd7204ed3455c68c83f4a41da4af2b74ef5c53f1d8ac70bdcb7ed185ce81bd84359d44254d95629e9855a94a7c1958d1f8ada5d0532ed8a5aa3fb2d17ba70eb6248e594e1a2297acbbb39d502f1a8c6eb6f1ce22b3de1a1f40cc24554119a831a9aad6079cad88425de6bde1a9187ebb6092cf67bf2b13fd65f27088d78b7e883c8759d2c4f5c65adb7553878ad575f9fad878e80a0c9ba63bcbcc2732e69485bbc9c90bfbd62481d9089beccf80cfe2df16a2cf65bd92dd597b0707e0917af48bbb75fed413d238f5555a7a569d80c3414a8d0859dc65a46128bab27af87a71314f318c782b23ebfe808b82b0ce26401d2e22f04d83d1255dc51addd3b75a2b1ae0784504df543af8969be3ea7082ff7fc9888c144da2af58429ec96031dbcad3dad9af0dcbaaaf268cb8fcffead94f3c7ca495e056a9b47acdb751fb73e666c6c655ade8297297d07ad1ba5e43f1bca32301651339e22904cc8c42f58c30c04aafdb038dda0847dd988dcda6f3bfd15c4b4c4525004aa06eeff8ca61783aacec57fb3d1f92b0fe2fd1a85f6724517b65e614ad6808d6f6ee34dff7310fdc82aebfd904b01e1dc54b2927094b2db68d6f903b68401adebf5a7e08d78ff4ef5d63653a65040cf9bfd4aca7984a74d37145986780fc0b16ac451649de6188a7dbdf191f64b5fc5e2ab47b57f7f7276cd419c17a3ca8e1b939ae49e488acba6b965610b5480109c8b17b80e1b7b750dfc7598d5d5011fd2dcc5600a32ef5b52a1ecc820e308aa342721aac0943bf6686b64b2579376504ccc493d97e6aed3fb0f9cd71a43dd497f01f17c0e2cb3797aa2a2f256656168e6c496afc5fb93246f6b1116398a346f1a641f3b041e989f7914f90cc2c7fff357876e506b50d334ba77c225bc307ba537152f3f1610e4eafe595f6d9d90d11faa933a15ef1369546868a7f3a45a96768d40fd9d03412c091c6315cf4fde7cb68606937380db2eaaa707b4c4185c32eddcdd306705e4dc1ffc872eeee475a64dfac86aba41c0618983f8741c5ef68d3a101e8a3b8cac60c905c15fc910840b94c00a0b9d0", + "key": { + "crv": "Ed25519", + "d": "9eV2fPFTMZUXYw8iaHa4bIFgzFg7wBN0TGvyVfXMDuU", + "kty": "OKP", + "x": "J4EX_BRMcjQPZ9DyMW6Dhs7_vyskKMnFH-98WX8dQm4", + "kid": "lZI1vM7tnlYapaF5-cy86ptx0tT_8Av721hhiNB5ti4" + } + }, + "output": "0aab4c900501b3e24d7cdf4663326a3a87df5e4843b2cbdb67cbf6e460fec350aa5371b1508f9f4528ecea23c436d94b5e8fcd4f681e30a6ac00a9704a188a03", + "errors": false + }, + { + "description": "error when given a public key", + "input": { + "data": "", + "key": { + "crv": "Ed25519", + "kid": "kPrK_qmxVWaYVA9wwBF6Iuo3vVzz7TxHCTwXBygrS4k", + "kty": "OKP", + "x": "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo" + } + }, + "errors": true + } + ] +} \ No newline at end of file diff --git a/test-vectors/crypto_ed25519/verify.json b/test-vectors/crypto_ed25519/verify.json new file mode 100644 index 0000000..bfc026b --- /dev/null +++ b/test-vectors/crypto_ed25519/verify.json @@ -0,0 +1,125 @@ +{ + "description": "Ed25519 verify test vectors", + "vectors": [ + { + "description": "verifies the signature for the RFC8032 0x9d... key and empty message", + "input": { + "data": "", + "key": { + "crv": "Ed25519", + "kid": "kPrK_qmxVWaYVA9wwBF6Iuo3vVzz7TxHCTwXBygrS4k", + "kty": "OKP", + "x": "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo" + }, + "signature": "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b" + }, + "output": true, + "errors": false + }, + { + "description": "verifies the signature for the RFC8032 0x4c... key and 72 message", + "input": { + "data": "72", + "key": { + "crv": "Ed25519", + "kid": "FtIu-VbGrfe_KB6CH7GNwODB72MNxj_ml11dEvO-7kk", + "kty": "OKP", + "x": "PUAXw-hDiVqStwqnTRt-vJyYLM8uxJaMwM1V8Sr0Zgw" + }, + "signature": "92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00" + }, + "output": true, + "errors": false + }, + { + "description": "verifies the signature for the RFC8032 0x00... key and 5a... message", + "input": { + "data": "5ac1dfc324f43e6cb79a87ab0470fa857b51fb944982e19074ca44b1e40082c1d07b92efa7ea55ad42b7c027e0b9e33756d95a2c1796a7c2066811dc41858377d4b835c1688d638884cd2ad8970b74c1a54aadd27064163928a77988b24403aa85af82ceab6b728e554761af7175aeb99215b7421e4474c04d213e01ff03e3529b11077cdf28964b8c49c5649e3a46fa0a09dcd59dcad58b9b922a83210acd5e65065531400234f5e40cddcf9804968e3e9ac6f5c44af65001e158067fc3a660502d13fa8874fa93332138d9606bc41b4cee7edc39d753dae12a873941bb357f7e92a4498847d6605456cb8c0b425a47d7d3ca37e54e903a41e6450a35ebe5237c6f0c1bbbc1fd71fb7cd893d189850295c199b7d88af26bc8548975fda1099ffefee42a52f3428ddff35e0173d3339562507ac5d2c45bbd2c19cfe89b", + "key": { + "crv": "Ed25519", + "kid": "M7TyrCUM12xZUUArpFOvdxvSN0CKasiRsxOIlVcyEaA", + "kty": "OKP", + "x": "d9HY66zRP04vikDijEpjvJzjv7aXFjNLyyijPrE0CGw" + }, + "signature": "0df3aa0d0999ad3dc580378f52d152700d5b3b057f56a66f92112e441e1cb9123c66f18712c87efe22d2573777296241216904d7cdd7d5ea433928bd2872fa0c" + }, + "output": true, + "errors": false + }, + { + "description": "verifies the signature for the RFC8032 0xf5... key and long message", + "input": { + "data": "08b8b2b733424243760fe426a4b54908632110a66c2f6591eabd3345e3e4eb98fa6e264bf09efe12ee50f8f54e9f77b1e355f6c50544e23fb1433ddf73be84d879de7c0046dc4996d9e773f4bc9efe5738829adb26c81b37c93a1b270b20329d658675fc6ea534e0810a4432826bf58c941efb65d57a338bbd2e26640f89ffbc1a858efcb8550ee3a5e1998bd177e93a7363c344fe6b199ee5d02e82d522c4feba15452f80288a821a579116ec6dad2b3b310da903401aa62100ab5d1a36553e06203b33890cc9b832f79ef80560ccb9a39ce767967ed628c6ad573cb116dbefefd75499da96bd68a8a97b928a8bbc103b6621fcde2beca1231d206be6cd9ec7aff6f6c94fcd7204ed3455c68c83f4a41da4af2b74ef5c53f1d8ac70bdcb7ed185ce81bd84359d44254d95629e9855a94a7c1958d1f8ada5d0532ed8a5aa3fb2d17ba70eb6248e594e1a2297acbbb39d502f1a8c6eb6f1ce22b3de1a1f40cc24554119a831a9aad6079cad88425de6bde1a9187ebb6092cf67bf2b13fd65f27088d78b7e883c8759d2c4f5c65adb7553878ad575f9fad878e80a0c9ba63bcbcc2732e69485bbc9c90bfbd62481d9089beccf80cfe2df16a2cf65bd92dd597b0707e0917af48bbb75fed413d238f5555a7a569d80c3414a8d0859dc65a46128bab27af87a71314f318c782b23ebfe808b82b0ce26401d2e22f04d83d1255dc51addd3b75a2b1ae0784504df543af8969be3ea7082ff7fc9888c144da2af58429ec96031dbcad3dad9af0dcbaaaf268cb8fcffead94f3c7ca495e056a9b47acdb751fb73e666c6c655ade8297297d07ad1ba5e43f1bca32301651339e22904cc8c42f58c30c04aafdb038dda0847dd988dcda6f3bfd15c4b4c4525004aa06eeff8ca61783aacec57fb3d1f92b0fe2fd1a85f6724517b65e614ad6808d6f6ee34dff7310fdc82aebfd904b01e1dc54b2927094b2db68d6f903b68401adebf5a7e08d78ff4ef5d63653a65040cf9bfd4aca7984a74d37145986780fc0b16ac451649de6188a7dbdf191f64b5fc5e2ab47b57f7f7276cd419c17a3ca8e1b939ae49e488acba6b965610b5480109c8b17b80e1b7b750dfc7598d5d5011fd2dcc5600a32ef5b52a1ecc820e308aa342721aac0943bf6686b64b2579376504ccc493d97e6aed3fb0f9cd71a43dd497f01f17c0e2cb3797aa2a2f256656168e6c496afc5fb93246f6b1116398a346f1a641f3b041e989f7914f90cc2c7fff357876e506b50d334ba77c225bc307ba537152f3f1610e4eafe595f6d9d90d11faa933a15ef1369546868a7f3a45a96768d40fd9d03412c091c6315cf4fde7cb68606937380db2eaaa707b4c4185c32eddcdd306705e4dc1ffc872eeee475a64dfac86aba41c0618983f8741c5ef68d3a101e8a3b8cac60c905c15fc910840b94c00a0b9d0", + "key": { + "crv": "Ed25519", + "kty": "OKP", + "x": "J4EX_BRMcjQPZ9DyMW6Dhs7_vyskKMnFH-98WX8dQm4", + "kid": "lZI1vM7tnlYapaF5-cy86ptx0tT_8Av721hhiNB5ti4" + }, + "signature": "0aab4c900501b3e24d7cdf4663326a3a87df5e4843b2cbdb67cbf6e460fec350aa5371b1508f9f4528ecea23c436d94b5e8fcd4f681e30a6ac00a9704a188a03" + }, + "output": true, + "errors": false + }, + { + "description": "verification fails if the data was tampered with", + "input": { + "data": "0002030405060708", + "key": { + "kty": "OKP", + "crv": "Ed25519", + "x": "XVXPU41VtJuEN0m1WTB-9-AqmIr4shYrsycDu05WmRs", + "kid": "QVq_liaHGqnWD1xzm3VCmZG7ibO_aZSEK7gZ4I9rEok" + }, + "signature": "6a38583c45ffa51c99cf621fd19219fcc80c39bfa64fba884b27ed90ca46bd4122d8c5c6c87b6757787716c37497948204aae42442023765e9c0bc70e3e7a600" + }, + "output": false, + "errors": false + }, + { + "description": "verification fails if the signature was tampered with", + "input": { + "data": "0102030405060708", + "key": { + "kty": "OKP", + "crv": "Ed25519", + "x": "5bXaMJzFcrB8638un6ccrzTQ3Mh-49mPZT9yN10FZJ8", + "kid": "_6WIXMTzaw5V0JTPQCluQF58MREJeBSVLCmG7EVCorE" + }, + "signature": "7b7f4334f3df755dc2085dbc9be69588f4e86289c5be22b860f09ee354e5368724c9d96895d20c1b7cf8b723f0191073e0cf9b7d90c0a88fcfbbcdbe8a2df108" + }, + "output": false, + "errors": false + }, + { + "description": "verification fails if the public key is not associated with the signing key", + "input": { + "data": "0102030405060708", + "key": { + "kty": "OKP", + "crv": "Ed25519", + "x": "Q7SbAMR1c3ZefhGMU1cSsyfVqSQ4JFShScvO4C4WleY", + "kid": "SSMbPCacyDpbL3emWwOY5ESkBpkgtzw4dseWZcFfqjc" + }, + "signature": "50b20a14a64942d3211621c1b8be110f0f5a35b3ff4da123ab2c2d38e98f24548e0727539d0a98cf653b7c4e7732b103ebc5ee0456acf4a601285c6ecedf8e0b" + }, + "output": false, + "errors": false + }, + { + "description": "error when given a private key", + "input": { + "data": "", + "key": { + "crv": "Ed25519", + "d": "nWGxne_9WmC6hEr0kuwsxERJxWl7MmkZcDusAxyuf2A", + "kid": "kPrK_qmxVWaYVA9wwBF6Iuo3vVzz7TxHCTwXBygrS4k", + "kty": "OKP", + "x": "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo" + }, + "signature": "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b" + }, + "errors": true + } + ] +} \ No newline at end of file diff --git a/test-vectors/crypto_es256k/README.md b/test-vectors/crypto_es256k/README.md new file mode 100644 index 0000000..3e7c7f8 --- /dev/null +++ b/test-vectors/crypto_es256k/README.md @@ -0,0 +1,70 @@ +# `ES256K` Test Vectors + +This directory contains test vectors for the secp256k1 with SHA-256 signature scheme, which is a +part of the Elliptic Curve Digital Signature Algorithm (ECDSA) family of signature algorithms as +detailed in the Standards for Efficient Cryptography Group (SECG) publication +[SEC1](https://www.secg.org/sec1-v2.pdf). + +The `ES256K` algorithm identifier is defined in +[RFC8812](https://datatracker.ietf.org/doc/html/rfc8812), which specifies the use of ECDSA with the +secp256k1 curve and the SHA-256 cryptographic hash function. + +> [!IMPORTANT] +> All ECDSA signatures, regardless of the curve, are subject to signature malleability such that +> for every valid signature there is a "mirror" signature that's equally valid for the same message +> and public key. Read more +> [here](https://github.com/TBD54566975/web5-js/blob/f4e8194301be302889c031fb904425ff1a7b34aa/packages/crypto/src/primitives/secp256k1.ts#L75-L101) +> about the practical implications and mitigation techniques. + +## `sign` + +Sign test vectors are detailed in a [JSON file](./sign.json). It includes cases for testing the +signing operation with the secp256k1 curve and SHA-256 hash function. + +### Input + +The `input` for the sign operation is an object with the following properties: + +| Property | Description | +| -------- | -------------------------------------------------------------------- | +| `key` | A JSON Web Key ([JWK][RFC7517]) object representing the private key. | +| `data` | The data to be signed, as a byte array in hexadecimal string format. | + +### Output + +The `output` is a hexadecimal string representing the signature byte array produced by the signing +operation. + +### Reference Implementations + +Reference implementations for the sign operation can be found in the following SDK repositories: + +- TypeScript: [`Secp256k1.sign()`](https://github.com/TBD54566975/web5-js/blob/44c38a116dec0b357ca15d807eb513f819341e50/packages/crypto/src/primitives/secp256k1.ts#L547-L595) + +## `verify` + +Verify test vectors are outlined in a [JSON file](./verify.json), encompassing both successful and unsuccessful signature verification cases. + +### Input + +The `input` for the verify operation includes: + +| Property | Description | +| ----------- | -------------------------------------------------------------------------------- | +| `key` | An JSON Web Key ([JWK][RFC7517]) object representing the public key. | +| `signature` | The signature to verify, as a byte array in hexadecimal string format. | +| `data` | The original data that was signed, as a byte array in hexadecimal string format. | + +### Output + +The `output` is a boolean value indicating whether the signature verification was successful +(`true`) or not (`false`). + +### Reference Implementations + +Reference implementations for the verify operation can also be found in the following SDK +repositories: + +- TypeScript: [`Secp256k1.verify()`](https://github.com/TBD54566975/web5-js/blob/44c38a116dec0b357ca15d807eb513f819341e50/packages/crypto/src/primitives/secp256k1.ts#L670-L724) + +[RFC7517]: https://datatracker.ietf.org/doc/html/rfc7517 diff --git a/test-vectors/crypto_es256k/sign.json b/test-vectors/crypto_es256k/sign.json new file mode 100644 index 0000000..7ac86c6 --- /dev/null +++ b/test-vectors/crypto_es256k/sign.json @@ -0,0 +1,65 @@ +{ + "description": "ES256K sign test vectors", + "vectors": [ + { + "description": "always generates low-S form signatures", + "input": { + "data": "333435", + "key": { + "crv": "secp256k1", + "d": "lZqISvM7R1S7zBgZ5JjUuOppZuYKXuCbYWBkqgwX88c", + "kid": "JOeO0oJDLMaXibhJBpsHVvskK47qq0k8uaLozxTtNhk", + "kty": "EC", + "x": "npaD6WyM4AZIxwPmieND_gdnYuROitnyDfskXwpv-J0", + "y": "y5_uOFRRNOCWAJPD-Ly1ENJd908lWJ0-0KGnTwxWzNM" + } + }, + "output": "95b9c99642a5765b4f5f4648671dbad2ad107f7507f1e538eb4ad365caf76a4d321db3e3682f5124d37c597b6f2b489171c6b7d90e82f67a87a7e4d8783f4d63", + "errors": false + }, + { + "description": "error when given a public key", + "input": { + "data": "", + "key": { + "crv": "secp256k1", + "kid": "JOeO0oJDLMaXibhJBpsHVvskK47qq0k8uaLozxTtNhk", + "kty": "EC", + "x": "npaD6WyM4AZIxwPmieND_gdnYuROitnyDfskXwpv-J0", + "y": "y5_uOFRRNOCWAJPD-Ly1ENJd908lWJ0-0KGnTwxWzNM" + } + }, + "errors": true + }, + { + "description": "error with invalid private key == 0 (not on curve)", + "input": { + "data": "0000000000000000000000000000000000000000000000000000000000000001", + "key": { + "kty": "EC", + "crv": "secp256k1", + "d": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "x": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "y": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "kid": "bBw8BkYm7Aeo-e8Xzbc76irs8TtXtPxvCIZiUuuU-PY" + } + }, + "errors": true + }, + { + "description": "error with invalid private key >= G (not on curve)", + "input": { + "data": "0000000000000000000000000000000000000000000000000000000000000001", + "key": { + "kty": "EC", + "crv": "secp256k1", + "d": "__________________________________________8", + "x": "__________________________________________8", + "y": "__________________________________________8", + "kid": "W-Oix7HogMrpbP0tj98DA8McTn2MLUEo9LYlbfk3-lA" + } + }, + "errors": true + } + ] +} \ No newline at end of file diff --git a/test-vectors/crypto_es256k/verify.json b/test-vectors/crypto_es256k/verify.json new file mode 100644 index 0000000..6bafb88 --- /dev/null +++ b/test-vectors/crypto_es256k/verify.json @@ -0,0 +1,132 @@ +{ + "description": "ES256K verify test vectors", + "vectors": [ + { + "description": "verifies the signature from Wycheproof test case 3", + "input": { + "data": "313233343030", + "key": { + "crv": "secp256k1", + "kid": "i8L_MOOCkkDoHKY1a8cXtZ2BSTLWzD29eiCUiR555ts", + "kty": "EC", + "x": "uDj_ROW8F3vyEYnQdmCC_J2EMiaIf8l2A3EQC37iCm8", + "y": "8MnXW_unsxpryhl0SW7rVt41cHGVXYPEsbraoLIYMuk" + }, + "signature": "813ef79ccefa9a56f7ba805f0e478584fe5f0dd5f567bc09b5123ccbc98323656ff18a52dcc0336f7af62400a6dd9b810732baf1ff758000d6f613a556eb31ba" + }, + "output": true, + "errors": false + }, + { + "description": "verifies low-S form signatures", + "input": { + "data": "333435", + "key": { + "crv": "secp256k1", + "kid": "9l2x1L-iUvyCy4RuqJdoqe7h0IPnCVXPjTHhVYCuLAc", + "kty": "EC", + "x": "A2ZbCLhod3ltBQ4Mw0zjkcQZ7h7B1FQ3s56ZtWavonQ", + "y": "JBerPwkut8tONfAfcXhNEBERj7jejohqMfbbs2aMMZA" + }, + "signature": "351757c538d0a13fa9473dabc259be82dba1bd8f44dcba71a7f222655429b4700608736ab97d0b31bae1a0c2cac4b35eeaf35f767f5ebdafdff042a68739dfb4" + }, + "output": true, + "errors": false + }, + { + "description": "verifies high-S form signatures", + "input": { + "data": "333435", + "key": { + "crv": "secp256k1", + "kid": "9l2x1L-iUvyCy4RuqJdoqe7h0IPnCVXPjTHhVYCuLAc", + "kty": "EC", + "x": "A2ZbCLhod3ltBQ4Mw0zjkcQZ7h7B1FQ3s56ZtWavonQ", + "y": "JBerPwkut8tONfAfcXhNEBERj7jejohqMfbbs2aMMZA" + }, + "signature": "351757c538d0a13fa9473dabc259be82dba1bd8f44dcba71a7f222655429b470f9f78c954682f4ce451e5f3d353b4c9fcfbb7d702fe9e28bdfe21be648fc618d" + }, + "output": true, + "errors": false + }, + { + "description": "verification fails if the data was tampered with", + "input": { + "data": "0002030405060708", + "key": { + "kty": "EC", + "crv": "secp256k1", + "x": "fmCdLkmSfkAW0sKwrDegDsCcIKVUC_S6RBSGqrqNDzw", + "y": "qG4iddPl2ddQS4QRGloxXJDMwqT6cwHEFr9o0_aXp0s", + "kid": "yF4nEQmfgPjaZSudWp55n0oD486mWw2S0tG6G0Vs9ds" + }, + "signature": "efcd2eb0df4137bf3993149b8dc0956aea9858c83c270ea0fcbf6fb8da77573d1e49798da017740b5e948a099cdc2abcda43421bc872c4ae1370de4661f9d879" + }, + "output": false, + "errors": false + }, + { + "description": "verification fails if the signature was tampered with", + "input": { + "data": "0102030405060708", + "key": { + "kty": "EC", + "crv": "secp256k1", + "x": "oFYWfw35gaUsuUKXTEfq9i0Rg8bJI8aautX7uUy-BlI", + "y": "CXnzACqBqCFvP5zEmolhFiuQJ7MFY6yiMDHKxiLv8SM", + "kid": "AkWUHqaYZCNM06UeEGCDKwYJD1fXNFqB4JOzmqFDTCQ" + }, + "signature": "3ce28829b29db2fce5ab3fbc1dd6822dc29787e806573ded683003a80e4bca85221b4c5e39c43117bbadb63dccd3649223729c5b5847f74935cfd6d810584de6" + }, + "output": false, + "errors": false + }, + { + "description": "verification fails if the public key is not associated with the signing key", + "input": { + "data": "0102030405060708", + "key": { + "kty": "EC", + "crv": "secp256k1", + "x": "rZumJRfoU39x5arLh3g6geDFnikLRpCsTneNOvWeAXw", + "y": "ACJk2iPQZinwFT6MeGEwu29jFxuvqjlEXA7jbaSYNx8", + "kid": "J15CEGRafTv4gR3jr3zaWqsO5txEzcxICDBhJO-bkRw" + }, + "signature": "006b365af98e60c9dd89884391bc2d41aa078586a899e7fff07104683a3195ec323589cf5050a4d485a2e6c281561f378dd0a9663954236b5d20fd64519bcbe7" + }, + "output": false, + "errors": false + }, + { + "description": "error when given a private key", + "input": { + "data": "", + "key": { + "crv": "secp256k1", + "d": "lZqISvM7R1S7zBgZ5JjUuOppZuYKXuCbYWBkqgwX88c", + "kid": "JOeO0oJDLMaXibhJBpsHVvskK47qq0k8uaLozxTtNhk", + "kty": "EC", + "x": "npaD6WyM4AZIxwPmieND_gdnYuROitnyDfskXwpv-J0", + "y": "y5_uOFRRNOCWAJPD-Ly1ENJd908lWJ0-0KGnTwxWzNM" + }, + "signature": "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b" + }, + "errors": true + }, + { + "description": "error with invalid public key X > P (not on curve)", + "input": { + "data": "", + "key": { + "crv": "secp256k1", + "kid": "zrExdhAYVSioQSqh8uTqzc1GEpEKGBax6Q7J8UdBt0s", + "kty": "EC", + "x": "_____________________________________v___DA", + "y": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE" + }, + "signature": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001" + }, + "errors": true + } + ] +} \ No newline at end of file diff --git a/test-vectors/did_dht/create.json b/test-vectors/did_dht/create.json new file mode 100644 index 0000000..46ef41d --- /dev/null +++ b/test-vectors/did_dht/create.json @@ -0,0 +1,150 @@ +{ + "description": "did:dht create", + "vectors": [ + { + "description": "creates a did document according to the vector in https://did-dht.com/#vector-1", + "input": { + "identityPublicJwk": { + "kty": "OKP", + "crv": "Ed25519", + "x": "YCcHYL2sYNPDlKaALcEmll2HHyT968M4UWbr-9CFGWE", + "alg": "EdDSA", + "kid": "0" + } + }, + "output": { + "id": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo", + "verificationMethod": [ + { + "id": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0", + "type": "JsonWebKey", + "controller": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo", + "publicKeyJwk": { + "kty": "OKP", + "crv": "Ed25519", + "x": "YCcHYL2sYNPDlKaALcEmll2HHyT968M4UWbr-9CFGWE", + "alg": "EdDSA", + "kid": "0" + } + } + ], + "authentication": [ + "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0" + ], + "assertionMethod": [ + "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0" + ], + "capabilityInvocation": [ + "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0" + ], + "capabilityDelegation": [ + "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0" + ] + } + }, + { + "description": "creates a did document according to the vector in https://did-dht.com/#vector-2", + "input": { + "identityPublicJwk": { + "kty": "OKP", + "crv": "Ed25519", + "x": "YCcHYL2sYNPDlKaALcEmll2HHyT968M4UWbr-9CFGWE", + "alg": "EdDSA", + "kid": "0" + }, + "services": [ + { + "id": "service-1", + "type": "TestService", + "serviceEndpoint": [ + "https://test-service.com/1", + "https://test-service.com/2" + ] + } + ], + "additionalVerificationMethods": [ + { + "jwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "1_o0IKHGNamet8-3VYNUTiKlhVK-LilcKrhJSPHSNP0", + "y": "qzU8qqh0wKB6JC_9HCu8pHE-ZPkDpw4AdJ-MsV2InVY", + "alg": "ES256K", + "kid": "0GkvkdCGu3DL7Mkv0W1DhTMCBT9-z0CkFqZoJQtw7vw" + }, + "purposes": [ + "assertionMethod", + "capabilityInvocation" + ] + } + ], + "controller": [ + "did:example:abcd" + ], + "alsoKnownAs": [ + "did:example:efgh", + "did:example:ijkl" + ] + }, + "output": { + "id": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo", + "controller": "did:example:abcd", + "alsoKnownAs": [ + "did:example:efgh", + "did:example:ijkl" + ], + "verificationMethod": [ + { + "id": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0", + "type": "JsonWebKey", + "controller": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo", + "publicKeyJwk": { + "kty": "OKP", + "crv": "Ed25519", + "x": "YCcHYL2sYNPDlKaALcEmll2HHyT968M4UWbr-9CFGWE", + "alg": "EdDSA", + "kid": "0" + } + }, + { + "id": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0GkvkdCGu3DL7Mkv0W1DhTMCBT9-z0CkFqZoJQtw7vw", + "type": "JsonWebKey", + "controller": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo", + "publicKeyJwk": { + "kty": "EC", + "crv": "secp256k1", + "x": "1_o0IKHGNamet8-3VYNUTiKlhVK-LilcKrhJSPHSNP0", + "y": "qzU8qqh0wKB6JC_9HCu8pHE-ZPkDpw4AdJ-MsV2InVY", + "alg": "ES256K", + "kid": "0GkvkdCGu3DL7Mkv0W1DhTMCBT9-z0CkFqZoJQtw7vw" + } + } + ], + "authentication": [ + "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0" + ], + "assertionMethod": [ + "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0", + "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0GkvkdCGu3DL7Mkv0W1DhTMCBT9-z0CkFqZoJQtw7vw" + ], + "capabilityInvocation": [ + "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0", + "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0GkvkdCGu3DL7Mkv0W1DhTMCBT9-z0CkFqZoJQtw7vw" + ], + "capabilityDelegation": [ + "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#0" + ], + "service": [ + { + "id": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoo#service-1", + "type": "TestService", + "serviceEndpoint": [ + "https://test-service.com/1", + "https://test-service.com/2" + ] + } + ] + } + } + ] +} \ No newline at end of file diff --git a/test-vectors/did_dht/resolve.json b/test-vectors/did_dht/resolve.json new file mode 100644 index 0000000..cbe28f4 --- /dev/null +++ b/test-vectors/did_dht/resolve.json @@ -0,0 +1,41 @@ +{ + "description": "did:dht resolution", + "vectors": [ + { + "description": "methodNotSupported error returned when did method is not dht", + "input": { + "didUri": "did:web:example.com" + }, + "output": { + "didResolutionMetadata": { + "error": "methodNotSupported" + } + }, + "errors": true + }, + { + "description": "notFound error returned when not published", + "input": { + "didUri": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfoz" + }, + "output": { + "didResolutionMetadata": { + "error": "notFound" + } + }, + "errors": true + }, + { + "description": "invalidDid error returned for suffix with invalid character", + "input": { + "didUri": "did:dht:cyuoqaf7itop8ohww4yn5ojg13qaq83r9zihgqntc5i9zwrfdfov" + }, + "output": { + "didResolutionMetadata": { + "error": "invalidDid" + } + }, + "errors": true + } + ] +} \ No newline at end of file diff --git a/web5-test-vectors/did_jwk/README.md b/test-vectors/did_jwk/README.md similarity index 100% rename from web5-test-vectors/did_jwk/README.md rename to test-vectors/did_jwk/README.md diff --git a/web5-test-vectors/did_jwk/resolve.json b/test-vectors/did_jwk/resolve.json similarity index 99% rename from web5-test-vectors/did_jwk/resolve.json rename to test-vectors/did_jwk/resolve.json index 51fe927..b1aec6b 100644 --- a/web5-test-vectors/did_jwk/resolve.json +++ b/test-vectors/did_jwk/resolve.json @@ -101,7 +101,7 @@ }, "didDocumentMetadata": {} }, - "errors": false + "errors": true } ] -} \ No newline at end of file +} diff --git a/test-vectors/did_web/README.md b/test-vectors/did_web/README.md new file mode 100644 index 0000000..4f2e13b --- /dev/null +++ b/test-vectors/did_web/README.md @@ -0,0 +1,24 @@ +# `did:web` Test Vectors + +## Resolve + +Resolution test vectors are available [here](./resolve.json) + +### Input + +The value of `input` is an object that contains the following properties: + +| Property | Description | +|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `didUri` | The DID URI to be resolved. | +| `mockServer` | Optional. Object used to describe mocking behavior. Every key in the object is a URL, and the value is the JSON object that should be sent back as the response to a HTTP GET request. | + +### Output + +The value of `output` is an object that contains the following properties. + +| Property | Description | +|-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `didDocument` | the expected [didDocument](https://www.w3.org/TR/did-core/#dfn-diddocument) when `input.didUri` is resolved. Note that `didDocument` is set to `{}` if resolution is unsuccessful | +| `didDocumentMetadata` | the expected [didDocumentMetadata](https://www.w3.org/TR/did-core/#dfn-diddocumentmetadata) when `input.didUri` is resolved. Note for `did:web` this is _always_ an empty object | +| `didResolutionMetadata` | the expected [didResolutionMetadata](https://www.w3.org/TR/did-core/#dfn-didresolutionmetadata) when `input.didUri` is resolved. Note for `did:web`, on success, this is _always_ an empty object | diff --git a/web5-test-vectors/did_web/resolve.json b/test-vectors/did_web/resolve.json similarity index 83% rename from web5-test-vectors/did_web/resolve.json rename to test-vectors/did_web/resolve.json index 3288428..a4b6633 100644 --- a/web5-test-vectors/did_web/resolve.json +++ b/test-vectors/did_web/resolve.json @@ -12,10 +12,11 @@ } }, "output": { - "didResolutionMetadata": {}, "didDocument": { "id": "did:web:example.com" - } + }, + "didDocumentMetadata": {}, + "didResolutionMetadata": {} } }, { @@ -29,10 +30,11 @@ } }, "output": { - "didResolutionMetadata": {}, "didDocument": { "id": "did:web:w3c-ccg.github.io:user:alice" - } + }, + "didDocumentMetadata": {}, + "didResolutionMetadata": {} } }, { @@ -46,10 +48,11 @@ } }, "output": { - "didResolutionMetadata": {}, "didDocument": { "id": "did:web:example.com%3A3000:user:alice" - } + }, + "didDocumentMetadata": {}, + "didResolutionMetadata": {} } }, { @@ -58,6 +61,8 @@ "didUri": "did:dht:gb46emk73wkenrut43ii67a3o5qctojcaucebth7r83pst6yeh8o" }, "output": { + "didDocument": null, + "didDocumentMetadata": {}, "didResolutionMetadata": { "error": "methodNotSupported" } @@ -70,6 +75,8 @@ "didUri": "did:web:doesnotexist.com" }, "output": { + "didDocument": null, + "didDocumentMetadata": {}, "didResolutionMetadata": { "error": "notFound" } @@ -82,6 +89,8 @@ "didUri": "did:web:invalidcharΓΈ.com" }, "output": { + "didDocument": null, + "didDocumentMetadata": {}, "didResolutionMetadata": { "error": "invalidDid" } diff --git a/web5-test-vectors/index.html b/test-vectors/index.html similarity index 100% rename from web5-test-vectors/index.html rename to test-vectors/index.html diff --git a/web5-test-vectors/presentation_exchange/README.md b/test-vectors/presentation_exchange/README.md similarity index 100% rename from web5-test-vectors/presentation_exchange/README.md rename to test-vectors/presentation_exchange/README.md diff --git a/web5-test-vectors/presentation_exchange/create_presentation_from_credentials.json b/test-vectors/presentation_exchange/create_presentation_from_credentials.json similarity index 100% rename from web5-test-vectors/presentation_exchange/create_presentation_from_credentials.json rename to test-vectors/presentation_exchange/create_presentation_from_credentials.json diff --git a/web5-test-vectors/presentation_exchange/select_credentials.json b/test-vectors/presentation_exchange/select_credentials.json similarity index 100% rename from web5-test-vectors/presentation_exchange/select_credentials.json rename to test-vectors/presentation_exchange/select_credentials.json diff --git a/test-vectors/presentation_exchange/validate_definition.json b/test-vectors/presentation_exchange/validate_definition.json new file mode 100644 index 0000000..41eb61b --- /dev/null +++ b/test-vectors/presentation_exchange/validate_definition.json @@ -0,0 +1,434 @@ +{ + "description":"Validate definition", + "vectors":[ + { + "description":"valid presentation definition 1", + "input":{ + "presentationDefinition":{ + "id":"test-pd-id", + "name":"simple PD", + "purpose":"pd for testing", + "input_descriptors":[ + { + "id":"whatever", + "purpose":"id for testing", + "constraints":{ + "fields":[ + { + "path":[ + "$.vc.credentialSubject.btcAddress", + "$.credentialSubject.btcAddress", + "$.btcAddress" + ] + } + ] + } + }, + { + "id":"whatever2", + "purpose":"id for testing2", + "constraints":{ + "fields":[ + { + "path":[ + "$.vc.credentialSubject.dogeAddress", + "$.credentialSubject.dogeAddress", + "$.dogeAddress" + ] + } + ] + } + } + ] + } + }, + "errors":false + }, + { + "description":"valid presentation definition 2", + "input":{ + "presentationDefinition":{ + "id":"presDefIdloanAppVerification123", + "name":"Loan Application Employment Verification", + "purpose":"To verify applicant’s employment, date of birth, and name", + "input_descriptors":[ + { + "id":"employmentVerification", + "purpose":"Confirm current employment status", + "constraints":{ + "fields":[ + { + "path":[ + "$.credentialSubject.employmentStatus" + ], + "filter":{ + "type":"string", + "pattern":"employed" + } + } + ] + } + }, + { + "id":"dobVerification", + "purpose":"Confirm the applicant’s date of birth", + "constraints":{ + "fields":[ + { + "path":[ + "$.credentialSubject.dateOfBirth" + ], + "filter":{ + "type":"string", + "format":"date" + } + } + ] + } + }, + { + "id":"nameVerification", + "purpose":"Confirm the applicant’s legal name", + "constraints":{ + "fields":[ + { + "path":[ + "$.credentialSubject.name" + ], + "filter":{ + "type":"string" + } + } + ] + } + } + ] + } + }, + "errors":false + }, + { + "description":"presentation definition with no id value", + "input":{ + "presentationDefinition":{ + "id":"", + "name":"simple PD", + "purpose":"purpose", + "input_descriptors":[ + + ] + } + }, + "errors":true + }, + { + "description":"presentation definition with no name value", + "input":{ + "presentationDefinition":{ + "id":"test-pd-id", + "name":"", + "purpose":"purpose", + "input_descriptors":[ + + ] + } + }, + "errors":true + }, + { + "description":"input descriptor with empty id", + "input":{ + "presentationDefinition":{ + "id":"test-pd-id", + "name":"name", + "purpose":"purpose", + "input_descriptors":[ + { + "id":"", + "purpose":"Confirm current employment status", + "constraints":{ } + } + ] + } + }, + "errors":true + }, + { + "description":"input descriptor with empty name", + "input":{ + "presentationDefinition":{ + "id":"test-pd-id", + "name":"name", + "purpose":"purpose", + "input_descriptors":[ + { + "id":"id", + "name": "", + "purpose":"purpose", + "constraints":{ } + } + ] + } + }, + "errors":true + }, + { + "description":"input descriptor with empty purpose", + "input":{ + "presentationDefinition":{ + "id":"test-pd-id", + "name":"name", + "purpose":"purpose", + "input_descriptors":[ + { + "id":"id", + "name": "name", + "purpose":"", + "constraints":{ } + } + ] + } + }, + "errors":true + }, + { + "description":"presentation definition with no purpose value", + "input":{ + "presentationDefinition":{ + "id":"test-pd-id", + "name":"simple PD", + "purpose":"", + "input_descriptors":[ + + ] + } + }, + "errors":true + }, + { + "description":"duplicate input descriptor ids", + "input":{ + "presentationDefinition":{ + "id":"test-pd-id", + "name":"simple PD", + "purpose":"pd for testing", + "input_descriptors":[ + { + "id":"dupe", + "purpose":"id for testing", + "constraints":{ + "fields":[ + { + "path":[ + "$.vc.credentialSubject.btcAddress", + "$.credentialSubject.btcAddress", + "$.btcAddress" + ] + } + ] + } + }, + { + "id":"dupe", + "purpose":"id for testing2", + "constraints":{ + "fields":[ + { + "path":[ + "$.vc.credentialSubject.dogeAddress", + "$.credentialSubject.dogeAddress", + "$.dogeAddress" + ] + } + ] + } + } + ] + } + }, + "errors":true + }, + { + "description":"fields have duplicate ids", + "input":{ + "presentationDefinition":{ + "id":"test-pd-id", + "name":"simple PD", + "purpose":"pd for testing", + "input_descriptors":[ + { + "id":"whatever", + "purpose":"id for testing", + "constraints":{ + "fields":[ + { + "id":"dupe", + "path":[ + "$.vc.credentialSubject.btcAddress", + "$.credentialSubject.btcAddress", + "$.btcAddress" + ] + } + ] + } + }, + { + "id":"whatever2", + "purpose":"id for testing2", + "constraints":{ + "fields":[ + { + "id":"dupe", + "path":[ + "$.vc.credentialSubject.dogeAddress", + "$.credentialSubject.dogeAddress", + "$.dogeAddress" + ] + } + ] + } + } + ] + } + }, + "errors":true + }, + { + "description":"empty path in input descriptor", + "input":{ + "presentationDefinition":{ + "id":"test-pd-id", + "name":"simple PD", + "purpose":"pd for testing", + "input_descriptors":[ + { + "id":"whatever", + "purpose":"id for testing", + "constraints":{ + "fields":[ + { + "id":"id1", + "path":[ + + ] + } + ] + } + } + ] + } + }, + "errors":true + }, + { + "description":"invalid path in input descriptor", + "input":{ + "presentationDefinition":{ + "id":"test-pd-id", + "name":"simple PD", + "purpose":"pd for testing", + "input_descriptors":[ + { + "id":"whatever", + "purpose":"id for testing", + "constraints":{ + "fields":[ + { + "id":"id1", + "path":[ + "$.store.book[(@.price == 10]" + ] + } + ] + } + } + ] + } + }, + "errors":true + }, + { + "description":"field id is empty", + "input":{ + "presentationDefinition":{ + "id":"test-pd-id", + "name":"simple PD", + "purpose":"pd for testing", + "input_descriptors":[ + { + "id":"whatever", + "purpose":"id for testing", + "constraints":{ + "fields":[ + { + "id":"", + "path":[ + "$.vc.dob" + ] + } + ] + } + } + ] + } + }, + "errors":true + }, + { + "description":"field purpose is empty", + "input":{ + "presentationDefinition":{ + "id":"test-pd-id", + "name":"simple PD", + "purpose":"pd for testing", + "input_descriptors":[ + { + "id":"whatever", + "purpose":"id for testing", + "constraints":{ + "fields":[ + { + "id":"id", + "purpose": "", + "path":[ + "$.vc.dob" + ] + } + ] + } + } + ] + } + }, + "errors":true + }, + { + "description":"field name is empty", + "input":{ + "presentationDefinition":{ + "id":"test-pd-id", + "name":"simple PD", + "purpose":"pd for testing", + "input_descriptors":[ + { + "id":"whatever", + "purpose":"id for testing", + "constraints":{ + "fields":[ + { + "id":"id", + "name": "", + "path":[ + "$.vc.dob" + ] + } + ] + } + } + ] + } + }, + "errors":true + } + ] +} \ No newline at end of file diff --git a/test-vectors/presentation_exchange/validate_submission.json b/test-vectors/presentation_exchange/validate_submission.json new file mode 100644 index 0000000..f0be9d6 --- /dev/null +++ b/test-vectors/presentation_exchange/validate_submission.json @@ -0,0 +1,243 @@ +{ + "description":"Validate submission", + "vectors":[ + { + "description":"valid simple presentation submission", + "input":{ + "presentationSubmission":{ + "id":"test-submission-id", + "definition_id":"test-definition-id", + "descriptor_map":[ + { + "id":"descriptor-map-id", + "format":"jwt_vc", + "path": "$.verifiableCredential[0]" + } + ] + } + }, + "errors":false + }, + { + "description":"valid presentation submission with path nested", + "input":{ + "presentationSubmission":{ + "id":"test-submission-id", + "definition_id":"test-definition-id", + "descriptor_map":[ + { + "id":"descriptor-map-id", + "format":"jwt_vc", + "path": "$.verifiableCredential[0]", + "path_nested" : { + "id":"descriptor-map-id", + "format":"jwt_vc", + "path": "$.verifiableCredential[0]", + "path_nested" : { + "id":"descriptor-map-id", + "format":"jwt_vc", + "path": "$.verifiableCredential[0]" + } + } + } + ] + } + }, + "errors":false + }, + { + "description":"valid submission with multiple descriptor map objects", + "input":{ + "presentationSubmission":{ + "id":"test-submission-id", + "definition_id":"test-definition-id", + "descriptor_map":[ + { + "id":"descriptor-map-id", + "format":"jwt_vc", + "path": "$.verifiableCredential[0]" + }, + { + "id":"descriptor-map-id-2", + "format":"jwt_vc", + "path": "$.verifiableCredential[0]" + } + ] + } + }, + "errors":false + }, + { + "description":"empty pres submission id", + "input":{ + "presentationSubmission":{ + "id":"", + "definition_id":"test-definition-id", + "descriptor_map":[ + { + "id":"descriptor-map-id", + "format":"jwt_vc", + "path": "$.verifiableCredential[0]" + } + ] + } + }, + "errors":true + }, + { + "description":"definition id is empty", + "input":{ + "presentationSubmission":{ + "id":"test-submission-id", + "definition_id":"", + "descriptor_map":[ + { + "id":"descriptor-map-id", + "format":"jwt_vc", + "path": "$.verifiableCredential[0]" + } + ] + } + }, + "errors":true + }, + { + "description":"empty descriptor map", + "input":{ + "presentationSubmission":{ + "id":"test-submission-id", + "definition_id":"test-definition-id", + "descriptor_map":[] + } + }, + "errors":true + }, + { + "description":"descriptor map has empty id", + "input":{ + "presentationSubmission":{ + "id":"test-submission-id", + "definition_id":"test-definition-id", + "descriptor_map":[ + { + "id":"", + "format":"jwt_vc", + "path": "$.verifiableCredential[0]" + } + ] + } + }, + "errors":true + }, + { + "description":"descriptor map has empty format", + "input":{ + "presentationSubmission":{ + "id":"test-submission-id", + "definition_id":"test-definition-id", + "descriptor_map":[ + { + "id":"descriptor-map-id", + "format":"", + "path": "$.verifiableCredential[0]" + } + ] + } + }, + "errors":true + }, + { + "description":"descriptor map has empty path", + "input":{ + "presentationSubmission":{ + "id":"test-submission-id", + "definition_id":"test-definition-id", + "descriptor_map":[ + { + "id":"descriptor-map-id", + "format":"jwt_vc", + "path": "" + } + ] + } + }, + "errors":true + }, + { + "description":"path nested has different id", + "input":{ + "presentationSubmission":{ + "id":"test-submission-id", + "definition_id":"test-definition-id", + "descriptor_map":[ + { + "id":"descriptor-map-id", + "format":"jwt_vc", + "path": "$.verifiableCredential[0]", + "path_nested" : { + "id":"descriptor-map-id", + "format":"jwt_vc", + "path": "$.verifiableCredential[0]", + "path_nested" : { + "id":"different-id", + "format":"jwt_vc", + "path": "$.verifiableCredential[0]" + } + } + } + ] + } + }, + "errors":true + }, + { + "description":"path nested has invliad path", + "input":{ + "presentationSubmission":{ + "id":"test-submission-id", + "definition_id":"test-definition-id", + "descriptor_map":[ + { + "id":"descriptor-map-id", + "format":"jwt_vc", + "path": "$.verifiableCredential[0]", + "path_nested" : { + "id":"descriptor-map-id", + "format":"jwt_vc", + "path": "$.verifiableCredential[0]", + "path_nested" : { + "id":"descriptor-map-id", + "format":"jwt_vc", + "path": "$.store.book[(@.price == 10]" + } + } + } + ] + } + }, + "errors":true + }, + { + "description":"multiple descriptor map objects have same duplicate id", + "input":{ + "presentationSubmission":{ + "id":"test-submission-id", + "definition_id":"test-definition-id", + "descriptor_map":[ + { + "id":"descriptor-map-id", + "format":"jwt_vc", + "path": "$.verifiableCredential[0]" + }, + { + "id":"descriptor-map-id", + "format":"jwt_vc", + "path": "$.verifiableCredential[0]" + } + ] + } + }, + "errors":true + } + ] +} \ No newline at end of file diff --git a/web5-test-vectors/vectors.schema.json b/test-vectors/vectors.schema.json similarity index 100% rename from web5-test-vectors/vectors.schema.json rename to test-vectors/vectors.schema.json