Permalink
Browse files

crypto: add function getDiffieHellman()

Returns a well known, predefined RFC group.
  • Loading branch information...
1 parent 19133ca commit c6a04ce78f9fcc07bc1ae108c402fba508344202 Tomasz Buchert committed with bnoordhuis Jan 22, 2012
Showing with 544 additions and 1 deletion.
  1. +30 −0 doc/api/crypto.markdown
  2. +4 −0 lib/crypto.js
  3. +54 −1 src/node_crypto.cc
  4. +386 −0 src/node_crypto_groups.h
  5. +70 −0 test/simple/test-crypto-dh.js
View
@@ -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
View
@@ -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;
@@ -173,6 +174,9 @@ exports.createDiffieHellman = function(size_or_key, enc) {
}
};
+exports.getDiffieHellman = function(group_name) {
+ return new DiffieHellmanGroup(group_name);
+};
exports.pbkdf2 = PBKDF2;
View
@@ -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>
@@ -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) {
@@ -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;
@@ -4375,4 +4429,3 @@ void InitCrypto(Handle<Object> target) {
} // namespace node
NODE_MODULE(node_crypto, node::crypto::InitCrypto)
-
Oops, something went wrong.

0 comments on commit c6a04ce

Please sign in to comment.