@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 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
@@ -0,0 +1,3 @@
1
+ # TODO
2
+
3
+ - Nothing on the current list.
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
+ */