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

getDiffieHellman: returns a well known, predefined RFC groups #2638

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions doc/api/crypto.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,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
6 changes: 5 additions & 1 deletion 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 @@ -171,8 +172,11 @@ exports.createDiffieHellman = function(size_or_key, enc) {
} else {
return new DiffieHellman(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 @@ -3525,6 +3526,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 @@ -3547,7 +3560,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 @@ -4366,4 +4420,3 @@ void InitCrypto(Handle<Object> target) {
} // namespace node

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

Loading