ssi
. Rebase is intended for a wide variety of uses ranging from server-side "witness" services, to VC reading validation services, to in-browser usage via WASM.rust/rebase/src
. The high-level goal of this implementation is to receive data from the end-user, create a statement for the user to sign, ask for the signature from the user (in addition to some other information in some cases), and presuming the statement and the signature match, issue a credential. Some flows are simpler than others, but all follow this basic format.SignerType
, which defines what cryptographic signature could be read in a claim and how it could be verified. A layer above that is the Signer<T: SignerType>
which is a struct capable of signing both plain text (in the case of a client) and a VC (in the case of an issuer).SchemaType
which is a trait that takes a simple struct, something like:SignerType
provides one portion of the VC's construction, and the SchemaType
provides the rest, and that the Signer<T: SignerType>
provides the signature to a given SchemaType
, all of these pieces can be mixed and matched. If a new SchemaType
is implemented, it works with all existing Signer
/SignerType
s. If a new Signer
is implemented, it works with all existing SchemaType
s.SignerType
that should be used to sign the statement.SignerType
described in the statement. In the case of linking two keys, this would just be the two SignerTypes
and two signatures.Statement
trait in src/witness/witness
, then when a user supplies such a struct, they are given back a statement to sign and a delimiter (if applicable) to place between the statement and the signature.format!("{}{}{}", statement, delimiter, signature)
(DNS is an exception to this rule, using a prefix
and format!("{}{}{}", prefix, delimiter, signature)
). Once they have posted the statement (if necessary), they then have to provide enough information to create a struct that implements Proof
. Proof
must implement Statement
to allow the witness to make sure that the statement found is the same as expected. Often, the same struct implements Proof
and SchemaType
.Generator
trait. This trait requires the user to implement a pair of functions:Generator
to receive a valid Proof
and return a Schema
, a Credential
, or a JWT String
depending on what is requested. The derived schema
function only allows the creation of credentials if they pass the parsing stage.DNS
, the Generator
is an empty struct, in the case of Twitter
, the Generator
has an api_key
field. Any required information for the post retrieval process can be specified in a struct, then that struct made to implement Generator
.src/witness
, specifically ProofTypes
, StatementTypes
and SignerTypes
, these are two enums that encompass all supported Proof
s and SignerType
s, then implement Proof
and SignerType
on the enum by calling their inner, concrete representation.src/signer/signer
there is a DID
enum which captures all the supported SignerType
s in a generic struct. To implement SignerType
, it's required to have the following function implemented:SignerType
s in src/signer/signer
but not have circular dependencies, and also allows for easy conversion back and forth between DID
and SignerType
.src/witness/generator
. Given a supported Proof
(i.e. those listed in ProofTypes
) and a supported SignerType
(i.e. those listed in SignerTypes
), the generator can validate a claim and produce a VC.StatementTypes
and SignerTypes
. Thus, the calling application doesn't even have to be aware of all the possible claims it can validate -- seen in the example worker.