Signatures

Introduction

Signup provides the capability for applications to get a permission from user to sign arbitrary payloads with their private key which later can be verified in the backend. Developers can use this feature to securely grants access to users to specific resources, prove their identity, provide passwordless login or use it as optional two factor authentication.

The payloads signed by the application contain some obligatory attributes to make sure the application is not allowed to sign payloads that belong to other applications.

Requesting Access

Before signing you need to request access from the user. This usually leads to a popup opening on the user side to grant the access from their non-custodial wallet.

const signup = new Signup.cash();
signup.requestAccess(["bch_address", "signature"]).then(({bchAddr}) => {
// user approved your request
}).catch((e) => {
// user denied
});

Signing a payload

const myData = {
foo: 'bar',
// insert any arbitrary properties
}
signup.sign(myData).then(({payload, bchAddr, signature}) => {
console.log(signature);
});

Which in the example above, payload would be a Signup Signature Payload (described below) and signature will be the digital signature of the the whole payload. The payload is passed through JSON.stringify() function before being signed. You need to use this payload to verify the signature in your servers later.

Signup Signature Payload

This payload is constructed using a normal JavaScript object with some additional properties to make sure that signature will not be re-played for use cases outside the requirements of the application. This objects is constructed as below:

{
signedBy: 'Signup.cash',
requestedBy: 'domain.tld',
data: { foo: 'bar' },
timestamp: 1599640414562,
}

Verifying the Signature

You can use any library for verifying the signatures from Signup including Bitbox or Bitcore. However, Signup provides a utils package that make the process of verification easier on the backend. This library is only available for Node JS at the moment.

import { verify } from "@signupcash/utils";
verify(payload, bchAddr, signature).then(res => {
console.log(res); // { verified: true }
}).catch(e => {
// not verified
});

Replay Protection

The timestamp in the standard Signup Signature Payload can be used for two purposed. First is obviously to recognize the exact time that the payload is signed. The second use case is to be used as a nonce value for reply protection. If you are using the payload for a usecase that could be replayed in future maliciously (for example login or access to some backend resources) you might want to make sure that an attacker who obtained the payload and signature can't replay it in future. In this case, it's a good practice to keep a SHA256 hash of the payload in your database and check its uniqueness with future payloads. The timestamp property ensures that the hash every time will be unique even if your data is always the same.