blindrsa-ts: A TypeScript Library for the RSA Blind Signature Protocol
Specification: Library is compliant with the RFC-9474 document by IETF/IRTF and matches the provided tests vectors.
Protocol
The RSA Blind Signature Protocol is a two-party protocol between a Client and Server where they interact to compute
sig = Sign(sk, input_msg)
where input_msg = Prepare(msg)
is a prepared version of the private message msg
provided by the Client, and sk
is the private signing key provided by the Server.
Client(pk, msg) Server(sk, pk)
-----------------------------------------------------
input_msg = Prepare(msg)
blinded_msg, inv = Blind(pk, input_msg)
blinded_msg
---------->
blind_sig = BlindSign(sk, blinded_msg)
blind_sig
<----------
sig = Finalize(pk, input_msg, blind_sig, inv)
Usage
Variants Supported
This package supports the four variants specified in RFC9474. Consult Section 5 of the document for the proper usage of each variant in an application.
import { RSABSSA } from "@cloudflare/blindrsa-ts"
const variants = [
RSABSSA.SHA384.PSS.Randomized,
RSABSSA.SHA384.PSSZero.Randomized,
RSABSSA.SHA384.PSS.Deterministic,
RSABSSA.SHA384.PSSZero.Deterministic,
]
Platform specific configuration
By default, this library uses the WebCrypto API. Certain platforms, such as Cloudflare Workers, have implemented native operation. These can be enabled by passing { supportRSARAW: true }
when retrieving a suite.
At the time of writing, this dedicated optimisation is done only for the BlindSign
operation. Key type does not have to be modified, and will be set to RSA-RAW
by the library for the time of the operation.
Setup
Once a Blind-RSA variant was chosen, start by generating the server's keypair. Both the key length and the public exponent can be specified.
const suite = RSABSSA.SHA384.PSS.Randomized();
const { privateKey, publicKey } = await suite.generateKey({
publicExponent: Uint8Array.from([1, 0, 1]),
modulusLength: 2048,
});
Server distributes its public key to clients.
Step 1
The client prepares arbitrary input to be blindly-signed by the server. The blind
method generates a blinded message and an inverse object that later will be used during the finalization step.
const msgString = 'Alice and Bob';
const message = new TextEncoder().encode(msgString);
const preparedMsg = suite.prepare(message);
const { blindedMsg, inv } = await suite.blind(publicKey, preparedMsg);
The client sends only the blinded message to the server.
Step 2
Once the server received the blinded message, it responds to the client with a blind signature.
const blindSignature = await suite.blindSign(privateKey, blindedMsg);
The server sends the blinded signature to the client.
Step 3
The client produces the final signature using blinded signature received from the server together with the inverse object generated at the first step.
const signature = await suite.finalize(publicKey, preparedMsg, blindSignature, inv);
Thus, the client obtains a pair (preparedMsg, signature)
which can be verified for validity.
Step 4
Anyone with access to the server's public key can verify the signature on top of the preparedMsg
.
const isValid = await suite.verify(publicKey, signature, preparedMsg);
Development
Task | NPM scripts |
---|
Installing | $ npm ci |
Building | $ npm run build |
Unit Tests | $ npm run test |
Examples | $ npm run examples |
Benchmarking | $ npm run bench |
Code Linting | $ npm run lint |
Code Formatting | $ npm run format |
Dependencies
This project uses the Stanford Javascript Crypto Library sjcl. Use the following command to configure the library.
$ make -f sjcl.Makefile
License
The project is licensed under the Apache-2.0 License.