@lumjs/encode 2.3.1 → 2.4.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 -1
- package/lib/base64.js +28 -13
- package/lib/hash.js +21 -1
- package/lib/index.js +6 -0
- package/lib/pem.js +128 -0
- package/lib/util.js +43 -3
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [2.4.0] - 2026-01-19
|
|
10
|
+
### Added
|
|
11
|
+
- A new `pem` module (which exports a `PEM` class) for parsing PEM strings.
|
|
12
|
+
- Tests for the `pem` module.
|
|
13
|
+
- A `str2ta()` function was added to the `util` module.
|
|
14
|
+
### Fixed
|
|
15
|
+
- A fatal error in the `base64.encodeData()` function.
|
|
16
|
+
|
|
17
|
+
## [2.3.2] - 2026-01-14
|
|
18
|
+
### Fixed
|
|
19
|
+
- More things I missed, sigh.
|
|
20
|
+
|
|
9
21
|
## [2.3.1] - 2026-01-14
|
|
10
22
|
### Fixed
|
|
11
23
|
- Another broken reference in the HOTP library from its prototype stage.
|
|
@@ -73,7 +85,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
73
85
|
### Added
|
|
74
86
|
- Initial release.
|
|
75
87
|
|
|
76
|
-
[Unreleased]: https://github.com/supernovus/lum.encode.js/compare/v2.
|
|
88
|
+
[Unreleased]: https://github.com/supernovus/lum.encode.js/compare/v2.4.0...HEAD
|
|
89
|
+
[2.4.0]: https://github.com/supernovus/lum.encode.js/compare/v2.3.2...v2.4.0
|
|
90
|
+
[2.3.2]: https://github.com/supernovus/lum.encode.js/compare/v2.3.1...v2.3.2
|
|
77
91
|
[2.3.1]: https://github.com/supernovus/lum.encode.js/compare/v2.3.0...v2.3.1
|
|
78
92
|
[2.3.0]: https://github.com/supernovus/lum.encode.js/compare/v2.2.2...v2.3.0
|
|
79
93
|
[2.2.2]: https://github.com/supernovus/lum.encode.js/compare/v2.2.0...v2.2.2
|
package/lib/base64.js
CHANGED
|
@@ -65,7 +65,7 @@ function deurlize(string)
|
|
|
65
65
|
/**
|
|
66
66
|
* Convert a Base64-encoded string into a Uint8Array.
|
|
67
67
|
*
|
|
68
|
-
* This is a low-level function with
|
|
68
|
+
* This is a low-level function with minimal options.
|
|
69
69
|
* See `decodeText()` for a more full-featured function.
|
|
70
70
|
*
|
|
71
71
|
* This now checks to see if `Uint8Array.fromBase64()` exists,
|
|
@@ -117,10 +117,16 @@ function fromBytes(bytes, options={})
|
|
|
117
117
|
/**
|
|
118
118
|
* Encode a string to Base64.
|
|
119
119
|
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
120
|
+
* This adds a bunch of extra features on top of `fromBytes()`,
|
|
121
|
+
* including optionally passing the output through `urlize()`.
|
|
122
|
+
*
|
|
123
|
+
* @param {(string|Uint8Array)} data - Data to be encoded.
|
|
124
|
+
*
|
|
125
|
+
* If this is a String we'll use a `TextEncoder` instance to
|
|
126
|
+
* convert it into a Uint8Array before passing it to fromBytes().
|
|
127
|
+
*
|
|
128
|
+
* If this is a Uint8Array, we can skip the TextEncoder part.
|
|
122
129
|
*
|
|
123
|
-
* @param {string} data - Any valid (Unicode) string
|
|
124
130
|
* @param {(object|boolean)} [options] Options
|
|
125
131
|
*
|
|
126
132
|
* - If `boolean`, used as `options.url`
|
|
@@ -138,8 +144,11 @@ function encodeText(data, options={})
|
|
|
138
144
|
options = {url: options};
|
|
139
145
|
}
|
|
140
146
|
|
|
141
|
-
|
|
142
|
-
|
|
147
|
+
if (!(data instanceof Uint8Array))
|
|
148
|
+
{
|
|
149
|
+
const encoder = new TextEncoder();
|
|
150
|
+
data = encoder.encode(data);
|
|
151
|
+
}
|
|
143
152
|
const toB64 = (typeof data.toBase64 === F);
|
|
144
153
|
|
|
145
154
|
if (toB64 && options.url)
|
|
@@ -171,13 +180,15 @@ function encodeText(data, options={})
|
|
|
171
180
|
* - Passed to `new TextDecoder()`
|
|
172
181
|
* - Passed to `decoder.decode()`
|
|
173
182
|
*
|
|
174
|
-
* @param {boolean} [options.
|
|
183
|
+
* @param {boolean} [options.string=true] Decode as a string?
|
|
184
|
+
* @param {boolean} [options.url=true] Deurlize the base64 string?
|
|
175
185
|
*
|
|
176
186
|
* Unless this is explicitly set as `false`, the `base64`
|
|
177
187
|
* string will be passed to `deurlize()` before being
|
|
178
188
|
* processed further.
|
|
179
189
|
*
|
|
180
|
-
* @returns {string}
|
|
190
|
+
* @returns {(string|Uint8Array)}
|
|
191
|
+
* Returned type depends on `opts.string`.
|
|
181
192
|
*/
|
|
182
193
|
function decodeText(base64, options={})
|
|
183
194
|
{
|
|
@@ -186,7 +197,7 @@ function decodeText(base64, options={})
|
|
|
186
197
|
options = {url: options};
|
|
187
198
|
}
|
|
188
199
|
|
|
189
|
-
if (options.url
|
|
200
|
+
if (options.url ?? true)
|
|
190
201
|
{ // Unless explicitly disabled, use deurlize() first.
|
|
191
202
|
if (UI8_FB64)
|
|
192
203
|
{
|
|
@@ -204,9 +215,13 @@ function decodeText(base64, options={})
|
|
|
204
215
|
}
|
|
205
216
|
}
|
|
206
217
|
|
|
207
|
-
const
|
|
208
|
-
|
|
209
|
-
|
|
218
|
+
const bytes = toBytes(base64, options);
|
|
219
|
+
if (options.string ?? true) {
|
|
220
|
+
const encoding = options.encoding ?? D_ENC;
|
|
221
|
+
const decoder = new TextDecoder(encoding, options);
|
|
222
|
+
return decoder.decode(bytes, options);
|
|
223
|
+
}
|
|
224
|
+
return bytes;
|
|
210
225
|
}
|
|
211
226
|
|
|
212
227
|
/**
|
|
@@ -324,7 +339,7 @@ async function fromDataUrl(dataUrl, options={})
|
|
|
324
339
|
*/
|
|
325
340
|
async function encodeData(data, options={})
|
|
326
341
|
{
|
|
327
|
-
let base64 = await toDataUrl(data, options).replace(R_PRE, '');
|
|
342
|
+
let base64 = (await toDataUrl(data, options)).replace(R_PRE, '');
|
|
328
343
|
return options.url ? urlize(base64, options) : base64;
|
|
329
344
|
}
|
|
330
345
|
|
package/lib/hash.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const {S,F,isObj,isNil} = require('@lumjs/core/types');
|
|
4
4
|
|
|
5
5
|
const util = require('./util');
|
|
6
|
+
const base32 = require('./base32');
|
|
6
7
|
const base64 = require('./base64');
|
|
7
8
|
const base91 = require('./base91');
|
|
8
9
|
|
|
@@ -156,6 +157,7 @@ module.exports = class
|
|
|
156
157
|
|
|
157
158
|
this.defaults =
|
|
158
159
|
{
|
|
160
|
+
base32: options.base32 ?? {},
|
|
159
161
|
base64: options.base64 ?? {},
|
|
160
162
|
base91: options.base91 ?? {},
|
|
161
163
|
}
|
|
@@ -289,6 +291,22 @@ module.exports = class
|
|
|
289
291
|
return (hashArr.map((b)=>b.toString(16).padStart(2, "0")).join(""));
|
|
290
292
|
}
|
|
291
293
|
|
|
294
|
+
/**
|
|
295
|
+
* Get hash as a Base32-encoded string.
|
|
296
|
+
*
|
|
297
|
+
* @param {(string|object|null)} [input]
|
|
298
|
+
* See [hash()]{@link module:@lumjs/encode/hash#hash}
|
|
299
|
+
*
|
|
300
|
+
* @param {object} [options] Options to pass to base32.encode().
|
|
301
|
+
*
|
|
302
|
+
* @returns {string}
|
|
303
|
+
*/
|
|
304
|
+
async base32(input, opts=this.defaults.base32)
|
|
305
|
+
{
|
|
306
|
+
const hash = await this.hash(input);
|
|
307
|
+
return base32.encode(new Uint8Array(hash), opts);
|
|
308
|
+
}
|
|
309
|
+
|
|
292
310
|
/**
|
|
293
311
|
* Get hash as a Base64-encoded string.
|
|
294
312
|
*
|
|
@@ -311,12 +329,14 @@ module.exports = class
|
|
|
311
329
|
/**
|
|
312
330
|
* Get hash as a Base91-encoded string.
|
|
313
331
|
*
|
|
314
|
-
* @param {(string|
|
|
332
|
+
* @param {(string|object|null)} [input]
|
|
315
333
|
* See [hash()]{@link module:@lumjs/encode/hash#hash}
|
|
316
334
|
* @param {object} [opts] Options for how to encode the hash.
|
|
317
335
|
*
|
|
318
336
|
* @param {(boolean|object)} [opts.nba=false] Use `numByteArray()` ?
|
|
319
337
|
*
|
|
338
|
+
* This options is deprecated and will be removed in v3.0.
|
|
339
|
+
*
|
|
320
340
|
* If this is `true` the *hash string* will be passed to `numByteArray()`
|
|
321
341
|
* with the *default options* and the output from that will be passed to
|
|
322
342
|
* `base91.encode()`.
|
package/lib/index.js
CHANGED
|
@@ -66,6 +66,12 @@ lazy(exports, 'HMAC', () => require('./hmac'), E);
|
|
|
66
66
|
*/
|
|
67
67
|
lazy(exports, 'HOTP', () => require('./hotp'), E);
|
|
68
68
|
|
|
69
|
+
/**
|
|
70
|
+
* @name module:@lumjs/encode.PEM
|
|
71
|
+
* @see {@link module:@lumjs/encode/pem}
|
|
72
|
+
*/
|
|
73
|
+
lazy(exports, 'PEM', () => require('./pem'), E);
|
|
74
|
+
|
|
69
75
|
/**
|
|
70
76
|
* @name module:@lumjs/encode.TOTP
|
|
71
77
|
* @see {@link module:@lumjs/encode/totp}
|
package/lib/pem.js
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { str2ta } = require('./util');
|
|
4
|
+
|
|
5
|
+
const UI8_FB64 = (typeof Uint8Array.fromBase64 === 'function');
|
|
6
|
+
const PEM_TEXT = /^\s*-----BEGIN\s+(?<label>[A-Z\s]+)-----\n(?<base64>.*?)\n-----END\s+\k<label>-----\s*$/s;
|
|
7
|
+
const parseText = (str) => (PEM_TEXT.exec(str)?.groups ?? null);
|
|
8
|
+
const validInfo = (pem) => (pem
|
|
9
|
+
&& typeof pem === 'object'
|
|
10
|
+
&& typeof pem.label === 'string'
|
|
11
|
+
&& typeof pem.base64 === 'string'
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A class for parsing and decoding PEM documents.
|
|
16
|
+
*
|
|
17
|
+
* PEM is a format commonly used for encryption keys.
|
|
18
|
+
* See: https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail
|
|
19
|
+
*
|
|
20
|
+
* @alias {module:@lumjs/encode/pem}
|
|
21
|
+
*/
|
|
22
|
+
class PEM {
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Parse a string into a PEM object instance.
|
|
26
|
+
*
|
|
27
|
+
* This method is strict and will throw an error on failure.
|
|
28
|
+
* For a more lenient way to parse PEM documents, see the
|
|
29
|
+
* {@link module:@lumjs/encode/pem.parse parse()} method.
|
|
30
|
+
*
|
|
31
|
+
* @param {string} pem - PEM format string to be parsed.
|
|
32
|
+
* @throws {TypeError} If the `pem` argument is an invalid value.
|
|
33
|
+
* @throws {SyntaxErrror} If the `pem` string was not able to be parsed.
|
|
34
|
+
*/
|
|
35
|
+
constructor(pem) {
|
|
36
|
+
|
|
37
|
+
if (typeof pem === 'string') {
|
|
38
|
+
let pemStr = pem;
|
|
39
|
+
pem = parseText(pemStr);
|
|
40
|
+
if (!validInfo(pem)) {
|
|
41
|
+
console.error('new PEM()', pemStr);
|
|
42
|
+
throw new SyntaxError("invalid PEM string passed to PEM constructor");
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
else if (!validInfo(pem)) {
|
|
46
|
+
console.error('new PEM()', pem);
|
|
47
|
+
throw new TypeError("invalid argument passed to PEM constructor");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Copy the properties from the info into this.
|
|
51
|
+
Object.assign(this, pem);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Decode the base64 content.
|
|
56
|
+
*
|
|
57
|
+
* @param {(boolean|function)} [typeClass=false] Return a TypedArray?
|
|
58
|
+
*
|
|
59
|
+
* This may be set to the constructor function of any TypedArray class.
|
|
60
|
+
* It may also be set to `true` as an alias for `Uint8Array`.
|
|
61
|
+
*
|
|
62
|
+
* If it is set to `false` (the default), then the binary string output
|
|
63
|
+
* from the `atob()` global function will be used as the return value.
|
|
64
|
+
*
|
|
65
|
+
* If this is set to Uint8Array (either explicitly or by using `true`),
|
|
66
|
+
* and a method named `Uint8Array.fromBase64` exists, then this will use
|
|
67
|
+
* that to parse the base64 content rather than using the
|
|
68
|
+
* {@link module:@lumjs/encode/util.str2ta str2ta()} function.
|
|
69
|
+
*
|
|
70
|
+
* @returns {(string|TypedArray|Error)}
|
|
71
|
+
*
|
|
72
|
+
* If an error is thrown by any functions being used to decode the base64
|
|
73
|
+
* content, that error will be the return value.
|
|
74
|
+
*
|
|
75
|
+
* Otherwise the `typeClass` argument will determine the returned type.
|
|
76
|
+
*/
|
|
77
|
+
decode(typeClass=false) {
|
|
78
|
+
if (typeClass === true) {
|
|
79
|
+
typeClass = Uint8Array;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
let val = null;
|
|
83
|
+
|
|
84
|
+
if (UI8_FB64 && typeClass === Uint8Array) {
|
|
85
|
+
try {
|
|
86
|
+
val = typeClass.fromBase64(this.base64);
|
|
87
|
+
} catch (err) {
|
|
88
|
+
return err;
|
|
89
|
+
}
|
|
90
|
+
return val;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
val = atob(this.base64);
|
|
95
|
+
} catch (err) {
|
|
96
|
+
return err;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (typeClass && typeof val === 'string') {
|
|
100
|
+
try {
|
|
101
|
+
val = str2ta(val, typeClass);
|
|
102
|
+
} catch (err) {
|
|
103
|
+
return err;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return val;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Parse a string into a PEM object instance.
|
|
112
|
+
*
|
|
113
|
+
* This is almost identical to the main class constructor,
|
|
114
|
+
* except this version will simply return null if the argument
|
|
115
|
+
* could not be parsed as a valid PEM string.
|
|
116
|
+
*
|
|
117
|
+
* @param {string} pemText - PEM format string to be parsed.
|
|
118
|
+
* @returns {?module:@lumjs/encode/pem} A PEM instance;
|
|
119
|
+
* or null if the pemText could not be parsed.
|
|
120
|
+
*/
|
|
121
|
+
static parse(pemText) {
|
|
122
|
+
let info = parseText(pemText);
|
|
123
|
+
return info ? new this(info) : info;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
module.exports = PEM;
|
package/lib/util.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
'use strict';
|
|
6
6
|
|
|
7
|
-
const {
|
|
7
|
+
const { TypedArray } = require('@lumjs/core/types');
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Return the ASCII/Unicode number for a character.
|
|
@@ -96,7 +96,7 @@ exports.ord = function (string)
|
|
|
96
96
|
*/
|
|
97
97
|
exports.numByteArray = function (numStr, options={})
|
|
98
98
|
{
|
|
99
|
-
if (typeof options ===
|
|
99
|
+
if (typeof options === 'number')
|
|
100
100
|
{
|
|
101
101
|
options = {size: options};
|
|
102
102
|
}
|
|
@@ -104,7 +104,7 @@ exports.numByteArray = function (numStr, options={})
|
|
|
104
104
|
const numOpt = (name, defval, min, max) =>
|
|
105
105
|
{
|
|
106
106
|
const optval = options[name];
|
|
107
|
-
if (typeof optval !==
|
|
107
|
+
if (typeof optval !== 'number')
|
|
108
108
|
{ // Was not a number, skip it.
|
|
109
109
|
return defval;
|
|
110
110
|
}
|
|
@@ -230,3 +230,43 @@ exports.hexToBytes = function(hex) {
|
|
|
230
230
|
return bytes;
|
|
231
231
|
}
|
|
232
232
|
|
|
233
|
+
/**
|
|
234
|
+
* Convert a binary string into a TypedArray.
|
|
235
|
+
*
|
|
236
|
+
* Inspired by the str2ab() example from:
|
|
237
|
+
* https://developer.chrome.com/blog/how-to-convert-arraybuffer-to-and-from-string
|
|
238
|
+
*
|
|
239
|
+
* The biggest difference being this version supports specifying the specific
|
|
240
|
+
* TypedArray class you want to use, and it returns the TypedArray by default
|
|
241
|
+
* rather than the ArrayBuffer.
|
|
242
|
+
*
|
|
243
|
+
* To get the ArrayBuffer just use: `str2ta(string).buffer;`
|
|
244
|
+
*
|
|
245
|
+
* @param {string} str - Binary string to convert.
|
|
246
|
+
* @param {function} [typeClass=Uint8Array] TypedArray class to use;
|
|
247
|
+
* MUST be a TypedArray class constructor. Default is `Uint8Array`.
|
|
248
|
+
* @returns {TypedArray} Will be an instance of `typeClass`.
|
|
249
|
+
* @throws {TypeError} If invalid arguments were passed.
|
|
250
|
+
*/
|
|
251
|
+
function str2ta(str, typeClass=Uint8Array)
|
|
252
|
+
{
|
|
253
|
+
let valid = {
|
|
254
|
+
str: (typeof str === 'string'),
|
|
255
|
+
typeClass: (TypedArray.isPrototypeOf(typeClass)),
|
|
256
|
+
}
|
|
257
|
+
if (!valid.str || !valid.typeClass) {
|
|
258
|
+
console.error('str2ab valid:', valid, 'values: ', {str, typeClass});
|
|
259
|
+
throw new TypeError("invalid arguments");
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
let buf = new ArrayBuffer(str.length*typeClass.BYTES_PER_ELEMENT);
|
|
263
|
+
let bufView = new typeClass(buf);
|
|
264
|
+
for (let i = 0, strLen = str.length; i < strLen; i++)
|
|
265
|
+
{
|
|
266
|
+
bufView[i] = str.charCodeAt(i);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return bufView;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
exports.str2ta = str2ta;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lumjs/encode",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"exports":
|
|
6
6
|
{
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"./hash": "./lib/hash.js",
|
|
12
12
|
"./hmac": "./lib/hmac.js",
|
|
13
13
|
"./hotp": "./lib/hotp.js",
|
|
14
|
+
"./pem": "./lib/pem.js",
|
|
14
15
|
"./signature": "./lib/signature.js",
|
|
15
16
|
"./totp": "./lib/totp.js",
|
|
16
17
|
"./util": "./lib/util.js",
|