Skip to content

Commit a219dee

Browse files
committed
Refactor cipher algorithms for improved performance
- Updated the $add method in ChaCha20, Salsa20, XOR, and AES modes (CBC, CTR, ECB, GCM, IGE, OFB, PCBC) to enhance efficiency by reducing loop iterations and improving state management. - Introduced a _nextBlock method to streamline block processing across various cipher implementations. - Adjusted handling of input data to minimize redundant calculations and improve overall throughput.
1 parent 07902ad commit a219dee

15 files changed

Lines changed: 379 additions & 340 deletions

File tree

BENCHMARK.md

Lines changed: 101 additions & 112 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 110 additions & 106 deletions
Large diffs are not rendered by default.

benchmark/aes_cbc.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ class CryptographyBenchmark extends AsyncBenchmark {
7373
: crypto.AesCbc.with256bits(
7474
macAlgorithm: crypto.MacAlgorithm.empty,
7575
);
76-
instance.encrypt(
76+
await instance.encrypt(
7777
input,
7878
secretKey: crypto.SecretKey(key),
7979
nonce: iv,

benchmark/aes_ctr.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ class CryptographyBenchmark extends AsyncBenchmark {
7373
: crypto.AesCtr.with256bits(
7474
macAlgorithm: crypto.MacAlgorithm.empty,
7575
);
76-
instance.encrypt(
76+
await instance.encrypt(
7777
input,
7878
secretKey: crypto.SecretKey(key),
7979
nonce: iv,

benchmark/aes_gcm.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class CryptographyBenchmark extends AsyncBenchmark {
6767
: key.length == 24
6868
? crypto.AesGcm.with192bits(nonceLength: iv.length)
6969
: crypto.AesGcm.with256bits(nonceLength: iv.length);
70-
instance.encrypt(
70+
await instance.encrypt(
7171
input,
7272
secretKey: crypto.SecretKey(key),
7373
nonce: iv,

lib/src/algorithms/aes_modes/cbc.dart

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,14 @@ class AESInCBCModeEncryptSink extends CipherSink {
5252
var output = Uint8List(n);
5353

5454
p = 0;
55-
for (i = start; i < end; ++i) {
56-
_block[_pos] ^= data[i];
57-
_pos++;
55+
for (i = start; i < end;) {
56+
for (; _pos < 16 && i < end; ++_pos, ++i) {
57+
_block[_pos] ^= data[i];
58+
}
5859
if (_pos == 16) {
5960
AESCore.$encryptLE(_block32, _xkey32);
60-
for (j = 0; j < 16; ++j) {
61-
output[p++] = _block[j];
61+
for (j = 0; j < 16; ++j, ++p) {
62+
output[p] = _block[j];
6263
}
6364
_pos = 0;
6465
}
@@ -134,10 +135,13 @@ class AESInCBCModeDecryptSink extends CipherSink {
134135
var output = Uint8List(n);
135136

136137
p = 0;
137-
for (i = start; i < end; ++i) {
138-
_block[_pos] = data[i];
139-
_nextSalt[_pos] = _block[_pos];
140-
_pos++;
138+
for (i = start; i < end;) {
139+
while (_pos < 16 && i < end) {
140+
_block[_pos] = data[i];
141+
_nextSalt[_pos] = _block[_pos];
142+
_pos++;
143+
i++;
144+
}
141145
if (_pos == 16) {
142146
AESCore.$decryptLE(_block32, _xkey32);
143147
for (j = 0; j < 16; ++j) {

lib/src/algorithms/aes_modes/ctr.dart

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,24 @@ class AESInCTRModeSink extends CipherSink {
4848
_s1 = (_iv[4] << 24) | (_iv[5] << 16) | (_iv[6] << 8) | (_iv[7]);
4949
_s2 = (_iv[8] << 24) | (_iv[9] << 16) | (_iv[10] << 8) | (_iv[11]);
5050
_s3 = (_iv[12] << 24) | (_iv[13] << 16) | (_iv[14] << 8) | (_iv[15]);
51+
_process();
52+
}
53+
54+
@pragma('vm:prefer-inline')
55+
void _process() {
56+
_block32[0] = _s0;
57+
_block32[1] = _s1;
58+
_block32[2] = _s2;
59+
_block32[3] = _s3;
60+
AESCore.$encrypt(_block32, _xkey32);
61+
_block32[0] = _swap32(_block32[0]);
62+
_block32[1] = _swap32(_block32[1]);
63+
_block32[2] = _swap32(_block32[2]);
64+
_block32[3] = _swap32(_block32[3]);
65+
_s3 = (_s3 + 1) & _mask32;
66+
if (_s3 == 0) {
67+
_s2 = (_s2 + 1) & _mask32;
68+
}
5169
}
5270

5371
@override
@@ -57,24 +75,16 @@ class AESInCTRModeSink extends CipherSink {
5775
var output = Uint8List(end - start);
5876

5977
p = 0;
60-
for (i = start; i < end; ++i) {
61-
if (_pos == 0) {
62-
_block32[0] = _s0;
63-
_block32[1] = _s1;
64-
_block32[2] = _s2;
65-
_block32[3] = _s3;
66-
AESCore.$encrypt(_block32, _xkey32);
67-
_block32[0] = _swap32(_block32[0]);
68-
_block32[1] = _swap32(_block32[1]);
69-
_block32[2] = _swap32(_block32[2]);
70-
_block32[3] = _swap32(_block32[3]);
71-
_s3 = (_s3 + 1) & _mask32;
72-
if (_s3 == 0) {
73-
_s2 = (_s2 + 1) & _mask32;
74-
}
78+
for (i = start; i < end;) {
79+
while (_pos < 16 && i < end) {
80+
output[p++] = _block[_pos] ^ data[i];
81+
_pos++;
82+
i++;
83+
}
84+
if (_pos == 16) {
85+
_process();
86+
_pos = 0;
7587
}
76-
output[p++] = _block[_pos] ^ data[i];
77-
_pos = (_pos + 1) & 15;
7888
}
7989

8090
return output;

lib/src/algorithms/aes_modes/ecb.dart

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,14 @@ class AESInECBModeEncryptSink extends CipherSink {
4343
var output = Uint8List(n);
4444

4545
p = 0;
46-
for (i = start; i < end; ++i) {
47-
_block[_pos] = data[i];
48-
_pos++;
46+
for (i = start; i < end;) {
47+
for (; _pos < 16 && i < end; ++_pos, ++i) {
48+
_block[_pos] = data[i];
49+
}
4950
if (_pos == 16) {
5051
AESCore.$encryptLE(_block32, _xkey32);
51-
for (j = 0; j < 16; ++j) {
52-
output[p++] = _block[j];
52+
for (j = 0; j < 16; ++j, ++p) {
53+
output[p] = _block[j];
5354
}
5455
_pos = 0;
5556
}
@@ -58,8 +59,8 @@ class AESInECBModeEncryptSink extends CipherSink {
5859
if (closed) {
5960
if (_padding.pad(_block, _pos)) {
6061
AESCore.$encryptLE(_block32, _xkey32);
61-
for (j = 0; j < 16; ++j) {
62-
output[p++] = _block[j];
62+
for (j = 0; j < 16; ++j, ++p) {
63+
output[p] = _block[j];
6364
}
6465
_pos = 0;
6566
}
@@ -111,19 +112,20 @@ class AESInECBModeDecryptSink extends CipherSink {
111112
p = 0;
112113
n = _rpos + end - start;
113114
var output = Uint8List(n);
114-
for (i = start; i < end; ++i) {
115-
_block[_pos] = data[i];
116-
_pos++;
115+
for (i = start; i < end;) {
116+
for (; _pos < 16 && i < end; ++_pos, ++i) {
117+
_block[_pos] = data[i];
118+
}
117119
if (_pos == 16) {
118120
AESCore.$decryptLE(_block32, _xkey32);
119-
for (j = 0; j < 16; ++j) {
121+
for (j = 0; j < 16; ++j, ++_rpos) {
120122
if (_rpos == 16) {
121-
for (k = 0; k < 16; ++k) {
122-
output[p++] = _residue[k];
123+
for (k = 0; k < 16; ++k, ++p) {
124+
output[p] = _residue[k];
123125
}
124126
_rpos = 0;
125127
}
126-
_residue[_rpos++] = _block[j];
128+
_residue[_rpos] = _block[j];
127129
}
128130
_pos = 0;
129131
}

lib/src/algorithms/aes_modes/gcm.dart

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,13 @@ abstract class _AESInGCMModeSinkBase extends CipherSink {
8181

8282
@override
8383
void reset() {
84+
super.reset();
8485
int i, n;
8586

8687
_pos = 0;
8788
_rpos = 0;
8889
_aadLength = 0;
8990
_msgLength = 0;
90-
super.reset();
9191

9292
// GHASH init
9393
for (i = 0; i < 16; ++i) {
@@ -150,8 +150,11 @@ abstract class _AESInGCMModeSinkBase extends CipherSink {
150150
_aadLength += n;
151151
}
152152
}
153+
154+
_nextBlock();
153155
}
154156

157+
@pragma('vm:prefer-inline')
155158
void _nextBlock() {
156159
int i;
157160
for (i = 15; i >= 12; i--) {
@@ -164,6 +167,7 @@ abstract class _AESInGCMModeSinkBase extends CipherSink {
164167
AESCore.$encryptLE(_block32, _xkey32);
165168
}
166169

170+
@pragma('vm:prefer-inline')
167171
void _serialize64(int a, int b) {
168172
a <<= 3;
169173
b <<= 3;
@@ -219,7 +223,7 @@ abstract class _AESInGCMModeSinkBase extends CipherSink {
219223
t3 = 0;
220224
for (x in _tag32) {
221225
for (i = 0; i < 32; i++) {
222-
if (x & _pow2[i] != 0) {
226+
if ((x & _pow2[i]) != 0) {
223227
t0 ^= _hcache32[p++];
224228
t1 ^= _hcache32[p++];
225229
t2 ^= _hcache32[p++];
@@ -267,15 +271,14 @@ class AESInGCMModeEncryptSink extends _AESInGCMModeSinkBase {
267271
if (closed) n += _tagSize;
268272
var output = Uint8List(n);
269273
p = 0;
270-
for (i = start; i < end; ++i) {
271-
if (_pos == 0) {
272-
_nextBlock();
274+
for (i = start; i < end;) {
275+
for (; _pos < 16 && i < end; ++_pos, ++i, ++p) {
276+
output[p] = _block[_pos] ^ data[i];
277+
_tag[_pos] ^= output[p];
273278
}
274-
output[p] = _block[_pos] ^ data[i];
275-
_tag[_pos] ^= output[p++];
276-
_pos++;
277279
if (_pos == 16) {
278280
_multiply128();
281+
_nextBlock();
279282
_pos = 0;
280283
}
281284
}
@@ -324,14 +327,12 @@ class AESInGCMModeDecryptSink extends _AESInGCMModeSinkBase {
324327
p = 0;
325328
for (i = start; i < end; ++i) {
326329
if (_msgLength >= _tagSize) {
327-
if (_pos == 0) {
328-
_nextBlock();
329-
}
330330
output[p++] = _block[_pos] ^ _residue[_rpos];
331331
_tag[_pos] ^= _residue[_rpos];
332332
_pos++;
333333
if (_pos == 16) {
334334
_multiply128();
335+
_nextBlock();
335336
_pos = 0;
336337
}
337338
}

lib/src/algorithms/aes_modes/ige.dart

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,17 @@ class AESInIGEModeEncryptSink extends CipherSink {
5757
var output = Uint8List(n);
5858

5959
p = 0;
60-
for (i = start; i < end; ++i) {
61-
_salt[_pos + 16] = data[i];
62-
_block[_pos++] ^= data[i];
60+
for (i = start; i < end;) {
61+
for (; _pos < 16 && i < end; ++_pos, ++i) {
62+
_salt[_pos + 16] = data[i];
63+
_block[_pos] ^= data[i];
64+
}
6365
if (_pos == 16) {
6466
AESCore.$encryptLE(_block32, _xkey32);
65-
for (j = 0; j < 16; ++j) {
67+
for (j = 0; j < 16; ++j, ++p) {
6668
_block[j] ^= _salt[j];
6769
_salt[j] = _salt[j + 16];
68-
output[p++] = _block[j];
70+
output[p] = _block[j];
6971
}
7072
_pos = 0;
7173
}
@@ -77,8 +79,8 @@ class AESInIGEModeEncryptSink extends CipherSink {
7779
_block[_pos] ^= _salt[_pos + 16];
7880
}
7981
AESCore.$encryptLE(_block32, _xkey32);
80-
for (j = 0; j < 16; ++j) {
81-
output[p++] = _block[j] ^ _salt[j];
82+
for (j = 0; j < 16; ++j, ++p) {
83+
output[p] = _block[j] ^ _salt[j];
8284
}
8385
_pos = 0;
8486
}
@@ -143,30 +145,32 @@ class AESInIGEModeDecryptSink extends CipherSink {
143145
var output = Uint8List(n);
144146

145147
p = 0;
146-
for (i = start; i < end; ++i) {
147-
_salt[_pos + 16] = data[i];
148-
_block[_pos++] ^= data[i];
148+
for (i = start; i < end;) {
149+
for (; _pos < 16 && i < end; ++_pos, ++i) {
150+
_salt[_pos + 16] = data[i];
151+
_block[_pos] ^= data[i];
152+
}
149153
if (_pos == 16) {
150154
AESCore.$decryptLE(_block32, _xkey32);
151-
for (j = 0; j < 16; ++j) {
155+
for (j = 0; j < 16; ++j, ++_rpos) {
152156
if (_rpos == 16) {
153-
for (k = 0; k < 16; ++k) {
154-
output[p++] = _residue[k];
157+
for (k = 0; k < 16; ++k, ++p) {
158+
output[p] = _residue[k];
155159
}
156160
_rpos = 0;
157161
}
158162
_block[j] ^= _salt[j];
159163
_salt[j] = _salt[j + 16];
160-
_residue[_rpos++] = _block[j];
164+
_residue[_rpos] = _block[j];
161165
}
162166
_pos = 0;
163167
}
164168
}
165169

166170
if (closed) {
167171
if (_rpos == 16) {
168-
for (k = 0; k < 16; ++k) {
169-
output[p++] = _residue[k];
172+
for (k = 0; k < 16; ++k, ++p) {
173+
output[p] = _residue[k];
170174
}
171175
_rpos = 0;
172176
}

0 commit comments

Comments
 (0)