Digital Signatures

The Designated Verifier Signature (DVS) scheme allows a client entity to sign a message/document which can be verified only by the designated verifier. The method you use for signature generation on the end user’s side depends on the type of integration you have:

Integration Library Documentation Signing Method
Web application Client JS Library Client JS Library
Mobile application Android/iOS Mobile SDKs
OIDC integration DVS Web Plugin DVS Web Plugin

For information about signing generation, see the corresponding documentation for each signing method.

You can read more about DVS in the concepts section.

# What Can Be Signed

In this article, we use the term ‘document’ to represent the data that is cryptographically signed. This, however, does not mean there are restrictions on the type of data you want to sign. DVS can be used on any blob of data as the signature is produced for the hash digest of the data rather than the raw value itself. On top of what is traditionally considered a document, you can also sign any type of transaction, like a transfer of financial funds or a representation of a write operation to be stored in an audit log.

It is important to note that the usage of a hash digest instead of the raw data also means that the actual value of what is being signed is never transmitted to the MIRACL Trust platform. This holds true for all parts of the process - both signing and verification.

# Verify Signature

Signature verification is done by making a request to the /dvs/verify endpoint of the MIRACL Trust platform from your back end. If the verification is successful, you will receive a certificate in the form of a signed JWT (JSON Web Token) in the response. The request’s payload must contain the signature object produced from the client library, the timestamp of the signing (must be the same timestamp passed to the sign method of the client library) and a type parameter set to verification.

# Verification Request Example

curl \
  --user "${YOUR_CLIENT_ID}:${YOUR_CLIENT_SECRET}" \
  --data '{
    "signature": {
      "dtas": "WyIyNWUwYzMxY2ZlYjk5NGNjYWY3ZWE4OGQxYjBiNmQwMDMyM2MxNDI5ZWVjMzEzNzFiZTVmNTM3NjhiMjcxNjBkIiwiMjVlMGMzMWNmZWI5OTRjY2FmN2VhODhkMWIwYjZkMDAzMjNjMTQyOWVlYzMxMzcxYmU1ZjUzNzY4YjI3MTYwZCJd",
      "hash": "74657374",
      "mpinId": "7b22696174223a313631343736333336322c22757365724944223a2274657374406578616d706c652e636f6d222c22634944223a2238366364336536342d663634312d343136612d626638302d363462396237656566386561222c2273616c74223a2263483141545930367879754555574d667551466a4351222c2276223a352c2273636f7065223a5b22647673225d2c22647461223a5b5d2c227674223a22647673227d",
      "publicKey": "16ef9515c8c35a3b11dc04f256c721a57b16857a612efe41ccfbf22514926b3511d51044366da78da224529447c04a9cf9dc4fbe142e783b02f9566e88b49ba700a5820ab2eafd9a541e1e37a7c04a1f75bfc8646979fb90886022a9c05b51b82382a1ba59a5ebad707930ef0692bba152b8faf596eead347a933d0b15ca2d0a",
      "u": "040cbde168ab69a65fff10b0cde73dd2e19d0d230cc7011247d2e476540ffaf3800a92075babe5e823313a5c1d020c4318fb68bdea6dd19b64837061451700525e",
      "v": "041be8fa9de40ed2925ca446048a2896532b88762f8b6e090f25f33a437c50396f09d441a500f7fa9646df5cbad7f4c8c2426c8e29e252d1a9c70ffa6d7dcd9201"
    },
    "timestamp": 123,
    "type": "verification"
  }' \
  https://api.mpin.io/dvs/verify

# Verification Response Example

{
  "certificate": "eyJhbGciOiJSUzI1NiIsImtpZCI6InMxIn0.eyJjQXQiOjE2NDk0MDQ1ODAsImV4cCI6MTY0OTQwNDU5MCwiaGFzaCI6Ijc0NjU3Mzc0In0.BoMXXJVdiJ3TNQ1m_qz2GMo9J9EniUHJz14XMmVOBJPBWjw6UWTn2G2henNOauB7t6oBqqtLhRudLr3KY1kLgWorOSXlvISoZicEFGsmUfEXS-hxP3d01acE0cRnqMmi1Au4VXbREdwLy7I7Cwb4ptLrziYvkEVh7KdbAMsD6Bw"
}

# Verify Certificate Validity

After receiving the certificate, you need to verify its validity to ensure that it was issued by MIRACL Trust and hasn’t expired. To do so, use the JWKS (public JSON Web Key Set) published on the https://api.mpin.io/dvs/jwks endpoint. Here is an example response from this endpoint:

{
  "keys": [
    {
      "use": "sig",
      "kty": "RSA",
      "kid": "-yj9_ZuyJYvel3z5Hf_uu6je45ejceAbTHGvUcS4JjM=",
      "alg": "RS256",
      "n": "ua3qYgjqf2MdtOFQyFergJH4etXywk6msxd854RMO92Vwx0v5uYSDCBeho2agL5fIQkCQf1M1kUeojnFD9TMEjycgERTiJTIC-sAlRG2SF3gOTioWBrxK6YqBgLzb-uBbkWt5L7dDTBz_DHg0UG54_I8_16fatpX2KV42wq_KtQR4mJFM19aGiEG5balrOwn4n-D8srwUg5rzzV4yMmIaSeeKerRXKfF7mOs-13-2ROCxREl5ZCxZuu2rxmYagOFns23Mw9poODEP_p53W4yeW_CjGw0w-ZiL6nHTmOI3CooN7uBsEw2GemUYUqOilKbctgu6bk4KzFsfnR4BDzwBQ",
      "e": "AQAB"
    }
  ]
}

The header of the JWT certificate contains the algorithm and the ID (kid) of the key used for signing the token in the following form:

{
  "alg": "RS256",
  "kid": "-yj9_ZuyJYvel3z5Hf_uu6je45ejceAbTHGvUcS4JjM="
}

When validating the token’s signature, you must use the key with the same kid from the https://api.mpin.io/dvs/jwks response.

Most JWT libraries support remote key sets and signature verification. For a list of libraries implementing JWT decoding and signature verification, see jtw.io.

# Certificate Payload

The JWT certificate contains a payload in the following form:

{
  "cAt": 1649404580,
  "exp": 1649404590,
  "hash": "74657374"
}

You need to ensure that the hash in the certificate matches the hash of the signed document. As the certificate only serves as proof for the current verification request, it is quite short-lived. There is no need to store the certificate. If necessary, you can make another verification request to ensure the validity of the signature.

# Handle JWKS rotation

When necessary, MIRACL Trust can change the signing key for the JWT certificate. Certificates issued after the rotation have the new kid in their header. Your implementation must ensure that the JWKS is fetched again from the https://api.mpin.io/dvs/jwks endpoint when it encounters a new kid.

# API Reference