Skip to content
Ben Walford edited this page Oct 9, 2015 · 6 revisions

Asymmetric crypto first has to be enabled with the --with-ecc option (see Getting Started). Once enabled, SJCL provides EC-ElGamal (for Diffie-Hellman exchanges) and ECDSA implementations.

Curves

SJCL implements a couple NIST and SECG curves:

Name Location Good Until
P-192 sjcl.ecc.curves.c192 2020
P-224 sjcl.ecc.curves.c224 2030
P-256 sjcl.ecc.curves.c256 >2030
P-384 sjcl.ecc.curves.c384 >>2030
P-521 sjcl.ecc.curves.c521 >>2030
secp192k1 sjcl.ecc.curves.k192 2020
secp224k1 sjcl.ecc.curves.k224 2030
secp256k1 sjcl.ecc.curves.k256 >2030

Curves beginning with a P were defined by NIST and are generally the standard choice.

Curves beginning with secp are called Koblitz curves--they work significantly faster than the NIST curves but are rarely seen outside of some specific, high-throughput environments.

The number at the end of the name denotes the curve's bitsize. On a curve of n bits, the private key is n bits and the public key is 2n bits.

Key Pair Generation

Generating a key pair is as simple as choosing the purpose and size:

// Curve P-256.  If only a bitsize is given, SJCL assumes a P-* curve.
sjcl.ecc.elGamal.generateKeys(256)
sjcl.ecc.ecdsa.generateKeys(256)

// Curve K-256.
sjcl.ecc.elGamal.generateKeys(sjcl.ecc.curves.k256)
sjcl.ecc.ecdsa.generateKeys(sjcl.ecc.curves.k256)

Generating key pairs requires that the DRBG be seeded. For more information, see Generating Random Bytes

(Do not use an ElGamal key pair as an ECDSA key pair or vice versa!)

Serializing Key Pairs

Sometimes it's necessary to serialize a public or private key for transmission or storage, so SJCL allows converting keys to and from bit arrays, which can then be fed through any of the Codecs.

var pair = sjcl.ecc.elGamal.generateKeys(256)
var pub = pair.pub.get(), sec = pair.sec.get()

// Serialized public key:
pub = sjcl.codec.base64.fromBits(pub.x.concat(pub.y))
// uQuXH/yeIpQq8hCWiwCTIMKdsaX...

// Unserialized public key:
pub = new sjcl.ecc.elGamal.publicKey(
    sjcl.ecc.curves.c256, 
    sjcl.codec.base64.toBits(pub)
)


// Serialized private key:
sec = sjcl.codec.base64.fromBits(sec)
// IXkJSpYK3RHRaVrd...

// Unserialized private key:
sec = new sjcl.ecc.elGamal.secretKey(
    sjcl.ecc.curves.c256,
    sjcl.ecc.curves.c256.field.fromBits(sjcl.codec.base64.toBits(sec))
)

Sending Messages

In addition to passwords or shared secret keys, the sjcl.encrypt function can also take ElGamal public keys as input and encrypt data such that only the holder of the private key can decrypt it. The cipher modes, associated data, etc. still work as before in the Symmetric Crypto section.

var pair = sjcl.ecc.elGamal.generateKeys(256)

var ct = sjcl.encrypt(pair.pub, "Hello World!")
var pt = sjcl.decrypt(pair.sec, ct)

It should be noted that this design only authenticates the receiver--the sender is functionally anonymous.

Finding Shared Secret Keys

In the event that you need the shared secret key directly (to build your own protocol or something), a raw Diffie-Hellman exchange can be performed:

// Party A's private key and party B's public key.
var pub = ..., sec = ...

// Returns shared secret key as bit array.
sec.dh(pub)
// [ 352201900, -2012199574, 600590189, ...

// Returns shared secret compatible with Java generateSecret.
sec.dhJavaEc(pub)
// [ 352201900, -2012199574, 600590189, ...

The derived key is the SHA-256 hash of the shared secret point. It doesn't necessarily need to be put through a KDF, but it wouldn't hurt.

Signing and Verifying

To sign and verify a corpus of data:

// Must be ECDSA!
var pair = sjcl.ecc.ecdsa.generateKeys(256)

var sig = pair.sec.sign(sjcl.hash.sha256.hash("Hello World!"))
// [ 799253862, -791427911, -170134622, ...

var ok = pair.pub.verify(sjcl.hash.sha256.hash("Hello World!"), sig)
// Either `true` or an error will be thrown.

Like key pair generation, signature generation requires that the DRBG be seeded. The hash (SHA-256 in the example) can be changed to SHA-1 or SHA-512, but it'll be truncated if it's too large for the curve's field.