@bsv/sdk 1.5.3 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/cjs/package.json +1 -1
  2. package/dist/cjs/src/primitives/AESGCM.js +113 -137
  3. package/dist/cjs/src/primitives/AESGCM.js.map +1 -1
  4. package/dist/cjs/src/primitives/BigNumber.js +1019 -3947
  5. package/dist/cjs/src/primitives/BigNumber.js.map +1 -1
  6. package/dist/cjs/src/primitives/K256.js +53 -37
  7. package/dist/cjs/src/primitives/K256.js.map +1 -1
  8. package/dist/cjs/src/primitives/Mersenne.js +16 -21
  9. package/dist/cjs/src/primitives/Mersenne.js.map +1 -1
  10. package/dist/cjs/src/primitives/MontgomoryMethod.js.map +1 -1
  11. package/dist/cjs/src/primitives/utils.js +27 -17
  12. package/dist/cjs/src/primitives/utils.js.map +1 -1
  13. package/dist/cjs/src/script/Spend.js +618 -858
  14. package/dist/cjs/src/script/Spend.js.map +1 -1
  15. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  16. package/dist/esm/src/primitives/AESGCM.js +112 -137
  17. package/dist/esm/src/primitives/AESGCM.js.map +1 -1
  18. package/dist/esm/src/primitives/BigNumber.js +1011 -3969
  19. package/dist/esm/src/primitives/BigNumber.js.map +1 -1
  20. package/dist/esm/src/primitives/K256.js +53 -37
  21. package/dist/esm/src/primitives/K256.js.map +1 -1
  22. package/dist/esm/src/primitives/Mersenne.js +16 -21
  23. package/dist/esm/src/primitives/Mersenne.js.map +1 -1
  24. package/dist/esm/src/primitives/MontgomoryMethod.js.map +1 -1
  25. package/dist/esm/src/primitives/utils.js +29 -17
  26. package/dist/esm/src/primitives/utils.js.map +1 -1
  27. package/dist/esm/src/script/Spend.js +618 -857
  28. package/dist/esm/src/script/Spend.js.map +1 -1
  29. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  30. package/dist/types/src/primitives/AESGCM.d.ts.map +1 -1
  31. package/dist/types/src/primitives/BigNumber.d.ts +238 -1705
  32. package/dist/types/src/primitives/BigNumber.d.ts.map +1 -1
  33. package/dist/types/src/primitives/K256.d.ts.map +1 -1
  34. package/dist/types/src/primitives/Mersenne.d.ts +2 -2
  35. package/dist/types/src/primitives/Mersenne.d.ts.map +1 -1
  36. package/dist/types/src/primitives/utils.d.ts +2 -0
  37. package/dist/types/src/primitives/utils.d.ts.map +1 -1
  38. package/dist/types/src/script/Spend.d.ts +11 -1
  39. package/dist/types/src/script/Spend.d.ts.map +1 -1
  40. package/dist/types/tsconfig.types.tsbuildinfo +1 -1
  41. package/dist/umd/bundle.js +1 -1
  42. package/docs/performance.md +70 -0
  43. package/docs/primitives.md +262 -3049
  44. package/package.json +1 -1
  45. package/src/auth/__tests/Peer.test.ts +38 -23
  46. package/src/auth/certificates/__tests/MasterCertificate.test.ts +27 -20
  47. package/src/auth/certificates/__tests/VerifiableCertificate.test.ts +24 -24
  48. package/src/primitives/AESGCM.ts +118 -164
  49. package/src/primitives/BigNumber.ts +867 -4180
  50. package/src/primitives/K256.ts +57 -37
  51. package/src/primitives/Mersenne.ts +16 -20
  52. package/src/primitives/MontgomoryMethod.ts +2 -2
  53. package/src/primitives/__tests/ReductionContext.test.ts +6 -1
  54. package/src/primitives/utils.ts +28 -17
  55. package/src/script/Spend.ts +634 -1309
  56. package/src/transaction/__tests/Transaction.test.ts +14 -16
  57. package/src/transaction/__tests/Transaction.benchmarks.test.ts +0 -237
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bsv/sdk",
3
- "version": "1.5.3",
3
+ "version": "1.6.0",
4
4
  "type": "module",
5
5
  "description": "BSV Blockchain Software Development Kit",
6
6
  "main": "dist/cjs/mod.js",
@@ -8,6 +8,10 @@ import { MasterCertificate } from '../../auth/certificates/MasterCertificate.js'
8
8
  import { getVerifiableCertificates } from '../../auth/utils/getVerifiableCertificates.js'
9
9
  import { CompletedProtoWallet } from '../certificates/__tests/CompletedProtoWallet.js'
10
10
 
11
+ const certifierPrivKey = new PrivateKey(21)
12
+ const alicePrivKey = new PrivateKey(22)
13
+ const bobPrivKey = new PrivateKey(23)
14
+
11
15
  jest.mock('../../auth/utils/getVerifiableCertificates')
12
16
 
13
17
  class LocalTransport implements Transport {
@@ -40,6 +44,19 @@ class LocalTransport implements Transport {
40
44
  }
41
45
  }
42
46
 
47
+ function waitForNextGeneralMessage (
48
+ peer: Peer,
49
+ handler?: (senderPublicKey: string, payload: number[]) => void
50
+ ): Promise<void> {
51
+ return new Promise(resolve => {
52
+ const listenerId = peer.listenForGeneralMessages((senderPublicKey, payload) => {
53
+ peer.stopListeningForGeneralMessages(listenerId)
54
+ if (handler !== undefined) handler(senderPublicKey, payload)
55
+ resolve()
56
+ })
57
+ })
58
+ }
59
+
43
60
  describe('Peer class mutual authentication and certificate exchange', () => {
44
61
  let walletA: WalletInterface, walletB: WalletInterface
45
62
  let transportA: LocalTransport, transportB: LocalTransport
@@ -49,7 +66,7 @@ describe('Peer class mutual authentication and certificate exchange', () => {
49
66
 
50
67
  const certificateType = Utils.toBase64(new Array(32).fill(1))
51
68
  // const certificateSerialNumber = Utils.toBase64(new Array(32).fill(2))
52
- const certifierPrivateKey = PrivateKey.fromRandom()
69
+ const certifierPrivateKey = certifierPrivKey
53
70
  const certifierPublicKey = certifierPrivateKey.toPublicKey().toString()
54
71
  const certificatesToRequest = {
55
72
  certifiers: [certifierPublicKey],
@@ -198,8 +215,8 @@ describe('Peer class mutual authentication and certificate exchange', () => {
198
215
  certificatesReceivedByAlice = []
199
216
  certificatesReceivedByBob = []
200
217
 
201
- walletA = new CompletedProtoWallet(PrivateKey.fromRandom())
202
- walletB = new CompletedProtoWallet(PrivateKey.fromRandom())
218
+ walletA = new CompletedProtoWallet(alicePrivKey)
219
+ walletB = new CompletedProtoWallet(bobPrivKey)
203
220
  })
204
221
 
205
222
  it('Neither Alice nor Bob request certificates, mutual authentication completes successfully', async () => {
@@ -235,10 +252,10 @@ describe('Peer class mutual authentication and certificate exchange', () => {
235
252
  const transportA2 = new LocalTransport()
236
253
  const transportB = new LocalTransport()
237
254
  transportA1.connect(transportB)
238
- const aliceKey = PrivateKey.fromRandom()
255
+ const aliceKey = alicePrivKey
239
256
  const walletA1 = new CompletedProtoWallet(aliceKey)
240
257
  const walletA2 = new CompletedProtoWallet(aliceKey)
241
- const walletB = new CompletedProtoWallet(PrivateKey.fromRandom())
258
+ const walletB = new CompletedProtoWallet(alicePrivKey)
242
259
  const aliceFirstDevice = new Peer(
243
260
  walletA1,
244
261
  transportA1
@@ -264,22 +281,14 @@ describe('Peer class mutual authentication and certificate exchange', () => {
264
281
  })().catch(e => { })
265
282
  })
266
283
  })
267
- let aliceReceivedGeneralMessageOnFirstDevice = new Promise<void>((resolve) => {
268
- aliceFirstDevice.listenForGeneralMessages((senderPublicKey, payload) => {
269
- (async () => {
270
- resolve()
271
- alice1MessageHandler(senderPublicKey, payload)
272
- })().catch(e => { })
273
- })
274
- })
275
- const aliceReceivedGeneralMessageOnOtherDevice = new Promise<void>((resolve) => {
276
- aliceOtherDevice.listenForGeneralMessages((senderPublicKey, payload) => {
277
- (async () => {
278
- resolve()
279
- alice2MessageHandler(senderPublicKey, payload)
280
- })().catch(e => { })
281
- })
282
- })
284
+ const aliceReceivedGeneralMessageOnFirstDevice = waitForNextGeneralMessage(
285
+ aliceFirstDevice,
286
+ alice1MessageHandler
287
+ )
288
+ const aliceReceivedGeneralMessageOnOtherDevice = waitForNextGeneralMessage(
289
+ aliceOtherDevice,
290
+ alice2MessageHandler
291
+ )
283
292
 
284
293
  await aliceFirstDevice.toPeer(Utils.toArray('Hello Bob!'))
285
294
  await bobReceivedGeneralMessage
@@ -288,8 +297,14 @@ describe('Peer class mutual authentication and certificate exchange', () => {
288
297
  await aliceOtherDevice.toPeer(Utils.toArray('Hello Bob from my other device!'))
289
298
  await aliceReceivedGeneralMessageOnOtherDevice
290
299
  transportA1.connect(transportB)
291
- await aliceFirstDevice.toPeer(Utils.toArray('Back on my first device now, Bob! Can you still hear me?'))
292
- await new Promise(resolve => setTimeout(resolve, 2000))
300
+ const waitForSecondMessage = waitForNextGeneralMessage(
301
+ aliceFirstDevice,
302
+ alice1MessageHandler
303
+ )
304
+ await aliceFirstDevice.toPeer(
305
+ Utils.toArray('Back on my first device now, Bob! Can you still hear me?')
306
+ )
307
+ await waitForSecondMessage
293
308
  expect(alice1MessageHandler.mock.calls.length).toEqual(2)
294
309
  }, 30000)
295
310
 
@@ -3,23 +3,30 @@ import { VerifiableCertificate } from '../../../auth/certificates/VerifiableCert
3
3
  import { PrivateKey, SymmetricKey, Utils, Random } from '../../../../mod'
4
4
  import { CompletedProtoWallet } from '../../../auth/certificates/__tests/CompletedProtoWallet'
5
5
 
6
+ const subjectPrivateKey = new PrivateKey(21)
7
+ const certifierPrivateKey = new PrivateKey(22)
8
+
9
+ const fieldSymFixed1 = new SymmetricKey(51)
10
+ const fieldSymWrong = new SymmetricKey(61)
11
+
12
+ const subjectKey2 = new PrivateKey(71)
13
+ const verifierKey2 = new PrivateKey(81)
14
+
15
+ // A mock revocation outpoint for testing
16
+ const mockRevocationOutpoint =
17
+ 'deadbeefdeadbeefdeadbeefdeadbeef00000000000000000000000000000000.1'
18
+
19
+ // Arbitrary certificate data (in plaintext)
20
+ const plaintextFields = {
21
+ name: 'Alice',
22
+ email: 'alice@example.com',
23
+ department: 'Engineering'
24
+ }
25
+
26
+ const subjectWallet = new CompletedProtoWallet(subjectPrivateKey)
27
+ const certifierWallet = new CompletedProtoWallet(certifierPrivateKey)
28
+
6
29
  describe('MasterCertificate', () => {
7
- const subjectPrivateKey = PrivateKey.fromRandom()
8
- const certifierPrivateKey = PrivateKey.fromRandom()
9
-
10
- // A mock revocation outpoint for testing
11
- const mockRevocationOutpoint =
12
- 'deadbeefdeadbeefdeadbeefdeadbeef00000000000000000000000000000000.1'
13
-
14
- // Arbitrary certificate data (in plaintext)
15
- const plaintextFields = {
16
- name: 'Alice',
17
- email: 'alice@example.com',
18
- department: 'Engineering'
19
- }
20
-
21
- const subjectWallet = new CompletedProtoWallet(subjectPrivateKey)
22
- const certifierWallet = new CompletedProtoWallet(certifierPrivateKey)
23
30
  let subjectIdentityKey: string
24
31
  let certifierIdentityKey: string
25
32
 
@@ -35,7 +42,7 @@ describe('MasterCertificate', () => {
35
42
  describe('constructor', () => {
36
43
  it('should construct a MasterCertificate successfully when masterKeyring is valid', () => {
37
44
  // Prepare a minimal valid MasterCertificate
38
- const fieldSymKey = SymmetricKey.fromRandom()
45
+ const fieldSymKey = fieldSymFixed1
39
46
  const encryptedFieldValue = Utils.toBase64(
40
47
  fieldSymKey.encrypt(Utils.toArray('Alice', 'utf8')) as number[]
41
48
  )
@@ -129,7 +136,7 @@ describe('MasterCertificate', () => {
129
136
  mockRevocationOutpoint,
130
137
  {
131
138
  name: Utils.toBase64(
132
- SymmetricKey.fromRandom().encrypt(
139
+ fieldSymWrong.encrypt(
133
140
  Utils.toArray('Alice', 'utf8')
134
141
  ) as number[]
135
142
  )
@@ -149,7 +156,7 @@ describe('MasterCertificate', () => {
149
156
  })
150
157
 
151
158
  describe('createKeyringForVerifier (static)', () => {
152
- const verifierPrivateKey = PrivateKey.fromRandom()
159
+ const verifierPrivateKey = verifierKey2
153
160
  const verifierWallet = new CompletedProtoWallet(verifierPrivateKey)
154
161
  let verifierIdentityKey: string
155
162
 
@@ -350,7 +357,7 @@ describe('MasterCertificate', () => {
350
357
  })
351
358
  it('should allow issuing a self-signed certificate and decrypt it with the same wallet', async () => {
352
359
  // In a self-signed scenario, the subject and certifier are the same
353
- const subjectWallet = new CompletedProtoWallet(PrivateKey.fromRandom())
360
+ const subjectWallet = new CompletedProtoWallet(subjectKey2)
354
361
 
355
362
  // Some sample fields
356
363
  const selfSignedFields = {
@@ -5,28 +5,31 @@ import { CompletedProtoWallet } from '../../../auth/certificates/__tests/Complet
5
5
  import { MasterCertificate } from '../../../auth/certificates/MasterCertificate'
6
6
  import { ProtoWallet, WalletCertificate } from '../../../wallet/index'
7
7
 
8
- describe('VerifiableCertificate', () => {
9
- const subjectPrivateKey = PrivateKey.fromRandom()
10
- const subjectIdentityKey = subjectPrivateKey.toPublicKey().toString()
11
- const certifierPrivateKey = PrivateKey.fromRandom()
12
- const certifierIdentityKey = certifierPrivateKey.toPublicKey().toString()
13
- const verifierPrivateKey = PrivateKey.fromRandom()
14
- const verifierIdentityKey = verifierPrivateKey.toPublicKey().toString()
15
-
16
- const subjectWallet = new CompletedProtoWallet(subjectPrivateKey)
17
- const verifierWallet = new CompletedProtoWallet(verifierPrivateKey)
18
-
19
- const sampleType = Utils.toBase64(new Array(32).fill(1))
20
- const sampleSerialNumber = Utils.toBase64(new Array(32).fill(2))
21
- const sampleRevocationOutpoint =
22
- 'deadbeefdeadbeefdeadbeefdeadbeef00000000000000000000000000000000.1'
23
-
24
- const plaintextFields = {
25
- name: 'Alice',
26
- email: 'alice@example.com',
27
- organization: 'Example Corp'
28
- }
8
+ const subjectPrivateKey = new PrivateKey(21)
9
+ const subjectIdentityKey = subjectPrivateKey.toPublicKey().toString()
10
+ const certifierPrivateKey = new PrivateKey(22)
11
+ const certifierIdentityKey = certifierPrivateKey.toPublicKey().toString()
12
+ const verifierPrivateKey = new PrivateKey(23)
13
+ const verifierIdentityKey = verifierPrivateKey.toPublicKey().toString()
14
+
15
+ const wrongPrivateKey = new PrivateKey(31)
16
+ const wrongWallet = new CompletedProtoWallet(wrongPrivateKey)
17
+
18
+ const subjectWallet = new CompletedProtoWallet(subjectPrivateKey)
19
+ const verifierWallet = new CompletedProtoWallet(verifierPrivateKey)
20
+
21
+ const sampleType = Utils.toBase64(new Array(32).fill(1))
22
+ const sampleSerialNumber = Utils.toBase64(new Array(32).fill(2))
23
+ const sampleRevocationOutpoint =
24
+ 'deadbeefdeadbeefdeadbeefdeadbeef00000000000000000000000000000000.1'
25
+
26
+ const plaintextFields = {
27
+ name: 'Alice',
28
+ email: 'alice@example.com',
29
+ organization: 'Example Corp'
30
+ }
29
31
 
32
+ describe('VerifiableCertificate', () => {
30
33
  let verifiableCert: VerifiableCertificate
31
34
 
32
35
  beforeEach(async () => {
@@ -79,9 +82,6 @@ describe('VerifiableCertificate', () => {
79
82
  })
80
83
 
81
84
  it('should fail if the verifier wallet does not have the correct private key (wrong key)', async () => {
82
- const wrongPrivateKey = PrivateKey.fromRandom()
83
- const wrongWallet = new CompletedProtoWallet(wrongPrivateKey)
84
-
85
85
  await expect(verifiableCert.decryptFields(wrongWallet)).rejects.toThrow(
86
86
  /Failed to decrypt selectively revealed certificate fields using keyring/
87
87
  )
@@ -1,53 +1,61 @@
1
1
 
2
2
  // @ts-nocheck
3
- const SBox = [[0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76],
4
- [0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0],
5
- [0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15],
6
- [0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75],
7
- [0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84],
8
- [0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf],
9
- [0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8],
10
- [0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2],
11
- [0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73],
12
- [0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb],
13
- [0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79],
14
- [0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08],
15
- [0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a],
16
- [0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e],
17
- [0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf],
18
- [0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16]]
19
- const Rcon = [[0x00, 0x00, 0x00, 0x00], [0x01, 0x00, 0x00, 0x00], [0x02, 0x00, 0x00, 0x00], [0x04, 0x00, 0x00, 0x00],
3
+ const SBox = new Uint8Array([
4
+ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
5
+ 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
6
+ 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
7
+ 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
8
+ 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
9
+ 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
10
+ 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
11
+ 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
12
+ 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
13
+ 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
14
+ 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
15
+ 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
16
+ 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
17
+ 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
18
+ 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
19
+ 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
20
+ ])
21
+ const Rcon = [
22
+ [0x00, 0x00, 0x00, 0x00], [0x01, 0x00, 0x00, 0x00], [0x02, 0x00, 0x00, 0x00], [0x04, 0x00, 0x00, 0x00],
20
23
  [0x08, 0x00, 0x00, 0x00], [0x10, 0x00, 0x00, 0x00], [0x20, 0x00, 0x00, 0x00], [0x40, 0x00, 0x00, 0x00],
21
- [0x80, 0x00, 0x00, 0x00], [0x1b, 0x00, 0x00, 0x00], [0x36, 0x00, 0x00, 0x00]]
24
+ [0x80, 0x00, 0x00, 0x00], [0x1b, 0x00, 0x00, 0x00], [0x36, 0x00, 0x00, 0x00]
25
+ ].map(v => new Uint8Array(v))
26
+
27
+ const mul2 = new Uint8Array(256)
28
+ const mul3 = new Uint8Array(256)
29
+ for (let i = 0; i < 256; i++) {
30
+ const m2 = ((i << 1) ^ ((i & 0x80) !== 0 ? 0x1b : 0)) & 0xff
31
+ mul2[i] = m2
32
+ mul3[i] = m2 ^ i
33
+ }
22
34
 
23
35
  function addRoundKey (
24
36
  state: number[][],
25
37
  roundKeyArray: number[][],
26
38
  offset: number
27
39
  ): void {
28
- let i
29
- let j: number
30
- for (i = 0; i < 4; i++) {
31
- for (j = 0; j < 4; j++) {
32
- state[i][j] = state[i][j] ^ roundKeyArray[offset + j][i]
40
+ for (let c = 0; c < 4; c++) {
41
+ const keyCol = roundKeyArray[offset + c]
42
+ for (let r = 0; r < 4; r++) {
43
+ state[r][c] ^= keyCol[r]
33
44
  }
34
45
  }
35
46
  }
36
47
 
37
48
  function subBytes (state: number[][]): void {
38
- let i
39
- let j
40
- for (i = 0; i < 4; i++) {
41
- for (j = 0; j < 4; j++) {
42
- state[i][j] = SBox[(state[i][j] & 0xF0) >> 4][(state[i][j] & 0x0F)]
49
+ for (let r = 0; r < 4; r++) {
50
+ for (let c = 0; c < 4; c++) {
51
+ state[r][c] = SBox[state[r][c]]
43
52
  }
44
53
  }
45
54
  }
46
55
 
47
56
  function subWord (value: number[]): void {
48
- let i
49
- for (i = 0; i < 4; i++) {
50
- value[i] = SBox[(value[i] & 0xF0) >> 4][(value[i] & 0x0F)]
57
+ for (let i = 0; i < 4; i++) {
58
+ value[i] = SBox[value[i]]
51
59
  }
52
60
  }
53
61
 
@@ -61,110 +69,65 @@ function rotWord (value: number[]): void {
61
69
  }
62
70
 
63
71
  function shiftRows (state: number[][]): void {
64
- let i: number
65
- let j: number
66
- let k: number
67
- let l: number
68
- let temp
69
-
70
- for (i = 1; i < 4; i++) {
71
- for (j = 0; j < ((i - 1) % 2) + 1; j++) {
72
- temp = state[i][j]
73
- k = j
74
- while (true) {
75
- l = k + i
76
- if (l >= 4) {
77
- l = l - 4
78
- }
79
-
80
- if (l === j) {
81
- break
82
- }
83
-
84
- state[i][k] = state[i][l]
85
- k = l
86
- }
87
-
88
- state[i][k] = temp
89
- }
90
- }
91
- }
92
-
93
- function finiteFieldMultiplication (value0: number, value1: number): number {
94
- let i
95
- let result = 0
96
-
97
- for (i = 0; i < 8; i++) {
98
- if ((value1 & 1) !== 0) {
99
- result = result ^ value0
100
- }
101
-
102
- if ((value0 & 0x80) !== 0) {
103
- value0 = value0 << 1
104
- value0 = value0 ^ 0x11b
105
- } else {
106
- value0 = value0 << 1
107
- }
108
-
109
- value1 = value1 >> 1
110
- }
111
-
112
- return result
72
+ let tmp = state[1][0]
73
+ state[1][0] = state[1][1]
74
+ state[1][1] = state[1][2]
75
+ state[1][2] = state[1][3]
76
+ state[1][3] = tmp
77
+
78
+ tmp = state[2][0]
79
+ const tmp2 = state[2][1]
80
+ state[2][0] = state[2][2]
81
+ state[2][1] = state[2][3]
82
+ state[2][2] = tmp
83
+ state[2][3] = tmp2
84
+
85
+ tmp = state[3][3]
86
+ state[3][3] = state[3][2]
87
+ state[3][2] = state[3][1]
88
+ state[3][1] = state[3][0]
89
+ state[3][0] = tmp
113
90
  }
114
91
 
115
92
  function mixColumns (state: number[][]): void {
116
- let i
117
- let j
118
- const temp: number[][] = [[], [], [], []]
119
-
120
- for (i = 0; i < 4; i++) {
121
- temp[0][i] = finiteFieldMultiplication(0x02, state[0][i]) ^ finiteFieldMultiplication(0x03, state[1][i]) ^
122
- state[2][i] ^ state[3][i]
123
- temp[1][i] = state[0][i] ^ finiteFieldMultiplication(0x02, state[1][i]) ^
124
- finiteFieldMultiplication(0x03, state[2][i]) ^ state[3][i]
125
- temp[2][i] = state[0][i] ^ state[1][i] ^ finiteFieldMultiplication(0x02, state[2][i]) ^
126
- finiteFieldMultiplication(0x03, state[3][i])
127
- temp[3][i] = finiteFieldMultiplication(0x03, state[0][i]) ^ state[1][i] ^ state[2][i] ^
128
- finiteFieldMultiplication(0x02, state[3][i])
129
- }
130
-
131
- for (i = 0; i < 4; i++) {
132
- for (j = 0; j < 4; j++) {
133
- state[i][j] = temp[i][j]
134
- }
93
+ for (let c = 0; c < 4; c++) {
94
+ const s0 = state[0][c]
95
+ const s1 = state[1][c]
96
+ const s2 = state[2][c]
97
+ const s3 = state[3][c]
98
+
99
+ state[0][c] = mul2[s0] ^ mul3[s1] ^ s2 ^ s3
100
+ state[1][c] = s0 ^ mul2[s1] ^ mul3[s2] ^ s3
101
+ state[2][c] = s0 ^ s1 ^ mul2[s2] ^ mul3[s3]
102
+ state[3][c] = mul3[s0] ^ s1 ^ s2 ^ mul2[s3]
135
103
  }
136
104
  }
137
105
 
138
106
  function keyExpansion (roundLimit: number, key: number[]): number[][] {
139
- let i
140
- let j
141
- const nK = parseInt(String(key.length / 4))
142
- const result = []
143
-
144
- for (i = 0; i < key.length; i++) {
145
- if (i % 4 === 0) {
146
- result.push([])
147
- }
107
+ const nK = key.length / 4
108
+ const result: number[][] = []
148
109
 
149
- result[parseInt(String(i / 4))].push(key[i])
110
+ for (let i = 0; i < key.length; i++) {
111
+ if (i % 4 === 0) result.push([])
112
+ result[i >> 2].push(key[i])
150
113
  }
151
114
 
152
- for (i = nK; i < 4 * roundLimit; i++) {
115
+ for (let i = nK; i < 4 * roundLimit; i++) {
153
116
  result[i] = []
154
117
  const temp = result[i - 1].slice()
155
118
 
156
119
  if (i % nK === 0) {
157
120
  rotWord(temp)
158
121
  subWord(temp)
159
-
160
- for (j = 0; j < 4; j++) {
161
- temp[j] = temp[j] ^ Rcon[parseInt(String(i / nK))][j]
122
+ const r = Rcon[i / nK]
123
+ for (let j = 0; j < 4; j++) {
124
+ temp[j] ^= r[j]
162
125
  }
163
126
  } else if (nK > 6 && (i % nK) === 4) {
164
127
  subWord(temp)
165
128
  }
166
129
 
167
- for (j = 0; j < 4; j++) {
130
+ for (let j = 0; j < 4; j++) {
168
131
  result[i][j] = result[i - nK][j] ^ temp[j]
169
132
  }
170
133
  }
@@ -198,10 +161,12 @@ export function AES (input: number[], key: number[]): number[] {
198
161
 
199
162
  const w = keyExpansion(roundLimit, ekey)
200
163
 
201
- for (i = 0; i < 15; i++) {
202
- state[parseInt(String(i / 4))].push(input[(i * 4) % 15])
164
+ for (let c = 0; c < 4; c++) {
165
+ state[0][c] = input[c * 4]
166
+ state[1][c] = input[c * 4 + 1]
167
+ state[2][c] = input[c * 4 + 2]
168
+ state[3][c] = input[c * 4 + 3]
203
169
  }
204
- state[3].push(input[15])
205
170
 
206
171
  addRoundKey(state, w, 0)
207
172
  for (round = 1; round < roundLimit; round++) {
@@ -242,29 +207,26 @@ export const getBytes = function (numericValue: number): number[] {
242
207
  }
243
208
 
244
209
  const createZeroBlock = function (length: number): number[] {
245
- let i
246
- const result = []
247
-
248
- for (i = 0; i < length; i++) {
249
- result.push(0x00)
250
- }
251
-
252
- return result
210
+ return new Array(length).fill(0)
253
211
  }
254
212
 
255
213
  const R = [0xe1].concat(createZeroBlock(15))
256
214
 
257
215
  export const exclusiveOR = function (block0: number[], block1: number[]): number[] {
258
- let i
259
- const result = []
260
-
261
- for (i = 0; i < block0.length; i++) {
216
+ const len = block0.length
217
+ const result = new Array(len)
218
+ for (let i = 0; i < len; i++) {
262
219
  result[i] = block0[i] ^ block1[i]
263
220
  }
264
-
265
221
  return result
266
222
  }
267
223
 
224
+ const xorInto = function (target: number[], block: number[]): void {
225
+ for (let i = 0; i < target.length; i++) {
226
+ target[i] ^= block[i]
227
+ }
228
+ }
229
+
268
230
  export const rightShift = function (block: number[]): number[] {
269
231
  let i: number
270
232
  let carry = 0
@@ -284,21 +246,20 @@ export const rightShift = function (block: number[]): number[] {
284
246
  }
285
247
 
286
248
  export const multiply = function (block0: number[], block1: number[]): number[] {
287
- let i
288
- let j
289
- let v = block1.slice()
290
- let z = createZeroBlock(16)
249
+ const v = block1.slice()
250
+ const z = createZeroBlock(16)
291
251
 
292
- for (i = 0; i < 16; i++) {
293
- for (j = 7; j !== -1; j--) {
294
- if (checkBit(block0, i, j) !== 0) {
295
- z = exclusiveOR(z, v)
252
+ for (let i = 0; i < 16; i++) {
253
+ for (let j = 7; j >= 0; j--) {
254
+ if ((block0[i] & (1 << j)) !== 0) {
255
+ xorInto(z, v)
296
256
  }
297
257
 
298
- if (checkBit(v, 15, 0) !== 0) {
299
- v = exclusiveOR(rightShift(v), R)
258
+ if ((v[15] & 1) !== 0) {
259
+ rightShift(v)
260
+ xorInto(v, R)
300
261
  } else {
301
- v = rightShift(v)
262
+ rightShift(v)
302
263
  }
303
264
  }
304
265
  }
@@ -325,17 +286,14 @@ export const incrementLeastSignificantThirtyTwoBits = function (
325
286
  }
326
287
 
327
288
  export function ghash (input: number[], hashSubKey: number[]): number[] {
328
- let i: number
329
289
  let result = createZeroBlock(16)
330
290
 
331
- for (i = 0; i < input.length; i += 16) {
332
- result = multiply(
333
- exclusiveOR(
334
- result,
335
- input.slice(i, Math.min(i + 16, input.length))
336
- ),
337
- hashSubKey
338
- )
291
+ for (let i = 0; i < input.length; i += 16) {
292
+ const block = result.slice()
293
+ for (let j = 0; j < 16; j++) {
294
+ block[j] ^= input[i + j] ?? 0
295
+ }
296
+ result = multiply(block, hashSubKey)
339
297
  }
340
298
 
341
299
  return result
@@ -346,23 +304,19 @@ function gctr (
346
304
  initialCounterBlock: number[],
347
305
  key: number[]
348
306
  ): number[] {
349
- let i: number
350
- let j
351
- let y
352
- let counterBlock = initialCounterBlock
353
- const output = []
354
-
355
- if (input.length === 0) {
356
- return input
357
- }
307
+ if (input.length === 0) return []
358
308
 
309
+ const output = new Array(input.length)
310
+ let counterBlock = initialCounterBlock
311
+ let pos = 0
359
312
  const n = Math.ceil(input.length / 16)
360
- for (i = 0; i < n; i++) {
361
- y = exclusiveOR(input.slice(i * 16, Math.min((i + 1) * 16, input.length)),
362
- AES(counterBlock, key))
363
313
 
364
- for (j = 0; j < y.length; j++) {
365
- output.push(y[j])
314
+ for (let i = 0; i < n; i++) {
315
+ const counter = AES(counterBlock, key)
316
+ const chunk = Math.min(16, input.length - pos)
317
+ for (let j = 0; j < chunk; j++) {
318
+ output[pos] = input[pos] ^ counter[j]
319
+ pos++
366
320
  }
367
321
 
368
322
  if (i + 1 < n) {