@li0ard/gost 0.1.6 → 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/gf256.d.ts +1 -0
- package/gf/gf256.js +62 -0
- package/gf/index.d.ts +4 -0
- package/gf/index.js +18 -0
- package/gost3410/const.js +20 -20
- package/gost3410/vko.js +1 -1
- package/gost341194/index.d.ts +3 -3
- package/gost341194/index.js +9 -9
- package/kdf.js +4 -6
- package/kuznyechik/const.js +0 -5
- package/kuznyechik/index.d.ts +9 -2
- package/kuznyechik/index.js +27 -35
- package/magma/const.d.ts +39 -39
- package/magma/const.js +191 -192
- package/magma/index.d.ts +9 -6
- package/magma/index.js +39 -47
- package/modes/_keytransform.d.ts +1 -1
- package/modes/ctr.js +5 -7
- package/modes/mac.js +43 -37
- package/modes/mgm.js +2 -17
- package/modes/wrap.d.ts +1 -1
- package/modes/wrap.js +1 -1
- package/package.json +1 -1
- package/streebog/index.d.ts +20 -6
- package/streebog/index.js +24 -11
package/modes/mac.js
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
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;
|
|
7
7
|
const Rb128 = 0b10000111;
|
|
8
|
+
const shift1 = (src, dst) => {
|
|
9
|
+
let b = 0;
|
|
10
|
+
for (let i = src.length - 1; i >= 0; i--) {
|
|
11
|
+
const bb = src[i] >> 7;
|
|
12
|
+
dst[i] = src[i] << 1 | b;
|
|
13
|
+
b = bb;
|
|
14
|
+
}
|
|
15
|
+
return b;
|
|
16
|
+
};
|
|
8
17
|
/**
|
|
9
18
|
* **EN:** Message Authentication Code (MAC) mode
|
|
10
19
|
*
|
|
@@ -12,36 +21,36 @@ const Rb128 = 0b10000111;
|
|
|
12
21
|
*/
|
|
13
22
|
export const mac = (cipher) => {
|
|
14
23
|
const encrypter = cipher.encrypt.bind(cipher);
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const Rb = cipher.blockSize === 16 ? Rb128 : Rb64;
|
|
18
|
-
const l = encrypter(new Uint8Array(cipher.blockSize));
|
|
19
|
-
let k1;
|
|
20
|
-
if ((l[0] & 0x80) !== 0)
|
|
21
|
-
k1 = macShift(l, Rb);
|
|
22
|
-
else
|
|
23
|
-
k1 = macShift(l);
|
|
24
|
-
let k2;
|
|
25
|
-
if ((k1[0] & 0x80) !== 0)
|
|
26
|
-
k2 = macShift(k1, Rb);
|
|
27
|
-
else
|
|
28
|
-
k2 = macShift(k1);
|
|
29
|
-
return [k1, k2];
|
|
30
|
-
};
|
|
24
|
+
const Rb = cipher.blockSize === 16 ? Rb128 : Rb64;
|
|
25
|
+
const L = encrypter(new Uint8Array(cipher.blockSize));
|
|
31
26
|
return {
|
|
32
27
|
compute: (msg) => {
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
if (
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
28
|
+
const k1 = new Uint8Array(cipher.blockSize);
|
|
29
|
+
const msb = shift1(L, k1);
|
|
30
|
+
if (msb)
|
|
31
|
+
k1[cipher.blockSize - 1] ^= Rb;
|
|
32
|
+
const k2 = new Uint8Array(cipher.blockSize);
|
|
33
|
+
const msb2 = shift1(k1, k2);
|
|
34
|
+
if (msb2)
|
|
35
|
+
k2[cipher.blockSize - 1] ^= Rb;
|
|
36
|
+
const n = Math.ceil(msg.length / cipher.blockSize) || 1;
|
|
37
|
+
const lastBlockComplete = msg.length > 0 && msg.length % cipher.blockSize === 0;
|
|
38
|
+
let buf = new Uint8Array(cipher.blockSize);
|
|
39
|
+
for (let i = 0; i < n - 1; i++) {
|
|
40
|
+
const m = msg.subarray(i * cipher.blockSize, (i + 1) * cipher.blockSize);
|
|
41
|
+
buf = encrypter(xorBytes(buf, m));
|
|
42
|
+
}
|
|
43
|
+
let lastBlock;
|
|
44
|
+
if (lastBlockComplete && msg.length > 0)
|
|
45
|
+
lastBlock = xorBytes(msg.subarray((n - 1) * cipher.blockSize, n * cipher.blockSize), k1);
|
|
46
|
+
else {
|
|
47
|
+
const padded = new Uint8Array(cipher.blockSize);
|
|
48
|
+
const remaining = msg.length - (n - 1) * cipher.blockSize;
|
|
49
|
+
padded.set(msg.subarray((n - 1) * cipher.blockSize));
|
|
50
|
+
padded[remaining] = 0x80;
|
|
51
|
+
lastBlock = xorBytes(padded, k2);
|
|
52
|
+
}
|
|
53
|
+
return encrypter(xorBytes(buf, lastBlock));
|
|
45
54
|
}
|
|
46
55
|
};
|
|
47
56
|
};
|
|
@@ -52,19 +61,16 @@ export const mac = (cipher) => {
|
|
|
52
61
|
*/
|
|
53
62
|
export const mac_legacy = (cipher, iv = new Uint8Array(cipher.blockSize)) => {
|
|
54
63
|
const split = (data) => [
|
|
55
|
-
(data
|
|
56
|
-
(data
|
|
64
|
+
Number(bytesToNumberLE(data.subarray(0, 4))),
|
|
65
|
+
Number(bytesToNumberLE(data.subarray(4, 8)))
|
|
57
66
|
];
|
|
58
|
-
const join = (ns) =>
|
|
59
|
-
(ns[1] >> 0) & 0xFF, (ns[1] >> 8) & 0xFF, (ns[1] >> 16) & 0xFF, (ns[1] >> 24) & 0xFF,
|
|
60
|
-
(ns[0] >> 0) & 0xFF, (ns[0] >> 8) & 0xFF, (ns[0] >> 16) & 0xFF, (ns[0] >> 24) & 0xFF
|
|
61
|
-
]);
|
|
67
|
+
const join = (ns) => concatBytes(numberToBytesLE(ns[1], 4), numberToBytesLE(ns[0], 4));
|
|
62
68
|
return {
|
|
63
69
|
compute: (msg) => {
|
|
64
70
|
const paddedData = pad1(msg, cipher.blockSize);
|
|
65
71
|
let prev = split(iv).reverse();
|
|
66
72
|
for (let i = 0; i < paddedData.length; i += cipher.blockSize)
|
|
67
|
-
prev = split(
|
|
73
|
+
prev = split(cipher.proceedBlock(xorBytes(paddedData.subarray(i, i + cipher.blockSize), join(prev)), magmaKeySequences.MAC));
|
|
68
74
|
return join(prev);
|
|
69
75
|
}
|
|
70
76
|
};
|
package/modes/mgm.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { concatBytes } from "@noble/hashes/utils.js";
|
|
2
2
|
import { bytesToNumberBE, equalBytes, numberToBytesBE } from "@noble/curves/utils.js";
|
|
3
3
|
import { pad1, xorBytes } from "../utils.js";
|
|
4
|
+
import { gf64Multiply, gf128Multiply } from "../gf/index.js";
|
|
4
5
|
/**
|
|
5
6
|
* **EN:** Multilinear Galois (MGM) mode (AEAD)
|
|
6
7
|
*
|
|
@@ -15,29 +16,13 @@ export const mgm = (cipher, nonce, tagSize = cipher.blockSize) => {
|
|
|
15
16
|
throw new Error("Invalid tagSize");
|
|
16
17
|
const encrypter = cipher.encrypt.bind(cipher);
|
|
17
18
|
const maxSize = (1n << BigInt(cipher.blockSize * 4)) - 1n;
|
|
18
|
-
const r = (cipher.blockSize == 8 ? 0x1B : 0x87);
|
|
19
19
|
const validateSizes = (plaintext, additional) => {
|
|
20
20
|
if (plaintext.length == 0 && additional.length == 0)
|
|
21
21
|
throw new Error("At least one of plaintext or additional_data required");
|
|
22
22
|
if ((plaintext.length + additional.length) > maxSize)
|
|
23
23
|
throw new Error("plaintext+additional_data are too big");
|
|
24
24
|
};
|
|
25
|
-
const mul = (
|
|
26
|
-
let x = bytesToNumberBE(a);
|
|
27
|
-
let y = bytesToNumberBE(b);
|
|
28
|
-
let z = 0n;
|
|
29
|
-
const max_bit = 1n << (BigInt(cipher.blockSize) * 8n - 1n);
|
|
30
|
-
while (y > 0n) {
|
|
31
|
-
if ((y & 1n) == 1n)
|
|
32
|
-
z ^= x;
|
|
33
|
-
if ((x & max_bit) > 0n)
|
|
34
|
-
x = ((x ^ max_bit) << 1n) ^ BigInt(r);
|
|
35
|
-
else
|
|
36
|
-
x <<= 1n;
|
|
37
|
-
y >>= 1n;
|
|
38
|
-
}
|
|
39
|
-
return numberToBytesBE(z, cipher.blockSize);
|
|
40
|
-
};
|
|
25
|
+
const mul = (cipher.blockSize == 8 ? gf64Multiply : gf128Multiply);
|
|
41
26
|
const crypt = (icn, data) => {
|
|
42
27
|
icn[0] &= 0x7F;
|
|
43
28
|
let enc = encrypter(icn);
|
package/modes/wrap.d.ts
CHANGED
|
@@ -11,4 +11,4 @@ export declare const kexp15: (cipherEnc: Cipher, cipherMac: Cipher, iv: TArg<Uin
|
|
|
11
11
|
*
|
|
12
12
|
* **RU:** Режим обёртки ключей шифрования согласно ГОСТ 28147-89
|
|
13
13
|
*/
|
|
14
|
-
export declare const kwp: (kek: TArg<Uint8Array>, isCryptoPro?: boolean, sbox?: TArg<Uint8Array>
|
|
14
|
+
export declare const kwp: (kek: TArg<Uint8Array>, isCryptoPro?: boolean, sbox?: TArg<Uint8Array>) => WrapModeMagma;
|
package/modes/wrap.js
CHANGED
|
@@ -2,7 +2,7 @@ import { concatBytes } from "@noble/hashes/utils.js";
|
|
|
2
2
|
import { mac as _mac, mac_legacy } from "./mac.js";
|
|
3
3
|
import { ctr } from "./ctr.js";
|
|
4
4
|
import { equalBytes } from "@noble/curves/utils.js";
|
|
5
|
-
import { ID_GOST_28147_89_CRYPTO_PRO_A_PARAM_SET } from "../magma/const";
|
|
5
|
+
import { ID_GOST_28147_89_CRYPTO_PRO_A_PARAM_SET } from "../magma/const.js";
|
|
6
6
|
import { Magma } from "../magma/index.js";
|
|
7
7
|
import { ecb } from "./ecb.js";
|
|
8
8
|
import { cp_kek_diversify } from "./_keytransform.js";
|
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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { concatBytes, createHasher } from "@noble/hashes/utils.js";
|
|
1
|
+
import { concatBytes, copyBytes, createHasher } from "@noble/hashes/utils.js";
|
|
2
2
|
import { A, C, TAU } from "./const.js";
|
|
3
3
|
import { PI } from "../kuznyechik/const.js";
|
|
4
4
|
import { pad1, xorBytes } from "../utils.js";
|
|
@@ -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++)
|
|
@@ -122,7 +121,7 @@ class Streebog {
|
|
|
122
121
|
return buffer;
|
|
123
122
|
}
|
|
124
123
|
digestInto(buf) {
|
|
125
|
-
const message = this.buffer
|
|
124
|
+
const message = copyBytes(this.buffer).reverse();
|
|
126
125
|
let n = new Uint8Array(this.blockLen);
|
|
127
126
|
let sigma = new Uint8Array(this.blockLen);
|
|
128
127
|
let hash = new Uint8Array(this.blockLen).fill(this.is512 ? 0 : 1);
|
|
@@ -144,13 +143,17 @@ class Streebog {
|
|
|
144
143
|
}
|
|
145
144
|
hash = G(_0, G(_0, G(n, hash, paddedMsg), add512(n, numberToBytesBE(msg.length * 8, 4))), add512(sigma, paddedMsg));
|
|
146
145
|
if (this.is512)
|
|
147
|
-
buf.set(hash
|
|
146
|
+
buf.set(copyBytes(hash).reverse());
|
|
148
147
|
else
|
|
149
148
|
buf.set(hash.slice(0, 32).reverse());
|
|
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);
|