@lumjs/encode 2.3.2 → 2.4.1
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 +22 -1
- package/lib/base64.js +12 -12
- package/lib/base91.js +3 -5
- package/lib/hash.js +16 -11
- package/lib/hotp.js +49 -23
- package/lib/index.js +11 -7
- package/lib/pem.js +128 -0
- package/lib/totp.js +7 -1
- package/lib/util.js +44 -4
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [2.4.1] - 2026-02-09
|
|
10
|
+
### Changed
|
|
11
|
+
- Refactored hashifier a bit to make resetting progressive digests simpler.
|
|
12
|
+
- Made all the debugging info in hotp/totp modules optional.
|
|
13
|
+
- Added `expires` to compiled options for totp module; provides the number
|
|
14
|
+
of seconds until the _current_ code expires.
|
|
15
|
+
- Added a getExpiry() method to totp class that calculates and returns
|
|
16
|
+
just the current expiry information (useful for countdown displays).
|
|
17
|
+
- Muted an expected error message in a test file.
|
|
18
|
+
- Some other minor cleanups.
|
|
19
|
+
|
|
20
|
+
## [2.4.0] - 2026-01-19
|
|
21
|
+
### Added
|
|
22
|
+
- A new `pem` module (which exports a `PEM` class) for parsing PEM strings.
|
|
23
|
+
- Tests for the `pem` module.
|
|
24
|
+
- A `str2ta()` function was added to the `util` module.
|
|
25
|
+
### Fixed
|
|
26
|
+
- A fatal error in the `base64.encodeData()` function.
|
|
27
|
+
|
|
9
28
|
## [2.3.2] - 2026-01-14
|
|
10
29
|
### Fixed
|
|
11
30
|
- More things I missed, sigh.
|
|
@@ -77,7 +96,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
77
96
|
### Added
|
|
78
97
|
- Initial release.
|
|
79
98
|
|
|
80
|
-
[Unreleased]: https://github.com/supernovus/lum.encode.js/compare/v2.
|
|
99
|
+
[Unreleased]: https://github.com/supernovus/lum.encode.js/compare/v2.4.1...HEAD
|
|
100
|
+
[2.4.1]: https://github.com/supernovus/lum.encode.js/compare/v2.4.0...v2.4.1
|
|
101
|
+
[2.4.0]: https://github.com/supernovus/lum.encode.js/compare/v2.3.2...v2.4.0
|
|
81
102
|
[2.3.2]: https://github.com/supernovus/lum.encode.js/compare/v2.3.1...v2.3.2
|
|
82
103
|
[2.3.1]: https://github.com/supernovus/lum.encode.js/compare/v2.3.0...v2.3.1
|
|
83
104
|
[2.3.0]: https://github.com/supernovus/lum.encode.js/compare/v2.2.2...v2.3.0
|
package/lib/base64.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
const {
|
|
2
|
+
const { isObj } = require('@lumjs/core/types');
|
|
3
3
|
|
|
4
4
|
const D_MIME = 'application/octet-stream';
|
|
5
5
|
const D_ENC = 'utf-8';
|
|
@@ -8,7 +8,7 @@ const P_B64 = ';base64,';
|
|
|
8
8
|
const R_PRE = /^data\:(.*?);base64,/;
|
|
9
9
|
const B_64U = 'base64url';
|
|
10
10
|
|
|
11
|
-
const UI8_FB64 = (typeof Uint8Array.fromBase64 ===
|
|
11
|
+
const UI8_FB64 = (typeof Uint8Array.fromBase64 === 'function');
|
|
12
12
|
const URL_CHARS = /_-/;
|
|
13
13
|
|
|
14
14
|
/**
|
|
@@ -103,7 +103,7 @@ function toBytes(base64, options={})
|
|
|
103
103
|
*/
|
|
104
104
|
function fromBytes(bytes, options={})
|
|
105
105
|
{
|
|
106
|
-
if (typeof bytes.toBase64 ===
|
|
106
|
+
if (typeof bytes.toBase64 === 'function')
|
|
107
107
|
{
|
|
108
108
|
return bytes.toBase64(options);
|
|
109
109
|
}
|
|
@@ -139,7 +139,7 @@ function fromBytes(bytes, options={})
|
|
|
139
139
|
*/
|
|
140
140
|
function encodeText(data, options={})
|
|
141
141
|
{
|
|
142
|
-
if (typeof options ===
|
|
142
|
+
if (typeof options === 'boolean')
|
|
143
143
|
{ // Assume the 'url' option.
|
|
144
144
|
options = {url: options};
|
|
145
145
|
}
|
|
@@ -149,15 +149,15 @@ function encodeText(data, options={})
|
|
|
149
149
|
const encoder = new TextEncoder();
|
|
150
150
|
data = encoder.encode(data);
|
|
151
151
|
}
|
|
152
|
-
const toB64 = (typeof data.toBase64 ===
|
|
152
|
+
const toB64 = (typeof data.toBase64 === 'function');
|
|
153
153
|
|
|
154
154
|
if (toB64 && options.url)
|
|
155
155
|
{
|
|
156
|
-
if (typeof options.alphabet !==
|
|
156
|
+
if (typeof options.alphabet !== 'string')
|
|
157
157
|
{
|
|
158
158
|
options.alphabet = B_64U;
|
|
159
159
|
}
|
|
160
|
-
if (!options.useTildes && typeof options.omitPadding !==
|
|
160
|
+
if (!options.useTildes && typeof options.omitPadding !== 'boolean')
|
|
161
161
|
{
|
|
162
162
|
options.omitPadding = true;
|
|
163
163
|
}
|
|
@@ -192,7 +192,7 @@ function encodeText(data, options={})
|
|
|
192
192
|
*/
|
|
193
193
|
function decodeText(base64, options={})
|
|
194
194
|
{
|
|
195
|
-
if (typeof options ===
|
|
195
|
+
if (typeof options === 'boolean')
|
|
196
196
|
{ // Assume the 'url' option.
|
|
197
197
|
options = {url: options};
|
|
198
198
|
}
|
|
@@ -201,7 +201,7 @@ function decodeText(base64, options={})
|
|
|
201
201
|
{ // Unless explicitly disabled, use deurlize() first.
|
|
202
202
|
if (UI8_FB64)
|
|
203
203
|
{
|
|
204
|
-
if (typeof options.alphabet !==
|
|
204
|
+
if (typeof options.alphabet !== 'string')
|
|
205
205
|
{
|
|
206
206
|
if (URL_CHARS.test(base64))
|
|
207
207
|
{
|
|
@@ -339,7 +339,7 @@ async function fromDataUrl(dataUrl, options={})
|
|
|
339
339
|
*/
|
|
340
340
|
async function encodeData(data, options={})
|
|
341
341
|
{
|
|
342
|
-
let base64 = await toDataUrl(data, options).replace(R_PRE, '');
|
|
342
|
+
let base64 = (await toDataUrl(data, options)).replace(R_PRE, '');
|
|
343
343
|
return options.url ? urlize(base64, options) : base64;
|
|
344
344
|
}
|
|
345
345
|
|
|
@@ -365,7 +365,7 @@ async function decodeData(base64, options={})
|
|
|
365
365
|
{ // Unless explicitly disabled, use deurlize() first.
|
|
366
366
|
base64 = deurlize(base64);
|
|
367
367
|
}
|
|
368
|
-
const type = (typeof options.type ===
|
|
368
|
+
const type = (typeof options.type === 'string') ? options.type : D_MIME;
|
|
369
369
|
base64 = P_DATA+type+P_B64+base64;
|
|
370
370
|
}
|
|
371
371
|
|
|
@@ -392,7 +392,7 @@ async function decodeData(base64, options={})
|
|
|
392
392
|
*/
|
|
393
393
|
function encode(data, options={})
|
|
394
394
|
{
|
|
395
|
-
if (options.blob || options.file || (typeof data !==
|
|
395
|
+
if (options.blob || options.file || (typeof data !== 'string'))
|
|
396
396
|
{
|
|
397
397
|
return encodeData(data, options);
|
|
398
398
|
}
|
package/lib/base91.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
const {S,B} = require('@lumjs/core/types');
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* A pure-Javascript base91 library.
|
|
5
3
|
*
|
|
@@ -33,7 +31,7 @@ exports.encode = function(data)
|
|
|
33
31
|
{
|
|
34
32
|
let output = '';
|
|
35
33
|
let len = data.length,
|
|
36
|
-
isStr = (typeof data ===
|
|
34
|
+
isStr = (typeof data === 'string'),
|
|
37
35
|
queue = 0,
|
|
38
36
|
numbits = 0,
|
|
39
37
|
value = 0;
|
|
@@ -131,7 +129,7 @@ exports.decode = function(data, opts={})
|
|
|
131
129
|
{
|
|
132
130
|
const output = [];
|
|
133
131
|
let len = data.length,
|
|
134
|
-
isStr = (typeof data ===
|
|
132
|
+
isStr = (typeof data === 'string'),
|
|
135
133
|
queue = 0,
|
|
136
134
|
numbits = 0,
|
|
137
135
|
value = -1,
|
|
@@ -164,7 +162,7 @@ exports.decode = function(data, opts={})
|
|
|
164
162
|
output.push(queue | (value << numbits));
|
|
165
163
|
}
|
|
166
164
|
|
|
167
|
-
if (typeof opts ===
|
|
165
|
+
if (typeof opts === 'boolean')
|
|
168
166
|
{
|
|
169
167
|
opts = {string: opts};
|
|
170
168
|
}
|
package/lib/hash.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const {
|
|
3
|
+
const { isObj, isNil } = require('@lumjs/core/types');
|
|
4
4
|
|
|
5
5
|
const util = require('./util');
|
|
6
6
|
const base32 = require('./base32');
|
|
@@ -130,7 +130,7 @@ module.exports = class
|
|
|
130
130
|
*/
|
|
131
131
|
constructor(options={})
|
|
132
132
|
{
|
|
133
|
-
if (typeof options ===
|
|
133
|
+
if (typeof options === 'string')
|
|
134
134
|
{
|
|
135
135
|
options = {algo: options};
|
|
136
136
|
}
|
|
@@ -146,7 +146,7 @@ module.exports = class
|
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
this.algo = this.getAlgorithm(
|
|
149
|
-
(typeof options.algo ===
|
|
149
|
+
(typeof options.algo === 'string')
|
|
150
150
|
? options.algo
|
|
151
151
|
: D_ALGO);
|
|
152
152
|
|
|
@@ -243,11 +243,11 @@ module.exports = class
|
|
|
243
243
|
|
|
244
244
|
const joiner = this.current.joiner;
|
|
245
245
|
|
|
246
|
-
if (typeof joiner ===
|
|
246
|
+
if (typeof joiner === 'function')
|
|
247
247
|
{
|
|
248
248
|
input = joiner.call(this, this.current.hash);
|
|
249
249
|
}
|
|
250
|
-
else if (typeof joiner ===
|
|
250
|
+
else if (typeof joiner === 'string')
|
|
251
251
|
{
|
|
252
252
|
input = this.current.hash.join(joiner);
|
|
253
253
|
}
|
|
@@ -258,10 +258,10 @@ module.exports = class
|
|
|
258
258
|
}
|
|
259
259
|
|
|
260
260
|
// Now clear the current hash values.
|
|
261
|
-
this.
|
|
261
|
+
this.reset();
|
|
262
262
|
}
|
|
263
263
|
|
|
264
|
-
if (typeof input ===
|
|
264
|
+
if (typeof input === 'string')
|
|
265
265
|
{ // This is super simple.
|
|
266
266
|
const encoder = new TextEncoder();
|
|
267
267
|
input = encoder.encode(input);
|
|
@@ -377,12 +377,12 @@ module.exports = class
|
|
|
377
377
|
*/
|
|
378
378
|
add(input, opts={})
|
|
379
379
|
{
|
|
380
|
-
if (typeof input !==
|
|
380
|
+
if (typeof input !== 'string')
|
|
381
381
|
{
|
|
382
382
|
let enc = this.current.encoder,
|
|
383
383
|
eopts = null;
|
|
384
384
|
|
|
385
|
-
if (typeof enc ===
|
|
385
|
+
if (typeof enc === 'string')
|
|
386
386
|
{
|
|
387
387
|
enc = DATA_ENCODERS[enc];
|
|
388
388
|
eopts = this.defaults[enc];
|
|
@@ -391,11 +391,11 @@ module.exports = class
|
|
|
391
391
|
// Compile the options for the encoder.
|
|
392
392
|
eopts = Object.assign({hashifier: this}, eopts, opts);
|
|
393
393
|
|
|
394
|
-
if (typeof enc ===
|
|
394
|
+
if (typeof enc === 'function')
|
|
395
395
|
{ // Call the function, using the hashifier instance as `this`.
|
|
396
396
|
input = enc.call(this, input, eopts);
|
|
397
397
|
}
|
|
398
|
-
else if (isObj(enc) && typeof enc.encode ===
|
|
398
|
+
else if (isObj(enc) && typeof enc.encode === 'function')
|
|
399
399
|
{ // Using an encoder object/instance.
|
|
400
400
|
input = enc.encode(input, eopts);
|
|
401
401
|
}
|
|
@@ -432,6 +432,11 @@ module.exports = class
|
|
|
432
432
|
return this;
|
|
433
433
|
}
|
|
434
434
|
|
|
435
|
+
reset() {
|
|
436
|
+
this.current.hash.length = 0;
|
|
437
|
+
return this;
|
|
438
|
+
}
|
|
439
|
+
|
|
435
440
|
static new(opts={})
|
|
436
441
|
{
|
|
437
442
|
return new this(opts);
|
package/lib/hotp.js
CHANGED
|
@@ -3,11 +3,17 @@
|
|
|
3
3
|
const HmacEncoder = require('./hmac');
|
|
4
4
|
const { intToBytes } = require('./util');
|
|
5
5
|
|
|
6
|
+
const DEBUG = Object.freeze({
|
|
7
|
+
LOG: 1,
|
|
8
|
+
INFO: 2,
|
|
9
|
+
});
|
|
10
|
+
|
|
6
11
|
const DEF_OPTS = {
|
|
7
12
|
algorithm: 'SHA-1',
|
|
8
13
|
checkSize: 7,
|
|
9
|
-
counter: 0,
|
|
10
|
-
|
|
14
|
+
counter: 0,
|
|
15
|
+
debug: 0,
|
|
16
|
+
window: 50
|
|
11
17
|
};
|
|
12
18
|
|
|
13
19
|
const cp = Object.assign;
|
|
@@ -50,9 +56,11 @@ class HOTP {
|
|
|
50
56
|
return [DEF_OPTS];
|
|
51
57
|
}
|
|
52
58
|
|
|
53
|
-
async generate(key = this.defaultKey, opts) {
|
|
54
|
-
|
|
55
|
-
|
|
59
|
+
async generate(key = this.defaultKey, opts, fromVerify=false) {
|
|
60
|
+
if (!fromVerify) {
|
|
61
|
+
needKey(key);
|
|
62
|
+
opts = this.getOptions(opts);
|
|
63
|
+
}
|
|
56
64
|
|
|
57
65
|
let encoder = new HmacEncoder(key, opts);
|
|
58
66
|
let data = new Uint8Array(intToBytes(opts.counter));
|
|
@@ -70,20 +78,27 @@ class HOTP {
|
|
|
70
78
|
let code = Array(opts.checkSize - v2.length).join('0') + v2;
|
|
71
79
|
|
|
72
80
|
let res = {
|
|
73
|
-
opts,
|
|
74
|
-
data,
|
|
75
|
-
hash,
|
|
76
|
-
hashBytes: hb,
|
|
77
|
-
offset,
|
|
78
|
-
v1,
|
|
79
|
-
v2,
|
|
80
81
|
code,
|
|
82
|
+
opts,
|
|
81
83
|
toString() {
|
|
82
84
|
return this.code;
|
|
83
85
|
},
|
|
84
86
|
}
|
|
85
87
|
|
|
86
|
-
if (opts.debug
|
|
88
|
+
if (opts.debug & DEBUG.INFO) {
|
|
89
|
+
cp(res, {
|
|
90
|
+
data,
|
|
91
|
+
hash,
|
|
92
|
+
hashBytes: hb,
|
|
93
|
+
offset,
|
|
94
|
+
v1,
|
|
95
|
+
v2,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (!fromVerify && (opts.debug & DEBUG.LOG)) {
|
|
100
|
+
console.debug(res.code, res);
|
|
101
|
+
}
|
|
87
102
|
|
|
88
103
|
return res;
|
|
89
104
|
}
|
|
@@ -95,25 +110,36 @@ class HOTP {
|
|
|
95
110
|
let win = opts.window;
|
|
96
111
|
let cnt = opts.counter;
|
|
97
112
|
let info = { ok: false };
|
|
113
|
+
let di = (opts.debug & DEBUG.INFO);
|
|
98
114
|
|
|
99
|
-
|
|
115
|
+
let done = (add) => {
|
|
116
|
+
if (add) cp(info, add); // add final info
|
|
117
|
+
if (opts.debug & DEBUG.LOG) console.debug(info);
|
|
118
|
+
|
|
119
|
+
if (!info.ok && opts.throw) {
|
|
120
|
+
let EClass = isError(opts.throw) ? opts.throw : Error;
|
|
121
|
+
throw new EClass("OTP verification failure");
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return info;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (di) info.stack = [];
|
|
100
128
|
|
|
101
129
|
for (let i = cnt - win; i <= cnt + win; ++i) {
|
|
102
130
|
opts.counter = i;
|
|
103
|
-
let res = this.generate(key, opts);
|
|
104
|
-
if (
|
|
131
|
+
let res = this.generate(key, opts, true);
|
|
132
|
+
if (di) info.stack.push(res);
|
|
105
133
|
if (res.code === token) {
|
|
106
|
-
return
|
|
134
|
+
return done({ ok: true, delta: i - cnt });
|
|
107
135
|
}
|
|
108
136
|
}
|
|
109
137
|
|
|
110
|
-
|
|
111
|
-
let EClass = isError(opts.throw) ? opts.throw : Error;
|
|
112
|
-
throw new EClass("OTP verification failure");
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
return info;
|
|
138
|
+
return done();
|
|
116
139
|
}
|
|
117
140
|
}
|
|
118
141
|
|
|
142
|
+
HOTP.DEBUG = DEBUG;
|
|
143
|
+
HOTP.prototype.DEBUG = DEBUG;
|
|
144
|
+
|
|
119
145
|
module.exports = HOTP;
|
package/lib/index.js
CHANGED
|
@@ -3,24 +3,22 @@
|
|
|
3
3
|
* @module @lumjs/encode
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
const {
|
|
7
|
-
|
|
8
|
-
const E = def.e;
|
|
9
|
-
|
|
6
|
+
const {df,lazy} = require('@lumjs/core');
|
|
7
|
+
const E = {enumerable: true};
|
|
10
8
|
const util = require('./util');
|
|
11
9
|
|
|
12
10
|
/**
|
|
13
11
|
* @alias module:@lumjs/encode.util
|
|
14
12
|
* @see {@link module:@lumjs/encode/util}
|
|
15
13
|
*/
|
|
16
|
-
|
|
14
|
+
df(exports, 'util', {value: util}, E);
|
|
17
15
|
|
|
18
16
|
/**
|
|
19
17
|
* @alias module:@lumjs/encode.ord
|
|
20
18
|
* @deprecated this alias to `util.ord` will be removed in 3.x.
|
|
21
19
|
* @see {@link module:@lumjs/encode/util.ord}
|
|
22
20
|
*/
|
|
23
|
-
|
|
21
|
+
df(exports, 'ord', util.ord, E);
|
|
24
22
|
|
|
25
23
|
/**
|
|
26
24
|
* @name module:@lumjs/encode.numByteArray
|
|
@@ -28,7 +26,7 @@ def(exports, 'ord', util.ord, E);
|
|
|
28
26
|
* @deprecated this alias to `util.numByteArray` will be removed in 3.x.
|
|
29
27
|
* @see {@link module:@lumjs/encode/util.numByteArray}
|
|
30
28
|
*/
|
|
31
|
-
|
|
29
|
+
df(exports, 'numByteArray', util.numByteArray, E);
|
|
32
30
|
|
|
33
31
|
/**
|
|
34
32
|
* @name module:@lumjs/encode.Base32
|
|
@@ -66,6 +64,12 @@ lazy(exports, 'HMAC', () => require('./hmac'), E);
|
|
|
66
64
|
*/
|
|
67
65
|
lazy(exports, 'HOTP', () => require('./hotp'), E);
|
|
68
66
|
|
|
67
|
+
/**
|
|
68
|
+
* @name module:@lumjs/encode.PEM
|
|
69
|
+
* @see {@link module:@lumjs/encode/pem}
|
|
70
|
+
*/
|
|
71
|
+
lazy(exports, 'PEM', () => require('./pem'), E);
|
|
72
|
+
|
|
69
73
|
/**
|
|
70
74
|
* @name module:@lumjs/encode.TOTP
|
|
71
75
|
* @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/totp.js
CHANGED
|
@@ -12,10 +12,16 @@ class TOTP extends HOTP {
|
|
|
12
12
|
return [...super.defaultOptions, DEF_OPTS];
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
getExpiry(opts) {
|
|
16
|
+
return this.getOptions(opts).expires;
|
|
17
|
+
}
|
|
18
|
+
|
|
15
19
|
getOptions() {
|
|
16
20
|
let opts = super.getOptions(...arguments);
|
|
17
21
|
if (!opts.time) opts.time = Date.now();
|
|
18
|
-
|
|
22
|
+
let ts = opts.time / 1000;
|
|
23
|
+
opts.counter = Math.floor(ts / opts.step);
|
|
24
|
+
opts.expires = 30 - Math.floor(ts) % 30;
|
|
19
25
|
return opts;
|
|
20
26
|
}
|
|
21
27
|
}
|
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
|
}
|
|
@@ -138,7 +138,7 @@ exports.numByteArray = function (numStr, options={})
|
|
|
138
138
|
remainder = strLen % len;
|
|
139
139
|
if (remainder !== 0)
|
|
140
140
|
{ // Something is wrong in the universe...
|
|
141
|
-
console.
|
|
141
|
+
console.error({numStr, strLen, len, remainder, arguments});
|
|
142
142
|
throw new Error("string has remainder after padding");
|
|
143
143
|
}
|
|
144
144
|
}
|
|
@@ -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.1",
|
|
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",
|