Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

Commit

Permalink
crypto: add function getDiffieHellman()
Browse files Browse the repository at this point in the history
Returns a well known, predefined RFC group.
  • Loading branch information
Tomasz Buchert authored and bnoordhuis committed Feb 21, 2012
1 parent 19133ca commit c6a04ce
Show file tree
Hide file tree
Showing 5 changed files with 544 additions and 1 deletion.
30 changes: 30 additions & 0 deletions doc/api/crypto.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,36 @@ or `'base64'`. Defaults to `'binary'`.
Sets the Diffie-Hellman private key. Key encoding can be `'binary'`, `'hex'`,
or `'base64'`. Defaults to `'binary'`.

### crypto.getDiffieHellman(group_name)

Creates a predefined Diffie-Hellman key exchange object.
The supported groups are: `'modp1'`, `'modp2'`, `'modp5'`
(defined in [RFC 2412](http://www.rfc-editor.org/rfc/rfc2412.txt ))
and `'modp14'`, `'modp15'`, `'modp16'`, `'modp17'`, `'modp18'`
(defined in [RFC 3526](http://www.rfc-editor.org/rfc/rfc3526.txt )).
The returned object mimics the interface of objects created by
[crypto.createDiffieHellman()](#crypto.createDiffieHellman) above, but
will not allow to change the keys (with
[diffieHellman.setPublicKey()](#diffieHellman.setPublicKey) for example).
The advantage of using this routine is that the parties don't have to
generate nor exchange group modulus beforehand, saving both processor and
communication time.

Example (obtaining a shared secret):

var crypto = require('crypto');
var alice = crypto.getDiffieHellman('modp5');
var bob = crypto.getDiffieHellman('modp5');

alice.generateKeys();
bob.generateKeys();

var alice_secret = alice.computeSecret(bob.getPublicKey(), 'binary', 'hex');
var bob_secret = bob.computeSecret(alice.getPublicKey(), 'binary', 'hex');

/* alice_secret and bob_secret should be the same */
console.log(alice_secret == bob_secret);

### pbkdf2(password, salt, iterations, keylen, callback)

Asynchronous PBKDF2 applies pseudorandom function HMAC-SHA1 to derive
Expand Down
4 changes: 4 additions & 0 deletions lib/crypto.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ try {
var Sign = binding.Sign;
var Verify = binding.Verify;
var DiffieHellman = binding.DiffieHellman;
var DiffieHellmanGroup = binding.DiffieHellmanGroup;
var PBKDF2 = binding.PBKDF2;
var randomBytes = binding.randomBytes;
var pseudoRandomBytes = binding.pseudoRandomBytes;
Expand Down Expand Up @@ -173,6 +174,9 @@ exports.createDiffieHellman = function(size_or_key, enc) {
}

};
exports.getDiffieHellman = function(group_name) {
return new DiffieHellmanGroup(group_name);
};

exports.pbkdf2 = PBKDF2;

Expand Down
55 changes: 54 additions & 1 deletion src/node_crypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
// USE OR OTHER DEALINGS IN THE SOFTWARE.

#include <node_crypto.h>
#include <node_crypto_groups.h>
#include <v8.h>

#include <node.h>
Expand Down Expand Up @@ -3535,6 +3536,18 @@ class DiffieHellman : public ObjectWrap {
NODE_SET_PROTOTYPE_METHOD(t, "setPrivateKey", SetPrivateKey);

target->Set(String::NewSymbol("DiffieHellman"), t->GetFunction());

Local<FunctionTemplate> t2 = FunctionTemplate::New(DiffieHellmanGroup);
t2->InstanceTemplate()->SetInternalFieldCount(1);

NODE_SET_PROTOTYPE_METHOD(t2, "generateKeys", GenerateKeys);
NODE_SET_PROTOTYPE_METHOD(t2, "computeSecret", ComputeSecret);
NODE_SET_PROTOTYPE_METHOD(t2, "getPrime", GetPrime);
NODE_SET_PROTOTYPE_METHOD(t2, "getGenerator", GetGenerator);
NODE_SET_PROTOTYPE_METHOD(t2, "getPublicKey", GetPublicKey);
NODE_SET_PROTOTYPE_METHOD(t2, "getPrivateKey", GetPrivateKey);

target->Set(String::NewSymbol("DiffieHellmanGroup"), t2->GetFunction());
}

bool Init(int primeLength) {
Expand All @@ -3557,7 +3570,48 @@ class DiffieHellman : public ObjectWrap {
return true;
}

bool Init(unsigned char* p, int p_len, unsigned char* g, int g_len) {
dh = DH_new();
dh->p = BN_bin2bn(p, p_len, 0);
dh->g = BN_bin2bn(g, g_len, 0);
initialised_ = true;
return true;
}

protected:
static Handle<Value> DiffieHellmanGroup(const Arguments& args) {
HandleScope scope;

DiffieHellman* diffieHellman = new DiffieHellman();

if (args.Length() != 1 || !args[0]->IsString()) {
return ThrowException(Exception::Error(
String::New("No group name given")));
}

String::Utf8Value group_name(args[0]->ToString());

modp_group* it = modp_groups;

while(it->name != NULL) {
if (!strcasecmp(*group_name, it->name))
break;
it++;
}

if (it->name != NULL) {
diffieHellman->Init(it->prime, it->prime_size,
it->gen, it->gen_size);
} else {
return ThrowException(Exception::Error(
String::New("Unknown group")));
}

diffieHellman->Wrap(args.This());

return args.This();
}

static Handle<Value> New(const Arguments& args) {
HandleScope scope;

Expand Down Expand Up @@ -4375,4 +4429,3 @@ void InitCrypto(Handle<Object> target) {
} // namespace node

NODE_MODULE(node_crypto, node::crypto::InitCrypto)

Loading

0 comments on commit c6a04ce

Please sign in to comment.