@li0ard/gost 0.1.7 → 0.1.8
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/README.md +1 -0
- package/gf/index.d.ts +3 -2
- package/gf/index.js +17 -2
- package/gost341194/index.d.ts +2 -2
- package/gost341194/index.js +9 -9
- package/kdf.js +3 -5
- package/kuznyechik/index.d.ts +9 -2
- package/kuznyechik/index.js +9 -2
- package/magma/const.d.ts +1 -1
- package/magma/const.js +1 -2
- package/magma/index.d.ts +8 -4
- package/magma/index.js +35 -41
- package/modes/ctr.js +5 -7
- package/modes/mac.js +6 -9
- package/package.json +1 -1
- package/streebog/index.d.ts +20 -6
- package/streebog/index.js +21 -8
- package/gf/gf128.d.ts +0 -2
- package/gf/gf128.js +0 -15
- package/gf/gf64.d.ts +0 -2
- package/gf/gf64.js +0 -15
package/README.md
CHANGED
|
@@ -28,6 +28,7 @@ npm i @li0ard/gost
|
|
|
28
28
|
- Kuznyechik cipher (GOST R 34.12-2015)
|
|
29
29
|
- Magma cipher (GOST R 34.12-2015)
|
|
30
30
|
- Supports legacy version from GOST 28147-89
|
|
31
|
+
- Various S-Box'es included (CryptoPro, DSSZZI, tests etc.)
|
|
31
32
|
- Streebog hash function (GOST R 34.11-2012)
|
|
32
33
|
- Supports HMAC, PBKDF2 (512 bit), `kdf_gostr3411_2012_256`, `kdf_tree_gostr3411_2012_256` and CPKDF
|
|
33
34
|
|
package/gf/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
1
|
+
import { type TArg, type TRet } from "@noble/curves/utils.js";
|
|
2
|
+
export declare const gf64Multiply: (a: TArg<Uint8Array>, b: TArg<Uint8Array>) => TRet<Uint8Array>;
|
|
3
|
+
export declare const gf128Multiply: (a: TArg<Uint8Array>, b: TArg<Uint8Array>) => TRet<Uint8Array>;
|
|
3
4
|
export { gf256Multiply } from "./gf256.js";
|
package/gf/index.js
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { bytesToNumberBE, numberToBytesBE } from "@noble/curves/utils.js";
|
|
2
|
+
const gf2m_multiply = (degree, poly, a, b) => {
|
|
3
|
+
let x = bytesToNumberBE(a), y = bytesToNumberBE(b), z = 0n;
|
|
4
|
+
const max_bit = 1n << (degree - 1n);
|
|
5
|
+
while (y > 0n) {
|
|
6
|
+
if ((y & 1n) == 1n)
|
|
7
|
+
z ^= x;
|
|
8
|
+
if ((x & max_bit) > 0n)
|
|
9
|
+
x = ((x ^ max_bit) << 1n) ^ poly;
|
|
10
|
+
else
|
|
11
|
+
x <<= 1n;
|
|
12
|
+
y >>= 1n;
|
|
13
|
+
}
|
|
14
|
+
return numberToBytesBE(z, Number(degree / 8n));
|
|
15
|
+
};
|
|
16
|
+
export const gf64Multiply = (a, b) => gf2m_multiply(64n, 0x1bn, a, b);
|
|
17
|
+
export const gf128Multiply = (a, b) => gf2m_multiply(128n, 0x87n, a, b);
|
|
3
18
|
export { gf256Multiply } from "./gf256.js";
|
package/gost341194/index.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { type Hash, type TArg, type TRet } from "@noble/hashes/utils.js";
|
|
2
2
|
/** GOST R 34.11-94 hash function */
|
|
3
3
|
export declare class Gost341194 implements Hash<Gost341194> {
|
|
4
|
-
private
|
|
4
|
+
private buffer;
|
|
5
5
|
private sbox;
|
|
6
6
|
readonly blockLen = 32;
|
|
7
7
|
readonly outputLen = 32;
|
|
8
8
|
readonly canXOF = false;
|
|
9
9
|
/** GOST R 34.11-94 hash function */
|
|
10
|
-
constructor(
|
|
10
|
+
constructor(buffer?: TArg<Uint8Array>, sbox?: TArg<Uint8Array>);
|
|
11
11
|
/** Create hash instance */
|
|
12
12
|
static create(): Gost341194;
|
|
13
13
|
destroy(): void;
|
package/gost341194/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { concatBytes } from "@noble/hashes/utils.js";
|
|
1
|
+
import { concatBytes, copyBytes } from "@noble/hashes/utils.js";
|
|
2
2
|
import { Magma } from "../magma/index.js";
|
|
3
3
|
import { DSSZZI_UA_DKE_1, ID_GOSTR_3411_94_CRYPTOPRO_PARAM_SET } from "../magma/const.js";
|
|
4
4
|
import { bytesToNumberBE, numberToBytesBE } from "@noble/curves/utils.js";
|
|
@@ -10,7 +10,7 @@ const C3 = new Uint8Array([
|
|
|
10
10
|
0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
|
|
11
11
|
0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00
|
|
12
12
|
]);
|
|
13
|
-
const A = (x) => concatBytes(xorBytes(x.subarray(24, 32), x.subarray(16, 24)), x.subarray(0,
|
|
13
|
+
const A = (x) => concatBytes(xorBytes(x.subarray(24, 32), x.subarray(16, 24)), x.subarray(0, 24));
|
|
14
14
|
const P = (x) => new Uint8Array([
|
|
15
15
|
x[0], x[8], x[16], x[24], x[1], x[9], x[17], x[25],
|
|
16
16
|
x[2], x[10], x[18], x[26], x[3], x[11], x[19], x[27],
|
|
@@ -44,35 +44,35 @@ const _step = (hin, m, sbox) => {
|
|
|
44
44
|
};
|
|
45
45
|
/** GOST R 34.11-94 hash function */
|
|
46
46
|
export class Gost341194 {
|
|
47
|
-
|
|
47
|
+
buffer;
|
|
48
48
|
sbox;
|
|
49
49
|
blockLen = 32;
|
|
50
50
|
outputLen = 32;
|
|
51
51
|
canXOF = false;
|
|
52
52
|
/** GOST R 34.11-94 hash function */
|
|
53
|
-
constructor(
|
|
54
|
-
this.
|
|
53
|
+
constructor(buffer = new Uint8Array(), sbox = ID_GOSTR_3411_94_CRYPTOPRO_PARAM_SET) {
|
|
54
|
+
this.buffer = buffer;
|
|
55
55
|
this.sbox = sbox;
|
|
56
56
|
}
|
|
57
57
|
/** Create hash instance */
|
|
58
58
|
static create() { return new Gost341194(); }
|
|
59
|
-
destroy() { this.
|
|
59
|
+
destroy() { this.buffer = new Uint8Array(); }
|
|
60
60
|
clone() { return this._cloneInto(); }
|
|
61
61
|
_cloneInto(to) {
|
|
62
62
|
to ||= new Gost341194();
|
|
63
|
-
to.
|
|
63
|
+
to.buffer = new Uint8Array(this.buffer);
|
|
64
64
|
to.sbox = this.sbox;
|
|
65
65
|
return to;
|
|
66
66
|
}
|
|
67
67
|
update(data) {
|
|
68
|
-
this.
|
|
68
|
+
this.buffer = concatBytes(this.buffer, data);
|
|
69
69
|
return this;
|
|
70
70
|
}
|
|
71
71
|
digestInto(buf) {
|
|
72
72
|
let len = 0n;
|
|
73
73
|
let checksum = 0n;
|
|
74
74
|
const h = new Uint8Array(this.blockLen);
|
|
75
|
-
const m =
|
|
75
|
+
const m = copyBytes(this.buffer);
|
|
76
76
|
for (let i = 0; i < m.length; i += this.blockLen) {
|
|
77
77
|
let part = m.slice(i, i + this.blockLen).reverse();
|
|
78
78
|
len += BigInt(part.length) * 8n;
|
package/kdf.js
CHANGED
|
@@ -8,8 +8,6 @@ import { pad1, xorBytes } from "./utils.js";
|
|
|
8
8
|
const _0 = new Uint8Array([0]);
|
|
9
9
|
const _1 = new Uint8Array([1]);
|
|
10
10
|
const _0100 = new Uint8Array([1, 0]);
|
|
11
|
-
const CPKDF_CONST = new Uint8Array(64);
|
|
12
|
-
CPKDF_CONST.set(new TextEncoder().encode("DENEFH028.760246785.IUEFHWUIO.EF"));
|
|
13
11
|
const _36 = new Uint8Array(64).fill(0x36);
|
|
14
12
|
const _5C = new Uint8Array(64).fill(0x5C);
|
|
15
13
|
export const kdf_gostr3411_2012_256 = (key, label, seed) => streebog256hmac(key, concatBytes(_1, label, _0, seed, _0100));
|
|
@@ -35,9 +33,9 @@ export const cpkdf = (password, salt) => {
|
|
|
35
33
|
if (password.length != 0)
|
|
36
34
|
hasher.update(pin);
|
|
37
35
|
const hash = hasher.digest();
|
|
38
|
-
const c =
|
|
39
|
-
|
|
40
|
-
const m1 = new Uint8Array(bs);
|
|
36
|
+
const c = new Uint8Array(64);
|
|
37
|
+
c.set(new TextEncoder().encode("DENEFH028.760246785.IUEFHWUIO.EF"));
|
|
38
|
+
const m0 = new Uint8Array(bs), m1 = new Uint8Array(bs);
|
|
41
39
|
for (let j = 0; j < (password.length != 0 ? 2000 : 2); j++) {
|
|
42
40
|
m0.set(xorBytes(c, _36));
|
|
43
41
|
m1.set(xorBytes(c, _5C));
|
package/kuznyechik/index.d.ts
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import { type TArg, type TRet } from "@noble/curves/utils.js";
|
|
2
2
|
import type { Cipher } from "../types.js";
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* **Kuznyechik cipher**
|
|
5
|
+
*
|
|
6
|
+
* Described by GOST R 34.12-2015 ([RFC 7801](https://datatracker.ietf.org/doc/html/rfc7801.html))
|
|
7
|
+
*/
|
|
4
8
|
export declare class Kuznyechik implements Cipher {
|
|
5
9
|
readonly keySize = 32;
|
|
6
10
|
readonly blockSize = 16;
|
|
7
11
|
private roundKeys;
|
|
8
|
-
/**
|
|
12
|
+
/**
|
|
13
|
+
* Kuznyechik (GOST R 34.12-2015) cipher
|
|
14
|
+
* @param key Encryption key
|
|
15
|
+
*/
|
|
9
16
|
constructor(key: TArg<Uint8Array>);
|
|
10
17
|
encrypt(plaintext: TArg<Uint8Array>): TRet<Uint8Array>;
|
|
11
18
|
decrypt(ciphertext: TArg<Uint8Array>): TRet<Uint8Array>;
|
package/kuznyechik/index.js
CHANGED
|
@@ -37,12 +37,19 @@ const LLr = (input) => Rr(Rr(Rr(Rr(Rr(Rr(Rr(Rr(Rr(Rr(Rr(Rr(Rr(Rr(Rr(Rr(input))))
|
|
|
37
37
|
const LLS = (block) => LL(S(block));
|
|
38
38
|
const SLLr = (block) => S(LLr(block), PI_REV);
|
|
39
39
|
const F = (inKey, inKey2, iter) => xorBytes(LLS(xorBytes(inKey, iter)), inKey2);
|
|
40
|
-
/**
|
|
40
|
+
/**
|
|
41
|
+
* **Kuznyechik cipher**
|
|
42
|
+
*
|
|
43
|
+
* Described by GOST R 34.12-2015 ([RFC 7801](https://datatracker.ietf.org/doc/html/rfc7801.html))
|
|
44
|
+
*/
|
|
41
45
|
export class Kuznyechik {
|
|
42
46
|
keySize = 32;
|
|
43
47
|
blockSize = 16;
|
|
44
48
|
roundKeys;
|
|
45
|
-
/**
|
|
49
|
+
/**
|
|
50
|
+
* Kuznyechik (GOST R 34.12-2015) cipher
|
|
51
|
+
* @param key Encryption key
|
|
52
|
+
*/
|
|
46
53
|
constructor(key) {
|
|
47
54
|
if (key.length !== this.keySize)
|
|
48
55
|
throw new Error("Invalid key length");
|
package/magma/const.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** S-Box from RFC
|
|
1
|
+
/** S-Box from RFC 8891 */
|
|
2
2
|
export declare const ID_TC26_GOST_28147_PARAM_Z: Uint8Array<ArrayBuffer>;
|
|
3
3
|
/** S-Box from RFC 4357 aka `CryptoPro Paramset A` */
|
|
4
4
|
export declare const ID_GOST_28147_89_CRYPTO_PRO_A_PARAM_SET: Uint8Array<ArrayBuffer>;
|
package/magma/const.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** S-Box from RFC
|
|
1
|
+
/** S-Box from RFC 8891 */
|
|
2
2
|
export const ID_TC26_GOST_28147_PARAM_Z = new Uint8Array([
|
|
3
3
|
0x0c, 0x04, 0x06, 0x02, 0x0a, 0x05, 0x0b, 0x09, 0x0e, 0x08, 0x0d, 0x07, 0x00, 0x03, 0x0f, 0x01,
|
|
4
4
|
0x06, 0x08, 0x02, 0x03, 0x09, 0x0a, 0x05, 0x0c, 0x01, 0x0e, 0x04, 0x07, 0x0b, 0x0d, 0x00, 0x0f,
|
|
@@ -64,7 +64,6 @@ export const DSSZZI_UA_DKE_1 = new Uint8Array([
|
|
|
64
64
|
0x03, 0x08, 0x0b, 0x05, 0x06, 0x04, 0x0e, 0x0a, 0x02, 0x0c, 0x01, 0x07, 0x09, 0x0f, 0x0d, 0x00,
|
|
65
65
|
0x01, 0x02, 0x03, 0x0e, 0x06, 0x0d, 0x0b, 0x08, 0x0f, 0x0a, 0x0c, 0x05, 0x07, 0x09, 0x00, 0x04,
|
|
66
66
|
]);
|
|
67
|
-
// Converted from tables by script, accuracy not guaranteed
|
|
68
67
|
/** S-Box from Instruction no. 114 by State Special Communications Service of Ukraine */
|
|
69
68
|
export const DSSZZI_UA_DKE_2 = new Uint8Array([
|
|
70
69
|
0x0e, 0x09, 0x03, 0x07, 0x0f, 0x04, 0x0c, 0x0b, 0x06, 0x0a, 0x0d, 0x01, 0x00, 0x05, 0x08, 0x02,
|
package/magma/index.d.ts
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import { type TArg, type TRet } from "@noble/curves/utils.js";
|
|
2
2
|
import type { Cipher } from "../types.js";
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* **Magma cipher**
|
|
5
|
+
*
|
|
6
|
+
* Described by GOST 28147-89 ([RFC 5830](https://datatracker.ietf.org/doc/html/rfc5830.html)) in 1989 (Uses LE byte order, no S-Box'es defined)
|
|
7
|
+
*
|
|
8
|
+
* Revised by GOST R 34.12-2015 ([RFC 8891](https://datatracker.ietf.org/doc/html/rfc8891.html)) in 2015 (Uses BE byte order and fixed {@link ID_TC26_GOST_28147_PARAM_Z S-Box})
|
|
9
|
+
*/
|
|
4
10
|
export declare class Magma implements Cipher {
|
|
11
|
+
private key;
|
|
5
12
|
private sbox;
|
|
6
13
|
isLegacy: boolean;
|
|
7
14
|
readonly keySize = 32;
|
|
8
15
|
readonly blockSize = 8;
|
|
9
|
-
private key;
|
|
10
16
|
/**
|
|
11
17
|
* Magma (GOST R 34.12-2015 and GOST 28147-89) cipher
|
|
12
18
|
* @param key Encryption key
|
|
@@ -17,7 +23,5 @@ export declare class Magma implements Cipher {
|
|
|
17
23
|
proceedBlock(block: TArg<Uint8Array>, sequence: number[]): TRet<Uint8Array>;
|
|
18
24
|
encrypt(plaintext: TArg<Uint8Array>): TRet<Uint8Array>;
|
|
19
25
|
decrypt(ciphertext: TArg<Uint8Array>): TRet<Uint8Array>;
|
|
20
|
-
static reverseKey(key: TArg<Uint8Array>): TRet<Uint8Array>;
|
|
21
|
-
static reverseChunks(data: TArg<Uint8Array>): TRet<Uint8Array>;
|
|
22
26
|
}
|
|
23
27
|
export { magmaSboxes, magmaKeySequences } from "./const.js";
|
package/magma/index.js
CHANGED
|
@@ -1,32 +1,38 @@
|
|
|
1
|
-
import { bytesToNumberBE,
|
|
1
|
+
import { bytesToNumberBE, bytesToNumberLE, concatBytes, numberToBytesBE, numberToBytesLE } from "@noble/curves/utils.js";
|
|
2
2
|
import { ID_TC26_GOST_28147_PARAM_Z, magmaKeySequences } from "./const.js";
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
(sbox[
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return ((
|
|
3
|
+
import { createView } from "@noble/hashes/utils.js";
|
|
4
|
+
const BLOCKSIZE = 8;
|
|
5
|
+
const G = (v, sbox) => {
|
|
6
|
+
const t = (sbox[(v & 0x0f)] << 0) |
|
|
7
|
+
(sbox[16 + ((v >> 4) & 0x0f)] << 4) |
|
|
8
|
+
(sbox[32 + ((v >> 8) & 0x0f)] << 8) |
|
|
9
|
+
(sbox[48 + ((v >> 12) & 0x0f)] << 12) |
|
|
10
|
+
(sbox[64 + ((v >> 16) & 0x0f)] << 16) |
|
|
11
|
+
(sbox[80 + ((v >> 20) & 0x0f)] << 20) |
|
|
12
|
+
(sbox[96 + ((v >> 24) & 0x0f)] << 24) |
|
|
13
|
+
(sbox[112 + ((v >> 28) & 0x0f)] << 28);
|
|
14
|
+
return ((t << 11) | (t >>> 21)) >>> 0;
|
|
15
15
|
};
|
|
16
|
-
const extendKey = (key, sequence) => {
|
|
17
|
-
const view =
|
|
16
|
+
const extendKey = (key, sequence, isLegacy) => {
|
|
17
|
+
const view = createView(key);
|
|
18
18
|
const chunks = new Uint32Array(BLOCKSIZE);
|
|
19
19
|
for (let i = 0; i < BLOCKSIZE; i++)
|
|
20
|
-
chunks[i] = view.getUint32(i * 4);
|
|
20
|
+
chunks[i] = view.getUint32(i * 4, isLegacy);
|
|
21
21
|
return new Uint32Array(sequence.map(i => chunks[i]));
|
|
22
22
|
};
|
|
23
|
-
/**
|
|
23
|
+
/**
|
|
24
|
+
* **Magma cipher**
|
|
25
|
+
*
|
|
26
|
+
* Described by GOST 28147-89 ([RFC 5830](https://datatracker.ietf.org/doc/html/rfc5830.html)) in 1989 (Uses LE byte order, no S-Box'es defined)
|
|
27
|
+
*
|
|
28
|
+
* Revised by GOST R 34.12-2015 ([RFC 8891](https://datatracker.ietf.org/doc/html/rfc8891.html)) in 2015 (Uses BE byte order and fixed {@link ID_TC26_GOST_28147_PARAM_Z S-Box})
|
|
29
|
+
*/
|
|
24
30
|
export class Magma {
|
|
31
|
+
key;
|
|
25
32
|
sbox;
|
|
26
33
|
isLegacy;
|
|
27
|
-
keySize =
|
|
34
|
+
keySize = 32;
|
|
28
35
|
blockSize = BLOCKSIZE;
|
|
29
|
-
key;
|
|
30
36
|
/**
|
|
31
37
|
* Magma (GOST R 34.12-2015 and GOST 28147-89) cipher
|
|
32
38
|
* @param key Encryption key
|
|
@@ -34,46 +40,34 @@ export class Magma {
|
|
|
34
40
|
* @param isLegacy Use GOST 28147-89 instead of GOST R 34.12-2015?
|
|
35
41
|
*/
|
|
36
42
|
constructor(key, sbox = ID_TC26_GOST_28147_PARAM_Z, isLegacy = false) {
|
|
43
|
+
this.key = key;
|
|
37
44
|
this.sbox = sbox;
|
|
38
45
|
this.isLegacy = isLegacy;
|
|
39
46
|
if (key.length !== this.keySize)
|
|
40
47
|
throw new Error("Invalid key length");
|
|
41
|
-
this.key = isLegacy ? Magma.reverseKey(key) : key;
|
|
42
48
|
}
|
|
43
49
|
proceedBlock(block, sequence) {
|
|
44
50
|
if (block.length !== this.blockSize)
|
|
45
51
|
throw new Error("Invalid block size");
|
|
46
|
-
const roundKeys = extendKey(this.key, sequence);
|
|
47
|
-
|
|
48
|
-
|
|
52
|
+
const roundKeys = extendKey(this.key, sequence, this.isLegacy);
|
|
53
|
+
const F = block.subarray(0, 4), S = block.subarray(4, 8);
|
|
54
|
+
const bytesToNumber = this.isLegacy ? bytesToNumberLE : bytesToNumberBE;
|
|
55
|
+
let a0 = Number(bytesToNumber(this.isLegacy ? S : F)), a1 = Number(bytesToNumber(this.isLegacy ? F : S));
|
|
49
56
|
for (let i = 0; i < roundKeys.length; i++) {
|
|
50
57
|
const temp = a1;
|
|
51
|
-
a1 = (a0 ^ G(a1
|
|
58
|
+
a1 = (a0 ^ G((a1 + roundKeys[i]) >>> 0, this.sbox)) >>> 0;
|
|
52
59
|
a0 = temp;
|
|
53
60
|
}
|
|
54
|
-
|
|
61
|
+
if (this.isLegacy)
|
|
62
|
+
return concatBytes(numberToBytesLE(a0, 4), numberToBytesLE(a1, 4));
|
|
63
|
+
else
|
|
64
|
+
return concatBytes(numberToBytesBE(a1, 4), numberToBytesBE(a0, 4));
|
|
55
65
|
}
|
|
56
66
|
encrypt(plaintext) {
|
|
57
|
-
if (this.isLegacy)
|
|
58
|
-
return Magma.reverseChunks(this.proceedBlock(Magma.reverseChunks(plaintext), magmaKeySequences.ENCRYPT));
|
|
59
67
|
return this.proceedBlock(plaintext, magmaKeySequences.ENCRYPT);
|
|
60
68
|
}
|
|
61
69
|
decrypt(ciphertext) {
|
|
62
|
-
if (this.isLegacy)
|
|
63
|
-
return Magma.reverseChunks(this.proceedBlock(Magma.reverseChunks(ciphertext), magmaKeySequences.DECRYPT));
|
|
64
70
|
return this.proceedBlock(ciphertext, magmaKeySequences.DECRYPT);
|
|
65
71
|
}
|
|
66
|
-
static reverseKey(key) {
|
|
67
|
-
const result = new Uint8Array(KEYSIZE);
|
|
68
|
-
for (let i = 0; i < BLOCKSIZE; i++)
|
|
69
|
-
result.set(copyBytes(key.subarray(i * 4, i * 4 + 4)).reverse(), i * 4);
|
|
70
|
-
return result;
|
|
71
|
-
}
|
|
72
|
-
static reverseChunks(data) {
|
|
73
|
-
const chunks = [];
|
|
74
|
-
for (let i = 0; i < data.length; i += BLOCKSIZE)
|
|
75
|
-
chunks.push(copyBytes(data.subarray(i, i + BLOCKSIZE)).reverse());
|
|
76
|
-
return concatBytes(...chunks);
|
|
77
|
-
}
|
|
78
72
|
}
|
|
79
73
|
export { magmaSboxes, magmaKeySequences } from "./const.js";
|
package/modes/ctr.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { concatBytes } from "@noble/hashes/utils.js";
|
|
2
2
|
import { getPadLength, xorBytes } from "../utils.js";
|
|
3
|
-
import {
|
|
3
|
+
import { bytesToNumberLE, numberToBytesBE, numberToBytesLE } from "@noble/curves/utils.js";
|
|
4
4
|
import { acpkm } from "./_keytransform.js";
|
|
5
5
|
/**
|
|
6
6
|
* **EN:** Counter (CTR) mode
|
|
@@ -42,19 +42,17 @@ export const ctr = (cipher, iv, isAcpkm, _isAcpkmOmac) => {
|
|
|
42
42
|
export const cnt = (cipher, iv) => {
|
|
43
43
|
if (iv.length !== cipher.blockSize)
|
|
44
44
|
throw new Error("Invalid IV size");
|
|
45
|
-
const C1 = 0x01010104n;
|
|
46
|
-
const C2 = 0x01010101n;
|
|
45
|
+
const C1 = 0x01010104n, C2 = 0x01010101n;
|
|
47
46
|
const encrypter = cipher.encrypt.bind(cipher);
|
|
48
47
|
return {
|
|
49
48
|
crypt: (msg) => {
|
|
50
|
-
const encryptedIv = encrypter(iv)
|
|
51
|
-
let
|
|
52
|
-
let n1 = (bytesToNumberBE(encryptedIv.subarray(4)));
|
|
49
|
+
const encryptedIv = encrypter(iv);
|
|
50
|
+
let n1 = bytesToNumberLE(encryptedIv.subarray(0, 4)), n2 = bytesToNumberLE(encryptedIv.subarray(4));
|
|
53
51
|
const gamma = [];
|
|
54
52
|
for (let i = 0; i < (msg.length + getPadLength(msg.length, cipher.blockSize)); i += cipher.blockSize) {
|
|
55
53
|
n1 = (n1 + C2) % 0x100000000n;
|
|
56
54
|
n2 = (n2 + C1) % 0xffffffffn;
|
|
57
|
-
gamma.push(encrypter(concatBytes(
|
|
55
|
+
gamma.push(encrypter(concatBytes(numberToBytesLE(n1, 4), numberToBytesLE(n2, 4))));
|
|
58
56
|
}
|
|
59
57
|
return xorBytes(concatBytes(...gamma), msg);
|
|
60
58
|
}
|
package/modes/mac.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {} from "@noble/hashes/utils.js";
|
|
1
|
+
import { concatBytes } from "@noble/hashes/utils.js";
|
|
2
2
|
import { pad1, pad3, xorBytes } from "../utils.js";
|
|
3
|
-
import { bytesToNumberBE, numberToVarBytesBE } from "@noble/curves/utils.js";
|
|
3
|
+
import { bytesToNumberBE, bytesToNumberLE, numberToBytesLE, numberToVarBytesBE } from "@noble/curves/utils.js";
|
|
4
4
|
import { magmaKeySequences, Magma } from "../magma/index.js";
|
|
5
5
|
import { acpkm_master } from "./_keytransform.js";
|
|
6
6
|
const Rb64 = 0b11011;
|
|
@@ -61,19 +61,16 @@ export const mac = (cipher) => {
|
|
|
61
61
|
*/
|
|
62
62
|
export const mac_legacy = (cipher, iv = new Uint8Array(cipher.blockSize)) => {
|
|
63
63
|
const split = (data) => [
|
|
64
|
-
(data
|
|
65
|
-
(data
|
|
64
|
+
Number(bytesToNumberLE(data.subarray(0, 4))),
|
|
65
|
+
Number(bytesToNumberLE(data.subarray(4, 8)))
|
|
66
66
|
];
|
|
67
|
-
const join = (ns) =>
|
|
68
|
-
(ns[1] >> 0) & 0xFF, (ns[1] >> 8) & 0xFF, (ns[1] >> 16) & 0xFF, (ns[1] >> 24) & 0xFF,
|
|
69
|
-
(ns[0] >> 0) & 0xFF, (ns[0] >> 8) & 0xFF, (ns[0] >> 16) & 0xFF, (ns[0] >> 24) & 0xFF
|
|
70
|
-
]);
|
|
67
|
+
const join = (ns) => concatBytes(numberToBytesLE(ns[1], 4), numberToBytesLE(ns[0], 4));
|
|
71
68
|
return {
|
|
72
69
|
compute: (msg) => {
|
|
73
70
|
const paddedData = pad1(msg, cipher.blockSize);
|
|
74
71
|
let prev = split(iv).reverse();
|
|
75
72
|
for (let i = 0; i < paddedData.length; i += cipher.blockSize)
|
|
76
|
-
prev = split(
|
|
73
|
+
prev = split(cipher.proceedBlock(xorBytes(paddedData.subarray(i, i + cipher.blockSize), join(prev)), magmaKeySequences.MAC));
|
|
77
74
|
return join(prev);
|
|
78
75
|
}
|
|
79
76
|
};
|
package/package.json
CHANGED
package/streebog/index.d.ts
CHANGED
|
@@ -15,7 +15,11 @@ declare abstract class Streebog<T extends Streebog<T>> implements Hash<Streebog<
|
|
|
15
15
|
digest(): TRet<Uint8Array>;
|
|
16
16
|
digestInto(buf: TArg<Uint8Array>): void;
|
|
17
17
|
}
|
|
18
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* **Streebog-256 hash function**
|
|
20
|
+
*
|
|
21
|
+
* Described by GOST R 34.11-2012 ([RFC 6986](https://datatracker.ietf.org/doc/html/rfc6986.html))
|
|
22
|
+
*/
|
|
19
23
|
export declare class Streebog256 extends Streebog<Streebog256> {
|
|
20
24
|
/** Streebog-256 (GOST R 34.11-2012) hash function */
|
|
21
25
|
constructor();
|
|
@@ -24,7 +28,11 @@ export declare class Streebog256 extends Streebog<Streebog256> {
|
|
|
24
28
|
clone(): Streebog256;
|
|
25
29
|
_cloneInto(to?: Streebog256): Streebog256;
|
|
26
30
|
}
|
|
27
|
-
/**
|
|
31
|
+
/**
|
|
32
|
+
* **Streebog-512 hash function**
|
|
33
|
+
*
|
|
34
|
+
* Described by GOST R 34.11-2012 ([RFC 6986](https://datatracker.ietf.org/doc/html/rfc6986.html))
|
|
35
|
+
*/
|
|
28
36
|
export declare class Streebog512 extends Streebog<Streebog512> {
|
|
29
37
|
/** Streebog-512 (GOST R 34.11-2012) hash function */
|
|
30
38
|
constructor();
|
|
@@ -33,8 +41,11 @@ export declare class Streebog512 extends Streebog<Streebog512> {
|
|
|
33
41
|
clone(): Streebog512;
|
|
34
42
|
_cloneInto(to?: Streebog512): Streebog512;
|
|
35
43
|
}
|
|
36
|
-
/**
|
|
37
|
-
|
|
44
|
+
/**
|
|
45
|
+
* **Streebog-256 hash function**
|
|
46
|
+
*
|
|
47
|
+
* Described by GOST R 34.11-2012 ([RFC 6986](https://datatracker.ietf.org/doc/html/rfc6986.html))
|
|
48
|
+
*/ export declare const streebog256: {
|
|
38
49
|
outputLen: number;
|
|
39
50
|
blockLen: number;
|
|
40
51
|
canXOF: boolean;
|
|
@@ -48,8 +59,11 @@ export declare const streebog256: {
|
|
|
48
59
|
oid?: TRet<Uint8Array> | undefined;
|
|
49
60
|
create: () => Streebog256;
|
|
50
61
|
};
|
|
51
|
-
/**
|
|
52
|
-
|
|
62
|
+
/**
|
|
63
|
+
* **Streebog-512 hash function**
|
|
64
|
+
*
|
|
65
|
+
* Described by GOST R 34.11-2012 ([RFC 6986](https://datatracker.ietf.org/doc/html/rfc6986.html))
|
|
66
|
+
*/ export declare const streebog512: {
|
|
53
67
|
outputLen: number;
|
|
54
68
|
blockLen: number;
|
|
55
69
|
canXOF: boolean;
|
package/streebog/index.js
CHANGED
|
@@ -8,8 +8,7 @@ const _0020 = new Uint8Array([0, 0, 2, 0]);
|
|
|
8
8
|
const _0 = new Uint8Array(64);
|
|
9
9
|
const add512 = (a, b) => {
|
|
10
10
|
const c = new Uint8Array(64);
|
|
11
|
-
const tmpA = new Uint8Array(64);
|
|
12
|
-
const tmpB = new Uint8Array(64);
|
|
11
|
+
const tmpA = new Uint8Array(64), tmpB = new Uint8Array(64);
|
|
13
12
|
for (let i = 0; i < a.length; i++)
|
|
14
13
|
tmpA[63 - i] = a[a.length - i - 1];
|
|
15
14
|
for (let i = 0; i < b.length; i++)
|
|
@@ -150,7 +149,11 @@ class Streebog {
|
|
|
150
149
|
this.destroy();
|
|
151
150
|
}
|
|
152
151
|
}
|
|
153
|
-
/**
|
|
152
|
+
/**
|
|
153
|
+
* **Streebog-256 hash function**
|
|
154
|
+
*
|
|
155
|
+
* Described by GOST R 34.11-2012 ([RFC 6986](https://datatracker.ietf.org/doc/html/rfc6986.html))
|
|
156
|
+
*/
|
|
154
157
|
export class Streebog256 extends Streebog {
|
|
155
158
|
/** Streebog-256 (GOST R 34.11-2012) hash function */
|
|
156
159
|
constructor() { super(false); }
|
|
@@ -163,7 +166,11 @@ export class Streebog256 extends Streebog {
|
|
|
163
166
|
return to;
|
|
164
167
|
}
|
|
165
168
|
}
|
|
166
|
-
/**
|
|
169
|
+
/**
|
|
170
|
+
* **Streebog-512 hash function**
|
|
171
|
+
*
|
|
172
|
+
* Described by GOST R 34.11-2012 ([RFC 6986](https://datatracker.ietf.org/doc/html/rfc6986.html))
|
|
173
|
+
*/
|
|
167
174
|
export class Streebog512 extends Streebog {
|
|
168
175
|
/** Streebog-512 (GOST R 34.11-2012) hash function */
|
|
169
176
|
constructor() { super(true); }
|
|
@@ -176,7 +183,13 @@ export class Streebog512 extends Streebog {
|
|
|
176
183
|
return to;
|
|
177
184
|
}
|
|
178
185
|
}
|
|
179
|
-
/**
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
186
|
+
/**
|
|
187
|
+
* **Streebog-256 hash function**
|
|
188
|
+
*
|
|
189
|
+
* Described by GOST R 34.11-2012 ([RFC 6986](https://datatracker.ietf.org/doc/html/rfc6986.html))
|
|
190
|
+
*/ export const streebog256 = createHasher(Streebog256.create);
|
|
191
|
+
/**
|
|
192
|
+
* **Streebog-512 hash function**
|
|
193
|
+
*
|
|
194
|
+
* Described by GOST R 34.11-2012 ([RFC 6986](https://datatracker.ietf.org/doc/html/rfc6986.html))
|
|
195
|
+
*/ export const streebog512 = createHasher(Streebog512.create);
|
package/gf/gf128.d.ts
DELETED
package/gf/gf128.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { bytesToNumberBE, numberToBytesBE } from "@noble/curves/utils.js";
|
|
2
|
-
export const gf128Multiply = (a, b) => {
|
|
3
|
-
let x = bytesToNumberBE(a), y = bytesToNumberBE(b), z = 0n;
|
|
4
|
-
const max_bit = 1n << 127n;
|
|
5
|
-
while (y > 0n) {
|
|
6
|
-
if ((y & 1n) == 1n)
|
|
7
|
-
z ^= x;
|
|
8
|
-
if ((x & max_bit) > 0n)
|
|
9
|
-
x = ((x ^ max_bit) << 1n) ^ 0x87n;
|
|
10
|
-
else
|
|
11
|
-
x <<= 1n;
|
|
12
|
-
y >>= 1n;
|
|
13
|
-
}
|
|
14
|
-
return numberToBytesBE(z, 16);
|
|
15
|
-
};
|
package/gf/gf64.d.ts
DELETED
package/gf/gf64.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { bytesToNumberBE, numberToBytesBE } from "@noble/curves/utils.js";
|
|
2
|
-
export const gf64Multiply = (a, b) => {
|
|
3
|
-
let x = bytesToNumberBE(a), y = bytesToNumberBE(b), z = 0n;
|
|
4
|
-
const max_bit = 1n << 63n;
|
|
5
|
-
while (y > 0n) {
|
|
6
|
-
if ((y & 1n) == 1n)
|
|
7
|
-
z ^= x;
|
|
8
|
-
if ((x & max_bit) > 0n)
|
|
9
|
-
x = ((x ^ max_bit) << 1n) ^ 0x1bn;
|
|
10
|
-
else
|
|
11
|
-
x <<= 1n;
|
|
12
|
-
y >>= 1n;
|
|
13
|
-
}
|
|
14
|
-
return numberToBytesBE(z, 8);
|
|
15
|
-
};
|