Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Make crypto functions accept buffers as arguments #2945

Closed
wants to merge 21 commits into from

4 participants

@thiagoarrais

This will someday fix #1393

@thiagoarrais

I think with these last commits (up to f28be11) I've finished converting the arguments (inputs). I have also updated the docs and will start working on the return values (outputs) next.

@thiagoarrais

By the way, I can rebase this if needed. Just say so.

@bnoordhuis
Owner

Looks good in general but I would opt for a simple RAII class instead of doing manual memory management with RetrieveData(). It's something I've been wanting to do anyway so might as well do it now.

@thiagoarrais

Good idea! But maybe even that isn't needed in case we ditch encoded strings altogether. What do you think, @bnoordhuis?

@bnoordhuis
Owner

That's not an option. We deprecate things before removing them. People need a chance to update their code.

@thiagoarrais

Sure. What I'm trying to say is that this should be deprecated and removed, since node seems to recommend buffers instead of encoded strings anyway. But this isn't the forum to discuss that.

I'll refactor the code to use a RAII class and then begin converting the function outputs.

If I have some time, I'll try to take a look at the rest of the core lib codebase (besides crypto) to check for other places that could use this improvement. That will help with deprecating encoded strings in the future.

@thiagoarrais

Here alloc_buf was previously set to false, but I thought it needed to be true since buf will soon be complete_hex that was allocated in line 2525/2534, thus needing to be free'd.

But maybe the previous code was right and I may have introduced a possible buffer overflow caused by a double free.

@thiagoarrais

I think that does it. Would someone please take a look?

I am not really sure about the changes to DecipherUpdate in 55fcf52. Please take a little more care when reviewing it (I've added a comment to the region that makes me unease).

@bnoordhuis
Owner

Sorry, I haven't had time to review the PR yet.

@thiagoarrais

No problem, @bnoordhuis. Take your time...

@langpavel

Is there added value against 63ff449?

@isaacs
Owner

This was already done on master.

@isaacs isaacs closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 16, 2012
  1. @thiagoarrais
  2. @thiagoarrais
  3. @thiagoarrais
  4. @thiagoarrais

    Extract function for retrieving data

    thiagoarrais authored
    Data can be retrieved from a buffer or an encoded string
    
    Refactoring only
  5. @thiagoarrais

    Making the linter happy

    thiagoarrais authored
  6. @thiagoarrais
  7. @thiagoarrais

    Input buffers done. Update docs.

    thiagoarrais authored
    Makes the docs a little more explicit where buffers are also
    accepted instead of string + encoding pair.
Commits on Mar 17, 2012
  1. @thiagoarrais
Commits on Mar 22, 2012
  1. @thiagoarrais
  2. @thiagoarrais

    Introduce class for simple memory management

    thiagoarrais authored
    It would be nice if someone else could take a look at the DecipherUpdate
    function. I'm affraid I either fixed a possible memory leak or introduced
    a buffer overflow.
Commits on Mar 23, 2012
  1. @thiagoarrais
  2. @thiagoarrais
  3. @thiagoarrais
  4. @thiagoarrais
  5. @thiagoarrais
Commits on Mar 29, 2012
  1. @thiagoarrais
Commits on Apr 14, 2012
  1. @thiagoarrais

    Merge branch 'master' into crypto-buffer

    thiagoarrais authored
    Conflicts:
    	src/node_crypto.cc
Commits on Apr 27, 2012
  1. @thiagoarrais

    Merge branch 'master' into crypto-buffer

    thiagoarrais authored
    Conflicts:
    	src/node_crypto.cc
Commits on Apr 28, 2012
  1. @thiagoarrais
Commits on Jun 27, 2012
  1. @thiagoarrais

    Merge branch 'master' into crypto-buffer

    thiagoarrais authored
    Conflicts:
    	doc/api/crypto.markdown
    	src/node_crypto.cc
    	test/simple/test-crypto.js
Commits on Jun 28, 2012
  1. @thiagoarrais
This page is out of date. Refresh to see the latest.
Showing with 363 additions and 314 deletions.
  1. +59 −42 doc/api/crypto.markdown
  2. +225 −268 src/node_crypto.cc
  3. +79 −4 test/simple/test-crypto.js
View
101 doc/api/crypto.markdown
@@ -63,15 +63,17 @@ Returned by `crypto.createHash`.
### hash.update(data, [input_encoding])
-Updates the hash content with the given `data`, the encoding of which is given
-in `input_encoding` and can be `'utf8'`, `'ascii'` or `'binary'`.
+Updates the hash content with the given `data`, which can be a string or a
+buffer. If `data` is a string, its encoding is given in `input_encoding`
+and can be `'utf8'`, `'ascii'` or `'binary'`.
Defaults to `'binary'`.
This can be called many times with new data as it is streamed.
### hash.digest([encoding])
Calculates the digest of all of the passed data to be hashed.
-The `encoding` can be `'hex'`, `'binary'` or `'base64'`.
+The `encoding` can be `'hex'`, `'binary'`, `'base64'` or `null` for returning
+a buffer.
Defaults to `'binary'`.
Note: `hash` object can not be used after `digest()` method been called.
@@ -98,7 +100,8 @@ This can be called many times with new data as it is streamed.
### hmac.digest([encoding])
Calculates the digest of all of the passed data to the hmac.
-The `encoding` can be `'hex'`, `'binary'` or `'base64'`.
+The `encoding` can be `'hex'`, `'binary'`, `'base64'` or `null` for returning
+a buffer.
Defaults to `'binary'`.
Note: `hmac` object can not be used after `digest()` method been called.
@@ -133,19 +136,23 @@ Returned by `crypto.createCipher` and `crypto.createCipheriv`.
### cipher.update(data, [input_encoding], [output_encoding])
-Updates the cipher with `data`, the encoding of which is given in
-`input_encoding` and can be `'utf8'`, `'ascii'` or `'binary'`.
+Updates the cipher with `data`, which can be a string or a buffer. If
+`data` is a string its encoding is given in `input_encoding` and can be
+`'utf8'`, `'ascii'` or `'binary'`.
Defaults to `'binary'`.
-The `output_encoding` specifies the output format of the enciphered data,
-and can be `'binary'`, `'base64'` or `'hex'`. Defaults to `'binary'`.
+The `output_encoding` specifies the output format of the enciphered data, and
+can be `'binary'`, `'base64'`, `'hex'` or `null`. If `null`, the enciphered
+data will be returned as a buffer. Defaults to `'binary'`.
-Returns the enciphered contents, and can be called many times with new data as it is streamed.
+Returns the enciphered contents, and can be called many times with new data
+as it is streamed.
### cipher.final([output_encoding])
-Returns any remaining enciphered contents, with `output_encoding` being one of:
-`'binary'`, `'base64'` or `'hex'`. Defaults to `'binary'`.
+Returns any remaining enciphered contents, with `output_encoding` being one
+of: `'binary'`, `'base64'`, `'hex'` or `null`. If `null`, the result will
+be a buffer. Defaults to `'binary'`.
Note: `cipher` object can not be used after `final()` method been called.
@@ -174,17 +181,19 @@ Returned by `crypto.createDecipher` and `crypto.createDecipheriv`.
### decipher.update(data, [input_encoding], [output_encoding])
-Updates the decipher with `data`, which is encoded in `'binary'`, `'base64'`
-or `'hex'`. Defaults to `'binary'`.
+Updates the decipher with `data`, which can be a string or a buffer. If
+`data` is a string its encoding is given in `input_encoding` and can be
+`'binary'`, `'base64'` or `'hex'`. Defaults to `'binary'`.
The `output_decoding` specifies in what format to return the deciphered
-plaintext: `'binary'`, `'ascii'` or `'utf8'`. Defaults to `'binary'`.
+plaintext: `'binary'`, `'ascii'`, `'utf8'` or `null`. If `null`, the plaintext
+will be returned as a buffer. Defaults to `'binary'`.
### decipher.final([output_encoding])
-Returns any remaining plaintext which is deciphered,
-with `output_encoding` being one of: `'binary'`, `'ascii'` or `'utf8'`.
-Defaults to `'binary'`.
+Returns any remaining plaintext which is deciphered, with `output_encoding`
+being one of: `'binary'`, `'ascii'`, `'utf8'` or `null`. If `null`, the
+plaintext will be returned as a buffer. Defaults to `'binary'`.
Note: `decipher` object can not be used after `final()` method been called.
@@ -211,13 +220,14 @@ Returned by `crypto.createSign`.
Updates the signer object with data.
This can be called many times with new data as it is streamed.
-### signer.sign(private_key, [output_format])
+### signer.sign(private_key, [output_encoding])
Calculates the signature on all the updated data passed through the signer.
`private_key` is a string containing the PEM encoded private key for signing.
-Returns the signature in `output_format` which can be `'binary'`, `'hex'` or
-`'base64'`. Defaults to `'binary'`.
+Returns the signature in `output_encoding` which can be `'binary'`, `'hex'`,
+`'base64'` or `null`. If `null`, the signature will be returned as a
+buffer. Defaults to `'binary'`.
Note: `signer` object can not be used after `sign()` method been called.
@@ -237,13 +247,13 @@ Returned by `crypto.createVerify`.
Updates the verifier object with data.
This can be called many times with new data as it is streamed.
-### verifier.verify(object, signature, [signature_format])
+### verifier.verify(object, signature, [encoding])
Verifies the signed data by using the `object` and `signature`. `object` is a
string containing a PEM encoded object, which can be one of RSA public key,
DSA public key, or X.509 certificate. `signature` is the previously calculated
-signature for the data, in the `signature_format` which can be `'binary'`,
-`'hex'` or `'base64'`. Defaults to `'binary'`.
+signature for the data; it can be a buffer or a string in the `encoding`
+which can be `'binary'`, `'hex'` or `'base64'`. Defaults to `'binary'`.
Returns true or false depending on the validity of the signature for the data and public key.
@@ -257,7 +267,8 @@ given bit length. The generator used is `2`.
## crypto.createDiffieHellman(prime, [encoding])
Creates a Diffie-Hellman key exchange object using the supplied prime. The
-generator used is `2`. Encoding can be `'binary'`, `'hex'`, or `'base64'`.
+generator used is `2`. `prime` can be a buffer or string encoded in
+`'binary'`, `'hex'`, or `'base64'`.
Defaults to `'binary'`.
## Class: DiffieHellman
@@ -270,47 +281,53 @@ Returned by `crypto.createDiffieHellman`.
Generates private and public Diffie-Hellman key values, and returns the
public key in the specified encoding. This key should be transferred to the
-other party. Encoding can be `'binary'`, `'hex'`, or `'base64'`.
-Defaults to `'binary'`.
+other party. Encoding can be `'binary'`, `'hex'`, `'base64'` or `null`. If
+`null`, the public key will be returned as a buffer. Defaults to `'binary'`.
### diffieHellman.computeSecret(other_public_key, [input_encoding], [output_encoding])
-Computes the shared secret using `other_public_key` as the other party's
-public key and returns the computed shared secret. Supplied key is
-interpreted using specified `input_encoding`, and secret is encoded using
-specified `output_encoding`. Encodings can be `'binary'`, `'hex'`, or
-`'base64'`. The input encoding defaults to `'binary'`.
-If no output encoding is given, the input encoding is used as output encoding.
+Computes the shared secret using `other_public_key` as the other
+party's public key and returns the computed shared secret. Supplied
+key can be a string or a buffer. If it is a string it is interpreted
+using specified `input_encoding`. Secret is encoded using specified
+`output_encoding`. Encodings can be `'binary'`, `'hex'`, `'base64'` or `null`
+for buffers. The input encoding defaults to `'binary'`.
+If no output encoding is given, the input encoding is used as output
+encoding.
### diffieHellman.getPrime([encoding])
-Returns the Diffie-Hellman prime in the specified encoding, which can be
-`'binary'`, `'hex'`, or `'base64'`. Defaults to `'binary'`.
+Returns the Diffie-Hellman prime in the specified encoding, which can
+be `'binary'`, `'hex'`, `'base64'` or `null`. If `null`, a buffer is
+returned. Defaults to `'binary'`.
### diffieHellman.getGenerator([encoding])
-Returns the Diffie-Hellman prime in the specified encoding, which can be
-`'binary'`, `'hex'`, or `'base64'`. Defaults to `'binary'`.
+Returns the Diffie-Hellman generator in the specified encoding, which can
+be `'binary'`, `'hex'`, `'base64'` or `null`. If `null`, a buffer is
+returned. Defaults to `'binary'`.
### diffieHellman.getPublicKey([encoding])
Returns the Diffie-Hellman public key in the specified encoding, which can
-be `'binary'`, `'hex'`, or `'base64'`. Defaults to `'binary'`.
+be `'binary'`, `'hex'`, `'base64'` or `null`. If `null`, a buffer is
+returned. Defaults to `'binary'`.
### diffieHellman.getPrivateKey([encoding])
Returns the Diffie-Hellman private key in the specified encoding, which can
-be `'binary'`, `'hex'`, or `'base64'`. Defaults to `'binary'`.
+be `'binary'`, `'hex'`, `'base64'` or `null`. If `null`, a buffer is
+returned. Defaults to `'binary'`.
### diffieHellman.setPublicKey(public_key, [encoding])
-Sets the Diffie-Hellman public key. Key encoding can be `'binary'`, `'hex'`,
-or `'base64'`. Defaults to `'binary'`.
+Sets the Diffie-Hellman public key. Key can be a buffer or a string
+encoded in `'binary'`, `'hex'`, or `'base64'`. Defaults to `'binary'`.
### diffieHellman.setPrivateKey(public_key, [encoding])
-Sets the Diffie-Hellman private key. Key encoding can be `'binary'`, `'hex'`,
-or `'base64'`. Defaults to `'binary'`.
+Sets the Diffie-Hellman private key. Key can be a buffer or a string
+encoded in `'binary'`, `'hex'`, or `'base64'`. Defaults to `'binary'`.
## crypto.getDiffieHellman(group_name)
View
493 src/node_crypto.cc
@@ -1975,6 +1975,33 @@ int local_EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx,
}
+class BinaryData {
+ public:
+ char* buf;
+ ssize_t buf_len;
+
+ BinaryData(const Local<Value> arg, const enum encoding enc, ssize_t len)
+ : buf_len(len),
+ clean(false) {
+ if (Buffer::HasInstance(arg)) {
+ Local<Object> buffer = arg->ToObject();
+ buf = Buffer::Data(buffer);
+ buf_len = Buffer::Length(buffer);
+ } else {
+ buf = new char[len];
+ ssize_t written = DecodeWrite(buf, len, arg, enc);
+ assert(written == len);
+ clean = true;
+ }
+ }
+
+ ~BinaryData() {
+ if (clean) delete [] buf;
+ }
+ private:
+ bool clean;
+};
+
class Cipher : public ObjectWrap {
public:
static void Initialize (v8::Handle<v8::Object> target) {
@@ -2108,15 +2135,11 @@ class Cipher : public ObjectWrap {
return ThrowException(exception);
}
- char* key_buf = new char[key_buf_len];
- ssize_t key_written = DecodeWrite(key_buf, key_buf_len, args[1], BINARY);
- assert(key_written == key_buf_len);
+ BinaryData key = BinaryData(args[1], BINARY, key_buf_len);
String::Utf8Value cipherType(args[0]);
- bool r = cipher->CipherInit(*cipherType, key_buf, key_buf_len);
-
- delete [] key_buf;
+ bool r = cipher->CipherInit(*cipherType, key.buf, key.buf_len);
if (!r) {
return ThrowException(Exception::Error(String::New("CipherInit error")));
@@ -2158,20 +2181,14 @@ class Cipher : public ObjectWrap {
return ThrowException(exception);
}
- char* key_buf = new char[key_len];
- ssize_t key_written = DecodeWrite(key_buf, key_len, args[1], BINARY);
- assert(key_written == key_len);
-
- char* iv_buf = new char[iv_len];
- ssize_t iv_written = DecodeWrite(iv_buf, iv_len, args[2], BINARY);
- assert(iv_written == iv_len);
+ BinaryData key = BinaryData(args[1], BINARY, key_len);
+ BinaryData iv = BinaryData(args[2], BINARY, iv_len);
String::Utf8Value cipherType(args[0]);
- bool r = cipher->CipherInitIv(*cipherType, key_buf,key_len,iv_buf,iv_len);
-
- delete [] key_buf;
- delete [] iv_buf;
+ bool r = cipher->CipherInitIv(*cipherType,
+ key.buf, key.buf_len,
+ iv.buf, iv.buf_len);
if (!r) {
return ThrowException(Exception::Error(String::New("CipherInitIv error")));
@@ -2195,21 +2212,11 @@ class Cipher : public ObjectWrap {
return ThrowException(exception);
}
- unsigned char *out=0;
- int out_len=0, r;
- if (Buffer::HasInstance(args[0])) {
- Local<Object> buffer_obj = args[0]->ToObject();
- char *buffer_data = Buffer::Data(buffer_obj);
- size_t buffer_length = Buffer::Length(buffer_obj);
+ unsigned char *out = 0;
+ int out_len = 0;
+ BinaryData data = BinaryData(args[0], enc, len);
- r = cipher->CipherUpdate(buffer_data, buffer_length, &out, &out_len);
- } else {
- char* buf = new char[len];
- ssize_t written = DecodeWrite(buf, len, args[0], enc);
- assert(written == len);
- r = cipher->CipherUpdate(buf, len,&out,&out_len);
- delete [] buf;
- }
+ int r = cipher->CipherUpdate(data.buf, data.buf_len, &out, &out_len);
if (!r) {
delete [] out;
@@ -2217,9 +2224,11 @@ class Cipher : public ObjectWrap {
return ThrowException(exception);
}
- Local<Value> outString;
- if (out_len==0) {
- outString=String::New("");
+ Handle<Value> output;
+ if (args[2]->IsNull()) {
+ output = Buffer::New((char*) out, out_len)->handle_;
+ } else if (out_len==0) {
+ output = String::New("");
} else {
char* out_hexdigest;
int out_hex_len;
@@ -2227,7 +2236,7 @@ class Cipher : public ObjectWrap {
if (enc == HEX) {
// Hex encoding
HexEncode(out, out_len, &out_hexdigest, &out_hex_len);
- outString = Encode(out_hexdigest, out_hex_len, BINARY);
+ output = Encode(out_hexdigest, out_hex_len, BINARY);
delete [] out_hexdigest;
} else if (enc == BASE64) {
// Base64 encoding
@@ -2257,10 +2266,10 @@ class Cipher : public ObjectWrap {
}
base64(out, out_len, &out_hexdigest, &out_hex_len);
- outString = Encode(out_hexdigest, out_hex_len, BINARY);
+ output = Encode(out_hexdigest, out_hex_len, BINARY);
delete [] out_hexdigest;
} else if (enc == BINARY) {
- outString = Encode(out, out_len, BINARY);
+ output = Encode(out, out_len, BINARY);
} else {
fprintf(stderr, "node-crypto : Cipher .update encoding "
"can be binary, hex or base64\n");
@@ -2269,7 +2278,7 @@ class Cipher : public ObjectWrap {
if (out) delete [] out;
- return scope.Close(outString);
+ return scope.Close(output);
}
static Handle<Value> SetAutoPadding(const Arguments& args) {
@@ -2290,7 +2299,7 @@ class Cipher : public ObjectWrap {
int out_len = -1;
char* out_hexdigest;
int out_hex_len;
- Local<Value> outString ;
+ Handle<Value> output ;
int r = cipher->CipherFinal(&out_value, &out_len);
@@ -2309,38 +2318,42 @@ class Cipher : public ObjectWrap {
}
}
- enum encoding enc = ParseEncoding(args[0], BINARY);
- if (enc == HEX) {
- // Hex encoding
- HexEncode(out_value, out_len, &out_hexdigest, &out_hex_len);
- outString = Encode(out_hexdigest, out_hex_len, BINARY);
- delete [] out_hexdigest;
- } else if (enc == BASE64) {
- // Check to see if we need to add in previous base64 overhang
- if (cipher->incomplete_base64!=NULL){
- unsigned char* complete_base64 = new unsigned char[out_len+cipher->incomplete_base64_len+1];
- memcpy(complete_base64, cipher->incomplete_base64, cipher->incomplete_base64_len);
- memcpy(&complete_base64[cipher->incomplete_base64_len], out_value, out_len);
- delete [] out_value;
-
- delete [] cipher->incomplete_base64;
- cipher->incomplete_base64=NULL;
-
- out_value=complete_base64;
- out_len += cipher->incomplete_base64_len;
- }
- base64(out_value, out_len, &out_hexdigest, &out_hex_len);
- outString = Encode(out_hexdigest, out_hex_len, BINARY);
- delete [] out_hexdigest;
- } else if (enc == BINARY) {
- outString = Encode(out_value, out_len, BINARY);
+ if (args[0]->IsNull()) {
+ output = Buffer::New((char*) out_value, out_len)->handle_;
} else {
- fprintf(stderr, "node-crypto : Cipher .final encoding "
- "can be binary, hex or base64\n");
+ enum encoding enc = ParseEncoding(args[0], BINARY);
+ if (enc == HEX) {
+ // Hex encoding
+ HexEncode(out_value, out_len, &out_hexdigest, &out_hex_len);
+ output = Encode(out_hexdigest, out_hex_len, BINARY);
+ delete [] out_hexdigest;
+ } else if (enc == BASE64) {
+ // Check to see if we need to add in previous base64 overhang
+ if (cipher->incomplete_base64!=NULL){
+ unsigned char* complete_base64 = new unsigned char[out_len+cipher->incomplete_base64_len+1];
+ memcpy(complete_base64, cipher->incomplete_base64, cipher->incomplete_base64_len);
+ memcpy(&complete_base64[cipher->incomplete_base64_len], out_value, out_len);
+ delete [] out_value;
+
+ delete [] cipher->incomplete_base64;
+ cipher->incomplete_base64=NULL;
+
+ out_value=complete_base64;
+ out_len += cipher->incomplete_base64_len;
+ }
+ base64(out_value, out_len, &out_hexdigest, &out_hex_len);
+ output = Encode(out_hexdigest, out_hex_len, BINARY);
+ delete [] out_hexdigest;
+ } else if (enc == BINARY) {
+ output = Encode(out_value, out_len, BINARY);
+ } else {
+ fprintf(stderr, "node-crypto : Cipher .final encoding "
+ "can be binary, hex or base64\n");
+ }
}
delete [] out_value;
- return scope.Close(outString);
+ return scope.Close(output);
}
Cipher () : ObjectWrap ()
@@ -2613,22 +2626,12 @@ class Decipher : public ObjectWrap {
"node`DecodeBytes() failed")));
}
- char* buf;
// if alloc_buf then buf must be deleted later
bool alloc_buf = false;
- if (Buffer::HasInstance(args[0])) {
- Local<Object> buffer_obj = args[0]->ToObject();
- char *buffer_data = Buffer::Data(buffer_obj);
- size_t buffer_length = Buffer::Length(buffer_obj);
- buf = buffer_data;
- len = buffer_length;
- } else {
- alloc_buf = true;
- buf = new char[len];
- ssize_t written = DecodeWrite(buf, len, args[0], BINARY);
- assert(written == len);
- }
+ BinaryData data = BinaryData(args[0], BINARY, len);
+ char* buf = data.buf;
+ len = data.buf_len;
char* ciphertext;
int ciphertext_len;
@@ -2641,10 +2644,7 @@ class Decipher : public ObjectWrap {
char* complete_hex = new char[len+2];
memcpy(complete_hex, &cipher->incomplete_hex, 1);
memcpy(complete_hex+1, buf, len);
- if (alloc_buf) {
- delete [] buf;
- alloc_buf = false;
- }
+ alloc_buf = true;
buf = complete_hex;
len += 1;
}
@@ -2666,9 +2666,6 @@ class Decipher : public ObjectWrap {
} else if (enc == BASE64) {
unbase64((unsigned char*)buf, len, (char **)&ciphertext, &ciphertext_len);
- if (alloc_buf) {
- delete [] buf;
- }
buf = ciphertext;
len = ciphertext_len;
alloc_buf = true;
@@ -2691,9 +2688,11 @@ class Decipher : public ObjectWrap {
return ThrowException(exception);
}
- Local<Value> outString;
- if (out_len==0) {
- outString=String::New("");
+ Handle<Value> output;
+ if (args[2]->IsNull()) {
+ output = Buffer::New((char*) out, out_len)->handle_;
+ } else if (out_len==0) {
+ output = String::New("");
} else {
enum encoding enc = ParseEncoding(args[2], BINARY);
if (enc == UTF8) {
@@ -2717,16 +2716,16 @@ class Decipher : public ObjectWrap {
cipher->incomplete_utf8 = new unsigned char[cipher->incomplete_utf8_len+1];
memcpy(cipher->incomplete_utf8, &out[utf8_len], cipher->incomplete_utf8_len);
}
- outString = Encode(out, utf8_len, enc);
+ output = Encode(out, utf8_len, enc);
} else {
- outString = Encode(out, out_len, enc);
+ output = Encode(out, out_len, enc);
}
}
if (out) delete [] out;
if (alloc_buf) delete [] buf;
- return scope.Close(outString);
+ return scope.Close(output);
}
@@ -2747,7 +2746,7 @@ class Decipher : public ObjectWrap {
unsigned char* out_value = NULL;
int out_len = -1;
- Local<Value> outString;
+ Handle<Value> output;
int r = cipher->DecipherFinal<TOLERATE_PADDING>(&out_value, &out_len);
@@ -2765,8 +2764,10 @@ class Decipher : public ObjectWrap {
}
}
- if (args.Length() == 0 || !args[0]->IsString()) {
- outString = Encode(out_value, out_len, BINARY);
+ if (args[0]->IsNull()) {
+ output = Buffer::New((char*) out_value, out_len)->handle_;
+ } else if (args.Length() == 0 || !args[0]->IsString()) {
+ output = Encode(out_value, out_len, BINARY);
} else {
enum encoding enc = ParseEncoding(args[0]);
if (enc == UTF8) {
@@ -2779,17 +2780,17 @@ class Decipher : public ObjectWrap {
delete [] cipher->incomplete_utf8;
cipher->incomplete_utf8=NULL;
- outString = Encode(complete_out, cipher->incomplete_utf8_len+out_len, enc);
+ output = Encode(complete_out, cipher->incomplete_utf8_len+out_len, enc);
delete [] complete_out;
} else {
- outString = Encode(out_value, out_len, enc);
+ output = Encode(out_value, out_len, enc);
}
} else {
- outString = Encode(out_value, out_len, enc);
+ output = Encode(out_value, out_len, enc);
}
}
delete [] out_value;
- return scope.Close(outString);
+ return scope.Close(output);
}
Decipher () : ObjectWrap () {
@@ -2891,23 +2892,8 @@ class Hmac : public ObjectWrap {
String::Utf8Value hashType(args[0]);
- bool r;
-
- if( Buffer::HasInstance(args[1])) {
- Local<Object> buffer_obj = args[1]->ToObject();
- char* buffer_data = Buffer::Data(buffer_obj);
- size_t buffer_length = Buffer::Length(buffer_obj);
-
- r = hmac->HmacInit(*hashType, buffer_data, buffer_length);
- } else {
- char* buf = new char[len];
- ssize_t written = DecodeWrite(buf, len, args[1], BINARY);
- assert(written == len);
-
- r = hmac->HmacInit(*hashType, buf, len);
-
- delete [] buf;
- }
+ BinaryData key = BinaryData(args[1], BINARY, len);
+ bool r = hmac->HmacInit(*hashType, key.buf, key.buf_len);
if (!r) {
return ThrowException(Exception::Error(String::New("hmac error")));
@@ -2930,21 +2916,8 @@ class Hmac : public ObjectWrap {
return ThrowException(exception);
}
- int r;
-
- if( Buffer::HasInstance(args[0])) {
- Local<Object> buffer_obj = args[0]->ToObject();
- char *buffer_data = Buffer::Data(buffer_obj);
- size_t buffer_length = Buffer::Length(buffer_obj);
-
- r = hmac->HmacUpdate(buffer_data, buffer_length);
- } else {
- char* buf = new char[len];
- ssize_t written = DecodeWrite(buf, len, args[0], enc);
- assert(written == len);
- r = hmac->HmacUpdate(buf, len);
- delete [] buf;
- }
+ BinaryData data = BinaryData(args[0], enc, len);
+ int r = hmac->HmacUpdate(data.buf, data.buf_len);
if (!r) {
Local<Value> exception = Exception::TypeError(String::New("HmacUpdate fail"));
@@ -2963,31 +2936,35 @@ class Hmac : public ObjectWrap {
unsigned int md_len = 0;
char* md_hexdigest;
int md_hex_len;
- Local<Value> outString;
+ Handle<Value> output;
int r = hmac->HmacDigest(&md_value, &md_len);
if (md_len == 0 || r == 0) {
return scope.Close(String::New(""));
}
- enum encoding enc = ParseEncoding(args[0], BINARY);
- if (enc == HEX) {
- // Hex encoding
- HexEncode(md_value, md_len, &md_hexdigest, &md_hex_len);
- outString = Encode(md_hexdigest, md_hex_len, BINARY);
- delete [] md_hexdigest;
- } else if (enc == BASE64) {
- base64(md_value, md_len, &md_hexdigest, &md_hex_len);
- outString = Encode(md_hexdigest, md_hex_len, BINARY);
- delete [] md_hexdigest;
- } else if (enc == BINARY) {
- outString = Encode(md_value, md_len, BINARY);
+ if (args[0]->IsNull()) {
+ output = Buffer::New((char*) md_value, md_len)->handle_;
} else {
- fprintf(stderr, "node-crypto : Hmac .digest encoding "
- "can be binary, hex or base64\n");
+ enum encoding enc = ParseEncoding(args[0], BINARY);
+ if (enc == HEX) {
+ // Hex encoding
+ HexEncode(md_value, md_len, &md_hexdigest, &md_hex_len);
+ output = Encode(md_hexdigest, md_hex_len, BINARY);
+ delete [] md_hexdigest;
+ } else if (enc == BASE64) {
+ base64(md_value, md_len, &md_hexdigest, &md_hex_len);
+ output = Encode(md_hexdigest, md_hex_len, BINARY);
+ delete [] md_hexdigest;
+ } else if (enc == BINARY) {
+ output = Encode(md_value, md_len, BINARY);
+ } else {
+ fprintf(stderr, "node-crypto : Hmac .digest encoding "
+ "can be binary, hex or base64\n");
+ }
}
delete [] md_value;
- return scope.Close(outString);
+ return scope.Close(output);
}
Hmac () : ObjectWrap () {
@@ -3076,20 +3053,8 @@ class Hash : public ObjectWrap {
return ThrowException(exception);
}
- int r;
-
- if (Buffer::HasInstance(args[0])) {
- Local<Object> buffer_obj = args[0]->ToObject();
- char *buffer_data = Buffer::Data(buffer_obj);
- size_t buffer_length = Buffer::Length(buffer_obj);
- r = hash->HashUpdate(buffer_data, buffer_length);
- } else {
- char* buf = new char[len];
- ssize_t written = DecodeWrite(buf, len, args[0], enc);
- assert(written == len);
- r = hash->HashUpdate(buf, len);
- delete[] buf;
- }
+ BinaryData data = BinaryData(args[0], enc, len);
+ int r = hash->HashUpdate(data.buf, data.buf_len);
if (!r) {
Local<Value> exception = Exception::TypeError(String::New("HashUpdate fail"));
@@ -3119,30 +3084,34 @@ class Hash : public ObjectWrap {
return scope.Close(String::New(""));
}
- Local<Value> outString;
+ Handle<Value> output;
- enum encoding enc = ParseEncoding(args[0], BINARY);
- if (enc == HEX) {
- // Hex encoding
- char* md_hexdigest;
- int md_hex_len;
- HexEncode(md_value, md_len, &md_hexdigest, &md_hex_len);
- outString = Encode(md_hexdigest, md_hex_len, BINARY);
- delete [] md_hexdigest;
- } else if (enc == BASE64) {
- char* md_hexdigest;
- int md_hex_len;
- base64(md_value, md_len, &md_hexdigest, &md_hex_len);
- outString = Encode(md_hexdigest, md_hex_len, BINARY);
- delete [] md_hexdigest;
- } else if (enc == BINARY) {
- outString = Encode(md_value, md_len, BINARY);
+ if (args[0]->IsNull()) {
+ output = Buffer::New((char*) md_value, md_len)->handle_;
} else {
- fprintf(stderr, "node-crypto : Hash .digest encoding "
- "can be binary, hex or base64\n");
+ enum encoding enc = ParseEncoding(args[0], BINARY);
+ if (enc == HEX) {
+ // Hex encoding
+ char* md_hexdigest;
+ int md_hex_len;
+ HexEncode(md_value, md_len, &md_hexdigest, &md_hex_len);
+ output = Encode(md_hexdigest, md_hex_len, BINARY);
+ delete [] md_hexdigest;
+ } else if (enc == BASE64) {
+ char* md_hexdigest;
+ int md_hex_len;
+ base64(md_value, md_len, &md_hexdigest, &md_hex_len);
+ output = Encode(md_hexdigest, md_hex_len, BINARY);
+ delete [] md_hexdigest;
+ } else if (enc == BINARY) {
+ output = Encode(md_value, md_len, BINARY);
+ } else {
+ fprintf(stderr, "node-crypto : Hash .digest encoding "
+ "can be binary, hex or base64\n");
+ }
}
- return scope.Close(outString);
+ return scope.Close(output);
}
Hash () : ObjectWrap () {
@@ -3267,21 +3236,8 @@ class Sign : public ObjectWrap {
return ThrowException(exception);
}
- int r;
-
- if (Buffer::HasInstance(args[0])) {
- Local<Object> buffer_obj = args[0]->ToObject();
- char *buffer_data = Buffer::Data(buffer_obj);
- size_t buffer_length = Buffer::Length(buffer_obj);
-
- r = sign->SignUpdate(buffer_data, buffer_length);
- } else {
- char* buf = new char[len];
- ssize_t written = DecodeWrite(buf, len, args[0], enc);
- assert(written == len);
- r = sign->SignUpdate(buf, len);
- delete [] buf;
- }
+ BinaryData data = BinaryData(args[0], enc, len);
+ int r = sign->SignUpdate(data.buf, data.buf_len);
if (!r) {
Local<Value> exception = Exception::TypeError(String::New("SignUpdate fail"));
@@ -3300,7 +3256,7 @@ class Sign : public ObjectWrap {
unsigned int md_len;
char* md_hexdigest;
int md_hex_len;
- Local<Value> outString;
+ Handle<Value> output;
md_len = 8192; // Maximum key size is 8192 bits
md_value = new unsigned char[md_len];
@@ -3327,26 +3283,30 @@ class Sign : public ObjectWrap {
return scope.Close(String::New(""));
}
- enum encoding enc = ParseEncoding(args[1], BINARY);
- if (enc == HEX) {
- // Hex encoding
- HexEncode(md_value, md_len, &md_hexdigest, &md_hex_len);
- outString = Encode(md_hexdigest, md_hex_len, BINARY);
- delete [] md_hexdigest;
- } else if (enc == BASE64) {
- base64(md_value, md_len, &md_hexdigest, &md_hex_len);
- outString = Encode(md_hexdigest, md_hex_len, BINARY);
- delete [] md_hexdigest;
- } else if (enc == BINARY) {
- outString = Encode(md_value, md_len, BINARY);
+ if (args[1]->IsNull()) {
+ output = Buffer::New((char*) md_value, md_len)->handle_;
} else {
- outString = String::New("");
- fprintf(stderr, "node-crypto : Sign .sign encoding "
- "can be binary, hex or base64\n");
+ enum encoding enc = ParseEncoding(args[1], BINARY);
+ if (enc == HEX) {
+ // Hex encoding
+ HexEncode(md_value, md_len, &md_hexdigest, &md_hex_len);
+ output = Encode(md_hexdigest, md_hex_len, BINARY);
+ delete [] md_hexdigest;
+ } else if (enc == BASE64) {
+ base64(md_value, md_len, &md_hexdigest, &md_hex_len);
+ output = Encode(md_hexdigest, md_hex_len, BINARY);
+ delete [] md_hexdigest;
+ } else if (enc == BINARY) {
+ output = Encode(md_value, md_len, BINARY);
+ } else {
+ output = String::New("");
+ fprintf(stderr, "node-crypto : Sign .sign encoding "
+ "can be binary, hex or base64\n");
+ }
}
delete [] md_value;
- return scope.Close(outString);
+ return scope.Close(output);
}
Sign () : ObjectWrap () {
@@ -3519,21 +3479,8 @@ class Verify : public ObjectWrap {
return ThrowException(exception);
}
- int r;
-
- if(Buffer::HasInstance(args[0])) {
- Local<Object> buffer_obj = args[0]->ToObject();
- char *buffer_data = Buffer::Data(buffer_obj);
- size_t buffer_length = Buffer::Length(buffer_obj);
-
- r = verify->VerifyUpdate(buffer_data, buffer_length);
- } else {
- char* buf = new char[len];
- ssize_t written = DecodeWrite(buf, len, args[0], enc);
- assert(written == len);
- r = verify->VerifyUpdate(buf, len);
- delete [] buf;
- }
+ BinaryData data = BinaryData(args[0], enc, len);
+ int r = verify->VerifyUpdate(data.buf, data.buf_len);
if (!r) {
Local<Value> exception = Exception::TypeError(String::New("VerifyUpdate fail"));
@@ -3570,34 +3517,32 @@ class Verify : public ObjectWrap {
return ThrowException(exception);
}
- unsigned char* hbuf = new unsigned char[hlen];
- ssize_t hwritten = DecodeWrite((char *)hbuf, hlen, args[1], BINARY);
- assert(hwritten == hlen);
unsigned char* dbuf;
int dlen;
+ BinaryData signature = BinaryData(args[1], BINARY, hlen);
+
int r=-1;
enum encoding enc = ParseEncoding(args[2], BINARY);
if (enc == HEX) {
// Hex encoding
- HexDecode(hbuf, hlen, (char **)&dbuf, &dlen);
+ HexDecode((unsigned char*) signature.buf, signature.buf_len, (char **)&dbuf, &dlen);
r = verify->VerifyFinal(kbuf, klen, dbuf, dlen);
delete [] dbuf;
} else if (enc == BASE64) {
// Base64 encoding
- unbase64(hbuf, hlen, (char **)&dbuf, &dlen);
+ unbase64((unsigned char*) signature.buf, signature.buf_len, (char **)&dbuf, &dlen);
r = verify->VerifyFinal(kbuf, klen, dbuf, dlen);
delete [] dbuf;
- } else if (enc == BINARY) {
- r = verify->VerifyFinal(kbuf, klen, hbuf, hlen);
+ } else if (enc == BINARY || Buffer::HasInstance(args[1])) {
+ r = verify->VerifyFinal(kbuf, klen, (unsigned char*) signature.buf, signature.buf_len);
} else {
fprintf(stderr, "node-crypto : Verify .verify encoding "
"can be binary, hex or base64\n");
}
delete [] kbuf;
- delete [] hbuf;
return Boolean::New(r && r != -1);
}
@@ -3778,21 +3723,23 @@ class DiffieHellman : public ObjectWrap {
String::New("Key generation failed")));
}
- Local<Value> outString;
+ Handle<Value> output;
int dataSize = BN_num_bytes(diffieHellman->dh->pub_key);
char* data = new char[dataSize];
BN_bn2bin(diffieHellman->dh->pub_key,
reinterpret_cast<unsigned char*>(data));
- if (args.Length() > 0 && args[0]->IsString()) {
- outString = EncodeWithEncoding(args[0], data, dataSize);
+ if (args[0]->IsNull()) {
+ output = Buffer::New((char*) data, dataSize)->handle_;
+ } else if (args.Length() > 0 && args[0]->IsString()) {
+ output = EncodeWithEncoding(args[0], data, dataSize);
} else {
- outString = Encode(data, dataSize, BINARY);
+ output = Encode(data, dataSize, BINARY);
}
delete[] data;
- return scope.Close(outString);
+ return scope.Close(output);
}
static Handle<Value> GetPrime(const Arguments& args) {
@@ -3809,17 +3756,19 @@ class DiffieHellman : public ObjectWrap {
char* data = new char[dataSize];
BN_bn2bin(diffieHellman->dh->p, reinterpret_cast<unsigned char*>(data));
- Local<Value> outString;
+ Handle<Value> output;
- if (args.Length() > 0 && args[0]->IsString()) {
- outString = EncodeWithEncoding(args[0], data, dataSize);
+ if (args[0]->IsNull()) {
+ output = Buffer::New((char*) data, dataSize)->handle_;
+ } else if (args.Length() > 0 && args[0]->IsString()) {
+ output = EncodeWithEncoding(args[0], data, dataSize);
} else {
- outString = Encode(data, dataSize, BINARY);
+ output = Encode(data, dataSize, BINARY);
}
delete[] data;
- return scope.Close(outString);
+ return scope.Close(output);
}
static Handle<Value> GetGenerator(const Arguments& args) {
@@ -3836,17 +3785,19 @@ class DiffieHellman : public ObjectWrap {
char* data = new char[dataSize];
BN_bn2bin(diffieHellman->dh->g, reinterpret_cast<unsigned char*>(data));
- Local<Value> outString;
+ Handle<Value> output;
- if (args.Length() > 0 && args[0]->IsString()) {
- outString = EncodeWithEncoding(args[0], data, dataSize);
+ if (args[0]->IsNull()) {
+ output = Buffer::New((char*) data, dataSize)->handle_;
+ } else if (args.Length() > 0 && args[0]->IsString()) {
+ output = EncodeWithEncoding(args[0], data, dataSize);
} else {
- outString = Encode(data, dataSize, BINARY);
+ output = Encode(data, dataSize, BINARY);
}
delete[] data;
- return scope.Close(outString);
+ return scope.Close(output);
}
static Handle<Value> GetPublicKey(const Arguments& args) {
@@ -3869,17 +3820,19 @@ class DiffieHellman : public ObjectWrap {
BN_bn2bin(diffieHellman->dh->pub_key,
reinterpret_cast<unsigned char*>(data));
- Local<Value> outString;
+ Handle<Value> output;
- if (args.Length() > 0 && args[0]->IsString()) {
- outString = EncodeWithEncoding(args[0], data, dataSize);
+ if (args[0]->IsNull()) {
+ output = Buffer::New((char*) data, dataSize)->handle_;
+ } else if (args.Length() > 0 && args[0]->IsString()) {
+ output = EncodeWithEncoding(args[0], data, dataSize);
} else {
- outString = Encode(data, dataSize, BINARY);
+ output = Encode(data, dataSize, BINARY);
}
delete[] data;
- return scope.Close(outString);
+ return scope.Close(output);
}
static Handle<Value> GetPrivateKey(const Arguments& args) {
@@ -3902,17 +3855,19 @@ class DiffieHellman : public ObjectWrap {
BN_bn2bin(diffieHellman->dh->priv_key,
reinterpret_cast<unsigned char*>(data));
- Local<Value> outString;
+ Handle<Value> output;
- if (args.Length() > 0 && args[0]->IsString()) {
- outString = EncodeWithEncoding(args[0], data, dataSize);
+ if (args[0]->IsNull()) {
+ output = Buffer::New((char*) data, dataSize)->handle_;
+ } else if (args.Length() > 0 && args[0]->IsString()) {
+ output = EncodeWithEncoding(args[0], data, dataSize);
} else {
- outString = Encode(data, dataSize, BINARY);
+ output = Encode(data, dataSize, BINARY);
}
delete[] data;
- return scope.Close(outString);
+ return scope.Close(output);
}
static Handle<Value> ComputeSecret(const Arguments& args) {
@@ -3964,7 +3919,7 @@ class DiffieHellman : public ObjectWrap {
key, diffieHellman->dh);
BN_free(key);
- Local<Value> outString;
+ Handle<Value> output;
// DH_size returns number of bytes in a prime number
// DH_compute_key returns number of bytes in a remainder of exponent, which
@@ -3993,17 +3948,19 @@ class DiffieHellman : public ObjectWrap {
return ThrowException(Exception::Error(String::New("Invalid key")));
}
} else {
- if (args.Length() > 2 && args[2]->IsString()) {
- outString = EncodeWithEncoding(args[2], data, dataSize);
+ if (args.Length() > 2 && args[2]->IsNull()) {
+ output = Buffer::New((char*) data, dataSize)->handle_;
+ } else if (args.Length() > 2 && args[2]->IsString()) {
+ output = EncodeWithEncoding(args[2], data, dataSize);
} else if (args.Length() > 1 && args[1]->IsString()) {
- outString = EncodeWithEncoding(args[1], data, dataSize);
+ output = EncodeWithEncoding(args[1], data, dataSize);
} else {
- outString = Encode(data, dataSize, BINARY);
+ output = Encode(data, dataSize, BINARY);
}
}
delete[] data;
- return scope.Close(outString);
+ return scope.Close(output);
}
static Handle<Value> SetPublicKey(const Arguments& args) {
View
83 test/simple/test-crypto.js
@@ -364,6 +364,12 @@ for (var i = 0, l = rfc2202_sha1.length; i < l; i++) {
'Test HMAC-SHA1 : Test case ' + (i + 1) + ' rfc 2202');
}
+var db = crypto.createHmac('md5', rfc2202_md5[0]['key'])
+ .update(rfc2202_md5[0]['data'])
+ .digest(null);
+assert.ok(Buffer.isBuffer(db));
+assert.equal(rfc2202_md5[0]['hmac'], db.toString('hex'), 'hmac digest buffer');
+
// Test hashing
var a0 = crypto.createHash('sha1').update('Test123').digest('hex');
var a1 = crypto.createHash('md5').update('Test123').digest('binary');
@@ -399,6 +405,9 @@ fileStream.on('close', function() {
'22723e553129a336ad96e10f6aecdf0f45e4149e',
'Test SHA1 of sample.png');
});
+var db = crypto.createHash('sha1').update(new Buffer('Test123')).digest(null);
+assert.ok(Buffer.isBuffer(db));
+assert.equal(h1, db.toString('hex'), 'hash digest buffer');
// Issue #2227: unknown digest method should throw an error.
assert.throws(function() {
@@ -436,10 +445,38 @@ function testCipher1(key) {
// Only use binary or hex, not base64.
ciph += cipher.final('hex');
+ cipher = crypto.createCipher('aes192', key);
+ //cypher text as buffer
+ var ctb1 = cipher.update(plaintext, 'utf8', null);
+ var ctb2 = cipher.final(null);
+
+ assert.ok(Buffer.isBuffer(ctb1));
+ assert.ok(Buffer.isBuffer(ctb2));
+
+ var ctb = new Buffer(ctb1.length + ctb2.length);
+ ctb1.copy(ctb);
+ ctb2.copy(ctb, ctb1.length);
+
+ assert.equal(ciph, ctb.toString('hex'), 'cipher output as buffer');
+
var decipher = crypto.createDecipher('aes192', key);
var txt = decipher.update(ciph, 'hex', 'utf8');
txt += decipher.final('utf8');
+ decipher = crypto.createDecipher('aes192', 'MySecretKey123');
+ //plain text as buffer
+ var ptb1 = decipher.update(ciph, 'hex', null);
+ var ptb2 = decipher.final(null);
+
+ assert.ok(Buffer.isBuffer(ptb1));
+ assert.ok(Buffer.isBuffer(ptb2));
+
+ var ptb = new Buffer(ptb1.length + ptb2.length);
+ ptb1.copy(ptb);
+ ptb2.copy(ptb, ptb1.length);
+
+ assert.equal(txt, ptb.toString('utf8'), 'decipher output as buffer');
+
assert.equal(txt, plaintext, 'encryption and decryption');
}
@@ -521,15 +558,43 @@ var privkey1 = dh1.getPrivateKey();
dh3.setPublicKey(key1);
dh3.setPrivateKey(privkey1);
-assert.equal(dh1.getPrime(), dh3.getPrime());
-assert.equal(dh1.getGenerator(), dh3.getGenerator());
-assert.equal(dh1.getPublicKey(), dh3.getPublicKey());
-assert.equal(dh1.getPrivateKey(), dh3.getPrivateKey());
+assert.equal(dh1.getPrime(null).toString('binary'), dh3.getPrime());
+assert.equal(dh1.getGenerator(), dh3.getGenerator(null).toString('binary'));
+assert.equal(dh1.getPublicKey(null).toString('base64'), dh3.getPublicKey(null).toString('base64'));
+assert.equal(dh1.getPrivateKey(null).toString('binary'), dh3.getPrivateKey());
+assert.ok(Buffer.isBuffer(dh1.getPrime(null)));
+assert.ok(Buffer.isBuffer(dh1.getGenerator(null)));
+assert.ok(Buffer.isBuffer(dh1.getPublicKey(null)));
+assert.ok(Buffer.isBuffer(dh1.getPrivateKey(null)));
var secret3 = dh3.computeSecret(key2, 'hex', 'base64');
assert.equal(secret1, secret3);
+// Test with yet another dh1, now using buffers
+var dh4 = crypto.createDiffieHellman(new Buffer(p1, 'base64'));
+dh4.setPublicKey(key1);
+dh4.setPrivateKey(privkey1);
+
+var secret4 = dh4.computeSecret(new Buffer(key2, 'hex'), null, 'base64');
+
+assert.equal(secret1, secret4);
+
+// Test Diffie-Hellman outputing buffers
+var dh5 = crypto.createDiffieHellman(256);
+var p2 = dh5.getPrime(null);
+var dh6 = crypto.createDiffieHellman(p2, null);
+var key5 = dh5.generateKeys(null);
+var key6 = dh6.generateKeys('base64');
+var secret5 = dh5.computeSecret(key6, 'base64', null);
+var secret6 = dh6.computeSecret(key5, null, null);
+
+assert.ok(Buffer.isBuffer(key5));
+assert.ok(Buffer.isBuffer(p2));
+assert.ok(Buffer.isBuffer(secret5));
+assert.ok(Buffer.isBuffer(secret6));
+assert.equal(secret5.toString('hex'), secret6.toString('hex'));
+
// https://github.com/joyent/node/issues/2338
assert.throws(function() {
var p = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' +
@@ -557,6 +622,16 @@ assert.equal(rsaSignature,
rsaVerify.update(rsaPubPem);
assert.strictEqual(rsaVerify.verify(rsaPubPem, rsaSignature, 'hex'), true);
+var bufSign = crypto.createSign('RSA-SHA1');
+var bufVerify = crypto.createVerify('RSA-SHA1');
+
+bufSign.update(rsaPubPem);
+var bufSignature = bufSign.sign(rsaKeyPem, null);
+assert.ok(Buffer.isBuffer(bufSignature));
+assert.equal(rsaSignature, bufSignature.toString('hex'));
+
+bufVerify.update(rsaPubPem);
+assert.strictEqual(bufVerify.verify(rsaPubPem, bufSignature), true);
//
// Test RSA signing and verification
Something went wrong with that request. Please try again.