Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
@root/encoding
Advanced tools
Leightweight, Zero-dependency, translation between Unicode, Buffers, Base64, Hex, Binary Strings, UCS-2, UTF-8, etc.
Lightweight, Zero-dependency, translation between Unicode Strings, Binary Strings, Buffers, Base64, Hex, UCS-2, UTF-8, etc.
| < 1k gzipped | 2.6k minified | 3.6k full |
Works identically on all platforms:
Vanilla JS
<script src="https://unpkg.com/@root/encoding@1.0.0/dist/encoding.all.js"></script>
<script src="https://unpkg.com/@root/encoding@1.0.0/dist/encoding.all.min.js"></script>
var Enc = window.Encoding;
Enc.strToBuf('Hello, 世界!');
WebPack, Node
var Enc = require('@root/encoding');
Enc.strToBuf('Hello, 世界!');
Typically you want to use this in a browser when you need to convert user input to some sort of Byte Array for hashing or encoding in an ancient format.
For example:
The purpose of this library is to make it easy to support common string and buffer encoding and decoding in both Browsers and node with minimal code.
Strings and Byte Arrays
var Enc = require('@root/encoding/bytes');
Enc.binToStr(bin);
Enc.binToBuf(bin);
Enc.bufToBin(buf);
Enc.bufToStr(buf);
Enc.strToBin(str);
Enc.strToBuf(str);
Hex
var Enc = require('@root/encoding/hex');
Enc.hexToBuf(hex);
Enc.hexToStr(hex);
Enc.bufToHex(buf);
Enc.strToHex(str);
Base64
var Enc = require('@root/encoding/base64');
Enc.base64ToBuf(b64);
Enc.base64ToStr(b64);
Enc.bufToBase64(buf);
Enc.strToBase64(str);
URL Safe Base64
(all of base64To*()
accept URL Safe Base64)
var Enc = require('@root/encoding/base64');
Enc.base64ToUrlBase64(b64);
Enc.urlBase64ToBase64(u64);
Enc.bufToUrlBase64(buf);
Enc.strToUrlBase64(str);
Base64 and Hex
require('@root/encoding/base64');
require('@root/encoding/hex');
var Enc = require('@root/encoding');
Enc.hexToBase64(hex);
Enc.base64ToHex(b64);
(the Node API signatures are the same, but implemented with Buffer
)
Conversions between these formats are supported:
JavaScript has two types of strings:
bin
str
(USC-2, essentially UTF-16)
encodeURIComponent
JavaScript has two (and a half) ways to support Byte Arrays:
Array
, which we call arr
Uint8Array
, which we call buf
(of the ArrayBuffer
family)Buffer
(node-only, but implemented as Uint8Array
)The API for the conversions is centered around Uint8Array
(Buffer
) but,
for browser compatibility, sometimes requires the use of Binary Strings.
API
We provide conversions directly to each of the following:
Name | Type | Description |
---|---|---|
str | Unicode String | Handled by split('') as two-byte characters |
bin | Binary String | Handled by split('') as single-byte chars |
buf | Byte Array | Truncated to single-byte chars |
The names and signatures of the functions are as follows:
To Buffer
To Unicode String
To Binary String
It's very easy to convert from Binary Strings to Byte Arrays (Uint8Array.from(bin.split(''))
)
and from Uint8Array
to Binary String (Array.from(buf).join('')
).
The real value is converting between Unicode Strings to (UTF-8) Binary Strings, and back:
function toBin(str) {
var escstr = encodeURIComponent(str);
return escstr.replace(/%([0-9A-F]{2})/g, function(match, p1) {
return String.fromCharCode(parseInt(p1, 16));
});
}
function toStr(bin) {
var escstr = bin.replace(/(.)/g, function(m, p) {
var code = p
.charCodeAt(0)
.toString(16)
.toUpperCase();
if (code.length < 2) {
code = '0' + code;
}
return '%' + code;
});
return decodeURIComponent(escstr);
}
JavaScript does not have a native way to create hex, aside from small numbers:
(12345).toString(16);
The hex functions convert to and from hexidecimal:
Name | Type | Description |
---|---|---|
hex | Hex String | Handled by split('') as half-byte characters |
To Hex
From Hex
However, assuming you have a single-byte string, it's very easy to convert back and forth:
function toHex(any) {
var hex = [];
var i, h;
var len = any.byteLength || any.length;
for (i = 0; i < len; i += 1) {
h = any[i].toString(16);
if (h.length % 2) {
h = '0' + h;
}
hex.push(h);
}
return hex.join('').toLowerCase();
}
function fromHex(hex) {
var arr = hex.match(/.{2}/g).map(function(h) {
return parseInt(h, 16);
});
return Uint8Array.from(arr);
}
Browser JavaScript does have a native way convert between Binary Strings and Base64:
var b64 = btoa('An ASCII string is a Binary String');
// Note: A Unicode String is NOT
var bin = atob('SGVsbG8sIOS4lueVjCE=');
However, it does not have a native way to convert between Unicode Strings and Binary Strings, nor to and from URL Safe Base64.
The base64 module provides simpler conversions to and from Base 64 and URL Safe Base64:
Name | Type | Description |
---|---|---|
b64 | Base64 | Standard Base64 as handled by btoa and atob |
u64 | URL Safe Base64 | Replaces + with - and / with _ , and omits padding |
To Base64
From Base64 (and URL Safe Base64)
To URL Safe Base64
We write code that works both in node and in browsers, and we like to keep it small, light, and focused.
By using browser native functions rather than 're-inventing the wheel'
The most common 'browserified' Buffer
implementations are quite large -
either because they don't use browser-native code or they guarantee perfect
compatibility with node's Buffer
, which isn't necessary for most people.
On the other hand, Browsers have already been able to translate between Base64, UTF-8, Binary Strings, and Byte Arrays (Buffers) all the way back since before IE6!
Using these browser-native methods eliminates hundreds of lines of code:
btoa
Binary String to Base64 (ASCII)atob
Base64 (ASCII) to Binary StringencodeURIComponent
Unicode String to Hex-Escaped StringdecodeURIComponent
Hex-Escaped String to Unicode StringString.prototype.charCodeAt
ASCII to ByteString.fromCharCode
Byte to ASCIIThe code is typically also much easier to read. In many cases the conversion is only one line long.
Since a node Buffer
is actually an ArrayBuffer
, node's Buffer
really only has the advantage
of convenient conversions, so that's really all that needs to be implemented.
In the case of ancient browsers which do not support Uint8Array
, the native Array
is still
the best substitute.
Unless you're writing code that's intended to work in the browser, you probably shouldn't -
Node's Buffer
does the job quite well.
The one function you may still be interested in, which Node's Buffer
omits, is this one:
function toUrlSafeBase64(base64) {
return base64
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
}
HOWEVER, if you believe that browser users would benefit from your library, this is a much better alternative for simple use cases where you're dealing with small bits of code.
FAQs
Leightweight, Zero-dependency, translation between Unicode, Buffers, Base64, Hex, Binary Strings, UCS-2, UTF-8, etc.
We found that @root/encoding demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.