@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.
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/src/primitives/AESGCM.js +113 -137
- package/dist/cjs/src/primitives/AESGCM.js.map +1 -1
- package/dist/cjs/src/primitives/BigNumber.js +1019 -3947
- package/dist/cjs/src/primitives/BigNumber.js.map +1 -1
- package/dist/cjs/src/primitives/K256.js +53 -37
- package/dist/cjs/src/primitives/K256.js.map +1 -1
- package/dist/cjs/src/primitives/Mersenne.js +16 -21
- package/dist/cjs/src/primitives/Mersenne.js.map +1 -1
- package/dist/cjs/src/primitives/MontgomoryMethod.js.map +1 -1
- package/dist/cjs/src/primitives/utils.js +27 -17
- package/dist/cjs/src/primitives/utils.js.map +1 -1
- package/dist/cjs/src/script/Spend.js +618 -858
- package/dist/cjs/src/script/Spend.js.map +1 -1
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/src/primitives/AESGCM.js +112 -137
- package/dist/esm/src/primitives/AESGCM.js.map +1 -1
- package/dist/esm/src/primitives/BigNumber.js +1011 -3969
- package/dist/esm/src/primitives/BigNumber.js.map +1 -1
- package/dist/esm/src/primitives/K256.js +53 -37
- package/dist/esm/src/primitives/K256.js.map +1 -1
- package/dist/esm/src/primitives/Mersenne.js +16 -21
- package/dist/esm/src/primitives/Mersenne.js.map +1 -1
- package/dist/esm/src/primitives/MontgomoryMethod.js.map +1 -1
- package/dist/esm/src/primitives/utils.js +29 -17
- package/dist/esm/src/primitives/utils.js.map +1 -1
- package/dist/esm/src/script/Spend.js +618 -857
- package/dist/esm/src/script/Spend.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/types/src/primitives/AESGCM.d.ts.map +1 -1
- package/dist/types/src/primitives/BigNumber.d.ts +238 -1705
- package/dist/types/src/primitives/BigNumber.d.ts.map +1 -1
- package/dist/types/src/primitives/K256.d.ts.map +1 -1
- package/dist/types/src/primitives/Mersenne.d.ts +2 -2
- package/dist/types/src/primitives/Mersenne.d.ts.map +1 -1
- package/dist/types/src/primitives/utils.d.ts +2 -0
- package/dist/types/src/primitives/utils.d.ts.map +1 -1
- package/dist/types/src/script/Spend.d.ts +11 -1
- package/dist/types/src/script/Spend.d.ts.map +1 -1
- package/dist/types/tsconfig.types.tsbuildinfo +1 -1
- package/dist/umd/bundle.js +1 -1
- package/docs/performance.md +70 -0
- package/docs/primitives.md +262 -3049
- package/package.json +1 -1
- package/src/auth/__tests/Peer.test.ts +38 -23
- package/src/auth/certificates/__tests/MasterCertificate.test.ts +27 -20
- package/src/auth/certificates/__tests/VerifiableCertificate.test.ts +24 -24
- package/src/primitives/AESGCM.ts +118 -164
- package/src/primitives/BigNumber.ts +867 -4180
- package/src/primitives/K256.ts +57 -37
- package/src/primitives/Mersenne.ts +16 -20
- package/src/primitives/MontgomoryMethod.ts +2 -2
- package/src/primitives/__tests/ReductionContext.test.ts +6 -1
- package/src/primitives/utils.ts +28 -17
- package/src/script/Spend.ts +634 -1309
- package/src/transaction/__tests/Transaction.test.ts +14 -16
- package/src/transaction/__tests/Transaction.benchmarks.test.ts +0 -237
package/package.json
CHANGED
|
@@ -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 =
|
|
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(
|
|
202
|
-
walletB = new CompletedProtoWallet(
|
|
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 =
|
|
255
|
+
const aliceKey = alicePrivKey
|
|
239
256
|
const walletA1 = new CompletedProtoWallet(aliceKey)
|
|
240
257
|
const walletA2 = new CompletedProtoWallet(aliceKey)
|
|
241
|
-
const walletB = new CompletedProtoWallet(
|
|
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
|
-
|
|
268
|
-
aliceFirstDevice
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
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
|
-
|
|
292
|
-
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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(
|
|
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
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
)
|
package/src/primitives/AESGCM.ts
CHANGED
|
@@ -1,53 +1,61 @@
|
|
|
1
1
|
|
|
2
2
|
// @ts-nocheck
|
|
3
|
-
const SBox = [
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
|
39
|
-
|
|
40
|
-
|
|
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
|
-
|
|
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
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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
|
-
|
|
140
|
-
|
|
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
|
-
|
|
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]
|
|
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 (
|
|
202
|
-
state[
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
288
|
-
|
|
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
|
|
294
|
-
if (
|
|
295
|
-
|
|
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 (
|
|
299
|
-
|
|
258
|
+
if ((v[15] & 1) !== 0) {
|
|
259
|
+
rightShift(v)
|
|
260
|
+
xorInto(v, R)
|
|
300
261
|
} else {
|
|
301
|
-
|
|
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
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
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
|
-
|
|
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
|
-
|
|
365
|
-
|
|
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) {
|