1209

Does Node.js have built-in Base64 encoding yet?

The reason why I ask this is that final() from crypto can only output hexadecimal, binary or ASCII data. For example:

var cipher = crypto.createCipheriv('des-ede3-cbc', encryption_key, iv);
var ciph = cipher.update(plaintext, 'utf8', 'hex');
ciph += cipher.final('hex');

var decipher = crypto.createDecipheriv('des-ede3-cbc', encryption_key, iv);
var txt = decipher.update(ciph, 'hex', 'utf8');
txt += decipher.final('utf8');

According to the documentation, update() can output Base64-encoded data. However, final() doesn't support Base64. I tried and it will break.

If I do this:

var ciph = cipher.update(plaintext, 'utf8', 'base64');
    ciph += cipher.final('hex');

Then what should I use for decryption? Hexadecimal or Base64?

Therefore, I'm looking for a function to Base64-encode my encrypted hexadecimal output.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
murvinlai
  • 48,919
  • 52
  • 129
  • 177

8 Answers8

2670

Buffers can be used for taking a string or piece of data and doing Base64 encoding of the result. For example:

> console.log(Buffer.from("Hello World").toString('base64'));
SGVsbG8gV29ybGQ=
> console.log(Buffer.from("SGVsbG8gV29ybGQ=", 'base64').toString('ascii'))
Hello World

Buffers are a global object, so no require is needed. Buffers created with strings can take an optional encoding parameter to specify what encoding the string is in. The available toString and Buffer constructor encodings are as follows:

'ascii' - for 7 bit ASCII data only. This encoding method is very fast, and will strip the high bit if set.

'utf8' - Multi byte encoded Unicode characters. Many web pages and other document formats use UTF-8.

'ucs2' - 2-bytes, little endian encoded Unicode characters. It can encode only BMP(Basic Multilingual Plane, U+0000 - U+FFFF).

'base64' - Base64 string encoding.

'binary' - A way of encoding raw binary data into strings by using only the first 8 bits of each character. This encoding method is deprecated and should be avoided in favor of Buffer objects where possible. This encoding will be removed in future versions of Node.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
onteria_
  • 68,181
  • 7
  • 71
  • 64
  • 3
    `const atob = (data) => Buffer.from(data, 'base64').toString('ascii');` – spencer.sm Oct 05 '18 at 17:19
  • that should be `.toString("binary")` (`atob` stands for ascii(base64) to binary, after all) – 12Me21 Jan 14 '20 at 19:55
  • @12Me21 I thought it stood for ascii to base64? – David Callanan Apr 10 '20 at 18:11
  • @DavidCallanan atob() converts from base64 – 12Me21 Apr 14 '20 at 14:47
  • I got this warning after `Buffer.from` (node:13765) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead. – JRichardsz Dec 05 '21 at 23:11
  • I have a related question that I think you'll know the answer to. I appreciate your help! https://stackoverflow.com/q/75416587/470749 – Ryan Feb 10 '23 at 22:10
  • "Buffers are a global object, so no require is needed." The NodeJS docs recommend "to explicitly reference it via an import or require statement." – uzluisf Apr 24 '23 at 20:59
370

The accepted answer previously contained new Buffer(), which is considered a security issue in Node.js versions greater than 6 (although it seems likely for this use case that the input can always be coerced to a string).

The Buffer constructor is deprecated according to the documentation.

The code snippets should read:

console.log(Buffer.from("Hello World").toString('base64'));
console.log(Buffer.from("SGVsbG8gV29ybGQ=", 'base64').toString('ascii'));

After this answer was written, it has been updated and now matches this.

3ventic
  • 1,023
  • 1
  • 20
  • 32
NotJavanese
  • 4,072
  • 1
  • 15
  • 15
  • When I try to use your first line, Node returns: [TypeError: this is not a typed array.] – Dave Voyles Sep 26 '16 at 21:48
  • 8
    This error happens on node versions older than v6. In these versions you'll need to use the constructor (`new Buffer`) rather than `Buffer.from`. – NotJavanese Sep 28 '16 at 02:13
  • [Buffer.from()](https://nodejs.org/dist/latest-v4.x/docs/api/buffer.html#buffer_class_method_buffer_from_array) was added in v4.5.0. – dskrvk Nov 30 '17 at 18:43
  • 98
    Just to save you few minutes that I lost trying to see difference between this example and the one in the accepted answer, the accepted answer is now updated to what this answer suggests. – Kunok Mar 22 '18 at 20:47
  • What is the "ws" library? Can you add a reference to? But ***without*** "Edit:", "Update:", or similar - the answer should appear as if it was written today. – Peter Mortensen Aug 01 '21 at 22:16
51

crypto now supports Base64 (reference):

cipher.final('base64')

So you could simply do:

var cipher = crypto.createCipheriv('des-ede3-cbc', encryption_key, iv);
var ciph = cipher.update(plaintext, 'utf8', 'base64');
ciph += cipher.final('base64');

var decipher = crypto.createDecipheriv('des-ede3-cbc', encryption_key, iv);
var txt = decipher.update(ciph, 'base64', 'utf8');
txt += decipher.final('utf8');
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Javier Ferrero
  • 8,741
  • 8
  • 45
  • 50
  • 3
    Any reason to use this over NotJavanese's answer? – Trevor Apr 17 '18 at 13:41
  • 3
    Had to match encryptions between Node and Python and this answer saved me a question! Thanks :) – GigiSan May 22 '18 at 13:58
  • 2
    This is incorrect since you can't just append multiple base64 strings and get a correctly concatenated base64 string. This only works if the update function returns chunks of length divisible by 4, of which there is no guarantee. – phiresky Dec 18 '20 at 13:11
12

Buffers can be used for taking a string or piece of data and doing Base64 encoding of the result. For example:

You can install Buffer via npm like: npm i buffer --save

You can use this in your js file like this:

var buffer = require('buffer/').Buffer;

->> console.log(buffer.from("Hello Vishal Thakur").toString('base64'));
SGVsbG8gVmlzaGFsIFRoYWt1cg==  // Result

->> console.log(buffer.from("SGVsbG8gVmlzaGFsIFRoYWt1cg==", 'base64').toString('ascii'))
Hello Vishal Thakur   // Result
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Vishal Thakur
  • 1,564
  • 16
  • 25
3

I am using the following code to decode a Base64 string in the Node.js API, Node.js version 10.7.0:

let data = 'c3RhY2thYnVzZS5jb20=';  // Base64 string
let buff = new Buffer(data, 'base64');  //Buffer
let text = buff.toString('ascii');  // This is the data type that you want your Base64 data to convert to
console.log('"' + data + '" converted from Base64 to ASCII is "' + text + '"');

Please don't try to run the above code in the console of the browser. It won't work. Put the code in the server-side files of Node.js. I am using the above line code in API development.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
0

Try doing this :

console.log(Buffer.from("Hello World").toString('base64'));
console.log(Buffer.from("SGVsbG8gV29ybGQ=", 'base64').toString('ascii'));

This will convert a string into base64 encoded string i.e. SGVsbG8gV29ybGQ= and then you can decode it back to Hello World

-2

I have created an ultimate small JavaScript npm library for the Base64 encode/decode conversion in Node.js.

Installation

npm install nodejs-base64-converter --save

Usage

var nodeBase64 = require('nodejs-base64-converter');

console.log(nodeBase64.encode("test text")); //dGVzdCB0ZXh0
console.log(nodeBase64.decode("dGVzdCB0ZXh0")); //test text
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Manish Prajapati
  • 1,583
  • 2
  • 13
  • 21
-3

You can do Base64 encoding and decoding with simple JavaScript.

$("input").keyup(function () {
    var value = $(this).val(),
        hash = Base64.encode(value);
    $(".test").html(hash);

    var decode = Base64.decode(hash);

    $(".decode").html(decode);
});

var Base64 = {_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(e){var t="";var n,r,i,s,o,u,a;var f=0;e=Base64._utf8_encode(e);while(f<e.length){n=e.charCodeAt(f++);r=e.charCodeAt(f++);i=e.charCodeAt(f++);s=n>>2;o=(n&3)<<4|r>>4;u=(r&15)<<2|i>>6;a=i&63;if(isNaN(r)){u=a=64}else if(isNaN(i)){a=64}t=t+this._keyStr.charAt(s)+this._keyStr.charAt(o)+this._keyStr.charAt(u)+this._keyStr.charAt(a)}return t},decode:function(e){var t="";var n,r,i;var s,o,u,a;var f=0;e=e.replace(/[^A-Za-z0-9+/=]/g,"");while(f<e.length){s=this._keyStr.indexOf(e.charAt(f++));o=this._keyStr.indexOf(e.charAt(f++));u=this._keyStr.indexOf(e.charAt(f++));a=this._keyStr.indexOf(e.charAt(f++));n=s<<2|o>>4;r=(o&15)<<4|u>>2;i=(u&3)<<6|a;t=t+String.fromCharCode(n);if(u!=64){t=t+String.fromCharCode(r)}if(a!=64){t=t+String.fromCharCode(i)}}t=Base64._utf8_decode(t);return t},_utf8_encode:function(e){e=e.replace(/rn/g,"n");var t="";for(var n=0;n<e.length;n++){var r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r)}else if(r>127&&r<2048){t+=String.fromCharCode(r>>6|192);t+=String.fromCharCode(r&63|128)}else{t+=String.fromCharCode(r>>12|224);t+=String.fromCharCode(r>>6&63|128);t+=String.fromCharCode(r&63|128)}}return t},_utf8_decode:function(e){var t="";var n=0;var r=c1=c2=0;while(n<e.length){r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r);n++}else if(r>191&&r<224){c2=e.charCodeAt(n+1);t+=String.fromCharCode((r&31)<<6|c2&63);n+=2}else{c2=e.charCodeAt(n+1);c3=e.charCodeAt(n+2);t+=String.fromCharCode((r&15)<<12|(c2&63)<<6|c3&63);n+=3}}return t}}

// Define the string
var string = 'Hello World!';

// Encode the string
var encodedString = Base64.encode(string);
console.log(encodedString); // Outputs: "SGVsbG8gV29ybGQh"

// Decode the string
var decodedString = Base64.decode(encodedString);
console.log(decodedString); // Outputs: "Hello World!"</script></div>

This is implemented in this Base64 encoder decoder.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ishaan Sharma
  • 55
  • 1
  • 8