Skip to content

Instantly share code, notes, and snippets.

@dacbd
Created September 27, 2012 20:05
Show Gist options
  • Save dacbd/3796173 to your computer and use it in GitHub Desktop.
Save dacbd/3796173 to your computer and use it in GitHub Desktop.
SJCL ecc encrypt/decrypt
var data = {
herp: "derp"
};
//Make the keys.
var temp = sjcl.ecc.elGamal.generateKeys(384, 1);
//to encrypt with publickey:
var pubjson = temp.pub.serialize();
var point = sjcl.ecc.curves["c" + pubjson.curve].fromBits(pubjson.point);
var publicKey = new sjcl.ecc.elGamal.publicKey(pubjson.curve, point.curve, point);
var symkey_obj = publicKey.kem(0);
var ciphertext = sjcl.encrypt(symkey_obj.key, JSON.stringify(data));
var message = JSON.stringify({ 'ciphertext': ciphertext, 'encrypted_key': symkey_obj.tag });
// and message gets saved off
//to decrypt with privatekey/recovering "message"
var cipherMessage = JSON.parse(message);
var secjson = temp.sec.serialize();
var ex = sjcl.bn.fromBits(secjson.exponent);
var privatekey_obj = new sjcl.ecc.elGamal.secretKey(secjson.curve, sjcl.ecc.curves["c" +secjson.curve], ex);
var symkey = privatekey_obj.unkem(cipherMessage.encrypted_key);
var decryptedData = sjcl.decrypt(symkey, cipherMessage.ciphertext);
@justindthomas
Copy link

kem() returns an object with a "key" and a "tag". So your sjcl.ecrypt should actually be:

var symkey_obj = publicKey.kem(0)
var ciphertext = sjcl.encrypt(symkey_obj.key, data)

The receiver needs symkey_obj.tag (that's the encrypted symmetric key). So you could send them an object like:

var message = JSON.stringify({ 'ciphertext': ciphertext, 'encrypted_key': symkey_obj.tag })

They would receive it and decrypt it like (assuming "secretKey" has already been instantiated):

var encrypted = JSON.parse(message)
var symkey = secretKey.unkem(encrypted.tag)
var plaintext = sjcl.decrypt(symkey, encrypted.ciphertext)

Make sense? Some of my stringifying/parsing may be wrong (it's a little bit funky - the "encrypt" method spits out an already stringified JSON object, but nothing else seems to).

@justindthomas
Copy link

Oops. In my example:

var symkey = secretKey.unkem(encrypted.tag)

...should be:

var symkey = secretKey.unkem(encrypted.encrypted_key)

@justindthomas
Copy link

And I don't think sjcl.encrypt will accept an object as the plaintext - it's looking for a string.

@dacbd
Copy link
Author

dacbd commented Sep 27, 2012

@justinthomas I do believe that you can pass the sjcl its native "bitArray" object and it should work fine, for example:

var ciphertext = sjcl.encrypt(sjcl.misc.pbkdf2("password", "salt"), JSON.stringify(data));

Oh but looking back you where probably referring to the fact that I hadn't yet JSON.stringify'd data

assuming that this is the sjcl "bitArray"

publicKey.kem(0).key

I'll see what those changes do for me.

@ledil
Copy link

ledil commented Aug 12, 2013

Are you using the sjcl ECC Branch for this gist ? Because ... frombits (line 10) is not working with the latest sjcl ecc branch version ...

@jamilbk
Copy link

jamilbk commented Feb 14, 2014

I'm also interested in an updated version of this. serialize() is no longer part of the ecc library

@ibmibmibm
Copy link

var sjcl = require('sjcl');

var data = {
    herp: "derp"
};

var curve = sjcl.ecc.curves.c384;
var temp = sjcl.ecc.elGamal.generateKeys(curve, 1);
var pub = temp.pub.get();
var sec = temp.sec.get();

var pubObj = new sjcl.ecc.elGamal.publicKey(curve, new sjcl.ecc.point(curve, sjcl.bn.prime.p384.fromBits(pub.x), sjcl.bn.prime.p384.fromBits(pub.y)));
var secObj = new sjcl.ecc.elGamal.secretKey(curve, sjcl.bn.prime.p384.fromBits(sec));

var ciphertext = sjcl.encrypt(pubObj, JSON.stringify(data));
var message = JSON.stringify({'ciphertext': ciphertext});

var cipherMessage = JSON.parse(message);
var decryptedData = sjcl.decrypt(secObj, cipherMessage.ciphertext);
console.log(decryptedData);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment