Awesome
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
Optimizations
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.
Partially Blind RSA verification
This library does not support Partially Blind RSA signature verification in browser. This is due to crypto.subtle
implementations not allowing large public exponents required by Partially Blind RSA. You can follow bugs for Chromium and Firefox.
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); // true
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.