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

Commit c6a04ce

Browse files
Tomasz Buchertbnoordhuis
authored andcommitted
crypto: add function getDiffieHellman()
Returns a well known, predefined RFC group.
1 parent 19133ca commit c6a04ce

File tree

5 files changed

+544
-1
lines changed

5 files changed

+544
-1
lines changed

doc/api/crypto.markdown

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,36 @@ or `'base64'`. Defaults to `'binary'`.
264264
Sets the Diffie-Hellman private key. Key encoding can be `'binary'`, `'hex'`,
265265
or `'base64'`. Defaults to `'binary'`.
266266

267+
### crypto.getDiffieHellman(group_name)
268+
269+
Creates a predefined Diffie-Hellman key exchange object.
270+
The supported groups are: `'modp1'`, `'modp2'`, `'modp5'`
271+
(defined in [RFC 2412](http://www.rfc-editor.org/rfc/rfc2412.txt ))
272+
and `'modp14'`, `'modp15'`, `'modp16'`, `'modp17'`, `'modp18'`
273+
(defined in [RFC 3526](http://www.rfc-editor.org/rfc/rfc3526.txt )).
274+
The returned object mimics the interface of objects created by
275+
[crypto.createDiffieHellman()](#crypto.createDiffieHellman) above, but
276+
will not allow to change the keys (with
277+
[diffieHellman.setPublicKey()](#diffieHellman.setPublicKey) for example).
278+
The advantage of using this routine is that the parties don't have to
279+
generate nor exchange group modulus beforehand, saving both processor and
280+
communication time.
281+
282+
Example (obtaining a shared secret):
283+
284+
var crypto = require('crypto');
285+
var alice = crypto.getDiffieHellman('modp5');
286+
var bob = crypto.getDiffieHellman('modp5');
287+
288+
alice.generateKeys();
289+
bob.generateKeys();
290+
291+
var alice_secret = alice.computeSecret(bob.getPublicKey(), 'binary', 'hex');
292+
var bob_secret = bob.computeSecret(alice.getPublicKey(), 'binary', 'hex');
293+
294+
/* alice_secret and bob_secret should be the same */
295+
console.log(alice_secret == bob_secret);
296+
267297
### pbkdf2(password, salt, iterations, keylen, callback)
268298

269299
Asynchronous PBKDF2 applies pseudorandom function HMAC-SHA1 to derive

lib/crypto.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ try {
3030
var Sign = binding.Sign;
3131
var Verify = binding.Verify;
3232
var DiffieHellman = binding.DiffieHellman;
33+
var DiffieHellmanGroup = binding.DiffieHellmanGroup;
3334
var PBKDF2 = binding.PBKDF2;
3435
var randomBytes = binding.randomBytes;
3536
var pseudoRandomBytes = binding.pseudoRandomBytes;
@@ -173,6 +174,9 @@ exports.createDiffieHellman = function(size_or_key, enc) {
173174
}
174175

175176
};
177+
exports.getDiffieHellman = function(group_name) {
178+
return new DiffieHellmanGroup(group_name);
179+
};
176180

177181
exports.pbkdf2 = PBKDF2;
178182

src/node_crypto.cc

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
// USE OR OTHER DEALINGS IN THE SOFTWARE.
2121

2222
#include <node_crypto.h>
23+
#include <node_crypto_groups.h>
2324
#include <v8.h>
2425

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

35373538
target->Set(String::NewSymbol("DiffieHellman"), t->GetFunction());
3539+
3540+
Local<FunctionTemplate> t2 = FunctionTemplate::New(DiffieHellmanGroup);
3541+
t2->InstanceTemplate()->SetInternalFieldCount(1);
3542+
3543+
NODE_SET_PROTOTYPE_METHOD(t2, "generateKeys", GenerateKeys);
3544+
NODE_SET_PROTOTYPE_METHOD(t2, "computeSecret", ComputeSecret);
3545+
NODE_SET_PROTOTYPE_METHOD(t2, "getPrime", GetPrime);
3546+
NODE_SET_PROTOTYPE_METHOD(t2, "getGenerator", GetGenerator);
3547+
NODE_SET_PROTOTYPE_METHOD(t2, "getPublicKey", GetPublicKey);
3548+
NODE_SET_PROTOTYPE_METHOD(t2, "getPrivateKey", GetPrivateKey);
3549+
3550+
target->Set(String::NewSymbol("DiffieHellmanGroup"), t2->GetFunction());
35383551
}
35393552

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

3573+
bool Init(unsigned char* p, int p_len, unsigned char* g, int g_len) {
3574+
dh = DH_new();
3575+
dh->p = BN_bin2bn(p, p_len, 0);
3576+
dh->g = BN_bin2bn(g, g_len, 0);
3577+
initialised_ = true;
3578+
return true;
3579+
}
3580+
35603581
protected:
3582+
static Handle<Value> DiffieHellmanGroup(const Arguments& args) {
3583+
HandleScope scope;
3584+
3585+
DiffieHellman* diffieHellman = new DiffieHellman();
3586+
3587+
if (args.Length() != 1 || !args[0]->IsString()) {
3588+
return ThrowException(Exception::Error(
3589+
String::New("No group name given")));
3590+
}
3591+
3592+
String::Utf8Value group_name(args[0]->ToString());
3593+
3594+
modp_group* it = modp_groups;
3595+
3596+
while(it->name != NULL) {
3597+
if (!strcasecmp(*group_name, it->name))
3598+
break;
3599+
it++;
3600+
}
3601+
3602+
if (it->name != NULL) {
3603+
diffieHellman->Init(it->prime, it->prime_size,
3604+
it->gen, it->gen_size);
3605+
} else {
3606+
return ThrowException(Exception::Error(
3607+
String::New("Unknown group")));
3608+
}
3609+
3610+
diffieHellman->Wrap(args.This());
3611+
3612+
return args.This();
3613+
}
3614+
35613615
static Handle<Value> New(const Arguments& args) {
35623616
HandleScope scope;
35633617

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

43774431
NODE_MODULE(node_crypto, node::crypto::InitCrypto)
4378-

0 commit comments

Comments
 (0)