Skip to content

Commit b010c87

Browse files
committed
crypto, string_bytes: treat buffer str as utf8
Do not treat crypto inputs as `binary` strings, convert them to Buffers using `new Buffer(..., 'utf8')`, or using newly updated StringBytes APIs. PR-URL: #5522 Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent 0eda5f5 commit b010c87

File tree

5 files changed

+27
-20
lines changed

5 files changed

+27
-20
lines changed

doc/api/crypto.markdown

+2-2
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,7 @@ called. Multiple calls will cause an error to be thrown.
601601
Updates the hash content with the given `data`, the encoding of which
602602
is given in `input_encoding` and can be `'utf8'`, `'ascii'` or
603603
`'binary'`. If `encoding` is not provided, and the `data` is a string, an
604-
encoding of `'binary'` is enforced. If `data` is a [`Buffer`][] then
604+
encoding of `'utf8'` is enforced. If `data` is a [`Buffer`][] then
605605
`input_encoding` is ignored.
606606

607607
This can be called many times with new data as it is streamed.
@@ -811,7 +811,7 @@ or [buffers][`Buffer`]. The default value is `'buffer'`, which makes methods
811811
default to [`Buffer`][] objects.
812812

813813
The `crypto.DEFAULT_ENCODING` mechanism is provided for backwards compatibility
814-
with legacy programs that expect `'binary'` to be the default encoding.
814+
with legacy programs that expect `'utf8'` to be the default encoding.
815815

816816
New applications should expect the default to be `'buffer'`. This property may
817817
become deprecated in a future Node.js release.

lib/crypto.js

+3-6
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,10 @@ const DH_GENERATOR = 2;
3030
// any explicit encoding in older versions of node, and we don't want
3131
// to break them unnecessarily.
3232
function toBuf(str, encoding) {
33-
encoding = encoding || 'binary';
3433
if (typeof str === 'string') {
35-
if (encoding === 'buffer')
36-
encoding = 'binary';
37-
str = new Buffer(str, encoding);
34+
if (encoding === 'buffer' || !encoding)
35+
encoding = 'utf8';
36+
return new Buffer(str, encoding);
3837
}
3938
return str;
4039
}
@@ -67,8 +66,6 @@ Hash.prototype._flush = function(callback) {
6766

6867
Hash.prototype.update = function(data, encoding) {
6968
encoding = encoding || exports.DEFAULT_ENCODING;
70-
if (encoding === 'buffer' && typeof data === 'string')
71-
encoding = 'binary';
7269
this._handle.update(data, encoding);
7370
return this;
7471
};

src/node_crypto.cc

+7-8
Original file line numberDiff line numberDiff line change
@@ -3369,7 +3369,7 @@ void CipherBase::Update(const FunctionCallbackInfo<Value>& args) {
33693369
// Only copy the data if we have to, because it's a string
33703370
if (args[0]->IsString()) {
33713371
StringBytes::InlineDecoder decoder;
3372-
if (!decoder.Decode(env, args[0].As<String>(), args[1], BINARY))
3372+
if (!decoder.Decode(env, args[0].As<String>(), args[1], UTF8))
33733373
return;
33743374
r = cipher->Update(decoder.out(), decoder.size(), &out, &out_len);
33753375
} else {
@@ -3548,7 +3548,7 @@ void Hmac::HmacUpdate(const FunctionCallbackInfo<Value>& args) {
35483548
bool r;
35493549
if (args[0]->IsString()) {
35503550
StringBytes::InlineDecoder decoder;
3551-
if (!decoder.Decode(env, args[0].As<String>(), args[1], BINARY))
3551+
if (!decoder.Decode(env, args[0].As<String>(), args[1], UTF8))
35523552
return;
35533553
r = hmac->HmacUpdate(decoder.out(), decoder.size());
35543554
} else {
@@ -3666,7 +3666,7 @@ void Hash::HashUpdate(const FunctionCallbackInfo<Value>& args) {
36663666
bool r;
36673667
if (args[0]->IsString()) {
36683668
StringBytes::InlineDecoder decoder;
3669-
if (!decoder.Decode(env, args[0].As<String>(), args[1], BINARY))
3669+
if (!decoder.Decode(env, args[0].As<String>(), args[1], UTF8))
36703670
return;
36713671
r = hash->HashUpdate(decoder.out(), decoder.size());
36723672
} else {
@@ -3818,7 +3818,7 @@ void Sign::SignUpdate(const FunctionCallbackInfo<Value>& args) {
38183818
Error err;
38193819
if (args[0]->IsString()) {
38203820
StringBytes::InlineDecoder decoder;
3821-
if (!decoder.Decode(env, args[0].As<String>(), args[1], BINARY))
3821+
if (!decoder.Decode(env, args[0].As<String>(), args[1], UTF8))
38223822
return;
38233823
err = sign->SignUpdate(decoder.out(), decoder.size());
38243824
} else {
@@ -4020,7 +4020,7 @@ void Verify::VerifyUpdate(const FunctionCallbackInfo<Value>& args) {
40204020
Error err;
40214021
if (args[0]->IsString()) {
40224022
StringBytes::InlineDecoder decoder;
4023-
if (!decoder.Decode(env, args[0].As<String>(), args[1], BINARY))
4023+
if (!decoder.Decode(env, args[0].As<String>(), args[1], UTF8))
40244024
return;
40254025
err = verify->VerifyUpdate(decoder.out(), decoder.size());
40264026
} else {
@@ -4119,12 +4119,11 @@ void Verify::VerifyFinal(const FunctionCallbackInfo<Value>& args) {
41194119

41204120
THROW_AND_RETURN_IF_NOT_STRING_OR_BUFFER(args[1]);
41214121

4122-
// BINARY works for both buffers and binary strings.
4123-
enum encoding encoding = BINARY;
4122+
enum encoding encoding = UTF8;
41244123
if (args.Length() >= 3) {
41254124
encoding = ParseEncoding(env->isolate(),
41264125
args[2]->ToString(env->isolate()),
4127-
BINARY);
4126+
UTF8);
41284127
}
41294128

41304129
ssize_t hlen = StringBytes::Size(env->isolate(), args[1], encoding);

src/string_bytes.cc

+3-3
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,6 @@ size_t StringBytes::Write(Isolate* isolate,
368368
switch (encoding) {
369369
case ASCII:
370370
case BINARY:
371-
case BUFFER:
372371
if (is_extern && str->IsOneByte()) {
373372
memcpy(buf, data, nbytes);
374373
} else {
@@ -379,6 +378,7 @@ size_t StringBytes::Write(Isolate* isolate,
379378
*chars_written = nbytes;
380379
break;
381380

381+
case BUFFER:
382382
case UTF8:
383383
nbytes = str->WriteUtf8(buf, buflen, chars_written, flags);
384384
break;
@@ -480,11 +480,11 @@ size_t StringBytes::StorageSize(Isolate* isolate,
480480

481481
switch (encoding) {
482482
case BINARY:
483-
case BUFFER:
484483
case ASCII:
485484
data_size = str->Length();
486485
break;
487486

487+
case BUFFER:
488488
case UTF8:
489489
// A single UCS2 codepoint never takes up more than 3 utf8 bytes.
490490
// It is an exercise for the caller to decide when a string is
@@ -532,11 +532,11 @@ size_t StringBytes::Size(Isolate* isolate,
532532

533533
switch (encoding) {
534534
case BINARY:
535-
case BUFFER:
536535
case ASCII:
537536
data_size = str->Length();
538537
break;
539538

539+
case BUFFER:
540540
case UTF8:
541541
data_size = str->Utf8Length();
542542
break;

test/parallel/test-crypto-hash.js

+12-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ var crypto = require('crypto');
1313
// Test hashing
1414
var a1 = crypto.createHash('sha1').update('Test123').digest('hex');
1515
var a2 = crypto.createHash('sha256').update('Test123').digest('base64');
16-
var a3 = crypto.createHash('sha512').update('Test123').digest(); // binary
16+
var a3 = crypto.createHash('sha512').update('Test123').digest(); // buffer
1717
var a4 = crypto.createHash('sha1').update('Test123').digest('buffer');
1818

1919
// stream interface
@@ -87,3 +87,14 @@ fileStream.on('close', function() {
8787
assert.throws(function() {
8888
crypto.createHash('xyzzy');
8989
});
90+
91+
// Default UTF-8 encoding
92+
var hutf8 = crypto.createHash('sha512').update('УТФ-8 text').digest('hex');
93+
assert.equal(
94+
hutf8,
95+
'4b21bbd1a68e690a730ddcb5a8bc94ead9879ffe82580767ad7ec6fa8ba2dea6' +
96+
'43a821af66afa9a45b6a78c712fecf0e56dc7f43aef4bcfc8eb5b4d8dca6ea5b');
97+
98+
assert.notEqual(
99+
hutf8,
100+
crypto.createHash('sha512').update('УТФ-8 text', 'binary').digest('hex'));

0 commit comments

Comments
 (0)