summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFedor Indutny <fedor.indutny@gmail.com>2012-09-13 00:35:59 +0400
committerFedor Indutny <fedor.indutny@gmail.com>2012-09-18 10:58:37 +0400
commit63ff449d87e23b5e3d475da960135c1a2fd0ed58 (patch)
tree74edcf4b4a3ad5496c69cdcf0d169ac96c496524
parent3301c90ff7857ef71de69e090d182ede60554a90 (diff)
downloadnode-63ff449d87e23b5e3d475da960135c1a2fd0ed58.tar.gz
crypto: bring module into modern age
Introduce 'buffer' encoding, allow returning and giving buffers as arguments of 'crypto' routines. Fix #3278
-rw-r--r--doc/api/crypto.markdown51
-rw-r--r--src/node.cc12
-rw-r--r--src/node.h2
-rw-r--r--src/node_crypto.cc205
-rw-r--r--test/simple/test-crypto-padding-aes256.js4
-rw-r--r--test/simple/test-crypto.js41
6 files changed, 173 insertions, 142 deletions
diff --git a/doc/api/crypto.markdown b/doc/api/crypto.markdown
index 87b9ac378..91095a202 100644
--- a/doc/api/crypto.markdown
+++ b/doc/api/crypto.markdown
@@ -64,14 +64,14 @@ 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'`.
+in `input_encoding` and can be `'buffer'`, `'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 `'buffer'`, `'hex'`, `'binary'` or `'base64'`.
Defaults to `'binary'`.
Note: `hash` object can not be used after `digest()` method been called.
@@ -98,7 +98,7 @@ 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 `'buffer'`, `'hex'`, `'binary'` or `'base64'`.
Defaults to `'binary'`.
Note: `hmac` object can not be used after `digest()` method been called.
@@ -134,18 +134,18 @@ 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'`.
+`input_encoding` and can be `'buffer'`, `'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'`.
+and can be `'buffer'`, `'binary'`, `'base64'` or `'hex'`. Defaults to `'binary'`.
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'`.
+`'buffer'`, `'binary'`, `'base64'` or `'hex'`. Defaults to `'binary'`.
Note: `cipher` object can not be used after `final()` method been called.
@@ -174,16 +174,18 @@ 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 is encoded in `'buffer'`, `'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: `'buffer'`, `'binary'`, `'ascii'` or `'utf8'`.
+Defaults to `'binary'`.
### decipher.final([output_encoding])
Returns any remaining plaintext which is deciphered,
-with `output_encoding` being one of: `'binary'`, `'ascii'` or `'utf8'`.
+with `output_encoding` being one of: `'buffer'`, `'binary'`, `'ascii'` or
+`'utf8'`.
Defaults to `'binary'`.
Note: `decipher` object can not be used after `final()` method been called.
@@ -216,8 +218,8 @@ This can be called many times with new data as it is streamed.
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_format` which can be `'buffer'`, `'binary'`,
+`'hex'` or `'base64'`. Defaults to `'binary'`.
Note: `signer` object can not be used after `sign()` method been called.
@@ -242,8 +244,8 @@ This can be called many times with new data as it is streamed.
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, in the `signature_format` which can be `'buffer'`,
+`'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 +259,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`. Encoding can be `'buffer'`, `'binary'`, `'hex'`, or
+`'base64'`.
Defaults to `'binary'`.
## Class: DiffieHellman
@@ -278,19 +281,19 @@ Defaults to `'binary'`.
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'`.
+specified `output_encoding`. Encodings can be `'buffer'`, `'binary'`, `'hex'`,
+or `'base64'`. 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'`.
+`'buffer'`, `'binary'`, `'hex'`, or `'base64'`. 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'`.
+`'buffer'`, `'binary'`, `'hex'`, or `'base64'`. Defaults to `'binary'`.
### diffieHellman.getPublicKey([encoding])
@@ -300,17 +303,17 @@ be `'binary'`, `'hex'`, or `'base64'`. 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 `'buffer'`, `'binary'`, `'hex'`, or `'base64'`. 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 encoding can be `'buffer', ``'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 encoding can be `'buffer'`, `'binary'`,
+`'hex'` or `'base64'`. Defaults to `'binary'`.
## crypto.getDiffieHellman(group_name)
diff --git a/src/node.cc b/src/node.cc
index 107816ed4..d6c8fb3a1 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -1067,6 +1067,8 @@ enum encoding ParseEncoding(Handle<Value> encoding_v, enum encoding _default) {
return UCS2;
} else if (strcasecmp(*encoding, "binary") == 0) {
return BINARY;
+ } else if (strcasecmp(*encoding, "buffer") == 0) {
+ return BUFFER;
} else if (strcasecmp(*encoding, "hex") == 0) {
return HEX;
} else if (strcasecmp(*encoding, "raw") == 0) {
@@ -1089,6 +1091,11 @@ enum encoding ParseEncoding(Handle<Value> encoding_v, enum encoding _default) {
Local<Value> Encode(const void *buf, size_t len, enum encoding encoding) {
HandleScope scope;
+ if (encoding == BUFFER) {
+ return scope.Close(
+ Buffer::New(static_cast<const char*>(buf), len)->handle_);
+ }
+
if (!len) return scope.Close(String::Empty());
if (encoding == BINARY) {
@@ -1119,7 +1126,7 @@ ssize_t DecodeBytes(v8::Handle<v8::Value> val, enum encoding encoding) {
return -1;
}
- if (encoding == BINARY && Buffer::HasInstance(val)) {
+ if ((encoding == BUFFER || encoding == BINARY) && Buffer::HasInstance(val)) {
return Buffer::Length(val->ToObject());
}
@@ -1158,7 +1165,8 @@ ssize_t DecodeWrite(char *buf,
bool is_buffer = Buffer::HasInstance(val);
- if (is_buffer && encoding == BINARY) { // fast path, copy buffer data
+ if (is_buffer && (encoding == BINARY || encoding == BUFFER)) {
+ // fast path, copy buffer data
const char* data = Buffer::Data(val.As<Object>());
size_t size = Buffer::Length(val.As<Object>());
size_t len = size < buflen ? size : buflen;
diff --git a/src/node.h b/src/node.h
index 56e36239e..96347ad4f 100644
--- a/src/node.h
+++ b/src/node.h
@@ -127,7 +127,7 @@ void SetPrototypeMethod(target_t target,
#define NODE_SET_METHOD node::SetMethod
#define NODE_SET_PROTOTYPE_METHOD node::SetPrototypeMethod
-enum encoding {ASCII, UTF8, BASE64, UCS2, BINARY, HEX};
+enum encoding {ASCII, UTF8, BASE64, UCS2, BINARY, HEX, BUFFER};
enum encoding ParseEncoding(v8::Handle<v8::Value> encoding_v,
enum encoding _default = BINARY);
NODE_EXTERN void FatalException(v8::TryCatch &try_catch);
diff --git a/src/node_crypto.cc b/src/node_crypto.cc
index f04657960..da4cfb6dc 100644
--- a/src/node_crypto.cc
+++ b/src/node_crypto.cc
@@ -1621,7 +1621,8 @@ Handle<Value> Connection::SetSession(const Arguments& args) {
Connection *ss = Connection::Unwrap(args);
- if (args.Length() < 1 || !args[0]->IsString()) {
+ if (args.Length() < 1 ||
+ (!args[0]->IsString() && !Buffer::HasInstance(args[0]))) {
Local<Value> exception = Exception::TypeError(String::New("Bad argument"));
return ThrowException(exception);
}
@@ -2379,53 +2380,49 @@ class Cipher : public ObjectWrap {
}
Local<Value> outString;
- if (out_len==0) {
- outString=String::New("");
- } else {
- char* out_hexdigest;
- int out_hex_len;
- enum encoding enc = ParseEncoding(args[2], BINARY);
- if (enc == HEX) {
- // Hex encoding
- HexEncode(out, out_len, &out_hexdigest, &out_hex_len);
- outString = Encode(out_hexdigest, out_hex_len, BINARY);
- delete [] out_hexdigest;
- } else if (enc == BASE64) {
- // Base64 encoding
- // 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, out_len);
- delete [] out;
-
- delete [] cipher->incomplete_base64;
- cipher->incomplete_base64=NULL;
-
- out=complete_base64;
- out_len += cipher->incomplete_base64_len;
- }
+ char* out_hexdigest;
+ int out_hex_len;
+ enum encoding out_enc = ParseEncoding(args[2], BINARY);
+ if (out_enc == HEX) {
+ // Hex encoding
+ HexEncode(out, out_len, &out_hexdigest, &out_hex_len);
+ outString = Encode(out_hexdigest, out_hex_len, BINARY);
+ delete [] out_hexdigest;
+ } else if (out_enc == BASE64) {
+ // Base64 encoding
+ // 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, out_len);
+ delete [] out;
- // Check to see if we need to trim base64 stream
- if (out_len%3!=0){
- cipher->incomplete_base64_len = out_len%3;
- cipher->incomplete_base64 = new char[cipher->incomplete_base64_len+1];
- memcpy(cipher->incomplete_base64,
- &out[out_len-cipher->incomplete_base64_len],
- cipher->incomplete_base64_len);
- out_len -= cipher->incomplete_base64_len;
- out[out_len]=0;
- }
+ delete [] cipher->incomplete_base64;
+ cipher->incomplete_base64=NULL;
- base64(out, 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, out_len, BINARY);
- } else {
- fprintf(stderr, "node-crypto : Cipher .update encoding "
- "can be binary, hex or base64\n");
+ out=complete_base64;
+ out_len += cipher->incomplete_base64_len;
}
+
+ // Check to see if we need to trim base64 stream
+ if (out_len%3!=0){
+ cipher->incomplete_base64_len = out_len%3;
+ cipher->incomplete_base64 = new char[cipher->incomplete_base64_len+1];
+ memcpy(cipher->incomplete_base64,
+ &out[out_len-cipher->incomplete_base64_len],
+ cipher->incomplete_base64_len);
+ out_len -= cipher->incomplete_base64_len;
+ out[out_len]=0;
+ }
+
+ base64(out, out_len, &out_hexdigest, &out_hex_len);
+ outString = Encode(out_hexdigest, out_hex_len, BINARY);
+ delete [] out_hexdigest;
+ } else if (out_enc == BINARY || out_enc == BUFFER) {
+ outString = Encode(out, out_len, out_enc);
+ } else {
+ fprintf(stderr, "node-crypto : Cipher .update encoding "
+ "can be binary, buffer, hex or base64\n");
}
if (out) delete [] out;
@@ -2461,12 +2458,11 @@ class Cipher : public ObjectWrap {
if (out_len == 0 || r == 0) {
// out_value always get allocated.
delete[] out_value;
+ out_value = NULL;
if (r == 0) {
Local<Value> exception = Exception::TypeError(
String::New("CipherFinal fail"));
return ThrowException(exception);
- } else {
- return scope.Close(String::New(""));
}
}
@@ -2493,11 +2489,11 @@ class Cipher : public ObjectWrap {
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);
+ } else if (enc == BINARY || enc == BUFFER) {
+ outString = Encode(out_value, out_len, enc);
} else {
fprintf(stderr, "node-crypto : Cipher .final encoding "
- "can be binary, hex or base64\n");
+ "can be binary, buffer, hex or base64\n");
}
delete [] out_value;
@@ -2826,12 +2822,12 @@ class Decipher : public ObjectWrap {
len = ciphertext_len;
alloc_buf = true;
- } else if (enc == BINARY) {
+ } else if (enc == BINARY || enc == BUFFER) {
// Binary - do nothing
} else {
fprintf(stderr, "node-crypto : Decipher .update encoding "
- "can be binary, hex or base64\n");
+ "can be binary, buffer, hex or base64\n");
}
unsigned char *out=0;
@@ -2845,35 +2841,31 @@ class Decipher : public ObjectWrap {
}
Local<Value> outString;
- if (out_len==0) {
- outString=String::New("");
- } else {
- enum encoding enc = ParseEncoding(args[2], BINARY);
- if (enc == UTF8) {
- // See if we have any overhang from last utf8 partial ending
- if (cipher->incomplete_utf8!=NULL) {
- char* complete_out = new char[cipher->incomplete_utf8_len + out_len];
- memcpy(complete_out, cipher->incomplete_utf8, cipher->incomplete_utf8_len);
- memcpy((char *)complete_out+cipher->incomplete_utf8_len, out, out_len);
- delete [] out;
-
- delete [] cipher->incomplete_utf8;
- cipher->incomplete_utf8 = NULL;
-
- out = (unsigned char*)complete_out;
- out_len += cipher->incomplete_utf8_len;
- }
- // Check to see if we have a complete utf8 stream
- int utf8_len = LengthWithoutIncompleteUtf8((char *)out, out_len);
- if (utf8_len<out_len) { // We have an incomplete ut8 ending
- cipher->incomplete_utf8_len = out_len-utf8_len;
- 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);
- } else {
- outString = Encode(out, out_len, enc);
+ enum encoding out_enc = ParseEncoding(args[2], BINARY);
+ if (out_enc == UTF8) {
+ // See if we have any overhang from last utf8 partial ending
+ if (cipher->incomplete_utf8!=NULL) {
+ char* complete_out = new char[cipher->incomplete_utf8_len + out_len];
+ memcpy(complete_out, cipher->incomplete_utf8, cipher->incomplete_utf8_len);
+ memcpy((char *)complete_out+cipher->incomplete_utf8_len, out, out_len);
+ delete [] out;
+
+ delete [] cipher->incomplete_utf8;
+ cipher->incomplete_utf8 = NULL;
+
+ out = (unsigned char*)complete_out;
+ out_len += cipher->incomplete_utf8_len;
+ }
+ // Check to see if we have a complete utf8 stream
+ int utf8_len = LengthWithoutIncompleteUtf8((char *)out, out_len);
+ if (utf8_len<out_len) { // We have an incomplete ut8 ending
+ cipher->incomplete_utf8_len = out_len-utf8_len;
+ 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, out_enc);
+ } else {
+ outString = Encode(out, out_len, out_enc);
}
if (out) delete [] out;
@@ -2908,19 +2900,18 @@ class Decipher : public ObjectWrap {
if (out_len == 0 || r == 0) {
delete [] out_value; // allocated even if out_len == 0
+ out_value = NULL;
if (r == 0) {
Local<Value> exception = Exception::TypeError(
String::New("DecipherFinal fail"));
return ThrowException(exception);
- } else {
- return scope.Close(String::New(""));
}
}
if (args.Length() == 0 || !args[0]->IsString()) {
outString = Encode(out_value, out_len, BINARY);
} else {
- enum encoding enc = ParseEncoding(args[0]);
+ enum encoding enc = ParseEncoding(args[0], BINARY);
if (enc == UTF8) {
// See if we have any overhang from last utf8 partial ending
if (cipher->incomplete_utf8!=NULL) {
@@ -3118,8 +3109,9 @@ class Hmac : public ObjectWrap {
Local<Value> outString;
int r = hmac->HmacDigest(&md_value, &md_len);
- if (md_len == 0 || r == 0) {
- return scope.Close(String::New(""));
+ if (r == 0) {
+ md_value = NULL;
+ md_len = 0;
}
enum encoding enc = ParseEncoding(args[0], BINARY);
@@ -3132,11 +3124,11 @@ class Hmac : public ObjectWrap {
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);
+ } else if (enc == BINARY || enc == BUFFER) {
+ outString = Encode(md_value, md_len, enc);
} else {
fprintf(stderr, "node-crypto : Hmac .digest encoding "
- "can be binary, hex or base64\n");
+ "can be binary, buffer, hex or base64\n");
}
delete [] md_value;
return scope.Close(outString);
@@ -3267,10 +3259,6 @@ class Hash : public ObjectWrap {
EVP_MD_CTX_cleanup(&hash->mdctx);
hash->initialised_ = false;
- if (md_len == 0) {
- return scope.Close(String::New(""));
- }
-
Local<Value> outString;
enum encoding enc = ParseEncoding(args[0], BINARY);
@@ -3287,11 +3275,11 @@ class Hash : public ObjectWrap {
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);
+ } else if (enc == BINARY || enc == BUFFER) {
+ outString = Encode(md_value, md_len, enc);
} else {
fprintf(stderr, "node-crypto : Hash .digest encoding "
- "can be binary, hex or base64\n");
+ "can be binary, buffer, hex or base64\n");
}
return scope.Close(outString);
@@ -3471,14 +3459,13 @@ class Sign : public ObjectWrap {
assert(written == len);
int r = sign->SignFinal(&md_value, &md_len, buf, len);
+ if (r == 0) {
+ md_value = NULL;
+ md_len = r;
+ }
delete [] buf;
- if (md_len == 0 || r == 0) {
- delete [] md_value;
- return scope.Close(String::New(""));
- }
-
enum encoding enc = ParseEncoding(args[1], BINARY);
if (enc == HEX) {
// Hex encoding
@@ -3489,12 +3476,12 @@ class Sign : public ObjectWrap {
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);
+ } else if (enc == BINARY || enc == BUFFER) {
+ outString = Encode(md_value, md_len, enc);
} else {
outString = String::New("");
fprintf(stderr, "node-crypto : Sign .sign encoding "
- "can be binary, hex or base64\n");
+ "can be binary, buffer, hex or base64\n");
}
delete [] md_value;
@@ -3741,11 +3728,11 @@ class Verify : public ObjectWrap {
unbase64(hbuf, hlen, (char **)&dbuf, &dlen);
r = verify->VerifyFinal(kbuf, klen, dbuf, dlen);
delete [] dbuf;
- } else if (enc == BINARY) {
+ } else if (enc == BINARY || enc == BUFFER) {
r = verify->VerifyFinal(kbuf, klen, hbuf, hlen);
} else {
fprintf(stderr, "node-crypto : Verify .verify encoding "
- "can be binary, hex or base64\n");
+ "can be binary, buffer, hex or base64\n");
}
delete [] kbuf;
@@ -4301,7 +4288,7 @@ class DiffieHellman : public ObjectWrap {
// Binary - do nothing
} else {
fprintf(stderr, "node-crypto : Diffie-Hellman parameter encoding "
- "can be binary, hex or base64\n");
+ "can be binary, buffer, hex or base64\n");
}
if (retbuf != 0) {
@@ -4331,11 +4318,11 @@ class DiffieHellman : public ObjectWrap {
base64(reinterpret_cast<unsigned char*>(buf), len, &retbuf, &retlen);
outString = Encode(retbuf, retlen, BINARY);
delete [] retbuf;
- } else if (enc == BINARY) {
- outString = Encode(buf, len, BINARY);
+ } else if (enc == BINARY || enc == BUFFER) {
+ outString = Encode(buf, len, enc);
} else {
fprintf(stderr, "node-crypto : Diffie-Hellman parameter encoding "
- "can be binary, hex or base64\n");
+ "can be binary, buffer, hex or base64\n");
}
return scope.Close(outString);
diff --git a/test/simple/test-crypto-padding-aes256.js b/test/simple/test-crypto-padding-aes256.js
index 83bc517fb..e3b5518a8 100644
--- a/test/simple/test-crypto-padding-aes256.js
+++ b/test/simple/test-crypto-padding-aes256.js
@@ -37,13 +37,13 @@ function aes256(decipherFinal) {
function encrypt(val, pad) {
var c = crypto.createCipheriv('aes256', key, iv);
c.setAutoPadding(pad);
- return c.update(val, 'utf8') + c.final('binary');
+ return c.update(val, 'utf8', 'binary') + c.final('binary');
}
function decrypt(val, pad) {
var c = crypto.createDecipheriv('aes256', key, iv);
c.setAutoPadding(pad);
- return c.update(val, 'binary') + c[decipherFinal]('utf8');
+ return c.update(val, 'binary', 'binary') + c[decipherFinal]('utf8');
}
// echo 0123456789abcdef0123456789abcdef \
diff --git a/test/simple/test-crypto.js b/test/simple/test-crypto.js
index abd83247d..b1517740e 100644
--- a/test/simple/test-crypto.js
+++ b/test/simple/test-crypto.js
@@ -369,6 +369,7 @@ var a0 = crypto.createHash('sha1').update('Test123').digest('hex');
var a1 = crypto.createHash('md5').update('Test123').digest('binary');
var a2 = crypto.createHash('sha256').update('Test123').digest('base64');
var a3 = crypto.createHash('sha512').update('Test123').digest(); // binary
+var a4 = crypto.createHash('sha1').update('Test123').digest('buffer');
assert.equal(a0, '8308651804facb7b9af8ffc53a33a22d6a1c8ac2', 'Test SHA1');
assert.equal(a1, 'h\u00ea\u00cb\u0097\u00d8o\fF!\u00fa+\u000e\u0017\u00ca' +
@@ -381,6 +382,9 @@ assert.equal(a3, '\u00c1(4\u00f1\u0003\u001fd\u0097!O\'\u00d4C/&Qz\u00d4' +
'\u00d7\u00d6\u00a2\u00a8\u0085\u00e3<\u0083\u009c\u0093' +
'\u00c2\u0006\u00da0\u00a1\u00879(G\u00ed\'',
'Test SHA512 as assumed binary');
+assert.deepEqual(a4,
+ new Buffer('8308651804facb7b9af8ffc53a33a22d6a1c8ac2', 'hex'),
+ 'Test SHA1');
// Test multiple updates to same hash
var h1 = crypto.createHash('sha1').update('Test123').digest('hex');
@@ -424,6 +428,15 @@ var verified = crypto.createVerify('RSA-SHA256')
.verify(certPem, s2); // binary
assert.strictEqual(verified, true, 'sign and verify (binary)');
+var s3 = crypto.createSign('RSA-SHA1')
+ .update('Test123')
+ .sign(keyPem, 'buffer');
+var verified = crypto.createVerify('RSA-SHA1')
+ .update('Test')
+ .update('123')
+ .verify(certPem, s3);
+assert.strictEqual(verified, true, 'sign and verify (buffer)');
+
function testCipher1(key) {
// Test encryption and decryption
@@ -484,6 +497,24 @@ function testCipher3(key, iv) {
}
+function testCipher4(key, iv) {
+ // Test encyrption and decryption with explicit key and iv
+ var plaintext =
+ '32|RmVZZkFUVmpRRkp0TmJaUm56ZU9qcnJkaXNNWVNpTTU*|iXmckfRWZBGWWELw' +
+ 'eCBsThSsfUHLeRe0KCsK8ooHgxie0zOINpXxfZi/oNG7uq9JWFVCk70gfzQH8ZUJ' +
+ 'jAfaFg**';
+ var cipher = crypto.createCipheriv('des-ede3-cbc', key, iv);
+ var ciph = cipher.update(plaintext, 'utf8', 'buffer');
+ ciph = Buffer.concat([ciph, cipher.final('buffer')]);
+
+ var decipher = crypto.createDecipheriv('des-ede3-cbc', key, iv);
+ var txt = decipher.update(ciph, 'buffer', 'utf8');
+ txt += decipher.final('utf8');
+
+ assert.equal(txt, plaintext, 'encryption and decryption with key and iv');
+}
+
+
testCipher1('MySecretKey123');
testCipher1(new Buffer('MySecretKey123'));
@@ -495,6 +526,8 @@ testCipher3('0123456789abcd0123456789', new Buffer('12345678'));
testCipher3(new Buffer('0123456789abcd0123456789'), '12345678');
testCipher3(new Buffer('0123456789abcd0123456789'), new Buffer('12345678'));
+testCipher4(new Buffer('0123456789abcd0123456789'), new Buffer('12345678'));
+
// update() should only take buffers / strings
assert.throws(function() {
@@ -505,18 +538,18 @@ assert.throws(function() {
// Test Diffie-Hellman with two parties sharing a secret,
// using various encodings as we go along
var dh1 = crypto.createDiffieHellman(256);
-var p1 = dh1.getPrime('base64');
+var p1 = dh1.getPrime('buffer');
var dh2 = crypto.createDiffieHellman(p1, 'base64');
var key1 = dh1.generateKeys();
var key2 = dh2.generateKeys('hex');
var secret1 = dh1.computeSecret(key2, 'hex', 'base64');
-var secret2 = dh2.computeSecret(key1, 'binary', 'base64');
+var secret2 = dh2.computeSecret(key1, 'binary', 'buffer');
-assert.equal(secret1, secret2);
+assert.equal(secret1, secret2.toString('base64'));
// Create "another dh1" using generated keys from dh1,
// and compute secret again
-var dh3 = crypto.createDiffieHellman(p1, 'base64');
+var dh3 = crypto.createDiffieHellman(p1, 'buffer');
var privkey1 = dh1.getPrivateKey();
dh3.setPublicKey(key1);
dh3.setPrivateKey(privkey1);