diff options
author | Fedor Indutny <fedor.indutny@gmail.com> | 2012-09-13 00:35:59 +0400 |
---|---|---|
committer | Fedor Indutny <fedor.indutny@gmail.com> | 2012-09-18 10:58:37 +0400 |
commit | 63ff449d87e23b5e3d475da960135c1a2fd0ed58 (patch) | |
tree | 74edcf4b4a3ad5496c69cdcf0d169ac96c496524 | |
parent | 3301c90ff7857ef71de69e090d182ede60554a90 (diff) | |
download | node-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.markdown | 51 | ||||
-rw-r--r-- | src/node.cc | 12 | ||||
-rw-r--r-- | src/node.h | 2 | ||||
-rw-r--r-- | src/node_crypto.cc | 205 | ||||
-rw-r--r-- | test/simple/test-crypto-padding-aes256.js | 4 | ||||
-rw-r--r-- | test/simple/test-crypto.js | 41 |
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); |