Git Product home page Git Product logo

c-blind-rsa-signatures's Introduction

Blind RSA signatures

Author-blinded RSASSA-PSS RSAE signatures.

This is an implementation of the RSA Blind Signatures RFC, based on the Zig implementation.

Protocol overview

A client asks a server to sign a message. The server receives the message, and returns the signature.

Using that (message, signature) pair, the client can locally compute a second, valid (message', signature') pair.

Anyone can verify that (message', signature') is valid for the server's public key, even though the server didn't see that pair before. But no one besides the client can link (message', signature') to (message, signature).

Using that scheme, a server can issue a token and verify that a client has a valid token, without being able to link both actions to the same client.

  1. The client creates a random message, and blinds it with a random, secret factor.
  2. The server receives the blind message, signs it and returns a blind signature.
  3. From the blind signature, and knowing the secret factor, the client can locally compute a (message, signature) pair that can be verified using the server's public key.
  4. Anyone, including the server, can thus later verify that (message, signature) is valid, without knowing when step 2 occurred.

The scheme was designed by David Chaum, and was originally implemented for anonymizing DigiCash transactions.

Random noise must be added to messages that don't include enough entropy. An optional "Message Randomizer" can be used for that purpose.

Dependencies

This implementation requires OpenSSL (1.1.x or 3.x.y) or BoringSSL.

Usage

    #include <blind_rsa.h>

    // Initialize a context with the default parameters
    BRSAContext context;
    brsa_context_init_default(&context);

    // [SERVER]: Generate a RSA-2048 key pair
    BRSASecretKey sk;
    BRSAPublicKey pk;
    assert(brsa_keypair_generate(&sk, &pk, 2048) == 0);

    // Noise is not required if the message is random.
    // If it is not NULL, it will be automatically filled by brsa_blind_sign().
    BRSAMessageRandomizer *msg_randomizer = NULL;

    // [CLIENT]: create a random message and blind it for the server whose public key is `pk`.
    // The client must store the message and the secret.
    uint8_t            msg[32];
    const size_t       msg_len = sizeof msg;
    BRSABlindMessage   blind_msg;
    BRSABlindingSecret client_secret;
    assert(brsa_blind_message_generate(&context, &blind_msg, msg, msg_len, &client_secret, &pk) ==
           0);

    // [SERVER]: compute a signature for a blind message, to be sent to the client.
    // The client secret should not be sent to the server.
    BRSABlindSignature blind_sig;
    assert(brsa_blind_sign(&context, &blind_sig, &sk, &blind_msg) == 0);
    brsa_blind_message_deinit(&blind_msg);

    // [CLIENT]: later, when the client wants to redeem a signed blind message,
    // using the blinding secret, it can locally compute the signature of the
    // original message.
    // The client then owns a new valid (message, signature) pair, and the
    // server cannot link it to a previous(blinded message, blind signature) pair.
    // Note that the finalization function also verifies that the signature is
    // correct for the server public key.
    BRSASignature sig;
    assert(brsa_finalize(
               &context, &sig, &blind_sig, &client_secret, msg_randomizer, &pk, msg, msg_len) == 0);
    brsa_blind_signature_deinit(&blind_sig);
    brsa_blinding_secret_deinit(&client_secret);

    // [SERVER]: a non-blind signature can be verified using the server's public key.
    assert(brsa_verify(&context, &sig, &pk, msg_randomizer, msg, msg_len) == 0);
    brsa_signature_deinit(&sig);

    brsa_secretkey_deinit(&sk);
    brsa_publickey_deinit(&pk);

Deterministic padding is also supported, by creating a context with brsa_context_init_deterministic():

    // Initialize a context to use deterministic padding
    BRSAContext context;
    brsa_context_init_deterministic(&context);

Most applications should use the default (probabilistic) mode instead.

A custom hash function and salt length can also be specified with brsa_context_init_custom():

    // Initialize a context with SHA-256 as a Hash and MGF function,
    // and a 48 byte salt.
    BRSAContext context;
    brsa_context_init_custom(&context, BRSA_SHA256, 48);

Some additional helper functions for key management are included:

    // Get a key identifier
    uint8_t key_id[4];
    assert(brsa_publickey_id(&context, key_id, sizeof key_id, &pk) == 0);

    // Key serialization
    BRSASerializedKey sk_der, pk_der;
    assert(brsa_secretkey_export(&sk_der, &sk) == 0);
    assert(brsa_publickey_export(&pk_der, &pk) == 0);

    // Store the SubjectPublicKeyInfo in DER format
    BRSASerializedKey spki_der;
    assert(brsa_publickey_export_spki(&context, &spki_der, &pk) == 0);

    // Free key resources
    brsa_secretkey_deinit(&sk);
    brsa_publickey_deinit(&pk);

    // Key deserialization
    assert(brsa_secretkey_import(&sk, sk_der.bytes, sk_der.bytes_len) == 0);
    assert(brsa_publickey_import(&pk, pk_der.bytes, pk_der.bytes_len) == 0);
    brsa_serializedkey_deinit(&sk_der);
    brsa_serializedkey_deinit(&pk_der);

All these functions return 0 on success and -1 on error.

For other languages

c-blind-rsa-signatures's People

Contributors

jedisct1 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

icodein

c-blind-rsa-signatures's Issues

Import Public Keys with Extra ASN1 Data

Currently it looks like brsa_publickey_import expects only the raw key structure (Sequence[2] -> [int][int]) when importing a key. Has any consideration been given to having import handle/skip over additional asn1 data if present prior to unpacking the key data or should the caller ensure it is removed prior to using?

Example of public key with extra data:

openssl.exe asn1parse -in public.txt -inform pem
    0:d=0  hl=4 l= 594 cons: SEQUENCE
    4:d=1  hl=2 l=  61 cons: SEQUENCE
    6:d=2  hl=2 l=   9 prim: OBJECT            :rsassaPss
   17:d=2  hl=2 l=  48 cons: SEQUENCE
   19:d=3  hl=2 l=  13 cons: cont [ 0 ]
   21:d=4  hl=2 l=  11 cons: SEQUENCE
   23:d=5  hl=2 l=   9 prim: OBJECT            :sha384
   34:d=3  hl=2 l=  26 cons: cont [ 1 ]
   36:d=4  hl=2 l=  24 cons: SEQUENCE
   38:d=5  hl=2 l=   9 prim: OBJECT            :mgf1
   49:d=5  hl=2 l=  11 cons: SEQUENCE
   51:d=6  hl=2 l=   9 prim: OBJECT            :sha384
   62:d=3  hl=2 l=   3 cons: cont [ 2 ]
   64:d=4  hl=2 l=   1 prim: INTEGER           :30
   67:d=1  hl=4 l= 527 prim: BIT STRING
openssl.exe asn1parse -strparse 67 -in public.txt -inform pem
    0:d=0  hl=4 l= 522 cons: SEQUENCE
    4:d=1  hl=4 l= 513 prim: INTEGER           :<removed>
  521:d=1  hl=2 l=   3 prim: INTEGER           :<removed>

ASN1_STRING string length != 13 in brsa_publickey_export_spki()

Running into an issue where the string length check at blind_rsa.c:810 fails.

The string length check fails because algor_mgf1_s is length 15, not 13. I'm not familiar with this crypto, but here are the 15 bytes:

30 5c 72 5c 78 36 5c 74 60 e2 80 a0 48 5c 78

If its helpful I'm using boringSSL for the crypto operations, and my context was init'd in the default way:
brsa_context_init_default

Batch issuance

Hi there,

Has there been any consideration into making an API surface that allows signing multiple message with the same context and client secret?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.