@lumjs/encode 2.0.0 → 2.2.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 +34 -1
- package/TODO.md +3 -0
- package/lib/base64.js +61 -7
- package/lib/hash.js +2 -0
- package/lib/hmac.js +73 -0
- package/lib/hotp.js +112 -0
- package/lib/index.js +30 -0
- package/lib/signature.js +36 -0
- package/lib/totp.js +23 -0
- package/lib/util.js +41 -0
- package/package.json +6 -2
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,35 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [2.2.0]
|
|
10
|
+
### Added
|
|
11
|
+
- intToBytes() and hexToBytes() functions added to util.js
|
|
12
|
+
- A HMAC wrapper library, and a generic Signature class used by it.
|
|
13
|
+
- HOTP/TOTP generation and valdiation classes.
|
|
14
|
+
They are loosely based on the ones from the `notp` package, but while that
|
|
15
|
+
package exports some static functions and depends on the node.js `crypto`
|
|
16
|
+
module, this one has two JS classes and uses the SubtleCrypto API.
|
|
17
|
+
- A TODO file with things I want to do.
|
|
18
|
+
|
|
19
|
+
## [2.1.0]
|
|
20
|
+
### Changed
|
|
21
|
+
- The `base64` library now supports the `Uint8Array.fromBase64` static method,
|
|
22
|
+
and the corresponding `toBase64()` instance method. As those are rather new
|
|
23
|
+
APIs and aren't supported by every JS runtime yet, it will check for them and
|
|
24
|
+
use them if found, and fall back to the prior implementation otherwise.
|
|
25
|
+
- Updated this changelog, as I forgot to after 2.0 was released last year.
|
|
26
|
+
|
|
27
|
+
## [2.0.0] - 2024-08-14
|
|
28
|
+
### Changed
|
|
29
|
+
- A major overhaul, removing the dependency on `crypto-js` library.
|
|
30
|
+
- Rewrote `base64` library to use `atob`, `btoa`, `TextEncoder`, and `TextDecoder`.
|
|
31
|
+
- Rewrote `hash` library using the modern `SubtleCrypto` APIs.
|
|
32
|
+
- Moved `urlize()` and `deurlize()` functions into `base64` library.
|
|
33
|
+
### Removed
|
|
34
|
+
- The `crypto` sub-module which was designed as a wrapper for `crypto-js`.
|
|
35
|
+
- The `safe64` library has been moved into a standalone [safe64-data] package.
|
|
36
|
+
- Dependencies on `php-serialize` and `ubjson` which were only used by `safe64`.
|
|
37
|
+
|
|
9
38
|
## [1.2.0] - 2023-01-06
|
|
10
39
|
### Changed
|
|
11
40
|
- Bumped `@lumjs/core` to `1.8.0`.
|
|
@@ -23,7 +52,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
23
52
|
### Added
|
|
24
53
|
- Initial release.
|
|
25
54
|
|
|
26
|
-
[Unreleased]: https://github.com/supernovus/lum.encode.js/compare/
|
|
55
|
+
[Unreleased]: https://github.com/supernovus/lum.encode.js/compare/v2.1.0...HEAD
|
|
56
|
+
[2.1.0]: https://github.com/supernovus/lum.encode.js/compare/v2.0.0...v2.1.0
|
|
57
|
+
[2.0.0]: https://github.com/supernovus/lum.encode.js/compare/v1.2.0...v2.0.0
|
|
27
58
|
[1.2.0]: https://github.com/supernovus/lum.encode.js/compare/v1.1.0...v1.2.0
|
|
28
59
|
[1.1.0]: https://github.com/supernovus/lum.encode.js/compare/v1.0.0...v1.1.0
|
|
29
60
|
[1.0.0]: https://github.com/supernovus/lum.encode.js/releases/tag/v1.0.0
|
|
61
|
+
[safe64-data]: https://github.com/supernovus/lum.safe64-data.js
|
|
62
|
+
|
package/TODO.md
ADDED
package/lib/base64.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
|
|
2
|
-
const {S,B,isObj} = require('@lumjs/core/types');
|
|
2
|
+
const {S,B,F,isObj} = require('@lumjs/core/types');
|
|
3
3
|
|
|
4
4
|
const D_MIME = 'application/octet-stream';
|
|
5
5
|
const D_ENC = 'utf-8';
|
|
6
6
|
const P_DATA = 'data:';
|
|
7
7
|
const P_B64 = ';base64,';
|
|
8
8
|
const R_PRE = /^data\:(.*?);base64,/;
|
|
9
|
+
const B_64U = 'base64url';
|
|
10
|
+
|
|
11
|
+
const UI8_FB64 = (typeof Uint8Array.fromBase64 === F);
|
|
12
|
+
const URL_CHARS = /_-/;
|
|
9
13
|
|
|
10
14
|
/**
|
|
11
15
|
* Base64 functions.
|
|
@@ -63,12 +67,22 @@ function deurlize(string)
|
|
|
63
67
|
*
|
|
64
68
|
* This is a low-level function with no options.
|
|
65
69
|
* See `decodeText()` for a more full-featured function.
|
|
70
|
+
*
|
|
71
|
+
* This now checks to see if `Uint8Array.fromBase64()` exists,
|
|
72
|
+
* and if it does, will use it. Otherwise it uses the original
|
|
73
|
+
* encoding algorithm.
|
|
66
74
|
*
|
|
67
75
|
* @param {string} base64 - Base64 encoded-string
|
|
76
|
+
* @param {object} [options] Passed to fromBase64() if it exists
|
|
68
77
|
* @returns {Uint8Array}
|
|
69
78
|
*/
|
|
70
|
-
function toBytes(base64)
|
|
79
|
+
function toBytes(base64, options={})
|
|
71
80
|
{
|
|
81
|
+
if (UI8_FB64)
|
|
82
|
+
{
|
|
83
|
+
return Uint8Array.fromBase64(base64, options);
|
|
84
|
+
}
|
|
85
|
+
|
|
72
86
|
const binString = atob(base64);
|
|
73
87
|
return Uint8Array.from(binString, (m) => m.codePointAt(0));
|
|
74
88
|
}
|
|
@@ -78,12 +92,22 @@ function toBytes(base64)
|
|
|
78
92
|
*
|
|
79
93
|
* This is a low-level function with no options.
|
|
80
94
|
* See `encodeText()` for a more full-featured function.
|
|
95
|
+
*
|
|
96
|
+
* This now checks to see if `bytes.toBase64()` exists,
|
|
97
|
+
* and if it does, will use it. Otherwise it uses the original
|
|
98
|
+
* decoding algorithm.
|
|
81
99
|
*
|
|
82
100
|
* @param {Uint8Array} bytes - Byte array to convert
|
|
101
|
+
* @param {object} [options] Passed to toBase64() if it exists
|
|
83
102
|
* @returns {string}
|
|
84
103
|
*/
|
|
85
|
-
function fromBytes(bytes)
|
|
104
|
+
function fromBytes(bytes, options={})
|
|
86
105
|
{
|
|
106
|
+
if (typeof bytes.toBase64 === F)
|
|
107
|
+
{
|
|
108
|
+
return bytes.toBase64(options);
|
|
109
|
+
}
|
|
110
|
+
|
|
87
111
|
const binString = Array.from(bytes, (byte) =>
|
|
88
112
|
String.fromCodePoint(byte),
|
|
89
113
|
).join("");
|
|
@@ -115,8 +139,23 @@ function encodeText(data, options={})
|
|
|
115
139
|
}
|
|
116
140
|
|
|
117
141
|
const encoder = new TextEncoder();
|
|
118
|
-
|
|
119
|
-
|
|
142
|
+
data = encoder.encode(data);
|
|
143
|
+
const toB64 = (typeof data.toBase64 === F);
|
|
144
|
+
|
|
145
|
+
if (toB64 && options.url)
|
|
146
|
+
{
|
|
147
|
+
if (typeof options.alphabet !== S)
|
|
148
|
+
{
|
|
149
|
+
options.alphabet = B_64U;
|
|
150
|
+
}
|
|
151
|
+
if (!options.useTildes && typeof options.omitPadding !== B)
|
|
152
|
+
{
|
|
153
|
+
options.omitPadding = true;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const base64 = fromBytes(data, options);
|
|
158
|
+
return (options.url && !toB64) ? urlize(base64, options) : base64;
|
|
120
159
|
}
|
|
121
160
|
|
|
122
161
|
/**
|
|
@@ -149,12 +188,25 @@ function decodeText(base64, options={})
|
|
|
149
188
|
|
|
150
189
|
if (options.url !== false)
|
|
151
190
|
{ // Unless explicitly disabled, use deurlize() first.
|
|
152
|
-
|
|
191
|
+
if (UI8_FB64)
|
|
192
|
+
{
|
|
193
|
+
if (typeof options.alphabet !== S)
|
|
194
|
+
{
|
|
195
|
+
if (URL_CHARS.test(base64))
|
|
196
|
+
{
|
|
197
|
+
options.alphabet = B_64U;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
else
|
|
202
|
+
{
|
|
203
|
+
base64 = deurlize(base64);
|
|
204
|
+
}
|
|
153
205
|
}
|
|
154
206
|
|
|
155
207
|
const encoding = options.encoding ?? D_ENC;
|
|
156
208
|
const decoder = new TextDecoder(encoding, options);
|
|
157
|
-
return decoder.decode(toBytes(base64), options);
|
|
209
|
+
return decoder.decode(toBytes(base64, options), options);
|
|
158
210
|
}
|
|
159
211
|
|
|
160
212
|
/**
|
|
@@ -373,4 +425,6 @@ module.exports =
|
|
|
373
425
|
toDataUrl, fromDataUrl,
|
|
374
426
|
encodeData, decodeData,
|
|
375
427
|
encode, decode,
|
|
428
|
+
NATIVE_BASE64: UI8_FB64,
|
|
376
429
|
}
|
|
430
|
+
|
package/lib/hash.js
CHANGED
package/lib/hmac.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const Signature = require('./signature');
|
|
4
|
+
|
|
5
|
+
const HMAC = 'HMAC';
|
|
6
|
+
const DEF_OPTS = { algorithm: 'SHA-256' };
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The main class to perform HMAC signing.
|
|
10
|
+
* @exports module:@lumjs/encode/hmac
|
|
11
|
+
*/
|
|
12
|
+
class HmacEncoder {
|
|
13
|
+
/**
|
|
14
|
+
* Create an encoder.
|
|
15
|
+
*
|
|
16
|
+
* @param {(string|TypedArray|ArrayBuffer)} keyValue - The secret key value.
|
|
17
|
+
* Will be used to generate the crypto key.
|
|
18
|
+
* @param {object} [options] Options
|
|
19
|
+
* @param {string} [options.algorithm="SHA-256"] Digest algorithm for HMAC.
|
|
20
|
+
*/
|
|
21
|
+
constructor(keyValue, options) {
|
|
22
|
+
this.te = new TextEncoder();
|
|
23
|
+
this.keyBytes = ArrayBuffer.isView(keyValue)
|
|
24
|
+
? keyValue
|
|
25
|
+
: this.te.encode(keyValue);
|
|
26
|
+
this.options = Object.assign({}, DEF_OPTS, options);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Get the crypto key for this encoder instance.
|
|
31
|
+
* @returns {Promise<CryptoKey>}
|
|
32
|
+
*/
|
|
33
|
+
async getKey() {
|
|
34
|
+
if (this._key) {
|
|
35
|
+
return this._key;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
let hmac = { name: HMAC, hash: this.options.algorithm }
|
|
39
|
+
let key = await crypto.subtle.importKey(
|
|
40
|
+
"raw", // Key format
|
|
41
|
+
this.keyBytes, // Key data
|
|
42
|
+
hmac, // Algorithm
|
|
43
|
+
false, // Not extractable
|
|
44
|
+
["sign"] // Usages
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
this._key = key;
|
|
48
|
+
return key;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Sign a message (any kind of data).
|
|
53
|
+
* @param {(string|TypedArray|ArrayBuffer)} message - Message to be signed.
|
|
54
|
+
* @returns {Promise<module:@lumjs/encode/signature>}
|
|
55
|
+
*/
|
|
56
|
+
async sign(message) {
|
|
57
|
+
if (!ArrayBuffer.isView(message)) {
|
|
58
|
+
message = this.te.encode(message);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
let key = await this.getKey();
|
|
62
|
+
let sig = await crypto.subtle.sign(
|
|
63
|
+
HMAC, // Algorithm
|
|
64
|
+
key, // HMAC CryptoKey
|
|
65
|
+
message, // Data to sign
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
return new Signature(sig);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
module.exports = HmacEncoder;
|
package/lib/hotp.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const HmacEncoder = require('./hmac');
|
|
4
|
+
const { intToBytes } = require('./util');
|
|
5
|
+
|
|
6
|
+
const DEF_OPTS = { algorithm: 'SHA-1', counter: 0, window: 50 };
|
|
7
|
+
|
|
8
|
+
const cp = Object.assign;
|
|
9
|
+
const isError = v => (typeof v === 'function' && Error.isPrototypeOf(v));
|
|
10
|
+
|
|
11
|
+
function needKey(key) {
|
|
12
|
+
if (!key) {
|
|
13
|
+
throw new Error("No signing key was specified");
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* HMAC-based One-Time-Passwords.
|
|
19
|
+
* @exports module:@lumjs/encode/hotp
|
|
20
|
+
*/
|
|
21
|
+
class HOTP {
|
|
22
|
+
constructor(options) {
|
|
23
|
+
this.setOptions(options);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
setOptions(options) {
|
|
27
|
+
if (this.options) {
|
|
28
|
+
cp(this.options, options);
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
this.options = cp({}, ...this.defaultOptions, options);
|
|
32
|
+
}
|
|
33
|
+
return this;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
getOptions() {
|
|
37
|
+
return cp({}, this.options, ...arguments);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
get defaultKey() {
|
|
41
|
+
return this.options.key;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
get defaultOptions() {
|
|
45
|
+
return [DEF_OPTS];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async generate(key = this.defaultKey, opts) {
|
|
49
|
+
needKey(key);
|
|
50
|
+
opts = this.getOptions(opts);
|
|
51
|
+
|
|
52
|
+
let encoder = new HmacEncoder(key, opts);
|
|
53
|
+
let data = new Uint8Array(intToBytes(opts.counter));
|
|
54
|
+
let hash = await encoder.sign(data);
|
|
55
|
+
let hb = hash.byteArray;
|
|
56
|
+
|
|
57
|
+
let offset = hb[19] & 0xf;
|
|
58
|
+
let v1 =
|
|
59
|
+
(hb[offset] & 0x7f) << 24 |
|
|
60
|
+
(hb[offset + 1] & 0xff) << 16 |
|
|
61
|
+
(hb[offset + 2] & 0xff) << 8 |
|
|
62
|
+
(hb[offset + 3] & 0xff);
|
|
63
|
+
|
|
64
|
+
let v2 = (v1 % 1000000) + '';
|
|
65
|
+
let code = Array(LEN - v2.length).join('0') + v2;
|
|
66
|
+
|
|
67
|
+
let res = {
|
|
68
|
+
opts,
|
|
69
|
+
data,
|
|
70
|
+
hash,
|
|
71
|
+
hashBytes: hb,
|
|
72
|
+
offset,
|
|
73
|
+
v1,
|
|
74
|
+
v2,
|
|
75
|
+
code,
|
|
76
|
+
toString,
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (opts.debug) console.debug(res.code, res);
|
|
80
|
+
|
|
81
|
+
return res;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async verify(token, key = this.defaultKey, opts) {
|
|
85
|
+
needKey(key);
|
|
86
|
+
opts = this.getOptions(opts);
|
|
87
|
+
|
|
88
|
+
let win = opts.window;
|
|
89
|
+
let cnt = opts.counter;
|
|
90
|
+
let info = { ok: false };
|
|
91
|
+
|
|
92
|
+
if (opts.debug) info.stack = [];
|
|
93
|
+
|
|
94
|
+
for (let i = cnt - win; i <= cnt + win; ++i) {
|
|
95
|
+
opts.counter = i;
|
|
96
|
+
let res = this.generate(key, opts);
|
|
97
|
+
if (opts.debug) info.stack.push(res);
|
|
98
|
+
if (res.code === token) {
|
|
99
|
+
return cp(info, { ok: true, delta: i - cnt });
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (opts.throw) {
|
|
104
|
+
let EClass = isError(opts.throw) ? opts.throw : Error;
|
|
105
|
+
throw new EClass("OTP verification failure");
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return info;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
module.exports = HOTP;
|
package/lib/index.js
CHANGED
|
@@ -9,6 +9,12 @@ const E = def.e;
|
|
|
9
9
|
|
|
10
10
|
const util = require('./util');
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* @alias module:@lumjs/encode.util
|
|
14
|
+
* @see {@link module:@lumjs/encode/util}
|
|
15
|
+
*/
|
|
16
|
+
def(exports, 'util', {value: util}, E);
|
|
17
|
+
|
|
12
18
|
/**
|
|
13
19
|
* @alias module:@lumjs/encode.ord
|
|
14
20
|
* @see {@link module:@lumjs/encode/util.ord}
|
|
@@ -39,3 +45,27 @@ lazy(exports, 'Base91', () => require('./base91'), E);
|
|
|
39
45
|
* @see {@link module:@lumjs/encode/hash}
|
|
40
46
|
*/
|
|
41
47
|
lazy(exports, 'Hash', () => require('./hash'), E);
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @name module:@lumjs/encode.HMAC
|
|
51
|
+
* @see {@link module:@lumjs/encode/hmac}
|
|
52
|
+
*/
|
|
53
|
+
lazy(exports, 'HMAC', () => require('./hmac'), E);
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @name module:@lumjs/encode.HOTP
|
|
57
|
+
* @see {@link module:@lumjs/encode/hotp}
|
|
58
|
+
*/
|
|
59
|
+
lazy(exports, 'HOTP', () => require('./hotp'), E);
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @name module:@lumjs/encode.TOTP
|
|
63
|
+
* @see {@link module:@lumjs/encode/totp}
|
|
64
|
+
*/
|
|
65
|
+
lazy(exports, 'TOTP', () => require('./totp'), E);
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* @name module:@lumjs/encode.Signature
|
|
69
|
+
* @see {@link module:@lumjs/encode/signature}
|
|
70
|
+
*/
|
|
71
|
+
lazy(exports, 'Signature', () => require('./signature'), E);
|
package/lib/signature.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A small wrapepr class representing a crypto signature.
|
|
5
|
+
* @alias module:@lumjs/encode/signature
|
|
6
|
+
*/
|
|
7
|
+
class Signature {
|
|
8
|
+
/**
|
|
9
|
+
* Build a Signature instance.
|
|
10
|
+
* @param {ArrayBuffer} buffer - The signature data.
|
|
11
|
+
*/
|
|
12
|
+
constructor(buffer) {
|
|
13
|
+
this.buffer = buffer;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Get the signature as a Uint8Array.
|
|
18
|
+
*/
|
|
19
|
+
get uint8Array() {
|
|
20
|
+
return new Uint8Array(this.buffer);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Get the signature as an array of bytes.
|
|
25
|
+
*/
|
|
26
|
+
get byteArray() {
|
|
27
|
+
return Array.from(this.uint8Array);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Get the signature as a Hex string.
|
|
32
|
+
*/
|
|
33
|
+
get hex() {
|
|
34
|
+
return this.byteArray.map(b => b.toString(16).padStart(2, '0')).join('');
|
|
35
|
+
}
|
|
36
|
+
}
|
package/lib/totp.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const HOTP = require('./hotp');
|
|
4
|
+
const DEF_OPTS = {step: 30};
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Time-based One-Time-Passwords.
|
|
8
|
+
* @exports module:@lumjs/encode/totp
|
|
9
|
+
*/
|
|
10
|
+
class TOTP extends HOTP {
|
|
11
|
+
get defaultOptions() {
|
|
12
|
+
return [...super.defaultOptions, DEF_OPTS];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
getOptions() {
|
|
16
|
+
let opts = super.getOptions(...arguments);
|
|
17
|
+
if (!opts.time) opts.time = Date.now();
|
|
18
|
+
opts.counter = Math.floor((opts.time / 1000) / opts.step);
|
|
19
|
+
return opts;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
module.exports = TOTP;
|
package/lib/util.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
* Low-level encoding utilities
|
|
3
3
|
* @module @lumjs/encode/util
|
|
4
4
|
*/
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
5
7
|
const {N} = require('@lumjs/core/types');
|
|
6
8
|
|
|
7
9
|
/**
|
|
@@ -189,3 +191,42 @@ exports.wordArrayToUint8Array = function(wordArray)
|
|
|
189
191
|
}
|
|
190
192
|
return result;
|
|
191
193
|
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Convert an integer to a byte array.
|
|
197
|
+
*
|
|
198
|
+
* This is a much simpler algorithm than numByteArray,
|
|
199
|
+
* and was borrowed from the `notp` package.
|
|
200
|
+
*
|
|
201
|
+
* @param {Integer} num
|
|
202
|
+
* @return {Array} bytes
|
|
203
|
+
*/
|
|
204
|
+
exports.intToBytes = function(num)
|
|
205
|
+
{
|
|
206
|
+
let bytes = [];
|
|
207
|
+
|
|
208
|
+
for(let i=7 ; i>=0 ; --i)
|
|
209
|
+
{
|
|
210
|
+
bytes[i] = num & (255);
|
|
211
|
+
num = num >> 8;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return bytes;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Convert a hex value to a byte array.
|
|
219
|
+
*
|
|
220
|
+
* Also taken from the `notp` package.
|
|
221
|
+
*
|
|
222
|
+
* @param {String} hex string of hex to convert to a byte array
|
|
223
|
+
* @return {Array} bytes
|
|
224
|
+
*/
|
|
225
|
+
exports.hexToBytes = function(hex) {
|
|
226
|
+
var bytes = [];
|
|
227
|
+
for(var c = 0, C = hex.length; c < C; c += 2) {
|
|
228
|
+
bytes.push(parseInt(hex.substr(c, 2), 16));
|
|
229
|
+
}
|
|
230
|
+
return bytes;
|
|
231
|
+
}
|
|
232
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lumjs/encode",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"exports":
|
|
6
6
|
{
|
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
"./base64": "./lib/base64.js",
|
|
9
9
|
"./base91": "./lib/base91.js",
|
|
10
10
|
"./hash": "./lib/hash.js",
|
|
11
|
+
"./hmac": "./lib/hmac.js",
|
|
12
|
+
"./hotp": "./lib/hotp.js",
|
|
13
|
+
"./signature": "./lib/signature.js",
|
|
14
|
+
"./totp": "./lib/totp.js",
|
|
11
15
|
"./util": "./lib/util.js",
|
|
12
16
|
"./package.json": "./package.json"
|
|
13
17
|
},
|
|
@@ -19,7 +23,7 @@
|
|
|
19
23
|
},
|
|
20
24
|
"dependencies":
|
|
21
25
|
{
|
|
22
|
-
"@lumjs/core": "^1.
|
|
26
|
+
"@lumjs/core": "^1.28.0"
|
|
23
27
|
},
|
|
24
28
|
"devDependencies":
|
|
25
29
|
{
|