diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0599c8dcfa7fd05e8db46ae810af8475b19012e3..643379e7e429dcdac53ae38592eba953013b9b8b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -14,7 +14,7 @@ linters: - golangci-lint run unit tests: - image: golang:1.21.3 + image: golang:1.21.4 stage: test script: - go version @@ -23,7 +23,7 @@ unit tests: coverage: '/total:\s+\(statements\)\s+(\d+.\d+\%)/' govulncheck: - image: golang:1.21.3 + image: golang:1.21.4 stage: test script: - go version diff --git a/.gitlab-ci.yml.old b/.gitlab-ci.yml.old deleted file mode 100644 index 9a68bdb7477ab7da0394827ca3b1ec64e5190b49..0000000000000000000000000000000000000000 --- a/.gitlab-ci.yml.old +++ /dev/null @@ -1,25 +0,0 @@ -stages: - - test - -before_script: - - ln -s /builds /go/src/code.vereign.com - - cd /go/src/code.vereign.com/${CI_PROJECT_PATH} - -lint: - image: golangci/golangci-lint:v1.46.2 - stage: test - tags: - - amd64-docker - script: - - golangci-lint --version - - golangci-lint run - -unit tests: - image: golang:1.17.10 - stage: test - tags: - - amd64-docker - script: - - go version - - go test -race ./... -coverprofile=coverage.out - - go tool cover -func=coverage.out diff --git a/deployment/ci/Dockerfile b/deployment/ci/Dockerfile index 45e75169d87f33dc61e2c7ad0f69de4f633a3eb2..6e562cf2eb25ed1ffc3066b03b2be6f9bc357ac8 100644 --- a/deployment/ci/Dockerfile +++ b/deployment/ci/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.21.3-alpine3.17 as builder +FROM golang:1.21.4-alpine3.17 as builder RUN apk add git diff --git a/deployment/compose/Dockerfile b/deployment/compose/Dockerfile index ff9ca4c9df44bb8233f02846e58990a2b0c4a16d..751616b3003b12835a0e05b4575ac8ddcd8de314 100644 --- a/deployment/compose/Dockerfile +++ b/deployment/compose/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.21.3 +FROM golang:1.21.4 RUN go install github.com/ysmood/kit/cmd/guard@v0.25.11 diff --git a/design/design.go b/design/design.go index 0831958978e6f3a725018381e84dae215a40852f..eafcfefa6ba78fd0b8be5cf2a3583c822ae377bf 100644 --- a/design/design.go +++ b/design/design.go @@ -119,6 +119,18 @@ var _ = Service("signer", func() { Response(StatusOK) }) }) + + Method("Sign", func() { + Description("Sign creates digital signature on base64 encoded binary data.") + Payload(SignRequest) + Result(SignResult) + HTTP(func() { + POST("/v1/sign") + Response(StatusOK) + Response(StatusNotFound) + Response(StatusInternalServerError) + }) + }) }) var _ = Service("health", func() { diff --git a/design/types.go b/design/types.go index 7d1debcd138bb0c0b8c872419d684a38aa9183cc..bbcc86a7dbe8c4d04e1462577c1191d6fe1e8c4a 100644 --- a/design/types.go +++ b/design/types.go @@ -159,6 +159,18 @@ var DIDVerificationMethod = Type("DIDVerificationMethod", func() { Required("id", "type", "controller", "publicKeyJwk") }) +var SignRequest = Type("SignRequest", func() { + Field(1, "namespace", String, "Key namespace to be used for signing.") + Field(2, "key", String, "Key to be used for signing.") + Field(3, "data", String, "Data that must be signed, encoded as base64 string.") + Required("namespace", "key", "data") +}) + +var SignResult = Type("SignResult", func() { + Field(1, "signature", String, "Signature encoded as base64 string.") + Required("signature") +}) + var HealthResponse = Type("HealthResponse", func() { Field(1, "service", String, "Service name.") Field(2, "status", String, "Status message.") diff --git a/gen/http/cli/signer/cli.go b/gen/http/cli/signer/cli.go index 7f2bfb0ab58414963f84c22913db3143ed6b2366..36aa7673c2d916b30bf4adcc1b57d715bec74d0b 100644 --- a/gen/http/cli/signer/cli.go +++ b/gen/http/cli/signer/cli.go @@ -23,7 +23,7 @@ import ( // // command (subcommand1|subcommand2|...) func UsageCommands() string { - return `signer (namespaces|namespace-keys|verification-method|verification-methods|credential-proof|presentation-proof|create-credential|create-presentation|verify-credential|verify-presentation) + return `signer (namespaces|namespace-keys|verification-method|verification-methods|credential-proof|presentation-proof|create-credential|create-presentation|verify-credential|verify-presentation|sign) health (liveness|readiness) ` } @@ -79,6 +79,9 @@ func ParseEndpoint( signerVerifyPresentationFlags = flag.NewFlagSet("verify-presentation", flag.ExitOnError) signerVerifyPresentationBodyFlag = signerVerifyPresentationFlags.String("body", "REQUIRED", "") + signerSignFlags = flag.NewFlagSet("sign", flag.ExitOnError) + signerSignBodyFlag = signerSignFlags.String("body", "REQUIRED", "") + healthFlags = flag.NewFlagSet("health", flag.ContinueOnError) healthLivenessFlags = flag.NewFlagSet("liveness", flag.ExitOnError) @@ -96,6 +99,7 @@ func ParseEndpoint( signerCreatePresentationFlags.Usage = signerCreatePresentationUsage signerVerifyCredentialFlags.Usage = signerVerifyCredentialUsage signerVerifyPresentationFlags.Usage = signerVerifyPresentationUsage + signerSignFlags.Usage = signerSignUsage healthFlags.Usage = healthUsage healthLivenessFlags.Usage = healthLivenessUsage @@ -167,6 +171,9 @@ func ParseEndpoint( case "verify-presentation": epf = signerVerifyPresentationFlags + case "sign": + epf = signerSignFlags + } case "health": @@ -232,6 +239,9 @@ func ParseEndpoint( case "verify-presentation": endpoint = c.VerifyPresentation() data, err = signerc.BuildVerifyPresentationPayload(*signerVerifyPresentationBodyFlag) + case "sign": + endpoint = c.Sign() + data, err = signerc.BuildSignPayload(*signerSignBodyFlag) } case "health": c := healthc.NewClient(scheme, host, doer, enc, dec, restore) @@ -269,6 +279,7 @@ COMMAND: create-presentation: CreatePresentation creates VP with proof from raw JSON data. verify-credential: VerifyCredential verifies the proof of a Verifiable Credential. verify-presentation: VerifyPresentation verifies the proof of a Verifiable Presentation. + sign: Sign creates digital signature on base64 encoded binary data. Additional help: %[1]s signer COMMAND --help @@ -356,10 +367,10 @@ PresentationProof adds a proof to a given Verifiable Presentation. Example: %[1]s signer presentation-proof --body '{ - "issuer": "Consequatur facilis eius.", + "issuer": "Neque impedit.", "key": "key1", "namespace": "transit", - "presentation": "Dicta commodi possimus recusandae et." + "presentation": "Sunt vitae." }' `, os.Args[0]) } @@ -420,7 +431,7 @@ VerifyCredential verifies the proof of a Verifiable Credential. -body STRING: Example: - %[1]s signer verify-credential --body "Q29ycnVwdGkgcHJhZXNlbnRpdW0gaW52ZW50b3JlLg==" + %[1]s signer verify-credential --body "RGVzZXJ1bnQgYSBuaWhpbC4=" `, os.Args[0]) } @@ -431,7 +442,22 @@ VerifyPresentation verifies the proof of a Verifiable Presentation. -body STRING: Example: - %[1]s signer verify-presentation --body "U2VkIHF1b3MgcmVydW0gZGVzZXJ1bnQgYSBuaWhpbCBhdXQu" + %[1]s signer verify-presentation --body "SWxsdW0gcXVpIG5paGlsLg==" +`, os.Args[0]) +} + +func signerSignUsage() { + fmt.Fprintf(os.Stderr, `%[1]s [flags] signer sign -body JSON + +Sign creates digital signature on base64 encoded binary data. + -body JSON: + +Example: + %[1]s signer sign --body '{ + "data": "Sapiente dolorem qui possimus qui labore veritatis.", + "key": "Nihil iste debitis.", + "namespace": "Occaecati repellat est non amet." + }' `, os.Args[0]) } diff --git a/gen/http/openapi.json b/gen/http/openapi.json index 74ef1e4b96234ca9fba61a01c0020da116df1d54..ec41590df013ad6657bfafa0b7da4e8787f33eda 100644 --- a/gen/http/openapi.json +++ b/gen/http/openapi.json @@ -1 +1 @@ -{"swagger":"2.0","info":{"title":"Signer Service","description":"Signer service exposes HTTP API for making and verifying digital signatures and proofs for Verifiable Credentials.","version":""},"host":"localhost:8085","consumes":["application/json","application/xml","application/gob"],"produces":["application/json","application/xml","application/gob"],"paths":{"/liveness":{"get":{"tags":["health"],"summary":"Liveness health","operationId":"health#Liveness","responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/HealthLivenessResponseBody","required":["service","status","version"]}}},"schemes":["http"]}},"/readiness":{"get":{"tags":["health"],"summary":"Readiness health","operationId":"health#Readiness","responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/HealthReadinessResponseBody","required":["service","status","version"]}}},"schemes":["http"]}},"/v1/credential":{"post":{"tags":["signer"],"summary":"CreateCredential signer","description":"CreateCredential creates VC with proof from raw JSON data.","operationId":"signer#CreateCredential","parameters":[{"name":"CreateCredentialRequestBody","in":"body","required":true,"schema":{"$ref":"#/definitions/SignerCreateCredentialRequestBody","required":["issuer","namespace","key","credentialSubject"]}}],"responses":{"200":{"description":"OK response.","schema":{"type":"string","format":"binary"}}},"schemes":["http"]}},"/v1/credential/proof":{"post":{"tags":["signer"],"summary":"CredentialProof signer","description":"CredentialProof adds a proof to a given Verifiable Credential.","operationId":"signer#CredentialProof","parameters":[{"name":"CredentialProofRequestBody","in":"body","required":true,"schema":{"$ref":"#/definitions/SignerCredentialProofRequestBody","required":["namespace","key","credential"]}}],"responses":{"200":{"description":"OK response.","schema":{"type":"string","format":"binary"}}},"schemes":["http"]}},"/v1/credential/verify":{"post":{"tags":["signer"],"summary":"VerifyCredential signer","description":"VerifyCredential verifies the proof of a Verifiable Credential.","operationId":"signer#VerifyCredential","parameters":[{"name":"bytes","in":"body","description":"Verifiable Credential in JSON format.","required":true,"schema":{"type":"string","format":"byte"}}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/SignerVerifyCredentialResponseBody","required":["valid"]}}},"schemes":["http"]}},"/v1/namespaces":{"get":{"tags":["signer"],"summary":"Namespaces signer","description":"Namespaces returns all keys namespaces, which corresponds to enabled Vault transit engines.","operationId":"signer#Namespaces","responses":{"200":{"description":"OK response.","schema":{"type":"array","items":{"type":"string","example":"Nihil iste debitis."}}}},"schemes":["http"]}},"/v1/namespaces/{namespace}/keys":{"get":{"tags":["signer"],"summary":"NamespaceKeys signer","description":"NamespaceKeys returns all keys in a given namespace.","operationId":"signer#NamespaceKeys","parameters":[{"name":"namespace","in":"path","description":"Namespace for signing keys.","required":true,"type":"string"}],"responses":{"200":{"description":"OK response.","schema":{"type":"array","items":{"type":"string","example":"Sapiente dolorem qui possimus qui labore veritatis."}}}},"schemes":["http"]}},"/v1/presentation":{"post":{"tags":["signer"],"summary":"CreatePresentation signer","description":"CreatePresentation creates VP with proof from raw JSON data.","operationId":"signer#CreatePresentation","parameters":[{"name":"CreatePresentationRequestBody","in":"body","required":true,"schema":{"$ref":"#/definitions/SignerCreatePresentationRequestBody","required":["issuer","namespace","key","data"]}}],"responses":{"200":{"description":"OK response.","schema":{"type":"string","format":"binary"}}},"schemes":["http"]}},"/v1/presentation/proof":{"post":{"tags":["signer"],"summary":"PresentationProof signer","description":"PresentationProof adds a proof to a given Verifiable Presentation.","operationId":"signer#PresentationProof","parameters":[{"name":"PresentationProofRequestBody","in":"body","required":true,"schema":{"$ref":"#/definitions/SignerPresentationProofRequestBody","required":["issuer","namespace","key","presentation"]}}],"responses":{"200":{"description":"OK response.","schema":{"type":"string","format":"binary"}}},"schemes":["http"]}},"/v1/presentation/verify":{"post":{"tags":["signer"],"summary":"VerifyPresentation signer","description":"VerifyPresentation verifies the proof of a Verifiable Presentation.","operationId":"signer#VerifyPresentation","parameters":[{"name":"bytes","in":"body","description":"Verifiable Presentation in JSON format.","required":true,"schema":{"type":"string","format":"byte"}}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/SignerVerifyPresentationResponseBody","required":["valid"]}}},"schemes":["http"]}},"/v1/verification-methods/{namespace}/{did}":{"get":{"tags":["signer"],"summary":"VerificationMethods signer","description":"VerificationMethods returns all public keys in a given namespace. The result is formatted as array of DID verification methods with their controller attribute being the given DID in the request.","operationId":"signer#VerificationMethods","parameters":[{"name":"namespace","in":"path","description":"Keys namespace.","required":true,"type":"string"},{"name":"did","in":"path","description":"DID controller of the keys.","required":true,"type":"string"}],"responses":{"200":{"description":"OK response.","schema":{"type":"array","items":{"$ref":"#/definitions/DIDVerificationMethodResponse"}}}},"schemes":["http"]}},"/v1/verification-methods/{namespace}/{key}/{did}":{"get":{"tags":["signer"],"summary":"VerificationMethod signer","description":"VerificationMethod returns a single public key formatted as DID verification method for a given namespace, key and did.","operationId":"signer#VerificationMethod","parameters":[{"name":"namespace","in":"path","description":"Key namespace.","required":true,"type":"string"},{"name":"key","in":"path","description":"Name of requested key.","required":true,"type":"string"},{"name":"did","in":"path","description":"DID controller of the key.","required":true,"type":"string"}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/SignerVerificationMethodResponseBody","required":["id","type","controller","publicKeyJwk"]}}},"schemes":["http"]}}},"definitions":{"DIDVerificationMethodResponse":{"title":"DIDVerificationMethodResponse","type":"object","properties":{"controller":{"type":"string","description":"Controller of verification method specified as DID.","example":"did:web:example.com"},"id":{"type":"string","description":"ID of verification method.","example":"key1"},"publicKeyJwk":{"type":"string","description":"Public Key encoded in JWK format.","example":"Et nulla illo totam optio quia ab.","format":"binary"},"type":{"type":"string","description":"Type of verification method key.","example":"JsonWebKey2020"}},"example":{"controller":"did:web:example.com","id":"key1","publicKeyJwk":"Quibusdam nemo ut iusto ut fugit.","type":"JsonWebKey2020"},"required":["id","type","controller","publicKeyJwk"]},"HealthLivenessResponseBody":{"title":"HealthLivenessResponseBody","type":"object","properties":{"service":{"type":"string","description":"Service name.","example":"Repudiandae quam reprehenderit sed molestias eaque."},"status":{"type":"string","description":"Status message.","example":"Rerum dolores ipsa."},"version":{"type":"string","description":"Service runtime version.","example":"Praesentium nesciunt."}},"example":{"service":"Laboriosam qui.","status":"Consequatur omnis architecto nobis vel id.","version":"Nam ea ducimus."},"required":["service","status","version"]},"HealthReadinessResponseBody":{"title":"HealthReadinessResponseBody","type":"object","properties":{"service":{"type":"string","description":"Service name.","example":"Ea quas praesentium voluptas occaecati est facere."},"status":{"type":"string","description":"Status message.","example":"Dolores velit."},"version":{"type":"string","description":"Service runtime version.","example":"Tempore suscipit ut occaecati."}},"example":{"service":"Ut dolor numquam et dolores.","status":"Neque blanditiis nostrum nihil consequuntur est.","version":"Explicabo possimus ea."},"required":["service","status","version"]},"SignerCreateCredentialRequestBody":{"title":"SignerCreateCredentialRequestBody","type":"object","properties":{"context":{"type":"array","items":{"type":"string","example":"Sed aut."},"description":"Additional JSONLD contexts to be specified in the VC.","example":["https://w3id.org/security/suites/jws-2020/v1","https://schema.org"]},"credentialSubject":{"type":"string","description":"Raw JSON that will be the VC subject.","example":{"hello":"world"},"format":"binary"},"issuer":{"type":"string","description":"Issuer DID of the Verifiable Credential.","example":"did:web:example.com"},"key":{"type":"string","description":"Key to use for the proof signature.","example":"key1"},"namespace":{"type":"string","description":"Key namespace.","example":"transit"}},"example":{"context":["https://w3id.org/security/suites/jws-2020/v1","https://schema.org"],"credentialSubject":{"hello":"world"},"issuer":"did:web:example.com","key":"key1","namespace":"transit"},"required":["issuer","namespace","key","credentialSubject"]},"SignerCreatePresentationRequestBody":{"title":"SignerCreatePresentationRequestBody","type":"object","properties":{"context":{"type":"array","items":{"type":"string","example":"Aut et aut adipisci voluptatem consectetur quidem."},"description":"Additional JSONLD contexts to be specified in the VP.","example":["https://w3id.org/security/suites/jws-2020/v1","https://schema.org"]},"data":{"type":"array","items":{"type":"string","example":"Facere quos corporis.","format":"binary"},"description":"Raw JSON to be included inside the VP as Verifiable Credential.","example":[{"hello":"world"},{"hola":"mundo"}]},"issuer":{"type":"string","description":"Issuer DID of the Verifiable Presentation.","example":"did:web:example.com"},"key":{"type":"string","description":"Key to use for the proof signature.","example":"key1"},"namespace":{"type":"string","description":"Key namespace.","example":"transit"}},"example":{"context":["https://w3id.org/security/suites/jws-2020/v1","https://schema.org"],"data":[{"hello":"world"},{"hola":"mundo"}],"issuer":"did:web:example.com","key":"key1","namespace":"transit"},"required":["issuer","namespace","key","data"]},"SignerCredentialProofRequestBody":{"title":"SignerCredentialProofRequestBody","type":"object","properties":{"credential":{"type":"string","description":"Verifiable Credential in JSON format.","example":{"@context":["https://www.w3.org/2018/credentials/v1","https://w3id.org/security/suites/jws-2020/v1","https://schema.org"],"type":"VerifiableCredential","issuer":"did:web:nginx:policy:policy:example:example:1.0:evaluation","issuanceDate":"2010-01-01T19:23:24.651387237Z","credentialSubject":{"name":"Alice","allow":true}},"format":"binary"},"key":{"type":"string","description":"Key to use for the proof signature (optional).","example":"key1"},"namespace":{"type":"string","description":"Key namespace.","example":"transit"}},"example":{"credential":{"@context":["https://www.w3.org/2018/credentials/v1","https://w3id.org/security/suites/jws-2020/v1","https://schema.org"],"type":"VerifiableCredential","issuer":"did:web:nginx:policy:policy:example:example:1.0:evaluation","issuanceDate":"2010-01-01T19:23:24.651387237Z","credentialSubject":{"name":"Alice","allow":true}},"key":"key1","namespace":"transit"},"required":["namespace","key","credential"]},"SignerPresentationProofRequestBody":{"title":"SignerPresentationProofRequestBody","type":"object","properties":{"issuer":{"type":"string","description":"Issuer DID used to specify proof verification info.","example":"Asperiores vitae rem."},"key":{"type":"string","description":"Key to use for the proof signature.","example":"key1"},"namespace":{"type":"string","description":"Key namespace.","example":"transit"},"presentation":{"type":"string","description":"Verifiable Presentation in JSON format.","example":"Quaerat odit optio.","format":"binary"}},"example":{"issuer":"Mollitia architecto rem beatae mollitia.","key":"key1","namespace":"transit","presentation":"Id tempora aut."},"required":["issuer","namespace","key","presentation"]},"SignerVerificationMethodResponseBody":{"title":"SignerVerificationMethodResponseBody","type":"object","properties":{"controller":{"type":"string","description":"Controller of verification method specified as DID.","example":"did:web:example.com"},"id":{"type":"string","description":"ID of verification method.","example":"key1"},"publicKeyJwk":{"type":"string","description":"Public Key encoded in JWK format.","example":"Fuga officia excepturi velit aut.","format":"binary"},"type":{"type":"string","description":"Type of verification method key.","example":"JsonWebKey2020"}},"description":"Public Key represented as DID Verification Method.","example":{"controller":"did:web:example.com","id":"key1","publicKeyJwk":"Natus quos ut corrupti.","type":"JsonWebKey2020"},"required":["id","type","controller","publicKeyJwk"]},"SignerVerifyCredentialResponseBody":{"title":"SignerVerifyCredentialResponseBody","type":"object","properties":{"valid":{"type":"boolean","description":"Valid specifies if the proof is successfully verified.","example":false}},"example":{"valid":false},"required":["valid"]},"SignerVerifyPresentationResponseBody":{"title":"SignerVerifyPresentationResponseBody","type":"object","properties":{"valid":{"type":"boolean","description":"Valid specifies if the proof is successfully verified.","example":true}},"example":{"valid":true},"required":["valid"]}}} \ No newline at end of file +{"swagger":"2.0","info":{"title":"Signer Service","description":"Signer service exposes HTTP API for making and verifying digital signatures and proofs for Verifiable Credentials.","version":""},"host":"localhost:8085","consumes":["application/json","application/xml","application/gob"],"produces":["application/json","application/xml","application/gob"],"paths":{"/liveness":{"get":{"tags":["health"],"summary":"Liveness health","operationId":"health#Liveness","responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/HealthLivenessResponseBody","required":["service","status","version"]}}},"schemes":["http"]}},"/readiness":{"get":{"tags":["health"],"summary":"Readiness health","operationId":"health#Readiness","responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/HealthReadinessResponseBody","required":["service","status","version"]}}},"schemes":["http"]}},"/v1/credential":{"post":{"tags":["signer"],"summary":"CreateCredential signer","description":"CreateCredential creates VC with proof from raw JSON data.","operationId":"signer#CreateCredential","parameters":[{"name":"CreateCredentialRequestBody","in":"body","required":true,"schema":{"$ref":"#/definitions/SignerCreateCredentialRequestBody","required":["issuer","namespace","key","credentialSubject"]}}],"responses":{"200":{"description":"OK response.","schema":{"type":"string","format":"binary"}}},"schemes":["http"]}},"/v1/credential/proof":{"post":{"tags":["signer"],"summary":"CredentialProof signer","description":"CredentialProof adds a proof to a given Verifiable Credential.","operationId":"signer#CredentialProof","parameters":[{"name":"CredentialProofRequestBody","in":"body","required":true,"schema":{"$ref":"#/definitions/SignerCredentialProofRequestBody","required":["namespace","key","credential"]}}],"responses":{"200":{"description":"OK response.","schema":{"type":"string","format":"binary"}}},"schemes":["http"]}},"/v1/credential/verify":{"post":{"tags":["signer"],"summary":"VerifyCredential signer","description":"VerifyCredential verifies the proof of a Verifiable Credential.","operationId":"signer#VerifyCredential","parameters":[{"name":"bytes","in":"body","description":"Verifiable Credential in JSON format.","required":true,"schema":{"type":"string","format":"byte"}}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/SignerVerifyCredentialResponseBody","required":["valid"]}}},"schemes":["http"]}},"/v1/namespaces":{"get":{"tags":["signer"],"summary":"Namespaces signer","description":"Namespaces returns all keys namespaces, which corresponds to enabled Vault transit engines.","operationId":"signer#Namespaces","responses":{"200":{"description":"OK response.","schema":{"type":"array","items":{"type":"string","example":"Facere quos corporis."}}}},"schemes":["http"]}},"/v1/namespaces/{namespace}/keys":{"get":{"tags":["signer"],"summary":"NamespaceKeys signer","description":"NamespaceKeys returns all keys in a given namespace.","operationId":"signer#NamespaceKeys","parameters":[{"name":"namespace","in":"path","description":"Namespace for signing keys.","required":true,"type":"string"}],"responses":{"200":{"description":"OK response.","schema":{"type":"array","items":{"type":"string","example":"Aut et aut adipisci voluptatem consectetur quidem."}}}},"schemes":["http"]}},"/v1/presentation":{"post":{"tags":["signer"],"summary":"CreatePresentation signer","description":"CreatePresentation creates VP with proof from raw JSON data.","operationId":"signer#CreatePresentation","parameters":[{"name":"CreatePresentationRequestBody","in":"body","required":true,"schema":{"$ref":"#/definitions/SignerCreatePresentationRequestBody","required":["issuer","namespace","key","data"]}}],"responses":{"200":{"description":"OK response.","schema":{"type":"string","format":"binary"}}},"schemes":["http"]}},"/v1/presentation/proof":{"post":{"tags":["signer"],"summary":"PresentationProof signer","description":"PresentationProof adds a proof to a given Verifiable Presentation.","operationId":"signer#PresentationProof","parameters":[{"name":"PresentationProofRequestBody","in":"body","required":true,"schema":{"$ref":"#/definitions/SignerPresentationProofRequestBody","required":["issuer","namespace","key","presentation"]}}],"responses":{"200":{"description":"OK response.","schema":{"type":"string","format":"binary"}}},"schemes":["http"]}},"/v1/presentation/verify":{"post":{"tags":["signer"],"summary":"VerifyPresentation signer","description":"VerifyPresentation verifies the proof of a Verifiable Presentation.","operationId":"signer#VerifyPresentation","parameters":[{"name":"bytes","in":"body","description":"Verifiable Presentation in JSON format.","required":true,"schema":{"type":"string","format":"byte"}}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/SignerVerifyPresentationResponseBody","required":["valid"]}}},"schemes":["http"]}},"/v1/sign":{"post":{"tags":["signer"],"summary":"Sign signer","description":"Sign creates digital signature on base64 encoded binary data.","operationId":"signer#Sign","parameters":[{"name":"SignRequestBody","in":"body","required":true,"schema":{"$ref":"#/definitions/SignerSignRequestBody","required":["namespace","key","data"]}}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/SignerSignOKResponseBody","required":["signature"]}},"404":{"description":"Not Found response.","schema":{"$ref":"#/definitions/SignerSignNotFoundResponseBody","required":["signature"]}},"500":{"description":"Internal Server Error response.","schema":{"$ref":"#/definitions/SignerSignInternalServerErrorResponseBody","required":["signature"]}}},"schemes":["http"]}},"/v1/verification-methods/{namespace}/{did}":{"get":{"tags":["signer"],"summary":"VerificationMethods signer","description":"VerificationMethods returns all public keys in a given namespace. The result is formatted as array of DID verification methods with their controller attribute being the given DID in the request.","operationId":"signer#VerificationMethods","parameters":[{"name":"namespace","in":"path","description":"Keys namespace.","required":true,"type":"string"},{"name":"did","in":"path","description":"DID controller of the keys.","required":true,"type":"string"}],"responses":{"200":{"description":"OK response.","schema":{"type":"array","items":{"$ref":"#/definitions/DIDVerificationMethodResponse"}}}},"schemes":["http"]}},"/v1/verification-methods/{namespace}/{key}/{did}":{"get":{"tags":["signer"],"summary":"VerificationMethod signer","description":"VerificationMethod returns a single public key formatted as DID verification method for a given namespace, key and did.","operationId":"signer#VerificationMethod","parameters":[{"name":"namespace","in":"path","description":"Key namespace.","required":true,"type":"string"},{"name":"key","in":"path","description":"Name of requested key.","required":true,"type":"string"},{"name":"did","in":"path","description":"DID controller of the key.","required":true,"type":"string"}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/SignerVerificationMethodResponseBody","required":["id","type","controller","publicKeyJwk"]}}},"schemes":["http"]}}},"definitions":{"DIDVerificationMethodResponse":{"title":"DIDVerificationMethodResponse","type":"object","properties":{"controller":{"type":"string","description":"Controller of verification method specified as DID.","example":"did:web:example.com"},"id":{"type":"string","description":"ID of verification method.","example":"key1"},"publicKeyJwk":{"type":"string","description":"Public Key encoded in JWK format.","example":"Molestias eaque eos rerum dolores ipsa dolores.","format":"binary"},"type":{"type":"string","description":"Type of verification method key.","example":"JsonWebKey2020"}},"example":{"controller":"did:web:example.com","id":"key1","publicKeyJwk":"Nesciunt eaque.","type":"JsonWebKey2020"},"required":["id","type","controller","publicKeyJwk"]},"HealthLivenessResponseBody":{"title":"HealthLivenessResponseBody","type":"object","properties":{"service":{"type":"string","description":"Service name.","example":"Velit sit exercitationem et eligendi incidunt."},"status":{"type":"string","description":"Status message.","example":"Molestiae eveniet vero est aliquam."},"version":{"type":"string","description":"Service runtime version.","example":"Totam quam."}},"example":{"service":"Voluptates consectetur et repellat.","status":"Repudiandae aut dolorum hic aut voluptatem soluta.","version":"Earum debitis."},"required":["service","status","version"]},"HealthReadinessResponseBody":{"title":"HealthReadinessResponseBody","type":"object","properties":{"service":{"type":"string","description":"Service name.","example":"Rerum veritatis delectus quis recusandae."},"status":{"type":"string","description":"Status message.","example":"Est quos possimus sed sit voluptates nihil."},"version":{"type":"string","description":"Service runtime version.","example":"Ducimus eum facere enim accusantium."}},"example":{"service":"Sint laudantium rerum neque.","status":"Suscipit expedita quos eligendi.","version":"Qui rerum."},"required":["service","status","version"]},"SignerCreateCredentialRequestBody":{"title":"SignerCreateCredentialRequestBody","type":"object","properties":{"context":{"type":"array","items":{"type":"string","example":"Dolores velit."},"description":"Additional JSONLD contexts to be specified in the VC.","example":["https://w3id.org/security/suites/jws-2020/v1","https://schema.org"]},"credentialSubject":{"type":"string","description":"Raw JSON that will be the VC subject.","example":{"hello":"world"},"format":"binary"},"issuer":{"type":"string","description":"Issuer DID of the Verifiable Credential.","example":"did:web:example.com"},"key":{"type":"string","description":"Key to use for the proof signature.","example":"key1"},"namespace":{"type":"string","description":"Key namespace.","example":"transit"}},"example":{"context":["https://w3id.org/security/suites/jws-2020/v1","https://schema.org"],"credentialSubject":{"hello":"world"},"issuer":"did:web:example.com","key":"key1","namespace":"transit"},"required":["issuer","namespace","key","credentialSubject"]},"SignerCreatePresentationRequestBody":{"title":"SignerCreatePresentationRequestBody","type":"object","properties":{"context":{"type":"array","items":{"type":"string","example":"Ut dolor numquam et dolores."},"description":"Additional JSONLD contexts to be specified in the VP.","example":["https://w3id.org/security/suites/jws-2020/v1","https://schema.org"]},"data":{"type":"array","items":{"type":"string","example":"Tempore suscipit ut occaecati.","format":"binary"},"description":"Raw JSON to be included inside the VP as Verifiable Credential.","example":[{"hello":"world"},{"hola":"mundo"}]},"issuer":{"type":"string","description":"Issuer DID of the Verifiable Presentation.","example":"did:web:example.com"},"key":{"type":"string","description":"Key to use for the proof signature.","example":"key1"},"namespace":{"type":"string","description":"Key namespace.","example":"transit"}},"example":{"context":["https://w3id.org/security/suites/jws-2020/v1","https://schema.org"],"data":[{"hello":"world"},{"hola":"mundo"}],"issuer":"did:web:example.com","key":"key1","namespace":"transit"},"required":["issuer","namespace","key","data"]},"SignerCredentialProofRequestBody":{"title":"SignerCredentialProofRequestBody","type":"object","properties":{"credential":{"type":"string","description":"Verifiable Credential in JSON format.","example":{"@context":["https://www.w3.org/2018/credentials/v1","https://w3id.org/security/suites/jws-2020/v1","https://schema.org"],"type":"VerifiableCredential","issuer":"did:web:nginx:policy:policy:example:example:1.0:evaluation","issuanceDate":"2010-01-01T19:23:24.651387237Z","credentialSubject":{"name":"Alice","allow":true}},"format":"binary"},"key":{"type":"string","description":"Key to use for the proof signature (optional).","example":"key1"},"namespace":{"type":"string","description":"Key namespace.","example":"transit"}},"example":{"credential":{"@context":["https://www.w3.org/2018/credentials/v1","https://w3id.org/security/suites/jws-2020/v1","https://schema.org"],"type":"VerifiableCredential","issuer":"did:web:nginx:policy:policy:example:example:1.0:evaluation","issuanceDate":"2010-01-01T19:23:24.651387237Z","credentialSubject":{"name":"Alice","allow":true}},"key":"key1","namespace":"transit"},"required":["namespace","key","credential"]},"SignerPresentationProofRequestBody":{"title":"SignerPresentationProofRequestBody","type":"object","properties":{"issuer":{"type":"string","description":"Issuer DID used to specify proof verification info.","example":"Qui et."},"key":{"type":"string","description":"Key to use for the proof signature.","example":"key1"},"namespace":{"type":"string","description":"Key namespace.","example":"transit"},"presentation":{"type":"string","description":"Verifiable Presentation in JSON format.","example":"Omnis architecto nobis vel id.","format":"binary"}},"example":{"issuer":"Nam ea ducimus.","key":"key1","namespace":"transit","presentation":"Ea quas praesentium voluptas occaecati est facere."},"required":["issuer","namespace","key","presentation"]},"SignerSignInternalServerErrorResponseBody":{"title":"SignerSignInternalServerErrorResponseBody","type":"object","properties":{"signature":{"type":"string","description":"Signature encoded as base64 string.","example":"Vel porro qui quidem unde."}},"example":{"signature":"Quis voluptas."},"required":["signature"]},"SignerSignNotFoundResponseBody":{"title":"SignerSignNotFoundResponseBody","type":"object","properties":{"signature":{"type":"string","description":"Signature encoded as base64 string.","example":"Corporis itaque eos dolorem doloremque quibusdam."}},"example":{"signature":"Molestiae id vitae vel."},"required":["signature"]},"SignerSignOKResponseBody":{"title":"SignerSignOKResponseBody","type":"object","properties":{"signature":{"type":"string","description":"Signature encoded as base64 string.","example":"Consequuntur est sit explicabo possimus."}},"example":{"signature":"Accusantium voluptas ut."},"required":["signature"]},"SignerSignRequestBody":{"title":"SignerSignRequestBody","type":"object","properties":{"data":{"type":"string","description":"Data that must be signed, encoded as base64 string.","example":"Accusamus ex nihil inventore ea qui."},"key":{"type":"string","description":"Key to be used for signing.","example":"Est occaecati nam."},"namespace":{"type":"string","description":"Key namespace to be used for signing.","example":"Qui consequatur eum nulla eaque."}},"example":{"data":"Dolores quis fugiat qui quia.","key":"Sunt incidunt et repellat cum sit quibusdam.","namespace":"Sapiente error nostrum."},"required":["namespace","key","data"]},"SignerVerificationMethodResponseBody":{"title":"SignerVerificationMethodResponseBody","type":"object","properties":{"controller":{"type":"string","description":"Controller of verification method specified as DID.","example":"did:web:example.com"},"id":{"type":"string","description":"ID of verification method.","example":"key1"},"publicKeyJwk":{"type":"string","description":"Public Key encoded in JWK format.","example":"Hic doloribus.","format":"binary"},"type":{"type":"string","description":"Type of verification method key.","example":"JsonWebKey2020"}},"description":"Public Key represented as DID Verification Method.","example":{"controller":"did:web:example.com","id":"key1","publicKeyJwk":"Soluta repudiandae quam reprehenderit.","type":"JsonWebKey2020"},"required":["id","type","controller","publicKeyJwk"]},"SignerVerifyCredentialResponseBody":{"title":"SignerVerifyCredentialResponseBody","type":"object","properties":{"valid":{"type":"boolean","description":"Valid specifies if the proof is successfully verified.","example":false}},"example":{"valid":false},"required":["valid"]},"SignerVerifyPresentationResponseBody":{"title":"SignerVerifyPresentationResponseBody","type":"object","properties":{"valid":{"type":"boolean","description":"Valid specifies if the proof is successfully verified.","example":true}},"example":{"valid":true},"required":["valid"]}}} \ No newline at end of file diff --git a/gen/http/openapi.yaml b/gen/http/openapi.yaml index e234a3ff13787781abeaba88482c5b334d1485c2..7a1baf62a8fda4c908a40484e853f5d8370d9c99 100644 --- a/gen/http/openapi.yaml +++ b/gen/http/openapi.yaml @@ -136,7 +136,7 @@ paths: type: array items: type: string - example: Nihil iste debitis. + example: Facere quos corporis. schemes: - http /v1/namespaces/{namespace}/keys: @@ -159,7 +159,7 @@ paths: type: array items: type: string - example: Sapiente dolorem qui possimus qui labore veritatis. + example: Aut et aut adipisci voluptatem consectetur quidem. schemes: - http /v1/presentation: @@ -238,6 +238,44 @@ paths: - valid schemes: - http + /v1/sign: + post: + tags: + - signer + summary: Sign signer + description: Sign creates digital signature on base64 encoded binary data. + operationId: signer#Sign + parameters: + - name: SignRequestBody + in: body + required: true + schema: + $ref: '#/definitions/SignerSignRequestBody' + required: + - namespace + - key + - data + responses: + "200": + description: OK response. + schema: + $ref: '#/definitions/SignerSignOKResponseBody' + required: + - signature + "404": + description: Not Found response. + schema: + $ref: '#/definitions/SignerSignNotFoundResponseBody' + required: + - signature + "500": + description: Internal Server Error response. + schema: + $ref: '#/definitions/SignerSignInternalServerErrorResponseBody' + required: + - signature + schemes: + - http /v1/verification-methods/{namespace}/{did}: get: tags: @@ -316,7 +354,7 @@ definitions: publicKeyJwk: type: string description: Public Key encoded in JWK format. - example: Et nulla illo totam optio quia ab. + example: Molestias eaque eos rerum dolores ipsa dolores. format: binary type: type: string @@ -325,7 +363,7 @@ definitions: example: controller: did:web:example.com id: key1 - publicKeyJwk: Quibusdam nemo ut iusto ut fugit. + publicKeyJwk: Nesciunt eaque. type: JsonWebKey2020 required: - id @@ -339,19 +377,19 @@ definitions: service: type: string description: Service name. - example: Repudiandae quam reprehenderit sed molestias eaque. + example: Velit sit exercitationem et eligendi incidunt. status: type: string description: Status message. - example: Rerum dolores ipsa. + example: Molestiae eveniet vero est aliquam. version: type: string description: Service runtime version. - example: Praesentium nesciunt. + example: Totam quam. example: - service: Laboriosam qui. - status: Consequatur omnis architecto nobis vel id. - version: Nam ea ducimus. + service: Voluptates consectetur et repellat. + status: Repudiandae aut dolorum hic aut voluptatem soluta. + version: Earum debitis. required: - service - status @@ -363,19 +401,19 @@ definitions: service: type: string description: Service name. - example: Ea quas praesentium voluptas occaecati est facere. + example: Rerum veritatis delectus quis recusandae. status: type: string description: Status message. - example: Dolores velit. + example: Est quos possimus sed sit voluptates nihil. version: type: string description: Service runtime version. - example: Tempore suscipit ut occaecati. + example: Ducimus eum facere enim accusantium. example: - service: Ut dolor numquam et dolores. - status: Neque blanditiis nostrum nihil consequuntur est. - version: Explicabo possimus ea. + service: Sint laudantium rerum neque. + status: Suscipit expedita quos eligendi. + version: Qui rerum. required: - service - status @@ -388,7 +426,7 @@ definitions: type: array items: type: string - example: Sed aut. + example: Dolores velit. description: Additional JSONLD contexts to be specified in the VC. example: - https://w3id.org/security/suites/jws-2020/v1 @@ -433,7 +471,7 @@ definitions: type: array items: type: string - example: Aut et aut adipisci voluptatem consectetur quidem. + example: Ut dolor numquam et dolores. description: Additional JSONLD contexts to be specified in the VP. example: - https://w3id.org/security/suites/jws-2020/v1 @@ -442,7 +480,7 @@ definitions: type: array items: type: string - example: Facere quos corporis. + example: Tempore suscipit ut occaecati. format: binary description: Raw JSON to be included inside the VP as Verifiable Credential. example: @@ -527,7 +565,7 @@ definitions: issuer: type: string description: Issuer DID used to specify proof verification info. - example: Asperiores vitae rem. + example: Qui et. key: type: string description: Key to use for the proof signature. @@ -539,18 +577,78 @@ definitions: presentation: type: string description: Verifiable Presentation in JSON format. - example: Quaerat odit optio. + example: Omnis architecto nobis vel id. format: binary example: - issuer: Mollitia architecto rem beatae mollitia. + issuer: Nam ea ducimus. key: key1 namespace: transit - presentation: Id tempora aut. + presentation: Ea quas praesentium voluptas occaecati est facere. required: - issuer - namespace - key - presentation + SignerSignInternalServerErrorResponseBody: + title: SignerSignInternalServerErrorResponseBody + type: object + properties: + signature: + type: string + description: Signature encoded as base64 string. + example: Vel porro qui quidem unde. + example: + signature: Quis voluptas. + required: + - signature + SignerSignNotFoundResponseBody: + title: SignerSignNotFoundResponseBody + type: object + properties: + signature: + type: string + description: Signature encoded as base64 string. + example: Corporis itaque eos dolorem doloremque quibusdam. + example: + signature: Molestiae id vitae vel. + required: + - signature + SignerSignOKResponseBody: + title: SignerSignOKResponseBody + type: object + properties: + signature: + type: string + description: Signature encoded as base64 string. + example: Consequuntur est sit explicabo possimus. + example: + signature: Accusantium voluptas ut. + required: + - signature + SignerSignRequestBody: + title: SignerSignRequestBody + type: object + properties: + data: + type: string + description: Data that must be signed, encoded as base64 string. + example: Accusamus ex nihil inventore ea qui. + key: + type: string + description: Key to be used for signing. + example: Est occaecati nam. + namespace: + type: string + description: Key namespace to be used for signing. + example: Qui consequatur eum nulla eaque. + example: + data: Dolores quis fugiat qui quia. + key: Sunt incidunt et repellat cum sit quibusdam. + namespace: Sapiente error nostrum. + required: + - namespace + - key + - data SignerVerificationMethodResponseBody: title: SignerVerificationMethodResponseBody type: object @@ -566,7 +664,7 @@ definitions: publicKeyJwk: type: string description: Public Key encoded in JWK format. - example: Fuga officia excepturi velit aut. + example: Hic doloribus. format: binary type: type: string @@ -576,7 +674,7 @@ definitions: example: controller: did:web:example.com id: key1 - publicKeyJwk: Natus quos ut corrupti. + publicKeyJwk: Soluta repudiandae quam reprehenderit. type: JsonWebKey2020 required: - id diff --git a/gen/http/openapi3.json b/gen/http/openapi3.json index 4b96dd787096d8609c54e24275c73d24db205d59..e0815d76cb6133c1af24af7bccb3bff25ec1aa06 100644 --- a/gen/http/openapi3.json +++ b/gen/http/openapi3.json @@ -1 +1 @@ -{"openapi":"3.0.3","info":{"title":"Signer Service","description":"Signer service exposes HTTP API for making and verifying digital signatures and proofs for Verifiable Credentials.","version":"1.0"},"servers":[{"url":"http://localhost:8085","description":"Signer Server"}],"paths":{"/liveness":{"get":{"tags":["health"],"summary":"Liveness health","operationId":"health#Liveness","responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"},"example":{"service":"Laboriosam qui est quaerat.","status":"Dolor illo aliquid ipsum optio.","version":"Et et cupiditate debitis."}}}}}}},"/readiness":{"get":{"tags":["health"],"summary":"Readiness health","operationId":"health#Readiness","responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"},"example":{"service":"Illum qui nihil.","status":"Ut occaecati repellat.","version":"Non amet."}}}}}}},"/v1/credential":{"post":{"tags":["signer"],"summary":"CreateCredential signer","description":"CreateCredential creates VC with proof from raw JSON data.","operationId":"signer#CreateCredential","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCredentialRequestBody"},"example":{"context":["https://w3id.org/security/suites/jws-2020/v1","https://schema.org"],"credentialSubject":{"hello":"world"},"issuer":"did:web:example.com","key":"key1","namespace":"transit"}}}},"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"string","example":"Est quos possimus sed sit voluptates nihil.","format":"binary"},"example":"Aperiam odit illo natus."}}}}}},"/v1/credential/proof":{"post":{"tags":["signer"],"summary":"CredentialProof signer","description":"CredentialProof adds a proof to a given Verifiable Credential.","operationId":"signer#CredentialProof","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CredentialProofRequestBody"},"example":{"credential":{"@context":["https://www.w3.org/2018/credentials/v1","https://w3id.org/security/suites/jws-2020/v1","https://schema.org"],"type":"VerifiableCredential","issuer":"did:web:nginx:policy:policy:example:example:1.0:evaluation","issuanceDate":"2010-01-01T19:23:24.651387237Z","credentialSubject":{"name":"Alice","allow":true}},"key":"key1","namespace":"transit"}}}},"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"string","example":"Sit exercitationem et eligendi incidunt.","format":"binary"},"example":"Laudantium nulla quod ab adipisci odio."}}}}}},"/v1/credential/verify":{"post":{"tags":["signer"],"summary":"VerifyCredential signer","description":"VerifyCredential verifies the proof of a Verifiable Credential.","operationId":"signer#VerifyCredential","requestBody":{"description":"Verifiable Credential in JSON format.","required":true,"content":{"application/json":{"schema":{"type":"string","description":"Verifiable Credential in JSON format.","example":"UXVpIHJlcnVtLg==","format":"binary"},"example":"T2NjYWVjYXRpIGRvbG9yZW1xdWUgYW5pbWkgcXVpYSBkZXNlcnVudCBxdWlkZW0gZXQu"}}},"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyResult"},"example":{"valid":true}}}}}}},"/v1/namespaces":{"get":{"tags":["signer"],"summary":"Namespaces signer","description":"Namespaces returns all keys namespaces, which corresponds to enabled Vault transit engines.","operationId":"signer#Namespaces","responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"array","items":{"type":"string","example":"Voluptas ut."},"description":"List of available keys namespaces.","example":["Itaque eos dolorem doloremque quibusdam.","Molestiae id vitae vel.","Vel porro qui quidem unde.","Quis voluptas."]},"example":["Quae accusantium similique beatae nihil molestias.","Neque voluptates dolores.","Reiciendis aut nobis qui debitis enim quaerat."]}}}}}},"/v1/namespaces/{namespace}/keys":{"get":{"tags":["signer"],"summary":"NamespaceKeys signer","description":"NamespaceKeys returns all keys in a given namespace.","operationId":"signer#NamespaceKeys","parameters":[{"name":"namespace","in":"path","description":"Namespace for signing keys.","required":true,"schema":{"type":"string","description":"Namespace for signing keys.","example":"did:web:example.com"},"example":"did:web:example.com"}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"array","items":{"type":"string","example":"Qui consequatur eum nulla eaque."},"description":"Array of key names in a given namespace.","example":["Occaecati nam temporibus.","Ex nihil.","Ea qui mollitia sapiente error nostrum quae."]},"example":["Illum minus quasi sequi molestiae.","Ducimus occaecati reprehenderit neque labore quia rem.","Eum hic autem in.","Magnam unde provident explicabo numquam culpa eum."]}}}}}},"/v1/presentation":{"post":{"tags":["signer"],"summary":"CreatePresentation signer","description":"CreatePresentation creates VP with proof from raw JSON data.","operationId":"signer#CreatePresentation","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePresentationRequestBody"},"example":{"context":["https://w3id.org/security/suites/jws-2020/v1","https://schema.org"],"data":[{"hello":"world"},{"hola":"mundo"}],"issuer":"did:web:example.com","key":"key1","namespace":"transit"}}}},"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"string","example":"Suscipit expedita quos eligendi.","format":"binary"},"example":"Tenetur ut consequuntur."}}}}}},"/v1/presentation/proof":{"post":{"tags":["signer"],"summary":"PresentationProof signer","description":"PresentationProof adds a proof to a given Verifiable Presentation.","operationId":"signer#PresentationProof","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PresentationProofRequestBody"},"example":{"issuer":"Consequatur facilis eius.","key":"key1","namespace":"transit","presentation":"Dicta commodi possimus recusandae et."}}}},"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"string","example":"Earum debitis.","format":"binary"},"example":"Nam accusamus ea dolorem tenetur."}}}}}},"/v1/presentation/verify":{"post":{"tags":["signer"],"summary":"VerifyPresentation signer","description":"VerifyPresentation verifies the proof of a Verifiable Presentation.","operationId":"signer#VerifyPresentation","requestBody":{"description":"Verifiable Presentation in JSON format.","required":true,"content":{"application/json":{"schema":{"type":"string","description":"Verifiable Presentation in JSON format.","example":"UGVyc3BpY2lhdGlzIHZlbGl0IHJlcHVkaWFuZGFlIHZvbHVwdGF0ZW0gbW9kaSByZXJ1bSByYXRpb25lLg==","format":"binary"},"example":"TWF4aW1lIHRvdGFtIHZvbHVwdGF0aWJ1cyBjb3JydXB0aSBpcHNhbS4="}}},"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyResult"},"example":{"valid":false}}}}}}},"/v1/verification-methods/{namespace}/{did}":{"get":{"tags":["signer"],"summary":"VerificationMethods signer","description":"VerificationMethods returns all public keys in a given namespace. The result is formatted as array of DID verification methods with their controller attribute being the given DID in the request.","operationId":"signer#VerificationMethods","parameters":[{"name":"namespace","in":"path","description":"Keys namespace.","required":true,"schema":{"type":"string","description":"Keys namespace.","example":"transit"},"example":"transit"},{"name":"did","in":"path","description":"DID controller of the keys.","required":true,"schema":{"type":"string","description":"DID controller of the keys.","example":"did:web:example.com"},"example":"did:web:example.com"}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/DIDVerificationMethod"},"description":"Array of public keys represented as DID Verification Methods.","example":[{"controller":"did:web:example.com","id":"key1","publicKeyJwk":"Omnis aut qui odit ut.","type":"JsonWebKey2020"},{"controller":"did:web:example.com","id":"key1","publicKeyJwk":"Omnis aut qui odit ut.","type":"JsonWebKey2020"},{"controller":"did:web:example.com","id":"key1","publicKeyJwk":"Omnis aut qui odit ut.","type":"JsonWebKey2020"}]},"example":[{"controller":"did:web:example.com","id":"key1","publicKeyJwk":"Omnis aut qui odit ut.","type":"JsonWebKey2020"},{"controller":"did:web:example.com","id":"key1","publicKeyJwk":"Omnis aut qui odit ut.","type":"JsonWebKey2020"}]}}}}}},"/v1/verification-methods/{namespace}/{key}/{did}":{"get":{"tags":["signer"],"summary":"VerificationMethod signer","description":"VerificationMethod returns a single public key formatted as DID verification method for a given namespace, key and did.","operationId":"signer#VerificationMethod","parameters":[{"name":"namespace","in":"path","description":"Key namespace.","required":true,"schema":{"type":"string","description":"Key namespace.","example":"transit"},"example":"transit"},{"name":"key","in":"path","description":"Name of requested key.","required":true,"schema":{"type":"string","description":"Name of requested key.","example":"key1"},"example":"key1"},{"name":"did","in":"path","description":"DID controller of the key.","required":true,"schema":{"type":"string","description":"DID controller of the key.","example":"did:web:example.com"},"example":"did:web:example.com"}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DIDVerificationMethod"},"example":{"controller":"did:web:example.com","id":"key1","publicKeyJwk":"Quasi exercitationem provident illum nesciunt similique veniam.","type":"JsonWebKey2020"}}}}}}}},"components":{"schemas":{"CreateCredentialRequestBody":{"type":"object","properties":{"context":{"type":"array","items":{"type":"string","example":"Rerum veritatis delectus quis recusandae."},"description":"Additional JSONLD contexts to be specified in the VC.","example":["https://w3id.org/security/suites/jws-2020/v1","https://schema.org"]},"credentialSubject":{"type":"string","description":"Raw JSON that will be the VC subject.","example":{"hello":"world"},"format":"binary"},"issuer":{"type":"string","description":"Issuer DID of the Verifiable Credential.","example":"did:web:example.com"},"key":{"type":"string","description":"Key to use for the proof signature.","example":"key1"},"namespace":{"type":"string","description":"Key namespace.","example":"transit"}},"example":{"context":["https://w3id.org/security/suites/jws-2020/v1","https://schema.org"],"credentialSubject":{"hello":"world"},"issuer":"did:web:example.com","key":"key1","namespace":"transit"},"required":["issuer","namespace","key","credentialSubject"]},"CreatePresentationRequestBody":{"type":"object","properties":{"context":{"type":"array","items":{"type":"string","example":"Sint laudantium rerum neque."},"description":"Additional JSONLD contexts to be specified in the VP.","example":["https://w3id.org/security/suites/jws-2020/v1","https://schema.org"]},"data":{"type":"array","items":{"type":"string","example":"Ducimus eum facere enim accusantium.","format":"binary"},"description":"Raw JSON to be included inside the VP as Verifiable Credential.","example":[{"hello":"world"},{"hola":"mundo"}]},"issuer":{"type":"string","description":"Issuer DID of the Verifiable Presentation.","example":"did:web:example.com"},"key":{"type":"string","description":"Key to use for the proof signature.","example":"key1"},"namespace":{"type":"string","description":"Key namespace.","example":"transit"}},"example":{"context":["https://w3id.org/security/suites/jws-2020/v1","https://schema.org"],"data":[{"hello":"world"},{"hola":"mundo"}],"issuer":"did:web:example.com","key":"key1","namespace":"transit"},"required":["issuer","namespace","key","data"]},"CredentialProofRequestBody":{"type":"object","properties":{"credential":{"type":"string","description":"Verifiable Credential in JSON format.","example":{"@context":["https://www.w3.org/2018/credentials/v1","https://w3id.org/security/suites/jws-2020/v1","https://schema.org"],"type":"VerifiableCredential","issuer":"did:web:nginx:policy:policy:example:example:1.0:evaluation","issuanceDate":"2010-01-01T19:23:24.651387237Z","credentialSubject":{"name":"Alice","allow":true}},"format":"binary"},"key":{"type":"string","description":"Key to use for the proof signature (optional).","example":"key1"},"namespace":{"type":"string","description":"Key namespace.","example":"transit"}},"example":{"credential":{"@context":["https://www.w3.org/2018/credentials/v1","https://w3id.org/security/suites/jws-2020/v1","https://schema.org"],"type":"VerifiableCredential","issuer":"did:web:nginx:policy:policy:example:example:1.0:evaluation","issuanceDate":"2010-01-01T19:23:24.651387237Z","credentialSubject":{"name":"Alice","allow":true}},"key":"key1","namespace":"transit"},"required":["namespace","key","credential"]},"DIDVerificationMethod":{"type":"object","properties":{"controller":{"type":"string","description":"Controller of verification method specified as DID.","example":"did:web:example.com"},"id":{"type":"string","description":"ID of verification method.","example":"key1"},"publicKeyJwk":{"type":"string","description":"Public Key encoded in JWK format.","example":"Incidunt et repellat cum sit quibusdam.","format":"binary"},"type":{"type":"string","description":"Type of verification method key.","example":"JsonWebKey2020"}},"description":"Public Key represented as DID Verification Method.","example":{"controller":"did:web:example.com","id":"key1","publicKeyJwk":"Dolores quis fugiat qui quia.","type":"JsonWebKey2020"},"required":["id","type","controller","publicKeyJwk"]},"HealthResponse":{"type":"object","properties":{"service":{"type":"string","description":"Service name.","example":"Asperiores rem tempora."},"status":{"type":"string","description":"Status message.","example":"Non aut inventore necessitatibus unde."},"version":{"type":"string","description":"Service runtime version.","example":"Ut similique molestias aperiam quia et."}},"example":{"service":"Est asperiores velit eum perferendis.","status":"Rerum quaerat sit.","version":"Omnis est aspernatur voluptas in."},"required":["service","status","version"]},"PresentationProofRequestBody":{"type":"object","properties":{"issuer":{"type":"string","description":"Issuer DID used to specify proof verification info.","example":"Molestiae eveniet vero est aliquam."},"key":{"type":"string","description":"Key to use for the proof signature.","example":"key1"},"namespace":{"type":"string","description":"Key namespace.","example":"transit"},"presentation":{"type":"string","description":"Verifiable Presentation in JSON format.","example":"Totam quam.","format":"binary"}},"example":{"issuer":"Voluptates consectetur et repellat.","key":"key1","namespace":"transit","presentation":"Repudiandae aut dolorum hic aut voluptatem soluta."},"required":["issuer","namespace","key","presentation"]},"VerifyResult":{"type":"object","properties":{"valid":{"type":"boolean","description":"Valid specifies if the proof is successfully verified.","example":false}},"example":{"valid":false},"required":["valid"]}}},"tags":[{"name":"signer","description":"Signer service makes digital signatures and proofs for verifiable credentials and presentations."},{"name":"health","description":"Health service provides health check endpoints."}]} \ No newline at end of file +{"openapi":"3.0.3","info":{"title":"Signer Service","description":"Signer service exposes HTTP API for making and verifying digital signatures and proofs for Verifiable Credentials.","version":"1.0"},"servers":[{"url":"http://localhost:8085","description":"Signer Server"}],"paths":{"/liveness":{"get":{"tags":["health"],"summary":"Liveness health","operationId":"health#Liveness","responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"},"example":{"service":"Quibusdam nemo ut iusto ut fugit.","status":"Asperiores vitae rem.","version":"Quaerat odit optio."}}}}}}},"/readiness":{"get":{"tags":["health"],"summary":"Readiness health","operationId":"health#Readiness","responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"},"example":{"service":"Mollitia architecto rem beatae mollitia.","status":"Id tempora aut.","version":"Sed aut."}}}}}}},"/v1/credential":{"post":{"tags":["signer"],"summary":"CreateCredential signer","description":"CreateCredential creates VC with proof from raw JSON data.","operationId":"signer#CreateCredential","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCredentialRequestBody"},"example":{"context":["https://w3id.org/security/suites/jws-2020/v1","https://schema.org"],"credentialSubject":{"hello":"world"},"issuer":"did:web:example.com","key":"key1","namespace":"transit"}}}},"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"string","example":"Ab adipisci odio.","format":"binary"},"example":"Temporibus maxime ipsum laudantium voluptatibus ipsam."}}}}}},"/v1/credential/proof":{"post":{"tags":["signer"],"summary":"CredentialProof signer","description":"CredentialProof adds a proof to a given Verifiable Credential.","operationId":"signer#CredentialProof","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CredentialProofRequestBody"},"example":{"credential":{"@context":["https://www.w3.org/2018/credentials/v1","https://w3id.org/security/suites/jws-2020/v1","https://schema.org"],"type":"VerifiableCredential","issuer":"did:web:nginx:policy:policy:example:example:1.0:evaluation","issuanceDate":"2010-01-01T19:23:24.651387237Z","credentialSubject":{"name":"Alice","allow":true}},"key":"key1","namespace":"transit"}}}},"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"string","example":"Aut nobis qui debitis enim.","format":"binary"},"example":"Recusandae unde consequatur odit ut at iste."}}}}}},"/v1/credential/verify":{"post":{"tags":["signer"],"summary":"VerifyCredential signer","description":"VerifyCredential verifies the proof of a Verifiable Credential.","operationId":"signer#VerifyCredential","requestBody":{"description":"Verifiable Credential in JSON format.","required":true,"content":{"application/json":{"schema":{"type":"string","description":"Verifiable Credential in JSON format.","example":"T2NjYWVjYXRpIGRvbG9yZW1xdWUgYW5pbWkgcXVpYSBkZXNlcnVudCBxdWlkZW0gZXQu","format":"binary"},"example":"VmVybyBxdWkgdXQgZHVjaW11cy4="}}},"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyResult"},"example":{"valid":true}}}}}}},"/v1/namespaces":{"get":{"tags":["signer"],"summary":"Namespaces signer","description":"Namespaces returns all keys namespaces, which corresponds to enabled Vault transit engines.","operationId":"signer#Namespaces","responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"array","items":{"type":"string","example":"Ut error perspiciatis velit repudiandae voluptatem."},"description":"List of available keys namespaces.","example":["Ratione voluptatibus asperiores.","Tempora et non aut inventore."]},"example":["Qui consequatur et.","Pariatur numquam porro facilis et.","Ut ea reiciendis vel nihil.","Doloremque ea saepe quidem dolores fugiat aliquam."]}}}}}},"/v1/namespaces/{namespace}/keys":{"get":{"tags":["signer"],"summary":"NamespaceKeys signer","description":"NamespaceKeys returns all keys in a given namespace.","operationId":"signer#NamespaceKeys","parameters":[{"name":"namespace","in":"path","description":"Namespace for signing keys.","required":true,"schema":{"type":"string","description":"Namespace for signing keys.","example":"did:web:example.com"},"example":"did:web:example.com"}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"array","items":{"type":"string","example":"Unde facilis ut similique molestias aperiam quia."},"description":"Array of key names in a given namespace.","example":["Est asperiores velit eum perferendis.","Rerum quaerat sit.","Omnis est aspernatur voluptas in."]},"example":["Maxime dolor et sed fugit quo.","Aut quisquam unde."]}}}}}},"/v1/presentation":{"post":{"tags":["signer"],"summary":"CreatePresentation signer","description":"CreatePresentation creates VP with proof from raw JSON data.","operationId":"signer#CreatePresentation","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePresentationRequestBody"},"example":{"context":["https://w3id.org/security/suites/jws-2020/v1","https://schema.org"],"data":[{"hello":"world"},{"hola":"mundo"}],"issuer":"did:web:example.com","key":"key1","namespace":"transit"}}}},"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"string","example":"Tenetur ut consequuntur.","format":"binary"},"example":"Eligendi nostrum eveniet et autem voluptas eos."}}}}}},"/v1/presentation/proof":{"post":{"tags":["signer"],"summary":"PresentationProof signer","description":"PresentationProof adds a proof to a given Verifiable Presentation.","operationId":"signer#PresentationProof","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PresentationProofRequestBody"},"example":{"issuer":"Neque impedit.","key":"key1","namespace":"transit","presentation":"Sunt vitae."}}}},"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"string","example":"Magnam unde provident explicabo numquam culpa eum.","format":"binary"},"example":"Numquam quaerat."}}}}}},"/v1/presentation/verify":{"post":{"tags":["signer"],"summary":"VerifyPresentation signer","description":"VerifyPresentation verifies the proof of a Verifiable Presentation.","operationId":"signer#VerifyPresentation","requestBody":{"description":"Verifiable Presentation in JSON format.","required":true,"content":{"application/json":{"schema":{"type":"string","description":"Verifiable Presentation in JSON format.","example":"Vm9sdXB0YXRpYnVzIGNvcnJ1cHRpIGlwc2FtIG1haW9yZXMgb2ZmaWNpaXMgbWFnbmkgY3VtLg==","format":"binary"},"example":"Tm9uIGF1dCBxdWlzcXVhbSBzdW50IGhpYy4="}}},"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyResult"},"example":{"valid":false}}}}}}},"/v1/sign":{"post":{"tags":["signer"],"summary":"Sign signer","description":"Sign creates digital signature on base64 encoded binary data.","operationId":"signer#Sign","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignRequestBody"},"example":{"data":"Sapiente dolorem qui possimus qui labore veritatis.","key":"Nihil iste debitis.","namespace":"Occaecati repellat est non amet."}}}},"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignResult"},"example":{"signature":"Fuga officia excepturi velit aut."}}}},"404":{"description":"Not Found response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignResult"},"example":{"signature":"Natus quos ut corrupti."}}}},"500":{"description":"Internal Server Error response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignResult"},"example":{"signature":"Et nulla illo totam optio quia ab."}}}}}}},"/v1/verification-methods/{namespace}/{did}":{"get":{"tags":["signer"],"summary":"VerificationMethods signer","description":"VerificationMethods returns all public keys in a given namespace. The result is formatted as array of DID verification methods with their controller attribute being the given DID in the request.","operationId":"signer#VerificationMethods","parameters":[{"name":"namespace","in":"path","description":"Keys namespace.","required":true,"schema":{"type":"string","description":"Keys namespace.","example":"transit"},"example":"transit"},{"name":"did","in":"path","description":"DID controller of the keys.","required":true,"schema":{"type":"string","description":"DID controller of the keys.","example":"did:web:example.com"},"example":"did:web:example.com"}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/DIDVerificationMethod"},"description":"Array of public keys represented as DID Verification Methods.","example":[{"controller":"did:web:example.com","id":"key1","publicKeyJwk":"Iure ex consequatur facilis.","type":"JsonWebKey2020"},{"controller":"did:web:example.com","id":"key1","publicKeyJwk":"Iure ex consequatur facilis.","type":"JsonWebKey2020"},{"controller":"did:web:example.com","id":"key1","publicKeyJwk":"Iure ex consequatur facilis.","type":"JsonWebKey2020"},{"controller":"did:web:example.com","id":"key1","publicKeyJwk":"Iure ex consequatur facilis.","type":"JsonWebKey2020"}]},"example":[{"controller":"did:web:example.com","id":"key1","publicKeyJwk":"Iure ex consequatur facilis.","type":"JsonWebKey2020"},{"controller":"did:web:example.com","id":"key1","publicKeyJwk":"Iure ex consequatur facilis.","type":"JsonWebKey2020"}]}}}}}},"/v1/verification-methods/{namespace}/{key}/{did}":{"get":{"tags":["signer"],"summary":"VerificationMethod signer","description":"VerificationMethod returns a single public key formatted as DID verification method for a given namespace, key and did.","operationId":"signer#VerificationMethod","parameters":[{"name":"namespace","in":"path","description":"Key namespace.","required":true,"schema":{"type":"string","description":"Key namespace.","example":"transit"},"example":"transit"},{"name":"key","in":"path","description":"Name of requested key.","required":true,"schema":{"type":"string","description":"Name of requested key.","example":"key1"},"example":"key1"},{"name":"did","in":"path","description":"DID controller of the key.","required":true,"schema":{"type":"string","description":"DID controller of the key.","example":"did:web:example.com"},"example":"did:web:example.com"}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DIDVerificationMethod"},"example":{"controller":"did:web:example.com","id":"key1","publicKeyJwk":"Qui ipsa aut non fuga iste.","type":"JsonWebKey2020"}}}}}}}},"components":{"schemas":{"CreateCredentialRequestBody":{"type":"object","properties":{"context":{"type":"array","items":{"type":"string","example":"Sunt laudantium nulla."},"description":"Additional JSONLD contexts to be specified in the VC.","example":["https://w3id.org/security/suites/jws-2020/v1","https://schema.org"]},"credentialSubject":{"type":"string","description":"Raw JSON that will be the VC subject.","example":{"hello":"world"},"format":"binary"},"issuer":{"type":"string","description":"Issuer DID of the Verifiable Credential.","example":"did:web:example.com"},"key":{"type":"string","description":"Key to use for the proof signature.","example":"key1"},"namespace":{"type":"string","description":"Key namespace.","example":"transit"}},"example":{"context":["https://w3id.org/security/suites/jws-2020/v1","https://schema.org"],"credentialSubject":{"hello":"world"},"issuer":"did:web:example.com","key":"key1","namespace":"transit"},"required":["issuer","namespace","key","credentialSubject"]},"CreatePresentationRequestBody":{"type":"object","properties":{"context":{"type":"array","items":{"type":"string","example":"Aperiam odit illo natus."},"description":"Additional JSONLD contexts to be specified in the VP.","example":["https://w3id.org/security/suites/jws-2020/v1","https://schema.org"]},"data":{"type":"array","items":{"type":"string","example":"Nam accusamus ea dolorem tenetur.","format":"binary"},"description":"Raw JSON to be included inside the VP as Verifiable Credential.","example":[{"hello":"world"},{"hola":"mundo"}]},"issuer":{"type":"string","description":"Issuer DID of the Verifiable Presentation.","example":"did:web:example.com"},"key":{"type":"string","description":"Key to use for the proof signature.","example":"key1"},"namespace":{"type":"string","description":"Key namespace.","example":"transit"}},"example":{"context":["https://w3id.org/security/suites/jws-2020/v1","https://schema.org"],"data":[{"hello":"world"},{"hola":"mundo"}],"issuer":"did:web:example.com","key":"key1","namespace":"transit"},"required":["issuer","namespace","key","data"]},"CredentialProofRequestBody":{"type":"object","properties":{"credential":{"type":"string","description":"Verifiable Credential in JSON format.","example":{"@context":["https://www.w3.org/2018/credentials/v1","https://w3id.org/security/suites/jws-2020/v1","https://schema.org"],"type":"VerifiableCredential","issuer":"did:web:nginx:policy:policy:example:example:1.0:evaluation","issuanceDate":"2010-01-01T19:23:24.651387237Z","credentialSubject":{"name":"Alice","allow":true}},"format":"binary"},"key":{"type":"string","description":"Key to use for the proof signature (optional).","example":"key1"},"namespace":{"type":"string","description":"Key namespace.","example":"transit"}},"example":{"credential":{"@context":["https://www.w3.org/2018/credentials/v1","https://w3id.org/security/suites/jws-2020/v1","https://schema.org"],"type":"VerifiableCredential","issuer":"did:web:nginx:policy:policy:example:example:1.0:evaluation","issuanceDate":"2010-01-01T19:23:24.651387237Z","credentialSubject":{"name":"Alice","allow":true}},"key":"key1","namespace":"transit"},"required":["namespace","key","credential"]},"DIDVerificationMethod":{"type":"object","properties":{"controller":{"type":"string","description":"Controller of verification method specified as DID.","example":"did:web:example.com"},"id":{"type":"string","description":"ID of verification method.","example":"key1"},"publicKeyJwk":{"type":"string","description":"Public Key encoded in JWK format.","example":"Unde quae accusantium similique beatae nihil molestias.","format":"binary"},"type":{"type":"string","description":"Type of verification method key.","example":"JsonWebKey2020"}},"description":"Public Key represented as DID Verification Method.","example":{"controller":"did:web:example.com","id":"key1","publicKeyJwk":"Neque voluptates dolores.","type":"JsonWebKey2020"},"required":["id","type","controller","publicKeyJwk"]},"HealthResponse":{"type":"object","properties":{"service":{"type":"string","description":"Service name.","example":"Voluptatibus aperiam eius velit."},"status":{"type":"string","description":"Status message.","example":"Dolores libero."},"version":{"type":"string","description":"Service runtime version.","example":"Tempora voluptatem error molestiae."}},"example":{"service":"Deleniti laudantium exercitationem tenetur iusto eos quidem.","status":"Dolorum et consequatur sed in vero qui.","version":"Ut et quasi eius error minima eaque."},"required":["service","status","version"]},"PresentationProofRequestBody":{"type":"object","properties":{"issuer":{"type":"string","description":"Issuer DID used to specify proof verification info.","example":"Consectetur aut illum."},"key":{"type":"string","description":"Key to use for the proof signature.","example":"key1"},"namespace":{"type":"string","description":"Key namespace.","example":"transit"},"presentation":{"type":"string","description":"Verifiable Presentation in JSON format.","example":"Quasi sequi molestiae assumenda ducimus occaecati reprehenderit.","format":"binary"}},"example":{"issuer":"Labore quia rem.","key":"key1","namespace":"transit","presentation":"Eum hic autem in."},"required":["issuer","namespace","key","presentation"]},"SignRequestBody":{"type":"object","properties":{"data":{"type":"string","description":"Data that must be signed, encoded as base64 string.","example":"Sit ut non est fugiat et repellat."},"key":{"type":"string","description":"Key to be used for signing.","example":"Porro iste."},"namespace":{"type":"string","description":"Key namespace to be used for signing.","example":"Culpa quibusdam sunt nemo tempora dolores."}},"example":{"data":"Et voluptatem.","key":"Minus et ut ullam quidem vitae qui.","namespace":"Consequatur veritatis ab."},"required":["namespace","key","data"]},"SignResult":{"type":"object","properties":{"signature":{"type":"string","description":"Signature encoded as base64 string.","example":"Saepe itaque ratione."}},"example":{"signature":"Laborum delectus."},"required":["signature"]},"VerifyResult":{"type":"object","properties":{"valid":{"type":"boolean","description":"Valid specifies if the proof is successfully verified.","example":true}},"example":{"valid":true},"required":["valid"]}}},"tags":[{"name":"signer","description":"Signer service makes digital signatures and proofs for verifiable credentials and presentations."},{"name":"health","description":"Health service provides health check endpoints."}]} \ No newline at end of file diff --git a/gen/http/openapi3.yaml b/gen/http/openapi3.yaml index d8096d18242e37f7b5da716b3d51b7fa212e004e..e1f1994cb89c036971e191dc0c4f5356ea193cd5 100644 --- a/gen/http/openapi3.yaml +++ b/gen/http/openapi3.yaml @@ -21,9 +21,9 @@ paths: schema: $ref: '#/components/schemas/HealthResponse' example: - service: Laboriosam qui est quaerat. - status: Dolor illo aliquid ipsum optio. - version: Et et cupiditate debitis. + service: Quibusdam nemo ut iusto ut fugit. + status: Asperiores vitae rem. + version: Quaerat odit optio. /readiness: get: tags: @@ -38,9 +38,9 @@ paths: schema: $ref: '#/components/schemas/HealthResponse' example: - service: Illum qui nihil. - status: Ut occaecati repellat. - version: Non amet. + service: Mollitia architecto rem beatae mollitia. + status: Id tempora aut. + version: Sed aut. /v1/credential: post: tags: @@ -70,9 +70,9 @@ paths: application/json: schema: type: string - example: Est quos possimus sed sit voluptates nihil. + example: Ab adipisci odio. format: binary - example: Aperiam odit illo natus. + example: Temporibus maxime ipsum laudantium voluptatibus ipsam. /v1/credential/proof: post: tags: @@ -107,9 +107,9 @@ paths: application/json: schema: type: string - example: Sit exercitationem et eligendi incidunt. + example: Aut nobis qui debitis enim. format: binary - example: Laudantium nulla quod ab adipisci odio. + example: Recusandae unde consequatur odit ut at iste. /v1/credential/verify: post: tags: @@ -126,68 +126,78 @@ paths: type: string description: Verifiable Credential in JSON format. example: - - 81 - - 117 + - 79 + - 99 + - 99 + - 97 + - 101 + - 99 + - 97 + - 116 - 105 - 32 + - 100 + - 111 + - 108 + - 111 - 114 - 101 + - 109 + - 113 + - 117 + - 101 + - 32 + - 97 + - 110 + - 105 + - 109 + - 105 + - 32 + - 113 + - 117 + - 105 + - 97 + - 32 + - 100 + - 101 + - 115 + - 101 - 114 - 117 + - 110 + - 116 + - 32 + - 113 + - 117 + - 105 + - 100 + - 101 - 109 + - 32 + - 101 + - 116 - 46 format: binary example: - - 79 - - 99 - - 99 - - 97 + - 86 - 101 - - 99 - - 97 - - 116 - - 105 - - 32 - - 100 - - 111 - - 108 - - 111 - 114 - - 101 - - 109 - - 113 - - 117 - - 101 - - 32 - - 97 - - 110 - - 105 - - 109 - - 105 + - 111 - 32 - 113 - 117 - 105 - - 97 - 32 - - 100 - - 101 - - 115 - - 101 - - 114 - 117 - - 110 - 116 - 32 - - 113 + - 100 - 117 + - 99 - 105 - - 100 - - 101 - 109 - - 32 - - 101 - - 116 + - 117 + - 115 - 46 responses: "200": @@ -214,17 +224,16 @@ paths: type: array items: type: string - example: Voluptas ut. + example: Ut error perspiciatis velit repudiandae voluptatem. description: List of available keys namespaces. example: - - Itaque eos dolorem doloremque quibusdam. - - Molestiae id vitae vel. - - Vel porro qui quidem unde. - - Quis voluptas. + - Ratione voluptatibus asperiores. + - Tempora et non aut inventore. example: - - Quae accusantium similique beatae nihil molestias. - - Neque voluptates dolores. - - Reiciendis aut nobis qui debitis enim quaerat. + - Qui consequatur et. + - Pariatur numquam porro facilis et. + - Ut ea reiciendis vel nihil. + - Doloremque ea saepe quidem dolores fugiat aliquam. /v1/namespaces/{namespace}/keys: get: tags: @@ -251,17 +260,15 @@ paths: type: array items: type: string - example: Qui consequatur eum nulla eaque. + example: Unde facilis ut similique molestias aperiam quia. description: Array of key names in a given namespace. example: - - Occaecati nam temporibus. - - Ex nihil. - - Ea qui mollitia sapiente error nostrum quae. + - Est asperiores velit eum perferendis. + - Rerum quaerat sit. + - Omnis est aspernatur voluptas in. example: - - Illum minus quasi sequi molestiae. - - Ducimus occaecati reprehenderit neque labore quia rem. - - Eum hic autem in. - - Magnam unde provident explicabo numquam culpa eum. + - Maxime dolor et sed fugit quo. + - Aut quisquam unde. /v1/presentation: post: tags: @@ -292,9 +299,9 @@ paths: application/json: schema: type: string - example: Suscipit expedita quos eligendi. + example: Tenetur ut consequuntur. format: binary - example: Tenetur ut consequuntur. + example: Eligendi nostrum eveniet et autem voluptas eos. /v1/presentation/proof: post: tags: @@ -309,10 +316,10 @@ paths: schema: $ref: '#/components/schemas/PresentationProofRequestBody' example: - issuer: Consequatur facilis eius. + issuer: Neque impedit. key: key1 namespace: transit - presentation: Dicta commodi possimus recusandae et. + presentation: Sunt vitae. responses: "200": description: OK response. @@ -320,9 +327,9 @@ paths: application/json: schema: type: string - example: Earum debitis. + example: Magnam unde provident explicabo numquam culpa eum. format: binary - example: Nam accusamus ea dolorem tenetur. + example: Numquam quaerat. /v1/presentation/verify: post: tags: @@ -339,109 +346,88 @@ paths: type: string description: Verifiable Presentation in JSON format. example: - - 80 - - 101 - - 114 - - 115 + - 86 + - 111 + - 108 + - 117 - 112 - - 105 - - 99 - - 105 + - 116 - 97 - 116 - 105 + - 98 + - 117 - 115 - 32 - - 118 - - 101 - - 108 - - 105 - - 116 - - 32 + - 99 + - 111 + - 114 - 114 - - 101 - - 112 - 117 - - 100 + - 112 + - 116 - 105 - - 97 - - 110 - - 100 - - 97 - - 101 - 32 - - 118 - - 111 - - 108 - - 117 + - 105 - 112 - - 116 + - 115 - 97 - - 116 - - 101 - 109 - 32 - 109 - - 111 - - 100 + - 97 - 105 - - 32 + - 111 - 114 - 101 - - 114 - - 117 - - 109 + - 115 - 32 - - 114 - - 97 - - 116 - - 105 - 111 + - 102 + - 102 + - 105 + - 99 + - 105 + - 105 + - 115 + - 32 + - 109 + - 97 + - 103 - 110 - - 101 + - 105 + - 32 + - 99 + - 117 + - 109 - 46 format: binary example: - - 77 - - 97 - - 120 - - 105 - - 109 - - 101 - - 32 - - 116 + - 78 - 111 - - 116 - - 97 - - 109 + - 110 - 32 - - 118 - - 111 - - 108 - - 117 - - 112 - - 116 - 97 + - 117 - 116 - - 105 - - 98 + - 32 + - 113 - 117 + - 105 - 115 + - 113 + - 117 + - 97 + - 109 - 32 - - 99 - - 111 - - 114 - - 114 + - 115 - 117 - - 112 + - 110 - 116 - - 105 - 32 + - 104 - 105 - - 112 - - 115 - - 97 - - 109 + - 99 - 46 responses: "200": @@ -452,6 +438,48 @@ paths: $ref: '#/components/schemas/VerifyResult' example: valid: false + /v1/sign: + post: + tags: + - signer + summary: Sign signer + description: Sign creates digital signature on base64 encoded binary data. + operationId: signer#Sign + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/SignRequestBody' + example: + data: Sapiente dolorem qui possimus qui labore veritatis. + key: Nihil iste debitis. + namespace: Occaecati repellat est non amet. + responses: + "200": + description: OK response. + content: + application/json: + schema: + $ref: '#/components/schemas/SignResult' + example: + signature: Fuga officia excepturi velit aut. + "404": + description: Not Found response. + content: + application/json: + schema: + $ref: '#/components/schemas/SignResult' + example: + signature: Natus quos ut corrupti. + "500": + description: Internal Server Error response. + content: + application/json: + schema: + $ref: '#/components/schemas/SignResult' + example: + signature: Et nulla illo totam optio quia ab. /v1/verification-methods/{namespace}/{did}: get: tags: @@ -491,24 +519,28 @@ paths: example: - controller: did:web:example.com id: key1 - publicKeyJwk: Omnis aut qui odit ut. + publicKeyJwk: Iure ex consequatur facilis. + type: JsonWebKey2020 + - controller: did:web:example.com + id: key1 + publicKeyJwk: Iure ex consequatur facilis. type: JsonWebKey2020 - controller: did:web:example.com id: key1 - publicKeyJwk: Omnis aut qui odit ut. + publicKeyJwk: Iure ex consequatur facilis. type: JsonWebKey2020 - controller: did:web:example.com id: key1 - publicKeyJwk: Omnis aut qui odit ut. + publicKeyJwk: Iure ex consequatur facilis. type: JsonWebKey2020 example: - controller: did:web:example.com id: key1 - publicKeyJwk: Omnis aut qui odit ut. + publicKeyJwk: Iure ex consequatur facilis. type: JsonWebKey2020 - controller: did:web:example.com id: key1 - publicKeyJwk: Omnis aut qui odit ut. + publicKeyJwk: Iure ex consequatur facilis. type: JsonWebKey2020 /v1/verification-methods/{namespace}/{key}/{did}: get: @@ -555,7 +587,7 @@ paths: example: controller: did:web:example.com id: key1 - publicKeyJwk: Quasi exercitationem provident illum nesciunt similique veniam. + publicKeyJwk: Qui ipsa aut non fuga iste. type: JsonWebKey2020 components: schemas: @@ -566,7 +598,7 @@ components: type: array items: type: string - example: Rerum veritatis delectus quis recusandae. + example: Sunt laudantium nulla. description: Additional JSONLD contexts to be specified in the VC. example: - https://w3id.org/security/suites/jws-2020/v1 @@ -610,7 +642,7 @@ components: type: array items: type: string - example: Sint laudantium rerum neque. + example: Aperiam odit illo natus. description: Additional JSONLD contexts to be specified in the VP. example: - https://w3id.org/security/suites/jws-2020/v1 @@ -619,7 +651,7 @@ components: type: array items: type: string - example: Ducimus eum facere enim accusantium. + example: Nam accusamus ea dolorem tenetur. format: binary description: Raw JSON to be included inside the VP as Verifiable Credential. example: @@ -710,7 +742,7 @@ components: publicKeyJwk: type: string description: Public Key encoded in JWK format. - example: Incidunt et repellat cum sit quibusdam. + example: Unde quae accusantium similique beatae nihil molestias. format: binary type: type: string @@ -720,7 +752,7 @@ components: example: controller: did:web:example.com id: key1 - publicKeyJwk: Dolores quis fugiat qui quia. + publicKeyJwk: Neque voluptates dolores. type: JsonWebKey2020 required: - id @@ -733,19 +765,19 @@ components: service: type: string description: Service name. - example: Asperiores rem tempora. + example: Voluptatibus aperiam eius velit. status: type: string description: Status message. - example: Non aut inventore necessitatibus unde. + example: Dolores libero. version: type: string description: Service runtime version. - example: Ut similique molestias aperiam quia et. + example: Tempora voluptatem error molestiae. example: - service: Est asperiores velit eum perferendis. - status: Rerum quaerat sit. - version: Omnis est aspernatur voluptas in. + service: Deleniti laudantium exercitationem tenetur iusto eos quidem. + status: Dolorum et consequatur sed in vero qui. + version: Ut et quasi eius error minima eaque. required: - service - status @@ -756,7 +788,7 @@ components: issuer: type: string description: Issuer DID used to specify proof verification info. - example: Molestiae eveniet vero est aliquam. + example: Consectetur aut illum. key: type: string description: Key to use for the proof signature. @@ -768,27 +800,61 @@ components: presentation: type: string description: Verifiable Presentation in JSON format. - example: Totam quam. + example: Quasi sequi molestiae assumenda ducimus occaecati reprehenderit. format: binary example: - issuer: Voluptates consectetur et repellat. + issuer: Labore quia rem. key: key1 namespace: transit - presentation: Repudiandae aut dolorum hic aut voluptatem soluta. + presentation: Eum hic autem in. required: - issuer - namespace - key - presentation + SignRequestBody: + type: object + properties: + data: + type: string + description: Data that must be signed, encoded as base64 string. + example: Sit ut non est fugiat et repellat. + key: + type: string + description: Key to be used for signing. + example: Porro iste. + namespace: + type: string + description: Key namespace to be used for signing. + example: Culpa quibusdam sunt nemo tempora dolores. + example: + data: Et voluptatem. + key: Minus et ut ullam quidem vitae qui. + namespace: Consequatur veritatis ab. + required: + - namespace + - key + - data + SignResult: + type: object + properties: + signature: + type: string + description: Signature encoded as base64 string. + example: Saepe itaque ratione. + example: + signature: Laborum delectus. + required: + - signature VerifyResult: type: object properties: valid: type: boolean description: Valid specifies if the proof is successfully verified. - example: false + example: true example: - valid: false + valid: true required: - valid tags: diff --git a/gen/http/signer/client/cli.go b/gen/http/signer/client/cli.go index 4c4b7ee2d2d2321b41b512f4acf6c442bf6fb4e0..d1873d38f68787e81f738f8e18f1f217d99ed4a7 100644 --- a/gen/http/signer/client/cli.go +++ b/gen/http/signer/client/cli.go @@ -103,7 +103,7 @@ func BuildPresentationProofPayload(signerPresentationProofBody string) (*signer. { err = json.Unmarshal([]byte(signerPresentationProofBody), &body) if err != nil { - return nil, fmt.Errorf("invalid JSON for body, \nerror: %s, \nexample of valid JSON:\n%s", err, "'{\n \"issuer\": \"Consequatur facilis eius.\",\n \"key\": \"key1\",\n \"namespace\": \"transit\",\n \"presentation\": \"Dicta commodi possimus recusandae et.\"\n }'") + return nil, fmt.Errorf("invalid JSON for body, \nerror: %s, \nexample of valid JSON:\n%s", err, "'{\n \"issuer\": \"Neque impedit.\",\n \"key\": \"key1\",\n \"namespace\": \"transit\",\n \"presentation\": \"Sunt vitae.\"\n }'") } if body.Presentation == nil { err = goa.MergeErrors(err, goa.MissingFieldError("presentation", "body")) @@ -224,3 +224,23 @@ func BuildVerifyPresentationPayload(signerVerifyPresentationBody string) (*signe return res, nil } + +// BuildSignPayload builds the payload for the signer Sign endpoint from CLI +// flags. +func BuildSignPayload(signerSignBody string) (*signer.SignRequest, error) { + var err error + var body SignRequestBody + { + err = json.Unmarshal([]byte(signerSignBody), &body) + if err != nil { + return nil, fmt.Errorf("invalid JSON for body, \nerror: %s, \nexample of valid JSON:\n%s", err, "'{\n \"data\": \"Sapiente dolorem qui possimus qui labore veritatis.\",\n \"key\": \"Nihil iste debitis.\",\n \"namespace\": \"Occaecati repellat est non amet.\"\n }'") + } + } + v := &signer.SignRequest{ + Namespace: body.Namespace, + Key: body.Key, + Data: body.Data, + } + + return v, nil +} diff --git a/gen/http/signer/client/client.go b/gen/http/signer/client/client.go index b41e17ac4eb3cb76ab44968796cc4f0649b14dfe..a260a4f75f84dc0454e6d8a9e7b6b34ff1079536 100644 --- a/gen/http/signer/client/client.go +++ b/gen/http/signer/client/client.go @@ -57,6 +57,9 @@ type Client struct { // VerifyPresentation endpoint. VerifyPresentationDoer goahttp.Doer + // Sign Doer is the HTTP client used to make requests to the Sign endpoint. + SignDoer goahttp.Doer + // RestoreResponseBody controls whether the response bodies are reset after // decoding so they can be read again. RestoreResponseBody bool @@ -87,6 +90,7 @@ func NewClient( CreatePresentationDoer: doer, VerifyCredentialDoer: doer, VerifyPresentationDoer: doer, + SignDoer: doer, RestoreResponseBody: restoreBody, scheme: scheme, host: host, @@ -314,3 +318,27 @@ func (c *Client) VerifyPresentation() goa.Endpoint { return decodeResponse(resp) } } + +// Sign returns an endpoint that makes HTTP requests to the signer service Sign +// server. +func (c *Client) Sign() goa.Endpoint { + var ( + encodeRequest = EncodeSignRequest(c.encoder) + decodeResponse = DecodeSignResponse(c.decoder, c.RestoreResponseBody) + ) + return func(ctx context.Context, v any) (any, error) { + req, err := c.BuildSignRequest(ctx, v) + if err != nil { + return nil, err + } + err = encodeRequest(req, v) + if err != nil { + return nil, err + } + resp, err := c.SignDoer.Do(req) + if err != nil { + return nil, goahttp.ErrRequestError("signer", "Sign", err) + } + return decodeResponse(resp) + } +} diff --git a/gen/http/signer/client/encode_decode.go b/gen/http/signer/client/encode_decode.go index 188c8ddd8c33e11c32d5c32f6934d2688a737ba8..e7dd0d4d9e24fea7951872c3ff64b08a74772a70 100644 --- a/gen/http/signer/client/encode_decode.go +++ b/gen/http/signer/client/encode_decode.go @@ -681,6 +681,77 @@ func DecodeVerifyPresentationResponse(decoder func(*http.Response) goahttp.Decod } } +// BuildSignRequest instantiates a HTTP request object with method and path set +// to call the "signer" service "Sign" endpoint +func (c *Client) BuildSignRequest(ctx context.Context, v any) (*http.Request, error) { + u := &url.URL{Scheme: c.scheme, Host: c.host, Path: SignSignerPath()} + req, err := http.NewRequest("POST", u.String(), nil) + if err != nil { + return nil, goahttp.ErrInvalidURL("signer", "Sign", u.String(), err) + } + if ctx != nil { + req = req.WithContext(ctx) + } + + return req, nil +} + +// EncodeSignRequest returns an encoder for requests sent to the signer Sign +// server. +func EncodeSignRequest(encoder func(*http.Request) goahttp.Encoder) func(*http.Request, any) error { + return func(req *http.Request, v any) error { + p, ok := v.(*signer.SignRequest) + if !ok { + return goahttp.ErrInvalidType("signer", "Sign", "*signer.SignRequest", v) + } + body := NewSignRequestBody(p) + if err := encoder(req).Encode(&body); err != nil { + return goahttp.ErrEncodingError("signer", "Sign", err) + } + return nil + } +} + +// DecodeSignResponse returns a decoder for responses returned by the signer +// Sign endpoint. restoreBody controls whether the response body should be +// restored after having been read. +func DecodeSignResponse(decoder func(*http.Response) goahttp.Decoder, restoreBody bool) func(*http.Response) (any, error) { + return func(resp *http.Response) (any, error) { + if restoreBody { + b, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + resp.Body = io.NopCloser(bytes.NewBuffer(b)) + defer func() { + resp.Body = io.NopCloser(bytes.NewBuffer(b)) + }() + } else { + defer resp.Body.Close() + } + switch resp.StatusCode { + case http.StatusOK: + var ( + body SignOKResponseBody + err error + ) + err = decoder(resp).Decode(&body) + if err != nil { + return nil, goahttp.ErrDecodingError("signer", "Sign", err) + } + err = ValidateSignOKResponseBody(&body) + if err != nil { + return nil, goahttp.ErrValidationError("signer", "Sign", err) + } + res := NewSignResultOK(&body) + return res, nil + default: + body, _ := io.ReadAll(resp.Body) + return nil, goahttp.ErrInvalidResponse("signer", "Sign", resp.StatusCode, string(body)) + } + } +} + // unmarshalDIDVerificationMethodResponseToSignerDIDVerificationMethod builds a // value of type *signer.DIDVerificationMethod from a value of type // *DIDVerificationMethodResponse. diff --git a/gen/http/signer/client/paths.go b/gen/http/signer/client/paths.go index 263b332f23837fba291bfcce58cc4cfee9343d97..7cf84029dfeacbad7a6175e67fa8891cde115f13 100644 --- a/gen/http/signer/client/paths.go +++ b/gen/http/signer/client/paths.go @@ -60,3 +60,8 @@ func VerifyCredentialSignerPath() string { func VerifyPresentationSignerPath() string { return "/v1/presentation/verify" } + +// SignSignerPath returns the URL path to the signer service Sign HTTP endpoint. +func SignSignerPath() string { + return "/v1/sign" +} diff --git a/gen/http/signer/client/types.go b/gen/http/signer/client/types.go index 91ed9fc4181c7be5ecd26d11d1bc922df54c1f8d..3e9c611bec80192dcefc399fa59868fee32ef143 100644 --- a/gen/http/signer/client/types.go +++ b/gen/http/signer/client/types.go @@ -66,6 +66,17 @@ type CreatePresentationRequestBody struct { Context []string `form:"context,omitempty" json:"context,omitempty" xml:"context,omitempty"` } +// SignRequestBody is the type of the "signer" service "Sign" endpoint HTTP +// request body. +type SignRequestBody struct { + // Key namespace to be used for signing. + Namespace string `form:"namespace" json:"namespace" xml:"namespace"` + // Key to be used for signing. + Key string `form:"key" json:"key" xml:"key"` + // Data that must be signed, encoded as base64 string. + Data string `form:"data" json:"data" xml:"data"` +} + // VerificationMethodResponseBody is the type of the "signer" service // "VerificationMethod" endpoint HTTP response body. type VerificationMethodResponseBody struct { @@ -97,6 +108,13 @@ type VerifyPresentationResponseBody struct { Valid *bool `form:"valid,omitempty" json:"valid,omitempty" xml:"valid,omitempty"` } +// SignOKResponseBody is the type of the "signer" service "Sign" endpoint HTTP +// response body. +type SignOKResponseBody struct { + // Signature encoded as base64 string. + Signature *string `form:"signature,omitempty" json:"signature,omitempty" xml:"signature,omitempty"` +} + // DIDVerificationMethodResponse is used to define fields on response body // types. type DIDVerificationMethodResponse struct { @@ -110,6 +128,19 @@ type DIDVerificationMethodResponse struct { PublicKeyJwk any `form:"publicKeyJwk,omitempty" json:"publicKeyJwk,omitempty" xml:"publicKeyJwk,omitempty"` } +// SignNotFoundResponseBody is used to define fields on response body types. +type SignNotFoundResponseBody struct { + // Signature encoded as base64 string. + Signature *string `form:"signature,omitempty" json:"signature,omitempty" xml:"signature,omitempty"` +} + +// SignInternalServerErrorResponseBody is used to define fields on response +// body types. +type SignInternalServerErrorResponseBody struct { + // Signature encoded as base64 string. + Signature *string `form:"signature,omitempty" json:"signature,omitempty" xml:"signature,omitempty"` +} + // NewCredentialProofRequestBody builds the HTTP request body from the payload // of the "CredentialProof" endpoint of the "signer" service. func NewCredentialProofRequestBody(p *signer.CredentialProofRequest) *CredentialProofRequestBody { @@ -176,6 +207,17 @@ func NewCreatePresentationRequestBody(p *signer.CreatePresentationRequest) *Crea return body } +// NewSignRequestBody builds the HTTP request body from the payload of the +// "Sign" endpoint of the "signer" service. +func NewSignRequestBody(p *signer.SignRequest) *SignRequestBody { + body := &SignRequestBody{ + Namespace: p.Namespace, + Key: p.Key, + Data: p.Data, + } + return body +} + // NewVerificationMethodDIDVerificationMethodOK builds a "signer" service // "VerificationMethod" endpoint result from a HTTP "OK" response. func NewVerificationMethodDIDVerificationMethodOK(body *VerificationMethodResponseBody) *signer.DIDVerificationMethod { @@ -220,6 +262,16 @@ func NewVerifyPresentationVerifyResultOK(body *VerifyPresentationResponseBody) * return v } +// NewSignResultOK builds a "signer" service "Sign" endpoint result from a HTTP +// "OK" response. +func NewSignResultOK(body *SignOKResponseBody) *signer.SignResult { + v := &signer.SignResult{ + Signature: *body.Signature, + } + + return v +} + // ValidateVerificationMethodResponseBody runs the validations defined on // VerificationMethodResponseBody func ValidateVerificationMethodResponseBody(body *VerificationMethodResponseBody) (err error) { @@ -256,6 +308,14 @@ func ValidateVerifyPresentationResponseBody(body *VerifyPresentationResponseBody return } +// ValidateSignOKResponseBody runs the validations defined on SignOKResponseBody +func ValidateSignOKResponseBody(body *SignOKResponseBody) (err error) { + if body.Signature == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("signature", "body")) + } + return +} + // ValidateDIDVerificationMethodResponse runs the validations defined on // DIDVerificationMethodResponse func ValidateDIDVerificationMethodResponse(body *DIDVerificationMethodResponse) (err error) { @@ -273,3 +333,21 @@ func ValidateDIDVerificationMethodResponse(body *DIDVerificationMethodResponse) } return } + +// ValidateSignNotFoundResponseBody runs the validations defined on SignNot +// FoundResponseBody +func ValidateSignNotFoundResponseBody(body *SignNotFoundResponseBody) (err error) { + if body.Signature == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("signature", "body")) + } + return +} + +// ValidateSignInternalServerErrorResponseBody runs the validations defined on +// SignInternal Server ErrorResponseBody +func ValidateSignInternalServerErrorResponseBody(body *SignInternalServerErrorResponseBody) (err error) { + if body.Signature == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("signature", "body")) + } + return +} diff --git a/gen/http/signer/server/encode_decode.go b/gen/http/signer/server/encode_decode.go index 41247ad56526214eeee77323b1c9f61039c99ba9..0e88f0ec4ac0538ccf7d12ef846af7d123449658 100644 --- a/gen/http/signer/server/encode_decode.go +++ b/gen/http/signer/server/encode_decode.go @@ -333,6 +333,43 @@ func DecodeVerifyPresentationRequest(mux goahttp.Muxer, decoder func(*http.Reque } } +// EncodeSignResponse returns an encoder for responses returned by the signer +// Sign endpoint. +func EncodeSignResponse(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder) func(context.Context, http.ResponseWriter, any) error { + return func(ctx context.Context, w http.ResponseWriter, v any) error { + res, _ := v.(*signer.SignResult) + enc := encoder(ctx, w) + body := NewSignOKResponseBody(res) + w.WriteHeader(http.StatusOK) + return enc.Encode(body) + } +} + +// DecodeSignRequest returns a decoder for requests sent to the signer Sign +// endpoint. +func DecodeSignRequest(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Decoder) func(*http.Request) (any, error) { + return func(r *http.Request) (any, error) { + var ( + body SignRequestBody + err error + ) + err = decoder(r).Decode(&body) + if err != nil { + if err == io.EOF { + return nil, goa.MissingPayloadError() + } + return nil, goa.DecodePayloadError(err.Error()) + } + err = ValidateSignRequestBody(&body) + if err != nil { + return nil, err + } + payload := NewSignRequest(&body) + + return payload, nil + } +} + // marshalSignerDIDVerificationMethodToDIDVerificationMethodResponse builds a // value of type *DIDVerificationMethodResponse from a value of type // *signer.DIDVerificationMethod. diff --git a/gen/http/signer/server/paths.go b/gen/http/signer/server/paths.go index 0550ca336568d194acdddebdaecd2d845af8d24a..855184e120bde7a0d2d090738f5430d2fa161af5 100644 --- a/gen/http/signer/server/paths.go +++ b/gen/http/signer/server/paths.go @@ -60,3 +60,8 @@ func VerifyCredentialSignerPath() string { func VerifyPresentationSignerPath() string { return "/v1/presentation/verify" } + +// SignSignerPath returns the URL path to the signer service Sign HTTP endpoint. +func SignSignerPath() string { + return "/v1/sign" +} diff --git a/gen/http/signer/server/server.go b/gen/http/signer/server/server.go index 9c298560146dac49e90c66948906ae61e55e93bb..dd1afe1f6ef13ab767e6d744aa1ac76958071a63 100644 --- a/gen/http/signer/server/server.go +++ b/gen/http/signer/server/server.go @@ -29,6 +29,7 @@ type Server struct { CreatePresentation http.Handler VerifyCredential http.Handler VerifyPresentation http.Handler + Sign http.Handler } // MountPoint holds information about the mounted endpoints. @@ -68,6 +69,7 @@ func New( {"CreatePresentation", "POST", "/v1/presentation"}, {"VerifyCredential", "POST", "/v1/credential/verify"}, {"VerifyPresentation", "POST", "/v1/presentation/verify"}, + {"Sign", "POST", "/v1/sign"}, }, Namespaces: NewNamespacesHandler(e.Namespaces, mux, decoder, encoder, errhandler, formatter), NamespaceKeys: NewNamespaceKeysHandler(e.NamespaceKeys, mux, decoder, encoder, errhandler, formatter), @@ -79,6 +81,7 @@ func New( CreatePresentation: NewCreatePresentationHandler(e.CreatePresentation, mux, decoder, encoder, errhandler, formatter), VerifyCredential: NewVerifyCredentialHandler(e.VerifyCredential, mux, decoder, encoder, errhandler, formatter), VerifyPresentation: NewVerifyPresentationHandler(e.VerifyPresentation, mux, decoder, encoder, errhandler, formatter), + Sign: NewSignHandler(e.Sign, mux, decoder, encoder, errhandler, formatter), } } @@ -97,6 +100,7 @@ func (s *Server) Use(m func(http.Handler) http.Handler) { s.CreatePresentation = m(s.CreatePresentation) s.VerifyCredential = m(s.VerifyCredential) s.VerifyPresentation = m(s.VerifyPresentation) + s.Sign = m(s.Sign) } // MethodNames returns the methods served. @@ -114,6 +118,7 @@ func Mount(mux goahttp.Muxer, h *Server) { MountCreatePresentationHandler(mux, h.CreatePresentation) MountVerifyCredentialHandler(mux, h.VerifyCredential) MountVerifyPresentationHandler(mux, h.VerifyPresentation) + MountSignHandler(mux, h.Sign) } // Mount configures the mux to serve the signer endpoints. @@ -623,3 +628,54 @@ func NewVerifyPresentationHandler( } }) } + +// MountSignHandler configures the mux to serve the "signer" service "Sign" +// endpoint. +func MountSignHandler(mux goahttp.Muxer, h http.Handler) { + f, ok := h.(http.HandlerFunc) + if !ok { + f = func(w http.ResponseWriter, r *http.Request) { + h.ServeHTTP(w, r) + } + } + mux.Handle("POST", "/v1/sign", f) +} + +// NewSignHandler creates a HTTP handler which loads the HTTP request and calls +// the "signer" service "Sign" endpoint. +func NewSignHandler( + endpoint goa.Endpoint, + mux goahttp.Muxer, + decoder func(*http.Request) goahttp.Decoder, + encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, + errhandler func(context.Context, http.ResponseWriter, error), + formatter func(ctx context.Context, err error) goahttp.Statuser, +) http.Handler { + var ( + decodeRequest = DecodeSignRequest(mux, decoder) + encodeResponse = EncodeSignResponse(encoder) + encodeError = goahttp.ErrorEncoder(encoder, formatter) + ) + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ctx := context.WithValue(r.Context(), goahttp.AcceptTypeKey, r.Header.Get("Accept")) + ctx = context.WithValue(ctx, goa.MethodKey, "Sign") + ctx = context.WithValue(ctx, goa.ServiceKey, "signer") + payload, err := decodeRequest(r) + if err != nil { + if err := encodeError(ctx, w, err); err != nil { + errhandler(ctx, w, err) + } + return + } + res, err := endpoint(ctx, payload) + if err != nil { + if err := encodeError(ctx, w, err); err != nil { + errhandler(ctx, w, err) + } + return + } + if err := encodeResponse(ctx, w, res); err != nil { + errhandler(ctx, w, err) + } + }) +} diff --git a/gen/http/signer/server/types.go b/gen/http/signer/server/types.go index 667b8073111024201cb115d5a9aaa3d5cd8fd0bf..0e4ae67c6f56c8cb332289dddbd07abb10cc807e 100644 --- a/gen/http/signer/server/types.go +++ b/gen/http/signer/server/types.go @@ -66,6 +66,17 @@ type CreatePresentationRequestBody struct { Context []string `form:"context,omitempty" json:"context,omitempty" xml:"context,omitempty"` } +// SignRequestBody is the type of the "signer" service "Sign" endpoint HTTP +// request body. +type SignRequestBody struct { + // Key namespace to be used for signing. + Namespace *string `form:"namespace,omitempty" json:"namespace,omitempty" xml:"namespace,omitempty"` + // Key to be used for signing. + Key *string `form:"key,omitempty" json:"key,omitempty" xml:"key,omitempty"` + // Data that must be signed, encoded as base64 string. + Data *string `form:"data,omitempty" json:"data,omitempty" xml:"data,omitempty"` +} + // VerificationMethodResponseBody is the type of the "signer" service // "VerificationMethod" endpoint HTTP response body. type VerificationMethodResponseBody struct { @@ -97,6 +108,13 @@ type VerifyPresentationResponseBody struct { Valid bool `form:"valid" json:"valid" xml:"valid"` } +// SignOKResponseBody is the type of the "signer" service "Sign" endpoint HTTP +// response body. +type SignOKResponseBody struct { + // Signature encoded as base64 string. + Signature string `form:"signature" json:"signature" xml:"signature"` +} + // DIDVerificationMethodResponse is used to define fields on response body // types. type DIDVerificationMethodResponse struct { @@ -150,6 +168,15 @@ func NewVerifyPresentationResponseBody(res *signer.VerifyResult) *VerifyPresenta return body } +// NewSignOKResponseBody builds the HTTP response body from the result of the +// "Sign" endpoint of the "signer" service. +func NewSignOKResponseBody(res *signer.SignResult) *SignOKResponseBody { + body := &SignOKResponseBody{ + Signature: res.Signature, + } + return body +} + // NewNamespaceKeysRequest builds a signer service NamespaceKeys endpoint // payload. func NewNamespaceKeysRequest(namespace string) *signer.NamespaceKeysRequest { @@ -268,6 +295,17 @@ func NewVerifyPresentationRequest(body []byte) *signer.VerifyPresentationRequest return res } +// NewSignRequest builds a signer service Sign endpoint payload. +func NewSignRequest(body *SignRequestBody) *signer.SignRequest { + v := &signer.SignRequest{ + Namespace: *body.Namespace, + Key: *body.Key, + Data: *body.Data, + } + + return v +} + // ValidateCredentialProofRequestBody runs the validations defined on // CredentialProofRequestBody func ValidateCredentialProofRequestBody(body *CredentialProofRequestBody) (err error) { @@ -336,3 +374,17 @@ func ValidateCreatePresentationRequestBody(body *CreatePresentationRequestBody) } return } + +// ValidateSignRequestBody runs the validations defined on SignRequestBody +func ValidateSignRequestBody(body *SignRequestBody) (err error) { + if body.Namespace == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("namespace", "body")) + } + if body.Key == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("key", "body")) + } + if body.Data == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("data", "body")) + } + return +} diff --git a/gen/signer/client.go b/gen/signer/client.go index 55a746d5c34cf05cb5ae517432a08949e14e1b97..2004a51e239cafc38c6bb4d3acbd00bdec27d3dd 100644 --- a/gen/signer/client.go +++ b/gen/signer/client.go @@ -25,10 +25,11 @@ type Client struct { CreatePresentationEndpoint goa.Endpoint VerifyCredentialEndpoint goa.Endpoint VerifyPresentationEndpoint goa.Endpoint + SignEndpoint goa.Endpoint } // NewClient initializes a "signer" service client given the endpoints. -func NewClient(namespaces, namespaceKeys, verificationMethod, verificationMethods, credentialProof, presentationProof, createCredential, createPresentation, verifyCredential, verifyPresentation goa.Endpoint) *Client { +func NewClient(namespaces, namespaceKeys, verificationMethod, verificationMethods, credentialProof, presentationProof, createCredential, createPresentation, verifyCredential, verifyPresentation, sign goa.Endpoint) *Client { return &Client{ NamespacesEndpoint: namespaces, NamespaceKeysEndpoint: namespaceKeys, @@ -40,6 +41,7 @@ func NewClient(namespaces, namespaceKeys, verificationMethod, verificationMethod CreatePresentationEndpoint: createPresentation, VerifyCredentialEndpoint: verifyCredential, VerifyPresentationEndpoint: verifyPresentation, + SignEndpoint: sign, } } @@ -149,3 +151,13 @@ func (c *Client) VerifyPresentation(ctx context.Context, p *VerifyPresentationRe } return ires.(*VerifyResult), nil } + +// Sign calls the "Sign" endpoint of the "signer" service. +func (c *Client) Sign(ctx context.Context, p *SignRequest) (res *SignResult, err error) { + var ires any + ires, err = c.SignEndpoint(ctx, p) + if err != nil { + return + } + return ires.(*SignResult), nil +} diff --git a/gen/signer/endpoints.go b/gen/signer/endpoints.go index dfcf024952a80cd61b95b2ffa6e4511d83c24022..1dd95410e1a1ad429dc54664beab122abd45c274 100644 --- a/gen/signer/endpoints.go +++ b/gen/signer/endpoints.go @@ -25,6 +25,7 @@ type Endpoints struct { CreatePresentation goa.Endpoint VerifyCredential goa.Endpoint VerifyPresentation goa.Endpoint + Sign goa.Endpoint } // NewEndpoints wraps the methods of the "signer" service with endpoints. @@ -40,6 +41,7 @@ func NewEndpoints(s Service) *Endpoints { CreatePresentation: NewCreatePresentationEndpoint(s), VerifyCredential: NewVerifyCredentialEndpoint(s), VerifyPresentation: NewVerifyPresentationEndpoint(s), + Sign: NewSignEndpoint(s), } } @@ -55,6 +57,7 @@ func (e *Endpoints) Use(m func(goa.Endpoint) goa.Endpoint) { e.CreatePresentation = m(e.CreatePresentation) e.VerifyCredential = m(e.VerifyCredential) e.VerifyPresentation = m(e.VerifyPresentation) + e.Sign = m(e.Sign) } // NewNamespacesEndpoint returns an endpoint function that calls the method @@ -145,3 +148,12 @@ func NewVerifyPresentationEndpoint(s Service) goa.Endpoint { return s.VerifyPresentation(ctx, p) } } + +// NewSignEndpoint returns an endpoint function that calls the method "Sign" of +// service "signer". +func NewSignEndpoint(s Service) goa.Endpoint { + return func(ctx context.Context, req any) (any, error) { + p := req.(*SignRequest) + return s.Sign(ctx, p) + } +} diff --git a/gen/signer/service.go b/gen/signer/service.go index a961b722f1429bad633023af6058883ce08120db..b24ca8e8eef808240d6a04ffa6c1b65ced53eb4c 100644 --- a/gen/signer/service.go +++ b/gen/signer/service.go @@ -38,6 +38,8 @@ type Service interface { VerifyCredential(context.Context, *VerifyCredentialRequest) (res *VerifyResult, err error) // VerifyPresentation verifies the proof of a Verifiable Presentation. VerifyPresentation(context.Context, *VerifyPresentationRequest) (res *VerifyResult, err error) + // Sign creates digital signature on base64 encoded binary data. + Sign(context.Context, *SignRequest) (res *SignResult, err error) } // ServiceName is the name of the service as defined in the design. This is the @@ -48,7 +50,7 @@ const ServiceName = "signer" // MethodNames lists the service method names as defined in the design. These // are the same values that are set in the endpoint request contexts under the // MethodKey key. -var MethodNames = [10]string{"Namespaces", "NamespaceKeys", "VerificationMethod", "VerificationMethods", "CredentialProof", "PresentationProof", "CreateCredential", "CreatePresentation", "VerifyCredential", "VerifyPresentation"} +var MethodNames = [11]string{"Namespaces", "NamespaceKeys", "VerificationMethod", "VerificationMethods", "CredentialProof", "PresentationProof", "CreateCredential", "CreatePresentation", "VerifyCredential", "VerifyPresentation", "Sign"} // CreateCredentialRequest is the payload type of the signer service // CreateCredential method. @@ -123,6 +125,22 @@ type PresentationProofRequest struct { Presentation any } +// SignRequest is the payload type of the signer service Sign method. +type SignRequest struct { + // Key namespace to be used for signing. + Namespace string + // Key to be used for signing. + Key string + // Data that must be signed, encoded as base64 string. + Data string +} + +// SignResult is the result type of the signer service Sign method. +type SignResult struct { + // Signature encoded as base64 string. + Signature string +} + // VerificationMethodRequest is the payload type of the signer service // VerificationMethod method. type VerificationMethodRequest struct { diff --git a/internal/service/signer/service.go b/internal/service/signer/service.go index bd9789da950bb53d8710651a57ebe0af3895ce51..685ecd112e4d870f4f58e8601753780d316307c4 100644 --- a/internal/service/signer/service.go +++ b/internal/service/signer/service.go @@ -4,6 +4,7 @@ import ( "context" "crypto/ed25519" "crypto/x509" + "encoding/base64" "encoding/json" "encoding/pem" "fmt" @@ -523,6 +524,31 @@ func (s *Service) VerifyPresentation(_ context.Context, req *signer.VerifyPresen return &signer.VerifyResult{Valid: true}, nil } +// Sign creates digital signature on base64 encoded binary data. +func (s *Service) Sign(_ context.Context, req *signer.SignRequest) (res *signer.SignResult, err error) { + logger := s.logger.With( + zap.String("operation", "sign"), + zap.String("namespace", req.Namespace), + zap.String("key", req.Key), + ) + + data, err := base64.StdEncoding.DecodeString(req.Data) + if err != nil { + logger.Error("cannot base64 decode data", zap.Error(err)) + return nil, errors.New(errors.BadRequest, "cannot base64 decode data", err) + } + + signature, err := s.vault.WithKey(req.Namespace, req.Key).Sign(data) + if err != nil { + logger.Error("error signing data", zap.Error(err)) + return nil, errors.New(err) + } + + encodedSignature := base64.StdEncoding.EncodeToString(signature) + + return &signer.SignResult{Signature: encodedSignature}, nil +} + func (s *Service) supportedKey(keyType string) bool { for _, kt := range s.supportedKeys { if kt == keyType { diff --git a/internal/service/signer/service_test.go b/internal/service/signer/service_test.go index 6bcbd42f2da3108ae9a2178049c43430ecdb16a6..70c919ad404ace0ed2545cf1811e80539e1aae7a 100644 --- a/internal/service/signer/service_test.go +++ b/internal/service/signer/service_test.go @@ -818,6 +818,75 @@ func TestService_CreateCredential(t *testing.T) { } } +func TestService_Sign(t *testing.T) { + tests := []struct { + name string + // input + signer signer.Vault + data string + // output + signature string + errkind errors.Kind + errtext string + }{ + { + name: "invalid encoding of data", + data: "not base64 encoded string", + errtext: "cannot base64 decode data", + errkind: errors.BadRequest, + }, + { + name: "signing key not found", + data: base64.StdEncoding.EncodeToString([]byte("something")), + signer: &signerfakes.FakeVault{ + WithKeyStub: func(namespace string, key string) signer.Vault { + return &signerfakes.FakeVault{SignStub: func(data []byte) ([]byte, error) { + return nil, errors.New(errors.NotFound, "key not found") + }} + }, + }, + errtext: "key not found", + errkind: errors.NotFound, + }, + { + name: "successful signing", + data: base64.StdEncoding.EncodeToString([]byte("something")), + signer: &signerfakes.FakeVault{ + WithKeyStub: func(namespace string, key string) signer.Vault { + return &signerfakes.FakeVault{SignStub: func(data []byte) ([]byte, error) { + return []byte("signature"), nil + }} + }, + }, + signature: base64.StdEncoding.EncodeToString([]byte("signature")), + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + svc := signer.New(test.signer, nil, nil, zap.NewNop()) + result, err := svc.Sign(context.Background(), &goasigner.SignRequest{ + Namespace: "transit", + Key: "key1", + Data: test.data, + }) + if err != nil { + require.NotEmpty(t, test.errtext, "expected no error but got %s", err) + require.Nil(t, result) + assert.ErrorContains(t, err, test.errtext) + e, ok := err.(*errors.Error) + require.True(t, ok) + assert.Equal(t, test.errkind, e.Kind) + return + } + + require.Empty(t, test.errtext, "got no error, but expected: %s", test.errtext) + require.NotNil(t, result) + assert.Equal(t, test.signature, result.Signature) + }) + } +} + // ---------- Verifiable Credentials ---------- // //nolint:gosec