@li0ard/gost 0.0.1 → 0.1.3

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.
Files changed (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +47 -45
  3. package/gost3410/const.d.ts +47 -0
  4. package/gost3410/const.js +126 -0
  5. package/gost3410/conversion.d.ts +19 -0
  6. package/gost3410/conversion.js +35 -0
  7. package/gost3410/index.d.ts +29 -0
  8. package/gost3410/index.js +84 -0
  9. package/gost3410/vko.d.ts +38 -0
  10. package/gost3410/vko.js +47 -0
  11. package/gost341194/index.d.ts +23 -0
  12. package/gost341194/index.js +193 -0
  13. package/hmac.d.ts +15 -0
  14. package/hmac.js +22 -0
  15. package/index.d.ts +9 -0
  16. package/index.js +9 -0
  17. package/kdf.d.ts +7 -0
  18. package/kdf.js +59 -0
  19. package/kuznyechik/const.d.ts +4 -0
  20. package/kuznyechik/const.js +78 -0
  21. package/kuznyechik/index.d.ts +12 -0
  22. package/kuznyechik/index.js +207 -0
  23. package/magma/const.d.ts +62 -0
  24. package/magma/const.js +244 -0
  25. package/magma/index.d.ts +24 -0
  26. package/magma/index.js +86 -0
  27. package/modes/_keytransform.d.ts +5 -0
  28. package/modes/_keytransform.js +35 -0
  29. package/modes/cbc.d.ts +8 -0
  30. package/modes/cbc.js +42 -0
  31. package/modes/cfb.d.ts +8 -0
  32. package/modes/cfb.js +37 -0
  33. package/modes/ctr.d.ts +15 -0
  34. package/modes/ctr.js +62 -0
  35. package/modes/ecb.d.ts +7 -0
  36. package/modes/ecb.js +21 -0
  37. package/modes/index.d.ts +8 -0
  38. package/modes/index.js +8 -0
  39. package/modes/mac.d.ts +21 -0
  40. package/modes/mac.js +119 -0
  41. package/modes/mgm.d.ts +8 -0
  42. package/modes/mgm.js +90 -0
  43. package/modes/ofb.d.ts +8 -0
  44. package/modes/ofb.js +25 -0
  45. package/modes/wrap.d.ts +14 -0
  46. package/modes/wrap.js +57 -0
  47. package/package.json +48 -7
  48. package/streebog/const.d.ts +4 -0
  49. package/streebog/const.js +102 -0
  50. package/streebog/index.d.ts +66 -0
  51. package/streebog/index.js +295 -0
  52. package/types.d.ts +50 -0
  53. package/types.js +1 -0
  54. package/utils.d.ts +7 -0
  55. package/utils.js +47 -0
@@ -0,0 +1,193 @@
1
+ import { concatBytes } from "@noble/hashes/utils.js";
2
+ import { Magma } from "../magma/index.js";
3
+ import { DSSZZI_UA_DKE_1, ID_GOSTR_3411_94_CRYPTOPRO_PARAM_SET } from "../magma/const.js";
4
+ import { bytesToNumberBE, numberToBytesBE } from "@noble/curves/utils.js";
5
+ import { xorBytes } from "../utils.js";
6
+ const BLOCKSIZE = 32;
7
+ const r = (1n << 256n) - 1n;
8
+ const C2 = new Uint8Array(32);
9
+ const C3 = new Uint8Array([
10
+ 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff,
11
+ 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00,
12
+ 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff,
13
+ 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00
14
+ ]);
15
+ const C4 = new Uint8Array(32);
16
+ const A = (x) => {
17
+ const x2 = x.subarray(16, 24);
18
+ return concatBytes(xorBytes(x.subarray(24, 32), x2), x.subarray(0, 8), x.subarray(8, 16), x2);
19
+ };
20
+ const P = (x) => new Uint8Array([
21
+ x[0], x[8], x[16], x[24], x[1], x[9], x[17], x[25],
22
+ x[2], x[10], x[18], x[26], x[3], x[11], x[19], x[27],
23
+ x[4], x[12], x[20], x[28], x[5], x[13], x[21], x[29],
24
+ x[6], x[14], x[22], x[30], x[7], x[15], x[23], x[31]
25
+ ]);
26
+ /*const chi = (Y: TArg<Uint8Array>): TRet<Uint8Array> => {
27
+ const byx = new Uint8Array(2);
28
+ byx[0] = Y[30] ^ Y[28] ^ Y[26] ^ Y[24] ^ Y[6] ^ Y[0];
29
+ byx[1] = Y[31] ^ Y[29] ^ Y[27] ^ Y[25] ^ Y[7] ^ Y[1];
30
+
31
+ const result = new Uint8Array(BLOCKSIZE);
32
+ result.set(byx, 0);
33
+ result.set(Y.slice(0,30), 2);
34
+
35
+ return result;
36
+ }*/
37
+ const chi = (Y) => new Uint8Array([
38
+ Y[30] ^ Y[28] ^ Y[26] ^ Y[24] ^ Y[6] ^ Y[0],
39
+ Y[31] ^ Y[29] ^ Y[27] ^ Y[25] ^ Y[7] ^ Y[1],
40
+ ...Y.subarray(0, 30)
41
+ ]);
42
+ const _step = (hin, m, sbox) => {
43
+ let u = hin;
44
+ let v = m;
45
+ let w = xorBytes(hin, m);
46
+ const k1 = new Magma(P(w).reverse(), sbox, true);
47
+ u = xorBytes(A(u), C2);
48
+ v = A(A(v));
49
+ w = xorBytes(u, v);
50
+ const k2 = new Magma(P(w).reverse(), sbox, true);
51
+ u = xorBytes(A(u), C3);
52
+ v = A(A(v));
53
+ w = xorBytes(u, v);
54
+ const k3 = new Magma(P(w).reverse(), sbox, true);
55
+ u = xorBytes(A(u), C4);
56
+ v = A(A(v));
57
+ w = xorBytes(u, v);
58
+ const k4 = new Magma(P(w).reverse(), sbox, true);
59
+ const s = concatBytes(k4.encrypt(hin.slice(0, 8).reverse()).reverse(), k3.encrypt(hin.slice(8, 16).reverse()).reverse(), k2.encrypt(hin.slice(16, 24).reverse()).reverse(), k1.encrypt(hin.slice(24, 32).reverse()).reverse());
60
+ //let x = new Uint8Array(s);
61
+ //for(let i = 0; i < 12; i++) x = chi(x);
62
+ let x = chi(s);
63
+ x = chi(x);
64
+ x = chi(x);
65
+ x = chi(x);
66
+ x = chi(x);
67
+ x = chi(x);
68
+ x = chi(x);
69
+ x = chi(x);
70
+ x = chi(x);
71
+ x = chi(x);
72
+ x = chi(x);
73
+ x = chi(x);
74
+ x = xorBytes(x, m);
75
+ x = chi(x);
76
+ x = xorBytes(hin, x);
77
+ //for(let i = 0; i < 61; i++) x = chi(x);
78
+ x = chi(x);
79
+ x = chi(x);
80
+ x = chi(x);
81
+ x = chi(x);
82
+ x = chi(x);
83
+ x = chi(x);
84
+ x = chi(x);
85
+ x = chi(x);
86
+ x = chi(x);
87
+ x = chi(x);
88
+ x = chi(x);
89
+ x = chi(x);
90
+ x = chi(x);
91
+ x = chi(x);
92
+ x = chi(x);
93
+ x = chi(x);
94
+ x = chi(x);
95
+ x = chi(x);
96
+ x = chi(x);
97
+ x = chi(x);
98
+ x = chi(x);
99
+ x = chi(x);
100
+ x = chi(x);
101
+ x = chi(x);
102
+ x = chi(x);
103
+ x = chi(x);
104
+ x = chi(x);
105
+ x = chi(x);
106
+ x = chi(x);
107
+ x = chi(x);
108
+ x = chi(x);
109
+ x = chi(x);
110
+ x = chi(x);
111
+ x = chi(x);
112
+ x = chi(x);
113
+ x = chi(x);
114
+ x = chi(x);
115
+ x = chi(x);
116
+ x = chi(x);
117
+ x = chi(x);
118
+ x = chi(x);
119
+ x = chi(x);
120
+ x = chi(x);
121
+ x = chi(x);
122
+ x = chi(x);
123
+ x = chi(x);
124
+ x = chi(x);
125
+ x = chi(x);
126
+ x = chi(x);
127
+ x = chi(x);
128
+ x = chi(x);
129
+ x = chi(x);
130
+ x = chi(x);
131
+ x = chi(x);
132
+ x = chi(x);
133
+ x = chi(x);
134
+ x = chi(x);
135
+ x = chi(x);
136
+ x = chi(x);
137
+ x = chi(x);
138
+ x = chi(x);
139
+ return x;
140
+ };
141
+ /** GOST R 34.11-94 hash function */
142
+ export class Gost341194 {
143
+ data;
144
+ sbox;
145
+ blockLen = BLOCKSIZE;
146
+ outputLen = 32;
147
+ canXOF = false;
148
+ /** GOST R 34.11-94 hash function */
149
+ constructor(data = new Uint8Array(), sbox = ID_GOSTR_3411_94_CRYPTOPRO_PARAM_SET) {
150
+ this.data = data;
151
+ this.sbox = sbox;
152
+ }
153
+ /** Create hash instance */
154
+ static create() { return new Gost341194(); }
155
+ destroy() { this.data = new Uint8Array(); }
156
+ clone() { return this._cloneInto(); }
157
+ _cloneInto(to) {
158
+ to ||= new Gost341194();
159
+ to.data = new Uint8Array(this.data);
160
+ to.sbox = this.sbox;
161
+ return to;
162
+ }
163
+ update(data) {
164
+ this.data = concatBytes(this.data, data);
165
+ return this;
166
+ }
167
+ digestInto(buf) {
168
+ let len = 0n;
169
+ let checksum = 0n;
170
+ const h = new Uint8Array(BLOCKSIZE);
171
+ const m = new Uint8Array(this.data);
172
+ for (let i = 0; i < m.length; i += BLOCKSIZE) {
173
+ let part = m.slice(i, i + BLOCKSIZE).reverse();
174
+ len += BigInt(part.length) * 8n;
175
+ checksum = (checksum + bytesToNumberBE(part)) & r;
176
+ if (part.length < BLOCKSIZE)
177
+ part = numberToBytesBE(bytesToNumberBE(part), BLOCKSIZE);
178
+ h.set(_step(h, part, this.sbox));
179
+ }
180
+ h.set(_step(_step(h, numberToBytesBE(len, BLOCKSIZE), this.sbox), numberToBytesBE(checksum, BLOCKSIZE), this.sbox));
181
+ buf.set(h.reverse());
182
+ this.destroy();
183
+ }
184
+ digest() {
185
+ const buffer = new Uint8Array(this.outputLen);
186
+ this.digestInto(buffer);
187
+ return buffer;
188
+ }
189
+ }
190
+ /** GOST R 34.11-94 hash function */
191
+ export const gost341194 = (msg, sbox) => new Gost341194(msg, sbox).digest();
192
+ /** DSTU GOST 34.311-95 */
193
+ export const gost3431195 = (msg) => gost341194(msg, DSSZZI_UA_DKE_1);
package/hmac.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ import { type TArg, type TRet } from "@noble/hashes/utils.js";
2
+ import { _HMAC } from "@noble/hashes/hmac.js";
3
+ import { Gost341194 } from "./gost341194/index.js";
4
+ export declare class Streebog256HMAC extends _HMAC<Streebog256HMAC> {
5
+ constructor(key: TArg<Uint8Array>);
6
+ }
7
+ export declare class Streebog512HMAC extends _HMAC<Streebog512HMAC> {
8
+ constructor(key: TArg<Uint8Array>);
9
+ }
10
+ export declare class Gost341194HMAC extends _HMAC<Gost341194> {
11
+ constructor(key: TArg<Uint8Array>);
12
+ }
13
+ export declare const streebog256hmac: (key: TArg<Uint8Array>, message: TArg<Uint8Array>) => TRet<Uint8Array>;
14
+ export declare const streebog512hmac: (key: TArg<Uint8Array>, message: TArg<Uint8Array>) => TRet<Uint8Array>;
15
+ export declare const gost341194hmac: (key: TArg<Uint8Array>, message: TArg<Uint8Array>) => TRet<Uint8Array>;
package/hmac.js ADDED
@@ -0,0 +1,22 @@
1
+ import { createHasher } from "@noble/hashes/utils.js";
2
+ import { _HMAC } from "@noble/hashes/hmac.js";
3
+ import { streebog256, streebog512 } from "./streebog/index.js";
4
+ import { Gost341194 } from "./gost341194/index.js";
5
+ export class Streebog256HMAC extends _HMAC {
6
+ constructor(key) {
7
+ super(streebog256, key);
8
+ }
9
+ }
10
+ export class Streebog512HMAC extends _HMAC {
11
+ constructor(key) {
12
+ super(streebog512, key);
13
+ }
14
+ }
15
+ export class Gost341194HMAC extends _HMAC {
16
+ constructor(key) {
17
+ super(createHasher(Gost341194.create), key);
18
+ }
19
+ }
20
+ export const streebog256hmac = (key, message) => new Streebog256HMAC(key).update(message).digest();
21
+ export const streebog512hmac = (key, message) => new Streebog512HMAC(key).update(message).digest();
22
+ export const gost341194hmac = (key, message) => new Gost341194HMAC(key).update(message).digest();
package/index.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ export * from "./gost3410/index.js";
2
+ export * from "./gost341194/index.js";
3
+ export * from "./kuznyechik/index.js";
4
+ export * from "./magma/index.js";
5
+ export * from "./modes/index.js";
6
+ export * from "./streebog/index.js";
7
+ export * from "./hmac.js";
8
+ export * from "./kdf.js";
9
+ export * from "./types.js";
package/index.js ADDED
@@ -0,0 +1,9 @@
1
+ export * from "./gost3410/index.js";
2
+ export * from "./gost341194/index.js";
3
+ export * from "./kuznyechik/index.js";
4
+ export * from "./magma/index.js";
5
+ export * from "./modes/index.js";
6
+ export * from "./streebog/index.js";
7
+ export * from "./hmac.js";
8
+ export * from "./kdf.js";
9
+ export * from "./types.js";
package/kdf.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ import { type TArg, type TRet } from "@noble/hashes/utils.js";
2
+ export declare const kdf_gostr3411_2012_256: (key: TArg<Uint8Array>, label: TArg<Uint8Array>, seed: TArg<Uint8Array>) => TRet<Uint8Array>;
3
+ export declare const kdf_tree_gostr3411_2012_256: (key: TArg<Uint8Array>, label: TArg<Uint8Array>, seed: TArg<Uint8Array>, keys: number, i_len?: number) => TRet<Uint8Array>[];
4
+ export declare const streebog256pbkdf2: (password: TArg<Uint8Array>, salt: TArg<Uint8Array>, iter: number, dkLen: number) => TRet<Uint8Array>;
5
+ export declare const streebog512pbkdf2: (password: TArg<Uint8Array>, salt: TArg<Uint8Array>, iter: number, dkLen: number) => TRet<Uint8Array>;
6
+ export declare const gost341194pbkdf2: (password: TArg<Uint8Array>, salt: TArg<Uint8Array>, iter: number, dkLen: number) => TRet<Uint8Array>;
7
+ export declare const cpkdf: (password: TArg<Uint8Array>, salt: TArg<Uint8Array>) => TRet<Uint8Array>;
package/kdf.js ADDED
@@ -0,0 +1,59 @@
1
+ import { concatBytes, createHasher } from "@noble/hashes/utils.js";
2
+ import { streebog256hmac } from "./hmac.js";
3
+ import { numberToBytesBE } from "@noble/curves/utils.js";
4
+ import { pbkdf2 } from "@noble/hashes/pbkdf2.js";
5
+ import { Streebog256, streebog256, streebog512 } from "./streebog/index.js";
6
+ import { Gost341194 } from "./gost341194/index.js";
7
+ import { pad1, xorBytes } from "./utils.js";
8
+ const _0 = new Uint8Array([0]);
9
+ const _1 = new Uint8Array([1]);
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
+ const _36 = new Uint8Array(64).fill(0x36);
14
+ const _5C = new Uint8Array(64).fill(0x5C);
15
+ export const kdf_gostr3411_2012_256 = (key, label, seed) => streebog256hmac(key, concatBytes(_1, label, _0, seed, _0100));
16
+ export const kdf_tree_gostr3411_2012_256 = (key, label, seed, keys, i_len = 1) => {
17
+ const keymat = [];
18
+ const length = numberToBytesBE(keys * 32 * 8, 2);
19
+ for (let i = 0; i < keys; i++)
20
+ keymat.push(streebog256hmac(key, concatBytes(numberToBytesBE(i + 1, i_len), label, _0, seed, length)));
21
+ return keymat;
22
+ };
23
+ export const streebog256pbkdf2 = (password, salt, iter, dkLen) => pbkdf2(streebog256, password, salt, { dkLen, c: iter });
24
+ export const streebog512pbkdf2 = (password, salt, iter, dkLen) => pbkdf2(streebog512, password, salt, { dkLen, c: iter });
25
+ export const gost341194pbkdf2 = (password, salt, iter, dkLen) => pbkdf2(createHasher(Gost341194.create), password, salt, { dkLen, c: iter });
26
+ export const cpkdf = (password, salt) => {
27
+ const hasher = Streebog256.create();
28
+ const bs = 64;
29
+ if (password.length * 4 > 1024)
30
+ throw new Error("Password cannot be longer than 256 symbols");
31
+ const pin = new Uint8Array(password.length * 4);
32
+ for (let i = 0; i < password.length; i++)
33
+ pin[i * 4] = password[i];
34
+ hasher.update(salt);
35
+ if (password.length != 0)
36
+ hasher.update(pin);
37
+ const hash = hasher.digest();
38
+ const c = new Uint8Array(CPKDF_CONST);
39
+ const m0 = new Uint8Array(bs);
40
+ const m1 = new Uint8Array(bs);
41
+ for (let j = 0; j < (password.length != 0 ? 2000 : 2); j++) {
42
+ m0.set(xorBytes(c, _36));
43
+ m1.set(xorBytes(c, _5C));
44
+ hasher.update(m0);
45
+ hasher.update(hash);
46
+ hasher.update(m1);
47
+ hasher.update(hash);
48
+ c.set(pad1(hasher.digest(), bs));
49
+ }
50
+ m0.set(xorBytes(c, _36));
51
+ m1.set(xorBytes(c, _5C));
52
+ hasher.update(m0.subarray(0, 32));
53
+ hasher.update(salt);
54
+ hasher.update(m1.subarray(0, 32));
55
+ if (password.length != 0)
56
+ hasher.update(pin);
57
+ hasher.update(hasher.digest());
58
+ return hasher.digest();
59
+ };
@@ -0,0 +1,4 @@
1
+ export declare const PI: Uint8Array;
2
+ export declare const PI_REV: Uint8Array;
3
+ export declare const L: Uint8Array;
4
+ export declare const ITER: Uint8Array<ArrayBuffer>[];
@@ -0,0 +1,78 @@
1
+ export const PI = new Uint8Array([
2
+ 0xfc, 0xee, 0xdd, 0x11, 0xcf, 0x6e, 0x31, 0x16, 0xfb, 0xc4, 0xfa, 0xda, 0x23, 0xc5, 0x04, 0x4d,
3
+ 0xe9, 0x77, 0xf0, 0xdb, 0x93, 0x2e, 0x99, 0xba, 0x17, 0x36, 0xf1, 0xbb, 0x14, 0xcd, 0x5f, 0xc1,
4
+ 0xf9, 0x18, 0x65, 0x5a, 0xe2, 0x5c, 0xef, 0x21, 0x81, 0x1c, 0x3c, 0x42, 0x8b, 0x01, 0x8e, 0x4f,
5
+ 0x05, 0x84, 0x02, 0xae, 0xe3, 0x6a, 0x8f, 0xa0, 0x06, 0x0b, 0xed, 0x98, 0x7f, 0xd4, 0xd3, 0x1f,
6
+ 0xeb, 0x34, 0x2c, 0x51, 0xea, 0xc8, 0x48, 0xab, 0xf2, 0x2a, 0x68, 0xa2, 0xfd, 0x3a, 0xce, 0xcc,
7
+ 0xb5, 0x70, 0x0e, 0x56, 0x08, 0x0c, 0x76, 0x12, 0xbf, 0x72, 0x13, 0x47, 0x9c, 0xb7, 0x5d, 0x87,
8
+ 0x15, 0xa1, 0x96, 0x29, 0x10, 0x7b, 0x9a, 0xc7, 0xf3, 0x91, 0x78, 0x6f, 0x9d, 0x9e, 0xb2, 0xb1,
9
+ 0x32, 0x75, 0x19, 0x3d, 0xff, 0x35, 0x8a, 0x7e, 0x6d, 0x54, 0xc6, 0x80, 0xc3, 0xbd, 0x0d, 0x57,
10
+ 0xdf, 0xf5, 0x24, 0xa9, 0x3e, 0xa8, 0x43, 0xc9, 0xd7, 0x79, 0xd6, 0xf6, 0x7c, 0x22, 0xb9, 0x03,
11
+ 0xe0, 0x0f, 0xec, 0xde, 0x7a, 0x94, 0xb0, 0xbc, 0xdc, 0xe8, 0x28, 0x50, 0x4e, 0x33, 0x0a, 0x4a,
12
+ 0xa7, 0x97, 0x60, 0x73, 0x1e, 0x00, 0x62, 0x44, 0x1a, 0xb8, 0x38, 0x82, 0x64, 0x9f, 0x26, 0x41,
13
+ 0xad, 0x45, 0x46, 0x92, 0x27, 0x5e, 0x55, 0x2f, 0x8c, 0xa3, 0xa5, 0x7d, 0x69, 0xd5, 0x95, 0x3b,
14
+ 0x07, 0x58, 0xb3, 0x40, 0x86, 0xac, 0x1d, 0xf7, 0x30, 0x37, 0x6b, 0xe4, 0x88, 0xd9, 0xe7, 0x89,
15
+ 0xe1, 0x1b, 0x83, 0x49, 0x4c, 0x3f, 0xf8, 0xfe, 0x8d, 0x53, 0xaa, 0x90, 0xca, 0xd8, 0x85, 0x61,
16
+ 0x20, 0x71, 0x67, 0xa4, 0x2d, 0x2b, 0x09, 0x5b, 0xcb, 0x9b, 0x25, 0xd0, 0xbe, 0xe5, 0x6c, 0x52,
17
+ 0x59, 0xa6, 0x74, 0xd2, 0xe6, 0xf4, 0xb4, 0xc0, 0xd1, 0x66, 0xaf, 0xc2, 0x39, 0x4b, 0x63, 0xb6,
18
+ ]);
19
+ export const PI_REV = new Uint8Array([
20
+ 0xa5, 0x2d, 0x32, 0x8f, 0x0e, 0x30, 0x38, 0xc0, 0x54, 0xe6, 0x9e, 0x39, 0x55, 0x7e, 0x52, 0x91,
21
+ 0x64, 0x03, 0x57, 0x5a, 0x1c, 0x60, 0x07, 0x18, 0x21, 0x72, 0xa8, 0xd1, 0x29, 0xc6, 0xa4, 0x3f,
22
+ 0xe0, 0x27, 0x8d, 0x0c, 0x82, 0xea, 0xae, 0xb4, 0x9a, 0x63, 0x49, 0xe5, 0x42, 0xe4, 0x15, 0xb7,
23
+ 0xc8, 0x06, 0x70, 0x9d, 0x41, 0x75, 0x19, 0xc9, 0xaa, 0xfc, 0x4d, 0xbf, 0x2a, 0x73, 0x84, 0xd5,
24
+ 0xc3, 0xaf, 0x2b, 0x86, 0xa7, 0xb1, 0xb2, 0x5b, 0x46, 0xd3, 0x9f, 0xfd, 0xd4, 0x0f, 0x9c, 0x2f,
25
+ 0x9b, 0x43, 0xef, 0xd9, 0x79, 0xb6, 0x53, 0x7f, 0xc1, 0xf0, 0x23, 0xe7, 0x25, 0x5e, 0xb5, 0x1e,
26
+ 0xa2, 0xdf, 0xa6, 0xfe, 0xac, 0x22, 0xf9, 0xe2, 0x4a, 0xbc, 0x35, 0xca, 0xee, 0x78, 0x05, 0x6b,
27
+ 0x51, 0xe1, 0x59, 0xa3, 0xf2, 0x71, 0x56, 0x11, 0x6a, 0x89, 0x94, 0x65, 0x8c, 0xbb, 0x77, 0x3c,
28
+ 0x7b, 0x28, 0xab, 0xd2, 0x31, 0xde, 0xc4, 0x5f, 0xcc, 0xcf, 0x76, 0x2c, 0xb8, 0xd8, 0x2e, 0x36,
29
+ 0xdb, 0x69, 0xb3, 0x14, 0x95, 0xbe, 0x62, 0xa1, 0x3b, 0x16, 0x66, 0xe9, 0x5c, 0x6c, 0x6d, 0xad,
30
+ 0x37, 0x61, 0x4b, 0xb9, 0xe3, 0xba, 0xf1, 0xa0, 0x85, 0x83, 0xda, 0x47, 0xc5, 0xb0, 0x33, 0xfa,
31
+ 0x96, 0x6f, 0x6e, 0xc2, 0xf6, 0x50, 0xff, 0x5d, 0xa9, 0x8e, 0x17, 0x1b, 0x97, 0x7d, 0xec, 0x58,
32
+ 0xf7, 0x1f, 0xfb, 0x7c, 0x09, 0x0d, 0x7a, 0x67, 0x45, 0x87, 0xdc, 0xe8, 0x4f, 0x1d, 0x4e, 0x04,
33
+ 0xeb, 0xf8, 0xf3, 0x3e, 0x3d, 0xbd, 0x8a, 0x88, 0xdd, 0xcd, 0x0b, 0x13, 0x98, 0x02, 0x93, 0x80,
34
+ 0x90, 0xd0, 0x24, 0x34, 0xcb, 0xed, 0xf4, 0xce, 0x99, 0x10, 0x44, 0x40, 0x92, 0x3a, 0x01, 0x26,
35
+ 0x12, 0x1a, 0x48, 0x68, 0xf5, 0x81, 0x8b, 0xc7, 0xd6, 0x20, 0x0a, 0x08, 0x00, 0x4c, 0xd7, 0x74,
36
+ ]);
37
+ export const L = new Uint8Array([
38
+ 0x01, 0x94, 0x20, 0x85, 0x10, 0xc2, 0xc0, 0x01, 0xfb, 0x01, 0xc0, 0xc2, 0x10, 0x85, 0x20, 0x94,
39
+ ]);
40
+ /*const ITER: Uint8Array[] = Array(32).fill(null).map(() => new Uint8Array(16).fill(0));
41
+ for(let i = 0; i < 32; i++) {
42
+ ITER[i][15] = i + 1;
43
+ ITER[i] = LL(ITER[i]);
44
+ }*/
45
+ export const ITER = [
46
+ new Uint8Array([0x6E, 0xA2, 0x76, 0x72, 0x6C, 0x48, 0x7A, 0xB8, 0x5D, 0x27, 0xBD, 0x10, 0xDD, 0x84, 0x94, 0x01]),
47
+ new Uint8Array([0xDC, 0x87, 0xEC, 0xE4, 0xD8, 0x90, 0xF4, 0xB3, 0xBA, 0x4E, 0xB9, 0x20, 0x79, 0xCB, 0xEB, 0x02]),
48
+ new Uint8Array([0xB2, 0x25, 0x9A, 0x96, 0xB4, 0xD8, 0x8E, 0x0B, 0xE7, 0x69, 0x04, 0x30, 0xA4, 0x4F, 0x7F, 0x03]),
49
+ new Uint8Array([0x7B, 0xCD, 0x1B, 0x0B, 0x73, 0xE3, 0x2B, 0xA5, 0xB7, 0x9C, 0xB1, 0x40, 0xF2, 0x55, 0x15, 0x04]),
50
+ new Uint8Array([0x15, 0x6F, 0x6D, 0x79, 0x1F, 0xAB, 0x51, 0x1D, 0xEA, 0xBB, 0x0C, 0x50, 0x2F, 0xD1, 0x81, 0x05]),
51
+ new Uint8Array([0xA7, 0x4A, 0xF7, 0xEF, 0xAB, 0x73, 0xDF, 0x16, 0x0D, 0xD2, 0x08, 0x60, 0x8B, 0x9E, 0xFE, 0x06]),
52
+ new Uint8Array([0xC9, 0xE8, 0x81, 0x9D, 0xC7, 0x3B, 0xA5, 0xAE, 0x50, 0xF5, 0xB5, 0x70, 0x56, 0x1A, 0x6A, 0x07]),
53
+ new Uint8Array([0xF6, 0x59, 0x36, 0x16, 0xE6, 0x05, 0x56, 0x89, 0xAD, 0xFB, 0xA1, 0x80, 0x27, 0xAA, 0x2A, 0x08]),
54
+ new Uint8Array([0x98, 0xFB, 0x40, 0x64, 0x8A, 0x4D, 0x2C, 0x31, 0xF0, 0xDC, 0x1C, 0x90, 0xFA, 0x2E, 0xBE, 0x09]),
55
+ new Uint8Array([0x2A, 0xDE, 0xDA, 0xF2, 0x3E, 0x95, 0xA2, 0x3A, 0x17, 0xB5, 0x18, 0xA0, 0x5E, 0x61, 0xC1, 0x0A]),
56
+ new Uint8Array([0x44, 0x7C, 0xAC, 0x80, 0x52, 0xDD, 0xD8, 0x82, 0x4A, 0x92, 0xA5, 0xB0, 0x83, 0xE5, 0x55, 0x0B]),
57
+ new Uint8Array([0x8D, 0x94, 0x2D, 0x1D, 0x95, 0xE6, 0x7D, 0x2C, 0x1A, 0x67, 0x10, 0xC0, 0xD5, 0xFF, 0x3F, 0x0C]),
58
+ new Uint8Array([0xE3, 0x36, 0x5B, 0x6F, 0xF9, 0xAE, 0x07, 0x94, 0x47, 0x40, 0xAD, 0xD0, 0x08, 0x7B, 0xAB, 0x0D]),
59
+ new Uint8Array([0x51, 0x13, 0xC1, 0xF9, 0x4D, 0x76, 0x89, 0x9F, 0xA0, 0x29, 0xA9, 0xE0, 0xAC, 0x34, 0xD4, 0x0E]),
60
+ new Uint8Array([0x3F, 0xB1, 0xB7, 0x8B, 0x21, 0x3E, 0xF3, 0x27, 0xFD, 0x0E, 0x14, 0xF0, 0x71, 0xB0, 0x40, 0x0F]),
61
+ new Uint8Array([0x2F, 0xB2, 0x6C, 0x2C, 0x0F, 0x0A, 0xAC, 0xD1, 0x99, 0x35, 0x81, 0xC3, 0x4E, 0x97, 0x54, 0x10]),
62
+ new Uint8Array([0x41, 0x10, 0x1A, 0x5E, 0x63, 0x42, 0xD6, 0x69, 0xC4, 0x12, 0x3C, 0xD3, 0x93, 0x13, 0xC0, 0x11]),
63
+ new Uint8Array([0xF3, 0x35, 0x80, 0xC8, 0xD7, 0x9A, 0x58, 0x62, 0x23, 0x7B, 0x38, 0xE3, 0x37, 0x5C, 0xBF, 0x12]),
64
+ new Uint8Array([0x9D, 0x97, 0xF6, 0xBA, 0xBB, 0xD2, 0x22, 0xDA, 0x7E, 0x5C, 0x85, 0xF3, 0xEA, 0xD8, 0x2B, 0x13]),
65
+ new Uint8Array([0x54, 0x7F, 0x77, 0x27, 0x7C, 0xE9, 0x87, 0x74, 0x2E, 0xA9, 0x30, 0x83, 0xBC, 0xC2, 0x41, 0x14]),
66
+ new Uint8Array([0x3A, 0xDD, 0x01, 0x55, 0x10, 0xA1, 0xFD, 0xCC, 0x73, 0x8E, 0x8D, 0x93, 0x61, 0x46, 0xD5, 0x15]),
67
+ new Uint8Array([0x88, 0xF8, 0x9B, 0xC3, 0xA4, 0x79, 0x73, 0xC7, 0x94, 0xE7, 0x89, 0xA3, 0xC5, 0x09, 0xAA, 0x16]),
68
+ new Uint8Array([0xE6, 0x5A, 0xED, 0xB1, 0xC8, 0x31, 0x09, 0x7F, 0xC9, 0xC0, 0x34, 0xB3, 0x18, 0x8D, 0x3E, 0x17]),
69
+ new Uint8Array([0xD9, 0xEB, 0x5A, 0x3A, 0xE9, 0x0F, 0xFA, 0x58, 0x34, 0xCE, 0x20, 0x43, 0x69, 0x3D, 0x7E, 0x18]),
70
+ new Uint8Array([0xB7, 0x49, 0x2C, 0x48, 0x85, 0x47, 0x80, 0xE0, 0x69, 0xE9, 0x9D, 0x53, 0xB4, 0xB9, 0xEA, 0x19]),
71
+ new Uint8Array([0x05, 0x6C, 0xB6, 0xDE, 0x31, 0x9F, 0x0E, 0xEB, 0x8E, 0x80, 0x99, 0x63, 0x10, 0xF6, 0x95, 0x1A]),
72
+ new Uint8Array([0x6B, 0xCE, 0xC0, 0xAC, 0x5D, 0xD7, 0x74, 0x53, 0xD3, 0xA7, 0x24, 0x73, 0xCD, 0x72, 0x01, 0x1B]),
73
+ new Uint8Array([0xA2, 0x26, 0x41, 0x31, 0x9A, 0xEC, 0xD1, 0xFD, 0x83, 0x52, 0x91, 0x03, 0x9B, 0x68, 0x6B, 0x1C]),
74
+ new Uint8Array([0xCC, 0x84, 0x37, 0x43, 0xF6, 0xA4, 0xAB, 0x45, 0xDE, 0x75, 0x2C, 0x13, 0x46, 0xEC, 0xFF, 0x1D]),
75
+ new Uint8Array([0x7E, 0xA1, 0xAD, 0xD5, 0x42, 0x7C, 0x25, 0x4E, 0x39, 0x1C, 0x28, 0x23, 0xE2, 0xA3, 0x80, 0x1E]),
76
+ new Uint8Array([0x10, 0x03, 0xDB, 0xA7, 0x2E, 0x34, 0x5F, 0xF6, 0x64, 0x3B, 0x95, 0x33, 0x3F, 0x27, 0x14, 0x1F]),
77
+ new Uint8Array([0x5E, 0xA7, 0xD8, 0x58, 0x1E, 0x14, 0x9B, 0x61, 0xF1, 0x6A, 0xC1, 0x45, 0x9C, 0xED, 0xA8, 0x20])
78
+ ];
@@ -0,0 +1,12 @@
1
+ import { type TArg, type TRet } from "@noble/curves/utils.js";
2
+ import type { Cipher } from "../types.js";
3
+ /** Kuznyechik (GOST R 34.12-2015) cipher */
4
+ export declare class Kuznyechik implements Cipher {
5
+ readonly keySize = 32;
6
+ readonly blockSize = 16;
7
+ private roundKeys;
8
+ /** Kuznyechik (GOST R 34.12-2015) cipher */
9
+ constructor(key: TArg<Uint8Array>);
10
+ encrypt(plaintext: TArg<Uint8Array>): TRet<Uint8Array>;
11
+ decrypt(ciphertext: TArg<Uint8Array>): TRet<Uint8Array>;
12
+ }
@@ -0,0 +1,207 @@
1
+ import { copyBytes } from "@noble/curves/utils.js";
2
+ import { ITER, L, PI, PI_REV } from "./const.js";
3
+ import { xorBytes } from "../utils.js";
4
+ const BLOCKSIZE = 16, KEYSIZE = 32;
5
+ const S = (input, pi = PI) => {
6
+ const result = new Uint8Array(BLOCKSIZE);
7
+ //for(let i = 0; i < BLOCKSIZE; i++) result[i] = pi[input[i]];
8
+ result[0] = pi[input[0]];
9
+ result[1] = pi[input[1]];
10
+ result[2] = pi[input[2]];
11
+ result[3] = pi[input[3]];
12
+ result[4] = pi[input[4]];
13
+ result[5] = pi[input[5]];
14
+ result[6] = pi[input[6]];
15
+ result[7] = pi[input[7]];
16
+ result[8] = pi[input[8]];
17
+ result[9] = pi[input[9]];
18
+ result[10] = pi[input[10]];
19
+ result[11] = pi[input[11]];
20
+ result[12] = pi[input[12]];
21
+ result[13] = pi[input[13]];
22
+ result[14] = pi[input[14]];
23
+ result[15] = pi[input[15]];
24
+ return result;
25
+ };
26
+ const gfMultiply = (a, b) => {
27
+ let result = 0;
28
+ let high_bit;
29
+ for (let i = 0; i < 8; i++) {
30
+ if ((b & 0b00000001) === 0b00000001)
31
+ result ^= a;
32
+ high_bit = a & 0b10000000;
33
+ a <<= 1;
34
+ if (high_bit == 0b10000000)
35
+ a ^= 0b11000011;
36
+ b >>= 1;
37
+ }
38
+ return result & 0xFF;
39
+ };
40
+ const R = (input) => {
41
+ const result = new Uint8Array(BLOCKSIZE);
42
+ result.set(input.slice(0, 15), 1);
43
+ result[0] = input[15];
44
+ //let temp = 0;
45
+ //for (let i = 0; i < BLOCKSIZE; i++) temp ^= gfMultiply(result[i], L[i]);
46
+ let temp = gfMultiply(result[0], L[0]);
47
+ temp ^= gfMultiply(result[1], L[1]);
48
+ temp ^= gfMultiply(result[2], L[2]);
49
+ temp ^= gfMultiply(result[3], L[3]);
50
+ temp ^= gfMultiply(result[4], L[4]);
51
+ temp ^= gfMultiply(result[5], L[5]);
52
+ temp ^= gfMultiply(result[6], L[6]);
53
+ temp ^= gfMultiply(result[7], L[7]);
54
+ temp ^= gfMultiply(result[8], L[8]);
55
+ temp ^= gfMultiply(result[9], L[9]);
56
+ temp ^= gfMultiply(result[10], L[10]);
57
+ temp ^= gfMultiply(result[11], L[11]);
58
+ temp ^= gfMultiply(result[12], L[12]);
59
+ temp ^= gfMultiply(result[13], L[13]);
60
+ temp ^= gfMultiply(result[14], L[14]);
61
+ temp ^= gfMultiply(result[15], L[15]);
62
+ result[0] = temp;
63
+ return result;
64
+ };
65
+ const Rr = (input) => {
66
+ const result = new Uint8Array(BLOCKSIZE);
67
+ //let temp = 0;
68
+ //for (let i = 0; i < BLOCKSIZE; i++) temp ^= gfMultiply(input[i], L[i]);
69
+ let temp = gfMultiply(input[0], L[0]);
70
+ temp ^= gfMultiply(input[1], L[1]);
71
+ temp ^= gfMultiply(input[2], L[2]);
72
+ temp ^= gfMultiply(input[3], L[3]);
73
+ temp ^= gfMultiply(input[4], L[4]);
74
+ temp ^= gfMultiply(input[5], L[5]);
75
+ temp ^= gfMultiply(input[6], L[6]);
76
+ temp ^= gfMultiply(input[7], L[7]);
77
+ temp ^= gfMultiply(input[8], L[8]);
78
+ temp ^= gfMultiply(input[9], L[9]);
79
+ temp ^= gfMultiply(input[10], L[10]);
80
+ temp ^= gfMultiply(input[11], L[11]);
81
+ temp ^= gfMultiply(input[12], L[12]);
82
+ temp ^= gfMultiply(input[13], L[13]);
83
+ temp ^= gfMultiply(input[14], L[14]);
84
+ temp ^= gfMultiply(input[15], L[15]);
85
+ result.set(input.slice(1));
86
+ result[15] = temp;
87
+ return result;
88
+ };
89
+ const LL = (input) => {
90
+ //let result = copyBytes(input);
91
+ //for(let i = 0; i < BLOCKSIZE; i++) result = R(result);
92
+ let result = R(copyBytes(input));
93
+ result = R(result);
94
+ result = R(result);
95
+ result = R(result);
96
+ result = R(result);
97
+ result = R(result);
98
+ result = R(result);
99
+ result = R(result);
100
+ result = R(result);
101
+ result = R(result);
102
+ result = R(result);
103
+ result = R(result);
104
+ result = R(result);
105
+ result = R(result);
106
+ result = R(result);
107
+ result = R(result);
108
+ return result;
109
+ };
110
+ const LLr = (input) => {
111
+ //let result = copyBytes(input);
112
+ //for(let i = 0; i < BLOCKSIZE; i++) result = Rr(result);
113
+ let result = Rr(copyBytes(input));
114
+ result = Rr(result);
115
+ result = Rr(result);
116
+ result = Rr(result);
117
+ result = Rr(result);
118
+ result = Rr(result);
119
+ result = Rr(result);
120
+ result = Rr(result);
121
+ result = Rr(result);
122
+ result = Rr(result);
123
+ result = Rr(result);
124
+ result = Rr(result);
125
+ result = Rr(result);
126
+ result = Rr(result);
127
+ result = Rr(result);
128
+ result = Rr(result);
129
+ return result;
130
+ };
131
+ const LLS = (block) => LL(S(block));
132
+ const SLLr = (block) => S(LLr(block), PI_REV);
133
+ const F = (in_key1, in_key2, iter_constant) => xorBytes(LLS(xorBytes(in_key1, iter_constant)), in_key2);
134
+ /** Kuznyechik (GOST R 34.12-2015) cipher */
135
+ export class Kuznyechik {
136
+ keySize = KEYSIZE;
137
+ blockSize = BLOCKSIZE;
138
+ roundKeys;
139
+ /** Kuznyechik (GOST R 34.12-2015) cipher */
140
+ constructor(key) {
141
+ if (key.length !== this.keySize)
142
+ throw new Error("Invalid key length");
143
+ const roundKeys = Array(10).fill(null).map(() => new Uint8Array(this.blockSize));
144
+ roundKeys[0] = key.slice(0, this.blockSize);
145
+ roundKeys[1] = key.slice(this.blockSize);
146
+ let temp1 = copyBytes(roundKeys[0]);
147
+ let temp2 = copyBytes(roundKeys[1]);
148
+ let temp3 = new Uint8Array(16);
149
+ let temp4 = new Uint8Array(16);
150
+ for (let i = 0; i < 4; i++) {
151
+ const baseIndex = i * 8;
152
+ temp3 = F(temp1, temp2, ITER[baseIndex]);
153
+ temp4 = copyBytes(temp1);
154
+ temp1 = F(temp3, temp4, ITER[baseIndex + 1]);
155
+ temp2 = copyBytes(temp3);
156
+ temp3 = F(temp1, temp2, ITER[baseIndex + 2]);
157
+ temp4 = copyBytes(temp1);
158
+ temp1 = F(temp3, temp4, ITER[baseIndex + 3]);
159
+ temp2 = copyBytes(temp3);
160
+ temp3 = F(temp1, temp2, ITER[baseIndex + 4]);
161
+ temp4 = copyBytes(temp1);
162
+ temp1 = F(temp3, temp4, ITER[baseIndex + 5]);
163
+ temp2 = copyBytes(temp3);
164
+ temp3 = F(temp1, temp2, ITER[baseIndex + 6]);
165
+ temp4 = copyBytes(temp1);
166
+ temp1 = F(temp3, temp4, ITER[baseIndex + 7]);
167
+ temp2 = copyBytes(temp3);
168
+ roundKeys[2 + 2 * i] = copyBytes(temp1);
169
+ roundKeys[3 + 2 * i] = copyBytes(temp2);
170
+ }
171
+ this.roundKeys = roundKeys;
172
+ }
173
+ encrypt(plaintext) {
174
+ if (plaintext.length !== this.blockSize)
175
+ throw new Error("Invalid block size");
176
+ //let currentBlock = copyBytes(plaintext);
177
+ //for (let i = 0; i < 9; i++) currentBlock = LLS(xorBytes(this.roundKeys[i], currentBlock));
178
+ let currentBlock = LLS(xorBytes(this.roundKeys[0], plaintext));
179
+ currentBlock = LLS(xorBytes(this.roundKeys[1], currentBlock));
180
+ currentBlock = LLS(xorBytes(this.roundKeys[2], currentBlock));
181
+ currentBlock = LLS(xorBytes(this.roundKeys[3], currentBlock));
182
+ currentBlock = LLS(xorBytes(this.roundKeys[4], currentBlock));
183
+ currentBlock = LLS(xorBytes(this.roundKeys[5], currentBlock));
184
+ currentBlock = LLS(xorBytes(this.roundKeys[6], currentBlock));
185
+ currentBlock = LLS(xorBytes(this.roundKeys[7], currentBlock));
186
+ currentBlock = LLS(xorBytes(this.roundKeys[8], currentBlock));
187
+ currentBlock = xorBytes(this.roundKeys[9], currentBlock);
188
+ return currentBlock;
189
+ }
190
+ decrypt(ciphertext) {
191
+ if (ciphertext.length !== this.blockSize)
192
+ throw new Error("Invalid block size");
193
+ let currentBlock = xorBytes(this.roundKeys[9], ciphertext);
194
+ //const reversedKeys = this.roundKeys.slice(0, 9).reverse();
195
+ //for (let i = 0; i < 9; i++) currentBlock = xorBytes(reversedKeys[i], SLLr(currentBlock));
196
+ currentBlock = xorBytes(this.roundKeys[8], SLLr(currentBlock));
197
+ currentBlock = xorBytes(this.roundKeys[7], SLLr(currentBlock));
198
+ currentBlock = xorBytes(this.roundKeys[6], SLLr(currentBlock));
199
+ currentBlock = xorBytes(this.roundKeys[5], SLLr(currentBlock));
200
+ currentBlock = xorBytes(this.roundKeys[4], SLLr(currentBlock));
201
+ currentBlock = xorBytes(this.roundKeys[3], SLLr(currentBlock));
202
+ currentBlock = xorBytes(this.roundKeys[2], SLLr(currentBlock));
203
+ currentBlock = xorBytes(this.roundKeys[1], SLLr(currentBlock));
204
+ currentBlock = xorBytes(this.roundKeys[0], SLLr(currentBlock));
205
+ return currentBlock;
206
+ }
207
+ }