Skip to content

Commit a1eacdf

Browse files
committed
crypto: Pass strings to binding layer directly
1 parent 119354f commit a1eacdf

2 files changed

Lines changed: 102 additions & 52 deletions

File tree

lib/crypto.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,8 @@ util.inherits(LazyTransform, stream.Transform);
163163
Object.defineProperty(LazyTransform.prototype, prop, {
164164
get: function() {
165165
stream.Transform.call(this, this._options);
166+
this._writableState.decodeStrings = false;
167+
this._writableState.defaultEncoding = 'binary';
166168
return this[prop];
167169
},
168170
set: function(val) {
@@ -201,8 +203,9 @@ Hash.prototype._flush = function(callback) {
201203

202204
Hash.prototype.update = function(data, encoding) {
203205
encoding = encoding || exports.DEFAULT_ENCODING;
204-
data = toBuf(data, encoding);
205-
this._binding.update(data);
206+
if (encoding === 'buffer' && typeof data === 'string')
207+
encoding = 'binary';
208+
this._binding.update(data, encoding);
206209
return this;
207210
};
208211

@@ -268,9 +271,8 @@ Cipher.prototype._flush = function(callback) {
268271
Cipher.prototype.update = function(data, inputEncoding, outputEncoding) {
269272
inputEncoding = inputEncoding || exports.DEFAULT_ENCODING;
270273
outputEncoding = outputEncoding || exports.DEFAULT_ENCODING;
271-
data = toBuf(data, inputEncoding);
272274

273-
var ret = this._binding.update(data);
275+
var ret = this._binding.update(data, inputEncoding);
274276

275277
if (outputEncoding && outputEncoding !== 'buffer') {
276278
this._decoder = getDecoder(this._decoder, outputEncoding);

src/node_crypto.cc

Lines changed: 96 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
#include "node.h"
2727
#include "node_buffer.h"
28+
#include "string_bytes.h"
2829
#include "node_root_certs.h"
2930

3031
#include <string.h>
@@ -41,6 +42,12 @@
4142
# define OPENSSL_CONST
4243
#endif
4344

45+
#define ASSERT_IS_STRING_OR_BUFFER(val) \
46+
if (!Buffer::HasInstance(val) && !val->IsString()) { \
47+
return ThrowException(Exception::TypeError(String::New( \
48+
"Not a string or buffer"))); \
49+
}
50+
4451
#define ASSERT_IS_BUFFER(val) \
4552
if (!Buffer::HasInstance(val)) { \
4653
return ThrowException(Exception::TypeError(String::New("Not a buffer"))); \
@@ -2225,24 +2232,33 @@ class Cipher : public ObjectWrap {
22252232

22262233
HandleScope scope;
22272234

2228-
ASSERT_IS_BUFFER(args[0]);
2235+
ASSERT_IS_STRING_OR_BUFFER(args[0]);
22292236

2237+
// Only copy the data if we have to, because it's a string
22302238
unsigned char* out=0;
22312239
int out_len=0, r;
2232-
char* buffer_data = Buffer::Data(args[0]);
2233-
size_t buffer_length = Buffer::Length(args[0]);
2234-
2235-
r = cipher->CipherUpdate(buffer_data, buffer_length, &out, &out_len);
2240+
if (args[0]->IsString()) {
2241+
enum encoding encoding = ParseEncoding(args[1], BINARY);
2242+
size_t buflen = StringBytes::SizeFast(args[0], encoding);
2243+
char* buf = static_cast<char*>(malloc(buflen));
2244+
size_t written = StringBytes::Write(buf, buflen, args[0], encoding);
2245+
r = cipher->CipherUpdate(buf, written, &out, &out_len);
2246+
free(buf);
2247+
} else {
2248+
char* buf = Buffer::Data(args[0]);
2249+
size_t buflen = Buffer::Length(args[0]);
2250+
r = cipher->CipherUpdate(buf, buflen, &out, &out_len);
2251+
}
22362252

22372253
if (r == 0) {
2238-
delete [] out;
2254+
delete[] out;
22392255
return ThrowCryptoTypeError(ERR_get_error());
22402256
}
22412257

22422258
Local<Value> outString;
22432259
outString = Encode(out, out_len, BUFFER);
22442260

2245-
if (out) delete [] out;
2261+
if (out) delete[] out;
22462262

22472263
return scope.Close(outString);
22482264
}
@@ -2525,25 +2541,26 @@ class Decipher : public ObjectWrap {
25252541

25262542
Decipher *cipher = ObjectWrap::Unwrap<Decipher>(args.This());
25272543

2528-
ASSERT_IS_BUFFER(args[0]);
2529-
2530-
ssize_t len;
2531-
2532-
char* buf;
2533-
// if alloc_buf then buf must be deleted later
2534-
bool alloc_buf = false;
2535-
char* buffer_data = Buffer::Data(args[0]);
2536-
size_t buffer_length = Buffer::Length(args[0]);
2537-
2538-
buf = buffer_data;
2539-
len = buffer_length;
2544+
ASSERT_IS_STRING_OR_BUFFER(args[0]);
25402545

2546+
// Only copy the data if we have to, because it's a string
25412547
unsigned char* out=0;
2542-
int out_len=0;
2543-
int r = cipher->DecipherUpdate(buf, len, &out, &out_len);
2548+
int out_len=0, r;
2549+
if (args[0]->IsString()) {
2550+
enum encoding encoding = ParseEncoding(args[1], BINARY);
2551+
size_t buflen = StringBytes::SizeFast(args[0], encoding);
2552+
char* buf = static_cast<char*>(malloc(buflen));
2553+
size_t written = StringBytes::Write(buf, buflen, args[0], encoding);
2554+
r = cipher->DecipherUpdate(buf, written, &out, &out_len);
2555+
free(buf);
2556+
} else {
2557+
char* buf = Buffer::Data(args[0]);
2558+
size_t buflen = Buffer::Length(args[0]);
2559+
r = cipher->DecipherUpdate(buf, buflen, &out, &out_len);
2560+
}
25442561

2545-
if (!r) {
2546-
delete [] out;
2562+
if (r == 0) {
2563+
delete[] out;
25472564
return ThrowCryptoTypeError(ERR_get_error());
25482565
}
25492566

@@ -2552,9 +2569,7 @@ class Decipher : public ObjectWrap {
25522569

25532570
if (out) delete [] out;
25542571

2555-
if (alloc_buf) delete [] buf;
25562572
return scope.Close(outString);
2557-
25582573
}
25592574

25602575
static Handle<Value> SetAutoPadding(const Arguments& args) {
@@ -2716,14 +2731,22 @@ class Hmac : public ObjectWrap {
27162731

27172732
HandleScope scope;
27182733

2719-
ASSERT_IS_BUFFER(args[0]);
2734+
ASSERT_IS_STRING_OR_BUFFER(args[0]);
27202735

2736+
// Only copy the data if we have to, because it's a string
27212737
int r;
2722-
2723-
char* buffer_data = Buffer::Data(args[0]);
2724-
size_t buffer_length = Buffer::Length(args[0]);
2725-
2726-
r = hmac->HmacUpdate(buffer_data, buffer_length);
2738+
if (args[0]->IsString()) {
2739+
enum encoding encoding = ParseEncoding(args[1], BINARY);
2740+
size_t buflen = StringBytes::SizeFast(args[0], encoding);
2741+
char* buf = static_cast<char*>(malloc(buflen));
2742+
size_t written = StringBytes::Write(buf, buflen, args[0], encoding);
2743+
r = hmac->HmacUpdate(buf, written);
2744+
free(buf);
2745+
} else {
2746+
char* buf = Buffer::Data(args[0]);
2747+
size_t buflen = Buffer::Length(args[0]);
2748+
r = hmac->HmacUpdate(buf, buflen);
2749+
}
27272750

27282751
if (!r) {
27292752
Local<Value> exception = Exception::TypeError(String::New("HmacUpdate fail"));
@@ -2831,13 +2854,22 @@ class Hash : public ObjectWrap {
28312854

28322855
Hash *hash = ObjectWrap::Unwrap<Hash>(args.This());
28332856

2834-
ASSERT_IS_BUFFER(args[0]);
2857+
ASSERT_IS_STRING_OR_BUFFER(args[0]);
28352858

2859+
// Only copy the data if we have to, because it's a string
28362860
int r;
2837-
2838-
char* buffer_data = Buffer::Data(args[0]);
2839-
size_t buffer_length = Buffer::Length(args[0]);
2840-
r = hash->HashUpdate(buffer_data, buffer_length);
2861+
if (args[0]->IsString()) {
2862+
enum encoding encoding = ParseEncoding(args[1], BINARY);
2863+
size_t buflen = StringBytes::SizeFast(args[0], encoding);
2864+
char* buf = static_cast<char*>(malloc(buflen));
2865+
size_t written = StringBytes::Write(buf, buflen, args[0], encoding);
2866+
r = hash->HashUpdate(buf, written);
2867+
free(buf);
2868+
} else {
2869+
char* buf = Buffer::Data(args[0]);
2870+
size_t buflen = Buffer::Length(args[0]);
2871+
r = hash->HashUpdate(buf, buflen);
2872+
}
28412873

28422874
if (!r) {
28432875
Local<Value> exception = Exception::TypeError(String::New("HashUpdate fail"));
@@ -2983,14 +3015,22 @@ class Sign : public ObjectWrap {
29833015

29843016
HandleScope scope;
29853017

2986-
ASSERT_IS_BUFFER(args[0]);
3018+
ASSERT_IS_STRING_OR_BUFFER(args[0]);
29873019

3020+
// Only copy the data if we have to, because it's a string
29883021
int r;
2989-
2990-
char* buffer_data = Buffer::Data(args[0]);
2991-
size_t buffer_length = Buffer::Length(args[0]);
2992-
2993-
r = sign->SignUpdate(buffer_data, buffer_length);
3022+
if (args[0]->IsString()) {
3023+
enum encoding encoding = ParseEncoding(args[1], BINARY);
3024+
size_t buflen = StringBytes::SizeFast(args[0], encoding);
3025+
char* buf = static_cast<char*>(malloc(buflen));
3026+
size_t written = StringBytes::Write(buf, buflen, args[0], encoding);
3027+
r = sign->SignUpdate(buf, written);
3028+
free(buf);
3029+
} else {
3030+
char* buf = Buffer::Data(args[0]);
3031+
size_t buflen = Buffer::Length(args[0]);
3032+
r = sign->SignUpdate(buf, buflen);
3033+
}
29943034

29953035
if (!r) {
29963036
Local<Value> exception = Exception::TypeError(String::New("SignUpdate fail"));
@@ -3194,14 +3234,22 @@ class Verify : public ObjectWrap {
31943234

31953235
Verify *verify = ObjectWrap::Unwrap<Verify>(args.This());
31963236

3197-
ASSERT_IS_BUFFER(args[0]);
3237+
ASSERT_IS_STRING_OR_BUFFER(args[0]);
31983238

3239+
// Only copy the data if we have to, because it's a string
31993240
int r;
3200-
3201-
char* buffer_data = Buffer::Data(args[0]);
3202-
size_t buffer_length = Buffer::Length(args[0]);
3203-
3204-
r = verify->VerifyUpdate(buffer_data, buffer_length);
3241+
if (args[0]->IsString()) {
3242+
enum encoding encoding = ParseEncoding(args[1], BINARY);
3243+
size_t buflen = StringBytes::SizeFast(args[0], encoding);
3244+
char* buf = static_cast<char*>(malloc(buflen));
3245+
size_t written = StringBytes::Write(buf, buflen, args[0], encoding);
3246+
r = verify->VerifyUpdate(buf, written);
3247+
free(buf);
3248+
} else {
3249+
char* buf = Buffer::Data(args[0]);
3250+
size_t buflen = Buffer::Length(args[0]);
3251+
r = verify->VerifyUpdate(buf, buflen);
3252+
}
32053253

32063254
if (!r) {
32073255
Local<Value> exception = Exception::TypeError(String::New("VerifyUpdate fail"));

0 commit comments

Comments
 (0)