Schemes - Boneh-Lynn-Shacham (BLS) Short Signatures Scheme

[wikipedia] In cryptography, the Boneh-Lynn-Shacham signature scheme allows a user to verify that a signer is authentic. The scheme uses a pairing function for verification and signatures are group elements in some elliptic curve. Working in an elliptic curve provides defense against index calculus attacks against allowing shorter signatures than FDH signatures. Signatures are often referred to as short signatures, BLS short signatures, or simply BLS signatures. The signature scheme is provably secure (that is, the scheme is existentially unforgeable under adaptive chosen-message attacks) assuming both the existence of random oracles and the intractability of the computational Diffie-Hellman problem.

In this page we will see how to:

  1. implement BLS using jPBC.
  2. use BLS in the context of the Bouncy Castle framework.

BLS

Key Generation

The key generation algorithm selects a random integer x in Zr .

  1. The Private Key is x;
  2. the Public Key is g x .

Let's see how to do that using jPBC:

import it.unisa.dia.gas.plaf.jpbc.pairing.PairingFactory;

// Init Pairings

CurveParams curveParams = new CurveParams().load("curve.properties");
Pairing pairing = PairingFactory.getPairing(curveParams);

// Generate system parameters

Element g = pairing.getG1().newRandomElement().getImmutable();

// Generate the secret key

Element x = pairing.getZr().newRandomElement();

// Generate the corresponding public key

Element pk = g.powZn(x);
                

Signing

Given the private key x , and some message m , first we compute the hash of the message and then we map the hash to some element h of G1. We output the signature sig = h x .

Using jPBC we have:

// Map the hash of the message m to some element of G1

byte[] hash = ... // Generate an hash from m (48-bit hash)
Element h = pairing.getG1().newElement().setFromHash(hash, 0, hash.length);

// Generate the signature

Element sig = h.powZn(x);

Verification

Given a signature sig and a public key g x , we verify that e(sig, g) =e(h, g x ) .

Again using jPBC::


// Map again the hash of the message m

byte[] hash = ... // Generate an hash from m (48-bit hash)
Element h = pairing.getG1().newElement().setFromHash(hash, 0, hash.length);

// Verify the signature

Element temp1 = pairing.pairing(sig, g);
Element temp2 = pairing.pairing(h, pk);

if (temp1.isEqual(temp2))
    System.out.println("The signature is valid.");
else
    System.out.println("The signature is NOT valid.");
                

BLS under BouncyCastle

You will find all the sources into the jpbc-crypto module.

Key Generation

import UTMAStrongParametersGenerator;
import UTMAStrongParameters;

// Init the generator.
BLSParametersGenerator parametersGenerator = new BLSParametersGenerator();
parametersGenerator.init(curveParams);

// Generate the parameters.
BLSParameters parameters = parametersGenerator.generateParameters();

// Store the parameters in a file.
FileOutputStream fileOutputStream = new FileOutputStream("bls.params");

parametersGenerator.store(fileOutputStream, parameters);

fileOutputStream.flush();
fileOutputStream.close();
                

Load the Public Information

import UTMAStrongParametersGenerator;
import UTMAStrongParameters;

// Init the generator.
BLSParametersGenerator parametersGenerator = new BLSParametersGenerator();

// Load the parameters from a file.
FileInputStream fileInputStream = new FileInputStream("utmas.params");

BLSParameters parameters = parametersGenerator.load(fileInputStream);

fileInputStream.close();
                

Generate and Store a Key-Pair

import UTMAStrongKeyPairGenerator;
import UTMAStrongKeyGenerationParameters;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;

// Init the generator.
BLSKeyPairGenerator keyPairGenerator = new BLSKeyPairGenerator();
keyPairGenerator.init(new BLSKeyGenerationParameters(null, parameters));

// Generate the key-pair.
AsymmetricCipherKeyPair keyPair = keyPairGenerator.generateKeyPair();

// Store the key-pair.
fileOutputStream = new FileOutputStream("bls_keypair.params");

keyPairGenerator.store(fileOutputStream, keyPair);

fileOutputStream.flush();
fileOutputStream.close();
                

Load a Key-Pair

import UTMAStrongKeyPairGenerator;
import UTMAStrongKeyGenerationParameters;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;

// Init the generator.
BLSKeyPairGenerator keyPairGenerator = new BLSKeyPairGenerator();

// Load the key-pair from a file.
fileInputStream = new FileInputStream("bls_keypair.params");

AsymmetricCipherKeyPair keyPair = keyPairGenerator.load(fileInputStream);

fileInputStream.close();
                

Signing

BLSSigner blsSigner = new BLSSigner(new SHA256Digest());

// Sign
blsSigner.init(true, keyPair.getPrivate());
blsSigner.update(message, 0, message.length);
byte[] sig = null;
try {
    sig = blsSigner.generateSignature();
} catch (CryptoException e) {
    fail(e.getMessage());
}
                

Verification

blsSigner.init(false, keyPair.getPublic());
assertTrue(blsSigner.verifySignature(sig));