@lumjs/encode 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/README.md +18 -0
- package/TODO.md +3 -0
- package/jsdoc.json +33 -0
- package/lib/base64.js +55 -0
- package/lib/base91.js +190 -0
- package/lib/crypto/index.js +171 -0
- package/lib/crypto/load.js +344 -0
- package/lib/hash.js +244 -0
- package/lib/index.js +53 -0
- package/lib/safe64/common.js +40 -0
- package/lib/safe64/header.js +142 -0
- package/lib/safe64/index.js +466 -0
- package/lib/safe64/json.js +12 -0
- package/lib/safe64/php.js +15 -0
- package/lib/safe64/settings.js +85 -0
- package/lib/safe64/ubjson.js +23 -0
- package/lib/util.js +190 -0
- package/package.json +39 -0
- package/ub-dev.js +11 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
All notable changes to this project will be documented in this file.
|
|
3
|
+
|
|
4
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
5
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [1.0.0] - 2022-09-30
|
|
10
|
+
### Added
|
|
11
|
+
- Initial release.
|
|
12
|
+
|
|
13
|
+
[Unreleased]: https://github.com/supernovus/lum.encode.js/compare/v1.0.0...HEAD
|
|
14
|
+
[1.0.0]: https://github.com/supernovus/lum.encode.js/releases/tag/v1.0.0
|
|
15
|
+
|
package/README.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# lum.encode.js
|
|
2
|
+
|
|
3
|
+
A bunch of encoding libraries.
|
|
4
|
+
|
|
5
|
+
## Official URLs
|
|
6
|
+
|
|
7
|
+
This library can be found in two places:
|
|
8
|
+
|
|
9
|
+
* [Github](https://github.com/supernovus/lum.encode.js)
|
|
10
|
+
* [NPM](https://www.npmjs.com/package/@lumjs/encode)
|
|
11
|
+
|
|
12
|
+
## Author
|
|
13
|
+
|
|
14
|
+
Timothy Totten <2010@totten.ca>
|
|
15
|
+
|
|
16
|
+
## License
|
|
17
|
+
|
|
18
|
+
[MIT](https://spdx.org/licenses/MIT.html)
|
package/TODO.md
ADDED
package/jsdoc.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"tags":
|
|
3
|
+
{
|
|
4
|
+
"allowUnknownTags": true
|
|
5
|
+
},
|
|
6
|
+
"source":
|
|
7
|
+
{
|
|
8
|
+
"include": ["./lib"]
|
|
9
|
+
},
|
|
10
|
+
"opts":
|
|
11
|
+
{
|
|
12
|
+
"destination": "./docs/api",
|
|
13
|
+
"recurse": true
|
|
14
|
+
},
|
|
15
|
+
"plugins":
|
|
16
|
+
[
|
|
17
|
+
"plugins/markdown"
|
|
18
|
+
],
|
|
19
|
+
"templates":
|
|
20
|
+
{
|
|
21
|
+
"cleverLinks": false,
|
|
22
|
+
"monospaceLinks": false,
|
|
23
|
+
"default":
|
|
24
|
+
{
|
|
25
|
+
"outputSourceFiles": true
|
|
26
|
+
},
|
|
27
|
+
"path": "ink-docstrap",
|
|
28
|
+
"theme": "cerulean",
|
|
29
|
+
"navType": "vertical",
|
|
30
|
+
"linenums": true,
|
|
31
|
+
"dateFormat": "YYYY-MM-DD, hh:mm:ss"
|
|
32
|
+
}
|
|
33
|
+
}
|
package/lib/base64.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
|
|
2
|
+
const {S,isObj} = require('@lumjs/core/types');
|
|
3
|
+
const Base64 = require('crypto-js/enc-base64');
|
|
4
|
+
const Utf8 = require('crypto-js/enc-utf8');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Base64 functions.
|
|
8
|
+
*
|
|
9
|
+
* Provides friendlier wrappers around the `crypto-js` libraries.
|
|
10
|
+
*
|
|
11
|
+
* @module @lumjs/encode/base64
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Encode data as a `Base64` string.
|
|
16
|
+
*
|
|
17
|
+
* @param {(string|WordArray)} rawdata - The data we want to encode.
|
|
18
|
+
*
|
|
19
|
+
* If this is a `string` we'll convert it into a `WordArray` using
|
|
20
|
+
* the `stringFormat` object.
|
|
21
|
+
*
|
|
22
|
+
* @param {object} [stringFormat=Utf8] The string format.
|
|
23
|
+
*
|
|
24
|
+
* Can be any encoding module from the `crypto-js` library.
|
|
25
|
+
* Default is `CryptoJS.enc.Utf8`
|
|
26
|
+
*
|
|
27
|
+
* @return {string} The encoded string.
|
|
28
|
+
*/
|
|
29
|
+
exports.encode = function(rawdata, stringFormat=Utf8)
|
|
30
|
+
{
|
|
31
|
+
const data = typeof rawdata === S ? stringFormat.parse(rawdata) : rawdata;
|
|
32
|
+
return Base64.stringify(data);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Decode a `Base64` string back into raw data.
|
|
37
|
+
*
|
|
38
|
+
* @param {string} string - The Base64 string to decode.
|
|
39
|
+
*
|
|
40
|
+
* @param {(object|false)} [stringFormat=Utf8] The string format.
|
|
41
|
+
*
|
|
42
|
+
* Can be any encoder library from the `crypto-js` library.
|
|
43
|
+
* Default is `CryptoJS.enc.Utf8`
|
|
44
|
+
*
|
|
45
|
+
* If this is `false`, we'll return a `WordArray` object.
|
|
46
|
+
*
|
|
47
|
+
* @return {(string|WordArray))} The decoded output.
|
|
48
|
+
*/
|
|
49
|
+
exports.decode = function(string, stringFormat=Utf8)
|
|
50
|
+
{
|
|
51
|
+
const data = Base64.parse(string);
|
|
52
|
+
return (isObj(stringFormat) ? data.toString(stringFormat) : data);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
exports.Utf8 = Utf8;
|
package/lib/base91.js
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
const {S,U,B} = require('@lumjs/core/types');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A pure-Javascript base91 library.
|
|
5
|
+
*
|
|
6
|
+
* Based off a combination of the `mscdex` and `deno` versions.
|
|
7
|
+
*
|
|
8
|
+
* @module @lumjs/encode/base91
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const lookup = [];
|
|
12
|
+
const revLookup = [];
|
|
13
|
+
const code =
|
|
14
|
+
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&()*+,./:;<=>?@[]^_`{|}~"';
|
|
15
|
+
|
|
16
|
+
for (let i = 0, len = code.length; i < len; ++i)
|
|
17
|
+
{
|
|
18
|
+
lookup[i] = code[i];
|
|
19
|
+
revLookup[code.charCodeAt(i)] = i;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Encode data to base91
|
|
24
|
+
*
|
|
25
|
+
* @param {*} data - Data to encode
|
|
26
|
+
*
|
|
27
|
+
* May be a string of raw data, a typed array,
|
|
28
|
+
* an ArrayBuffer, or just an array of bytes.
|
|
29
|
+
*
|
|
30
|
+
* @returns {string} The base91 string.
|
|
31
|
+
*/
|
|
32
|
+
exports.encode = function(data)
|
|
33
|
+
{
|
|
34
|
+
let output = '';
|
|
35
|
+
let len = data.length,
|
|
36
|
+
isStr = (typeof data === S),
|
|
37
|
+
queue = 0,
|
|
38
|
+
numbits = 0,
|
|
39
|
+
value = 0;
|
|
40
|
+
|
|
41
|
+
for (let i = 0; i < len; i++)
|
|
42
|
+
{
|
|
43
|
+
if (isStr)
|
|
44
|
+
{
|
|
45
|
+
let byte = data.charCodeAt(i);
|
|
46
|
+
let lenj = (byte < 128
|
|
47
|
+
? 1
|
|
48
|
+
: (byte > 127 && byte < 2048
|
|
49
|
+
? 2
|
|
50
|
+
: 3));
|
|
51
|
+
for (let j = 0; j < lenj; ++j)
|
|
52
|
+
{
|
|
53
|
+
if (lenj === 1)
|
|
54
|
+
{
|
|
55
|
+
queue |= byte << numbits;
|
|
56
|
+
}
|
|
57
|
+
else if (lenj === 2)
|
|
58
|
+
{
|
|
59
|
+
if (j === 0)
|
|
60
|
+
queue |= ((byte >> 6) | 192) << numbits;
|
|
61
|
+
else
|
|
62
|
+
queue |= ((byte & 63) | 128) << numbits;
|
|
63
|
+
}
|
|
64
|
+
else
|
|
65
|
+
{
|
|
66
|
+
if (j === 0)
|
|
67
|
+
queue |= ((byte >> 12) | 224) << numbits;
|
|
68
|
+
else if (j === 1)
|
|
69
|
+
queue |= (((byte >> 6) & 63) | 128) << numbits;
|
|
70
|
+
else
|
|
71
|
+
queue |= ((byte & 63) | 128) << numbits;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
else
|
|
76
|
+
{
|
|
77
|
+
queue |= (data[i] & 255) << numbits;
|
|
78
|
+
}
|
|
79
|
+
numbits += 8;
|
|
80
|
+
if (numbits >= 13)
|
|
81
|
+
{
|
|
82
|
+
value = queue & 8191;
|
|
83
|
+
if (value > 88)
|
|
84
|
+
{
|
|
85
|
+
queue >>= 13;
|
|
86
|
+
numbits -= 13;
|
|
87
|
+
}
|
|
88
|
+
else
|
|
89
|
+
{
|
|
90
|
+
value = queue & 16383;
|
|
91
|
+
queue >>= 14;
|
|
92
|
+
numbits -= 14;
|
|
93
|
+
}
|
|
94
|
+
output += lookup[value % 91];
|
|
95
|
+
output += lookup[Math.trunc(value / 91)];
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (numbits > 0)
|
|
99
|
+
{
|
|
100
|
+
output += lookup[queue % 91];
|
|
101
|
+
if (numbits > 7 || queue > 90)
|
|
102
|
+
{
|
|
103
|
+
output += lookup[Math.trunc(queue / 91)];
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return output;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Decode a base91 value back to its original bytes.
|
|
112
|
+
*
|
|
113
|
+
* @param {string} data - The base91 data.
|
|
114
|
+
*
|
|
115
|
+
* May also be an array of bytes.
|
|
116
|
+
*
|
|
117
|
+
* @param {(object|boolean)} [opts] Options
|
|
118
|
+
*
|
|
119
|
+
* If this is a `boolean` it's a shortcut to `opts.string`.
|
|
120
|
+
*
|
|
121
|
+
* @param {boolean} [opts.string=false] Return a String.
|
|
122
|
+
* @param {boolean} [opts.uint=false] Return a Uint8Array.
|
|
123
|
+
* @param {boolean} [opts.buffer=false] Return a `Buffer`.
|
|
124
|
+
*
|
|
125
|
+
* @returns {mixed} Output depends on options.
|
|
126
|
+
*
|
|
127
|
+
* By default it's a simple Javascript array of raw byte values.
|
|
128
|
+
*
|
|
129
|
+
*/
|
|
130
|
+
exports.decode = function(data, opts={})
|
|
131
|
+
{
|
|
132
|
+
const output = [];
|
|
133
|
+
let len = data.length,
|
|
134
|
+
isStr = (typeof data === S),
|
|
135
|
+
queue = 0,
|
|
136
|
+
numbits = 0,
|
|
137
|
+
value = -1,
|
|
138
|
+
byte = 0;
|
|
139
|
+
|
|
140
|
+
for (let i = 0; i < len; i++)
|
|
141
|
+
{
|
|
142
|
+
byte = revLookup[isStr ? data.charCodeAt(i) : data[i]];
|
|
143
|
+
if (byte === undefined) continue;
|
|
144
|
+
if (value == -1)
|
|
145
|
+
{
|
|
146
|
+
value = byte;
|
|
147
|
+
}
|
|
148
|
+
else
|
|
149
|
+
{
|
|
150
|
+
value += byte * 91;
|
|
151
|
+
queue |= value << numbits;
|
|
152
|
+
numbits += (value & 8191) > 88 ? 13 : 14;
|
|
153
|
+
do
|
|
154
|
+
{
|
|
155
|
+
output.push(queue);
|
|
156
|
+
queue >>= 8;
|
|
157
|
+
numbits -= 8;
|
|
158
|
+
} while (numbits > 7);
|
|
159
|
+
value = -1;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
if (value != -1)
|
|
163
|
+
{
|
|
164
|
+
output.push(queue | (value << numbits));
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (typeof opts === B)
|
|
168
|
+
{
|
|
169
|
+
opts = {string: opts};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (opts.string && typeof Uint8Array !== U && typeof TextDecoder !== U)
|
|
173
|
+
{
|
|
174
|
+
const uint = Uint8Array.from(output);
|
|
175
|
+
const td = new TextDecoder();
|
|
176
|
+
return td.decode(uint);
|
|
177
|
+
}
|
|
178
|
+
if (opts.uint && typeof Uint8Array !== U)
|
|
179
|
+
{
|
|
180
|
+
return Uint8Array.from(output);
|
|
181
|
+
}
|
|
182
|
+
else if (opts.buffer && typeof Buffer !== U)
|
|
183
|
+
{
|
|
184
|
+
return new Buffer.from(output);
|
|
185
|
+
}
|
|
186
|
+
else
|
|
187
|
+
{
|
|
188
|
+
return output;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Crypto-JS helpers.
|
|
3
|
+
*
|
|
4
|
+
* Uses a lot of magic proxy abilities.
|
|
5
|
+
* Look at the `test/020-crypto.js` for examples.
|
|
6
|
+
*
|
|
7
|
+
* The top-level properties are *case-sensitive*, as
|
|
8
|
+
* is standard in Javascript. In some cases this means
|
|
9
|
+
* there are two names that differ only in case, such as
|
|
10
|
+
* `crypto.hash` (a proxy object returning hashing functions)
|
|
11
|
+
* versus `crypto.HASH` (a proxy object returning object instaces).
|
|
12
|
+
*
|
|
13
|
+
* The child properties of any *proxy object* properties
|
|
14
|
+
* are *case-insensitive*. So `crypto.hash.sha256` is the
|
|
15
|
+
* same as `crypto.hash.SHA256`.
|
|
16
|
+
*
|
|
17
|
+
* @module @lumjs/encode/crypto
|
|
18
|
+
*/
|
|
19
|
+
const {def} = require('@lumjs/core/types');
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A link to the `crypto-js/core` library.
|
|
23
|
+
*
|
|
24
|
+
* This corresponds to the `CryptoJS` global in the original
|
|
25
|
+
* implementation, and is used by all the other modules
|
|
26
|
+
* in the `crypto-js` collection.
|
|
27
|
+
*
|
|
28
|
+
* @alias module:@lumjs/encode/crypto.core
|
|
29
|
+
*/
|
|
30
|
+
const cc = require('crypto-js/core');
|
|
31
|
+
exports.core = cc;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* A link to the `crypto-js/core.lib.WordArray` library.
|
|
35
|
+
*
|
|
36
|
+
* We always load the `lib-typedarray` plugin that allows
|
|
37
|
+
* conversion from `WordArray` objects.
|
|
38
|
+
*/
|
|
39
|
+
exports.WordArray = require('crypto-js/lib-typedarrays');
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Our custom module loader.
|
|
43
|
+
*
|
|
44
|
+
* Can be used as a `function` itself, but generally one of the
|
|
45
|
+
* child methods is a lot simpler, and works around weird
|
|
46
|
+
* gotchyas in the `crypto-js` library.
|
|
47
|
+
*
|
|
48
|
+
* All of the *proxy objects* use this as the underlying
|
|
49
|
+
* target object, and each of them corresponds to one of
|
|
50
|
+
* the methods from this.
|
|
51
|
+
*
|
|
52
|
+
* @see {@link module:@lumjs/encode/crypto/load}
|
|
53
|
+
* @see {@link module:@lumjs/encode/crypto/load.load}
|
|
54
|
+
*/
|
|
55
|
+
exports.load = require('./load');
|
|
56
|
+
|
|
57
|
+
// A list of loader properties to *not* make proxies for.
|
|
58
|
+
const NO_LOAD = ['load'];
|
|
59
|
+
|
|
60
|
+
// Make proxy objects for the loader properties.
|
|
61
|
+
for (const loader in exports.load)
|
|
62
|
+
{
|
|
63
|
+
if (NO_LOAD.includes(loader)) continue;
|
|
64
|
+
exports[loader] = new Proxy(exports.load,
|
|
65
|
+
{
|
|
66
|
+
get(load, lib)
|
|
67
|
+
{
|
|
68
|
+
return load[loader](lib);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* A proxy object for building a progressive hashing instance.
|
|
75
|
+
*
|
|
76
|
+
* Any property of this should be the name of a *Hash algorithm*.
|
|
77
|
+
*
|
|
78
|
+
* Each property is a `function` which takes an optional `object`
|
|
79
|
+
* parameter called `options`, and will call `load.hash(algorithm, options)`,
|
|
80
|
+
* which will return a progressive hashing instance.
|
|
81
|
+
*
|
|
82
|
+
* For a non-progressive hashing function, use the lowercase
|
|
83
|
+
* [hash]{@link module:@lumjs/encode/crypto.hash} property instead.
|
|
84
|
+
*/
|
|
85
|
+
exports.HASH = new Proxy(exports.load,
|
|
86
|
+
{
|
|
87
|
+
get(load, lib)
|
|
88
|
+
{
|
|
89
|
+
return (options => load.hash(lib, options ?? {}));
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* A proxy object for building a progressive **HMAC** hashing instance.
|
|
95
|
+
*
|
|
96
|
+
* Any property of this should be the name of a *Hash algorithm*.
|
|
97
|
+
*
|
|
98
|
+
* Each property is a `function` which takes a mandatory `string`
|
|
99
|
+
* parameter called `secret`, and will call `load.hmac(algorithm, secret)`,
|
|
100
|
+
* which will return a progressive HMAC hashing instance.
|
|
101
|
+
*
|
|
102
|
+
* For a non-progressive HMAC hashing function, use the lowercase
|
|
103
|
+
* [hmac]{@link module:@lumjs/encode/crypto.hmac} property instead.
|
|
104
|
+
*/
|
|
105
|
+
exports.HMAC = new Proxy(exports.load,
|
|
106
|
+
{
|
|
107
|
+
get(load, lib)
|
|
108
|
+
{
|
|
109
|
+
return (secret => load.hmac(lib, secret));
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* A proxy object for loading Hashing functions.
|
|
115
|
+
*
|
|
116
|
+
* Any property of this should be the name of a *Hash algorithm*,
|
|
117
|
+
* and the property will return the corresponding hashing function.
|
|
118
|
+
*
|
|
119
|
+
* For a progressive hashing instance, use the uppercase
|
|
120
|
+
* [HASH]{@link module:@lumjs/encode/crypto.HASH} property instead.
|
|
121
|
+
*
|
|
122
|
+
* @name module:@lumjs/encode/crypto.hash
|
|
123
|
+
*/
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* A proxy object for loading HMAC hashing functions.
|
|
127
|
+
*
|
|
128
|
+
* Any property of this should be the name of a *Hash algorithm*,
|
|
129
|
+
* and the property will return the corresponding HMAC hashing function.
|
|
130
|
+
*
|
|
131
|
+
* For a progressive HMAC hashing instance, use the uppercase
|
|
132
|
+
* [HMAC]{@link module:@lumjs/encode/crypto.HMAC} property instead.
|
|
133
|
+
*
|
|
134
|
+
* @name module:@lumjs/encode/crypto.hmac
|
|
135
|
+
*/
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* A proxy object for loading Cipher libraries.
|
|
139
|
+
*
|
|
140
|
+
* @name module:@lumjs/encode/crypto.cipher
|
|
141
|
+
*/
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* A proxy object for loading Algorithm libraries.
|
|
145
|
+
*
|
|
146
|
+
* @name module:@lumjs/encode/crypto.algo
|
|
147
|
+
*/
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* A proxy object for loading Encoding libraries.
|
|
151
|
+
*
|
|
152
|
+
* @name module:@lumjs/encode/crypto.enc
|
|
153
|
+
*/
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* A proxy object for loading Padding plugins.
|
|
157
|
+
*
|
|
158
|
+
* @name module:@lumjs/encode/crypto.pad
|
|
159
|
+
*/
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* A proxy object for loading Mode plugins.
|
|
163
|
+
*
|
|
164
|
+
* @name module:@lumjs/encode/crypto.mode
|
|
165
|
+
*/
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* A proxy object for loading Format plugins.
|
|
169
|
+
*
|
|
170
|
+
* @name module:@lumjs/encode/crypto.format
|
|
171
|
+
*/
|