blindrsa-ts: A TypeScript Library for Blind and Partially-Blind RSA Signature Protocols
Specification: Library is compliant with the RFC-9474 document by IETF/IRTF, with Partially Blind RSA Signatures Draft 02, and matches the provided tests vectors, resp.
Blind RSA Signature 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)
Partially-Blind RSA Signature Protocol
One possible generalization of the protocol above is Partially-Blind Signatures, in which an additional info
string can be provided, allowing public metadata to be shared.
Client(pk, msg, info) Server(sk, pk, info)
-------------------------------------------------------
input_msg = Prepare(msg)
blind_msg, inv = Blind(pk, input_msg, info)
blind_msg
---------->
blind_sig = BlindSign(sk, blind_msg, info)
blind_sig
<----------
sig = Finalize(pk, input_msg, info, 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,
];
In addition, it supports the four variants specified in Partially Blind RSA Signatures Draft 02. Consult Section 6 of the document for the proper usage of each variant in an application.
import { RSAPBSSA } from '@cloudflare/blindrsa-ts';
const variants = [
RSAPBSSA.SHA384.PSS.Randomized,
RSAPBSSA.SHA384.PSSZero.Randomized,
RSAPBSSA.SHA384.PSS.Deterministic,
RSAPBSSA.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 optimization 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 key pair. 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.
Partially Blind RSA Signatures consideration
Partially Blind RSA Signatures requires Client and Server to have a public byte array info
shared out-of-band. Where applicable, this byte array has to be provided as a parameter. Please refer to the example provided in examples/partially_blindrsa.ts to see usage.
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 |
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.