New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

base85

Package Overview
Dependencies
Maintainers
1
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

base85 - npm Package Compare versions

Comparing version 1.1.0 to 1.2.0

tags

97

lib/alphabets.js

@@ -201,2 +201,99 @@ 'use strict';

alphabet.ipv6 = {};
alphabet.ipv6.enc = {
0: '0',
1: '1',
2: '2',
3: '3',
4: '4',
5: '5',
6: '6',
7: '7',
8: '8',
9: '9',
10: 'A',
11: 'B',
12: 'C',
13: 'D',
14: 'E',
15: 'F',
16: 'G',
17: 'H',
18: 'I',
19: 'J',
20: 'K',
21: 'L',
22: 'M',
23: 'N',
24: 'O',
25: 'P',
26: 'Q',
27: 'R',
28: 'S',
29: 'T',
30: 'U',
31: 'V',
32: 'W',
33: 'X',
34: 'Y',
35: 'Z',
36: 'a',
37: 'b',
38: 'c',
39: 'd',
40: 'e',
41: 'f',
42: 'g',
43: 'h',
44: 'i',
45: 'j',
46: 'k',
47: 'l',
48: 'm',
49: 'n',
50: 'o',
51: 'p',
52: 'q',
53: 'r',
54: 's',
55: 't',
56: 'u',
57: 'v',
58: 'w',
59: 'x',
60: 'y',
61: 'z',
62: '!',
63: '#',
64: '$',
65: '%',
66: '&',
67: '(',
68: ')',
69: '*',
70: '+',
71: '-',
72: ';',
73: '<',
74: '=',
75: '>',
76: '?',
77: '@',
78: '^',
79: '_',
80: '`',
81: '{',
82: '|',
83: '}',
84: '~'
};
alphabet.ipv6.dec = _.object(
_.map(_.values(alphabet.ipv6.enc), function(v) { /* The keys */
return v.charCodeAt(0);
}),
_.map(_.keys(alphabet.ipv6.enc), function(v) { /* The values */
return parseInt(v);
})
);
module.exports = alphabet;

81

lib/base85.js
'use strict';
var alphabets = require('./alphabets');
var v6 = require('ipv6').v6;
var bignum = require('bignum');

@@ -26,2 +28,69 @@ var NUM_MAXVALUE = Math.pow(2, 32) - 1;

/* Function borrowed from noseglid/canumb (github) */
function pad(width, number)
{
return new Array(1 + width - number.length).join('0') + number;
}
function encodeBignumIPv6(num)
{
var enctable = alphabets.ipv6.enc;
var enc = [];
for (var i = 1; i < 20; ++i) {
enc.push(enctable[num.mod(85).toNumber()]); /* Ranges between 0 - 84 */
num = num.div(85);
}
enc.push(enctable[num.toNumber()]); /* What's left is also in range 0 - 84 */
return enc.reverse().join('');
}
function encodeBufferIPv6(buffer)
{
if (16 !== buffer.length) {
/* An IPv6 address must be exactly 16 bytes, 128 bits long */
return false;
}
return encodeBignumIPv6(bignum.fromBuffer(buffer));
}
function encodeStringIPv6(string)
{
var addr = new v6.Address(string);
if (!addr.isValid()) {
return false;
}
var num = bignum(addr.parsedAddress.map(function(el) {
return pad(4, el);
}).join(''), 16);
return encodeBignumIPv6(num);
}
function decodeStringIPv6(string)
{
if (20 !== string.length) {
/* An encoded IPv6 is always (5/4) * 16 = 20 bytes */
return false;
}
var dectable = alphabets.ipv6.dec;
var i = 0;
var binary = string.split('').reduceRight(function(memo, el) {
var num = bignum(dectable[el.charCodeAt(0)]);
var fact = bignum(85).pow(i++);
var contrib = num.mul(fact);
return memo.add(contrib);
}, bignum(0));
return v6.Address.fromBigInteger(binary).correctForm();
}
function decodeBufferIPv6(buffer)
{
return decodeStringIPv6(buffer.toString());
}
function encodeBuffer(buffer, encoding)

@@ -131,3 +200,3 @@ {

encoding = encoding || DEFAULT_ENCODING;
if (-1 === [ 'ascii85', 'z85' ].indexOf(encoding)) {
if (-1 === [ 'ascii85', 'z85', 'ipv6' ].indexOf(encoding)) {
return false;

@@ -137,7 +206,7 @@ }

if (data instanceof Buffer) {
return encodeBuffer(data, encoding);
return ('ipv6' === encoding) ? encodeBufferIPv6(data) : encodeBuffer(data, encoding);
}
if (typeof data === 'string') {
return encodeString(data, encoding);
return ('ipv6' === encoding) ? encodeStringIPv6(data) : encodeString(data, encoding);
}

@@ -150,3 +219,3 @@

encoding = encoding || DEFAULT_ENCODING;
if (-1 === [ 'ascii85', 'z85' ].indexOf(encoding)) {
if (-1 === [ 'ascii85', 'z85', 'ipv6' ].indexOf(encoding)) {
return false;

@@ -156,7 +225,7 @@ }

if (data instanceof Buffer) {
return decodeBuffer(data, encoding);
return ('ipv6' === encoding) ? decodeBufferIPv6(data) : decodeBuffer(data, encoding);
}
if (typeof data === 'string') {
return decodeString(data, encoding);
return ('ipv6' === encoding) ? decodeStringIPv6(data) : decodeString(data, encoding);
}

@@ -163,0 +232,0 @@

{
"name": "base85",
"version": "1.1.0",
"version": "1.2.0",
"description": "Base85 (Ascii85) encode and decode functionality",

@@ -9,2 +9,6 @@ "main": "lib/base85.js",

},
"dependencies": {
"bignum": "0.6.x",
"ipv6": "3.1.x"
},
"devDependencies": {

@@ -11,0 +15,0 @@ "nodeunit": "0.8.x",

133

README.md

@@ -5,10 +5,15 @@ [![Build Status](https://travis-ci.org/noseglid/base85.png?branch=master)](https://travis-ci.org/noseglid/base85)

Simple utility to manage base85. Where [base64 adds approximately 1/3][Base64],
[base85 only adds about 1/4][Base85]. Of course there's a tradeoff. The Base85
alphabet includes characters that might not be as friendly as the base64 alphabet.
While it's still only printable characters, the [Ascii85][Base85] specification contains
quotes (`'` and `"`) which needs escaping in many programming languages,
and the [ZeroMQ][Base85ZeroMQ] specification contains `<` and `>` which need escaping
in most (all?) [SGML][SGML] languages.
Base85 encoder/decoder written in native javascript.
Where base64 [adds approximately 1/3][Base64], base85 only [adds about
1/4][Base85]. Of course there's a tradeoff. The Base85 alphabet includes
characters that might not be as friendly as the base64 alphabet. While it's
still only printable characters, the [Ascii85][Base85] specification contains
quotes (`'` and `"`) which needs escaping in many programming languages, and
the [ZeroMQ][Base85ZeroMQ] specification contains `<` and `>` which need
escaping in most (all?) [SGML][SGML] languages.
IPv6 encoding should only be used for encoding IPv6 addresses. When using IPv6,
input for encoding must always be 16 bytes, and input for decoding must always be 20 bytes.
Supported encoding specifications

@@ -18,2 +23,3 @@

* [ZeroMQ][Base85ZeroMQ]
* [IPv6][Base85IPv6]

@@ -27,61 +33,107 @@ ## Installation

For encoding:
### Encoding:
var base85 = require('base85');
console.log(base85.encode('Hello, world!')); // 'nm=QNz.92Pz/PV8aP'
console.log(base85.encode('Hello, world!', 'ascii85')); // ' <~87cURD_*#TDfTZ)+T~>'
For decoding:
var z85 = base85.encode('Hello, world!');
console.log(z85); // nm=QNz.92Pz/PV8aP
### Decoding:
var base85 = require('base85');
var decoded = base85.decode('vqG:5Cw?IqayPd#az#9uAbn%daz>L5wPF#evpK6}vix96y?$k6z*q');
console.log(decoded.toString('utf8')); // 'all work and no play makes jack a dull boy'
console.log(decoded.toString('utf8')); // all work and no play makes jack a dull boy
## Bugs
### IPv6 ([RFC1924][Base85IPv6]), can take [any correctly formatted IPv6 address](http://en.wikipedia.org/wiki/IPv6):
Doesn't support the z-abbreviation for [Ascii85][Base85]. This means that data encoded with this
support will cause the library to return false. An all-zero input buffer will be encoded
as `<~!!!!!~>`, rather than `<~z~>`
var base85 = require('base85');
Doesn't support [IPv6 encoding specification (RFC1924)][Base85IPv6] for now. This baby requires
requires 128-bit arithmetic, which is rather problematic. I'm thrilled to see that the author
of the RFC took this in consideration, specifically - quote from the [RFC][Base85IPv6]: "This is not
considered a serious drawback in the representation, but a flaw of the processor designs."
Silly processor designers.
var ipv6 = base85.encode('2001:db8:100:f101::1', 'ipv6');
console.log(ipv6); // 9R}vSQZ1W=8fRv3*HAqn
var decoded = base85.decode('9R}vSQZ1W=8fRv3*HAqn', 'ipv6');
console.log(decoded); // 2001:db8:100:f101::1
## API
### `encode(data[, encoding])`
### `encode(data [, encoding])`
> _Encodes the specified data. If encoding is `ascii85`, the encoded data will be prepended
> with `<~` and appended with `~>`._
> Encodes the specified data. If encoding is `ascii85`, the encoded data will be prepended
> with `<~` and appended with `~>`.
>
> **data** The data to encode, may be a `String` or a [Buffer][NodeBuffer].
> **data**
>> The data to encode, may be a `String` or a [Buffer][NodeBuffer].
>
> **encoding** Which specification to use when encoding `data`. May be either
> `ascii85` ([Adobe][Base85]) or `z85` ([ZeroMQ][Base85ZeroMQ]).
> Default is `z85`.
> **encoding**
>> Which specification to use when encoding `data`. Valid values are:
>> `ascii85`, `z85` or `ipv6`. Default is `z85`.
>>
>> For `ipv6`, if `data` is a buffer, it is expected to be the binary representation
>> of an IPv6 address (16 bytes). It **cannot** be a textual representation. If it is a string,
>> it can be on any valid IPv6 form (e.g. `::1` or `1080:0:0:0:8:800:200c:417a`,
>> parsing is done using [javascript-ipv6][JavaScriptIPv6]).
>
> **returns** A `String` with the encoded data.
> **returns**
>> A `String` with the encoded data.
### `decode(data[, encoding])`
### `decode(data [, encoding])`
> _Decodes the specified data. If encoding is `ascii85`, the data is expected
> Decodes the specified data. If encoding is `ascii85`, the data is expected
> to start with `<~` and and end with `~>`. No checks are actually made for
> this, but output will be unexpected if this is not the case._
> this, but output will be unexpected if this is not the case. If encoding is
> `ipv6`, the length of data must be exactly 20 bytes. `ipv6` encoding cannot
> be used with arbitrary data.
>
> _A buffer is always returned as data may not be representable in a string.
> A buffer is always returned as data may not be representable in a string.
> If you know it is, you can easily convert it to a string using the
> [Buffer.toString()][NodeBufferToString] utility._
> [Buffer.toString()][NodeBufferToString] utility.
>
> **data** The data to decode. May be a `String` or a [Buffer][NodeBuffer].
> Expected to be enclosed in `<~` and `~>`.
> **data**
>> The data to decode. May be a `String` or a [Buffer][NodeBuffer].
>> Expected to be enclosed in `<~` and `~>`.
>
> **encoding** Which specification `data` is encoded with. May be either
> `ascii85` ([Adobe][Base85]) or `z85` ([ZeroMQ][Base85ZeroMQ]).
> Default is `z85`.
> **encoding**
>> Which specification `data` is encoded with. Valid values are:
>> `ascii85`, `z85` or `ipv6`. Default is `z85`.
>
> **returns** A [Buffer][NodeBuffer] With the decoded data, or **boolean** `false` if the buffer could not be decoded. When testing if the result succeeded, [always use operators with 3 characters][JSCompare] ('===' or '!==').
> **returns**
>> A [Buffer][NodeBuffer] With the decoded data, or **boolean** `false`
>> if the buffer could not be decoded. When testing if the result succeeded,
>> [always use operators with 3 characters][JSCompare] ('===' or '!==').
>
## Which specification to use?
ZeroMQ appears to be a better specification for most applications. It doesn't
include quotes in its alphabet which makes it useful in many quoted languages
(such as C, C++, JavaScript, Java, Python, Perl, Ruby... the list goes on).
Neither does it add the 4 extra enclosing bytes Ascii85 does. There may,
however, be some problems using it in SGML and its derivatives since
both less-than `<` and greater-than `>` are part of the alphabet. But
then again, Ascii85 has that as well.
Ascii85 appears to be the most used of the base85 specifications however. As for why
completely eludes me. This may very well be the only reason to pick Ascii85.
If you control both decoding and encoding side, use ZeroMQ.
If you need interoperability with Ascii85, use that.
As IPv6 encoding only supports exactly 128 bits (16 bytes), this is not very useful for
arbitrary data. Only use IPv6 if you're actually encoding IPv6 addresses.
## Bugs
Doesn't support the z-abbreviation for [Ascii85][Base85]. This means that data encoded with this
support will cause the library to return false. An all-zero input buffer will be encoded
as `<~!!!!!~>`, rather than `<~z~>`
[IPv6 encoding specification (RFC1924)][Base85IPv6] requires 128-bit arithmetic,
which is rather problematic. I'm thrilled to see that the author of the RFC took this
in consideration, specifically - quote from the [RFC][Base85IPv6]: "This is not
considered a serious drawback in the representation, but a flaw of the processor designs."
Silly processor designers. Currently, this is implemented using an arbitrary precision algorithm,
it's slow but it does the job. Now let's poke those processor designers for 128-bit processors.
[Base64]: http://en.wikipedia.org/wiki/Base64

@@ -95,1 +147,2 @@ [Base85]: http://en.wikipedia.org/wiki/Ascii85

[SGML]: https://en.wikipedia.org/wiki/Standard_Generalized_Markup_Language
[JavaScriptIPv6]: https://github.com/beaugunderson/javascript-ipv6
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc