@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 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
- export { gf64Multiply } from "./gf64.js";
2
- export { gf128Multiply } from "./gf128.js";
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
- export { gf64Multiply } from "./gf64.js";
2
- export { gf128Multiply } from "./gf128.js";
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";
@@ -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 data;
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(data?: TArg<Uint8Array>, sbox?: TArg<Uint8Array>);
10
+ constructor(buffer?: TArg<Uint8Array>, sbox?: TArg<Uint8Array>);
11
11
  /** Create hash instance */
12
12
  static create(): Gost341194;
13
13
  destroy(): void;
@@ -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, 8), x.subarray(8, 16), x.subarray(16, 24));
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
- data;
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(data = new Uint8Array(), sbox = ID_GOSTR_3411_94_CRYPTOPRO_PARAM_SET) {
54
- this.data = data;
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.data = new Uint8Array(); }
59
+ destroy() { this.buffer = new Uint8Array(); }
60
60
  clone() { return this._cloneInto(); }
61
61
  _cloneInto(to) {
62
62
  to ||= new Gost341194();
63
- to.data = new Uint8Array(this.data);
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.data = concatBytes(this.data, data);
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 = new Uint8Array(this.data);
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 = copyBytes(CPKDF_CONST);
39
- const m0 = new Uint8Array(bs);
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));
@@ -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
- /** Kuznyechik (GOST R 34.12-2015) cipher */
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
- /** Kuznyechik (GOST R 34.12-2015) cipher */
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>;
@@ -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
- /** Kuznyechik (GOST R 34.12-2015) cipher */
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
- /** Kuznyechik (GOST R 34.12-2015) cipher */
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 7836 */
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 7836 */
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
- /** Magma (GOST R 34.12-2015 and GOST 28147-89) cipher */
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, concatBytes, copyBytes, numberToBytesBE } from "@noble/curves/utils.js";
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
- const BLOCKSIZE = 8, KEYSIZE = 32;
4
- const T = (value, sbox) => ((sbox[((value >> 0) & 0x0f)] << 0) |
5
- (sbox[16 + ((value >> 4) & 0x0f)] << 4) |
6
- (sbox[32 + ((value >> 8) & 0x0f)] << 8) |
7
- (sbox[48 + ((value >> 12) & 0x0f)] << 12) |
8
- (sbox[64 + ((value >> 16) & 0x0f)] << 16) |
9
- (sbox[80 + ((value >> 20) & 0x0f)] << 20) |
10
- (sbox[96 + ((value >> 24) & 0x0f)] << 24) |
11
- (sbox[112 + ((value >> 28) & 0x0f)] << 28)) >>> 0;
12
- const G = (a, k, sbox) => {
13
- const substituted = T((a + k) >>> 0, sbox);
14
- return ((substituted << 11) | (substituted >>> 21)) >>> 0;
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 = new DataView(key.buffer, key.byteOffset, key.byteLength);
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
- /** Magma (GOST R 34.12-2015 and GOST 28147-89) cipher */
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 = 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
- let a0 = Number(bytesToNumberBE(block.subarray(0, 4)));
48
- let a1 = Number(bytesToNumberBE(block.subarray(4, 8)));
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, roundKeys[i], this.sbox)) >>> 0;
58
+ a1 = (a0 ^ G((a1 + roundKeys[i]) >>> 0, this.sbox)) >>> 0;
52
59
  a0 = temp;
53
60
  }
54
- return concatBytes(numberToBytesBE(a1, 4), numberToBytesBE(a0, 4));
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 { bytesToNumberBE, numberToBytesBE } from "@noble/curves/utils.js";
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).reverse();
51
- let n2 = (bytesToNumberBE(encryptedIv.subarray(0, 4)));
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(numberToBytesBE(n2, 4), numberToBytesBE(n1, 4)).reverse()));
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[0] | data[1] << 8 | data[2] << 16 | data[3] << 24) >>> 0,
65
- (data[4] | data[5] << 8 | data[6] << 16 | data[7] << 24) >>> 0
64
+ Number(bytesToNumberLE(data.subarray(0, 4))),
65
+ Number(bytesToNumberLE(data.subarray(4, 8)))
66
66
  ];
67
- const join = (ns) => new Uint8Array([
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(Magma.reverseChunks(cipher.proceedBlock(Magma.reverseChunks(xorBytes(paddedData.subarray(i, i + cipher.blockSize), join(prev))), magmaKeySequences.MAC)));
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@li0ard/gost",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "main": "index.js",
5
5
  "types": "index.d.ts",
6
6
  "type": "module",
@@ -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
- /** Streebog-256 (GOST R 34.11-2012) hash function */
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
- /** Streebog-512 (GOST R 34.11-2012) hash function */
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
- /** Streebog-256 (GOST R 34.11-2012) hash function */
37
- export declare const streebog256: {
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
- /** Streebog-512 (GOST R 34.11-2012) hash function */
52
- export declare const streebog512: {
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
- /** Streebog-256 (GOST R 34.11-2012) hash function */
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
- /** Streebog-512 (GOST R 34.11-2012) hash function */
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
- /** Streebog-256 (GOST R 34.11-2012) hash function */
180
- export const streebog256 = createHasher(Streebog256.create);
181
- /** Streebog-512 (GOST R 34.11-2012) hash function */
182
- export const streebog512 = createHasher(Streebog512.create);
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
@@ -1,2 +0,0 @@
1
- import { type TArg, type TRet } from "@noble/curves/utils.js";
2
- export declare const gf128Multiply: (a: TArg<Uint8Array>, b: TArg<Uint8Array>) => TRet<Uint8Array>;
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
@@ -1,2 +0,0 @@
1
- import { type TArg, type TRet } from "@noble/curves/utils.js";
2
- export declare const gf64Multiply: (a: TArg<Uint8Array>, b: TArg<Uint8Array>) => TRet<Uint8Array>;
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
- };