Skip to content

Commit 91ec549

Browse files
committed
Adds more tests to increase coverage
1 parent 7c34242 commit 91ec549

34 files changed

+1216
-122
lines changed

.github/workflows/test.yml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ jobs:
2424
with:
2525
sdk: ${{ matrix.sdk }}
2626

27+
- name: 'Install global packages'
28+
run: |
29+
dart pub global activate coverage
30+
dart pub global activate cobertura
31+
2732
- name: Run tests with coverage
2833
run: bash ./scripts/coverage.sh
2934

@@ -33,7 +38,6 @@ jobs:
3338
token: ${{ secrets.CODECOV_TOKEN }}
3439

3540
test-on-stable:
36-
if: github.repository == 'bitanon/cipherlib'
3741
strategy:
3842
matrix:
3943
os: [ubuntu-latest, macos-latest, windows-latest]
@@ -59,10 +63,9 @@ jobs:
5963
run: dart test
6064

6165
test-on-legacy:
62-
if: github.repository == 'bitanon/cipherlib'
6366
strategy:
6467
matrix:
65-
os: [ubuntu-latest, macos-latest, windows-latest]
68+
os: [ubuntu-latest, windows-latest]
6669
sdk: ['2.14.0']
6770
runs-on: ${{ matrix.os }}
6871
steps:
@@ -76,7 +79,6 @@ jobs:
7679
run: dart test
7780

7881
test-on-beta:
79-
if: github.repository == 'bitanon/cipherlib'
8082
strategy:
8183
matrix:
8284
os: [ubuntu-latest]

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# cipherlib
22

3+
[![plugin version](https://img.shields.io/pub/v/cipherlib?label=pub)](https://pub.dev/packages/cipherlib)
34
[![test](https://github.com/bitanon/cipherlib/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/bitanon/cipherlib/actions/workflows/test.yml)
45
[![codecov](https://codecov.io/gh/bitanon/cipherlib/graph/badge.svg?token=ISIYJ8MNI0)](https://codecov.io/gh/bitanon/cipherlib)
5-
[![plugin version](https://img.shields.io/pub/v/cipherlib?label=pub)](https://pub.dev/packages/cipherlib)
66
[![dart support](https://img.shields.io/badge/dart-%3e%3d%202.14.0-39f?logo=dart)](https://dart.dev/guides/whats-new#september-8-2021-214-release)
77
[![likes](https://img.shields.io/pub/likes/cipherlib?logo=dart)](https://pub.dev/packages/cipherlib/score)
88
[![pub points](https://img.shields.io/pub/points/cipherlib?logo=dart&color=teal)](https://pub.dev/packages/cipherlib/score)

lib/src/algorithms/aes/cfb.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ class AESInCFBModeDecryptSink extends CipherSink {
158158
/// Provides encryption for AES cipher in CFB mode.
159159
class AESInCFBModeEncrypt extends SaltedCipher {
160160
@override
161-
String get name => "AES#encrypt/CFB";
161+
String get name => "AES#encrypt/CFB/${Padding.none.name}";
162162

163163
/// Key for the cipher
164164
final Uint8List key;
@@ -181,7 +181,7 @@ class AESInCFBModeEncrypt extends SaltedCipher {
181181
/// Provides decryption for AES cipher in CFB mode.
182182
class AESInCFBModeDecrypt extends SaltedCipher {
183183
@override
184-
String get name => "AES#decrypt/CFB";
184+
String get name => "AES#decrypt/CFB/${Padding.none.name}";
185185

186186
/// Key for the cipher
187187
final Uint8List key;

lib/src/algorithms/aes/ctr.dart

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ class AESInCTRModeSink extends CipherSink {
9797
/// Provides AES cipher in CTR mode.
9898
class AESInCTRModeCipher extends SaltedCipher {
9999
@override
100-
final String name = "AES/CTR";
100+
String get name => "AES#cipher/CTR/${Padding.none.name}";
101101

102102
/// Key for the cipher
103103
final Uint8List key;
@@ -140,9 +140,10 @@ class AESInCTRMode extends SaltedCollateCipher {
140140
}
141141
var iv8 = iv is Uint8List ? iv : Uint8List.fromList(iv);
142142
var key8 = key is Uint8List ? key : Uint8List.fromList(key);
143+
var cipher = AESInCTRModeCipher(key8, iv8);
143144
return AESInCTRMode._(
144-
encryptor: AESInCTRModeCipher(key8, iv8),
145-
decryptor: AESInCTRModeCipher(key8, iv8),
145+
encryptor: cipher,
146+
decryptor: cipher,
146147
);
147148
}
148149

lib/src/algorithms/aes/gcm.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ class AESInGCMModeDecryptSink extends _AESInGCMModeSinkBase {
398398
/// Provides AES cipher in GCM mode for encryption.
399399
class AESInGCMModeEncrypt extends SaltedCipher {
400400
@override
401-
final String name = "AES#encrypt/GCM";
401+
String get name => "AES#encrypt/GCM/${Padding.none.name}";
402402

403403
/// Key for the cipher
404404
final Uint8List key;
@@ -425,7 +425,7 @@ class AESInGCMModeEncrypt extends SaltedCipher {
425425
/// Provides AES cipher in GCM mode for decryption.
426426
class AESInGCMModeDecrypt extends SaltedCipher {
427427
@override
428-
final String name = "AES#decrypt/GCM";
428+
String get name => "AES#decrypt/GCM/${Padding.none.name}";
429429

430430
/// Key for the cipher
431431
final Uint8List key;

lib/src/algorithms/aes/ofb.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ class AESInOFBModeSink extends CipherSink {
8686
/// Provides encryption for AES cipher in OFB mode.
8787
class AESInOFBModeCipher extends SaltedCipher {
8888
@override
89-
final String name = "AES#cipher/OFB";
89+
String get name => "AES#cipher/OFB/${Padding.none.name}";
9090

9191
/// Key for the cipher
9292
final Uint8List key;

lib/src/algorithms/aes/xts.dart

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import 'dart:typed_data';
55

6+
import 'package:cipherlib/cipherlib.dart';
67
import 'package:cipherlib/src/core/cipher_sink.dart';
78
import 'package:cipherlib/src/core/salted_cipher.dart';
89
import 'package:cipherlib/src/utils/nonce.dart';
@@ -327,7 +328,7 @@ class AESInXTSModeDecryptSink extends CipherSink {
327328
/// Provides encryption for AES cipher in XTS mode.
328329
class AESInXTSModeEncrypt extends SaltedCipher {
329330
@override
330-
String get name => "AES#encrypt/XTS";
331+
String get name => "AES#encrypt/XTS/${Padding.none.name}";
331332

332333
/// Key for the plaintext encryption
333334
final Uint8List ekey;
@@ -350,7 +351,7 @@ class AESInXTSModeEncrypt extends SaltedCipher {
350351
/// Provides decryption for AES cipher in XTS mode.
351352
class AESInXTSModeDecrypt extends SaltedCipher {
352353
@override
353-
String get name => "AES#decrypt/XTS";
354+
String get name => "AES#decrypt/XTS/${Padding.none.name}";
354355

355356
/// Key for the ciphertext decryption
356357
final Uint8List ekey;
@@ -373,7 +374,7 @@ class AESInXTSModeDecrypt extends SaltedCipher {
373374
/// Provides encryption and decryption for AES cipher in XTS mode.
374375
class AESInXTSMode extends SaltedCollateCipher {
375376
@override
376-
String get name => "AES/XTS";
377+
String get name => "AES/XTS/${Padding.none.name}";
377378

378379
@override
379380
final AESInXTSModeEncrypt encryptor;

lib/src/algorithms/chacha20.dart

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,11 @@ class ChaCha20Sink extends CipherSink {
1919
if (_nonce.length != 8 && _nonce.length != 12) {
2020
throw ArgumentError('The nonce should be either 8 or 12 bytes');
2121
}
22-
if (_counter.length != 4 && _counter.length != 8) {
23-
throw ArgumentError('The counter should be either 4 or 8 bytes');
22+
if (_nonce.length == 8 && _counter.length < 8) {
23+
throw ArgumentError('The counter should be 8 bytes');
24+
}
25+
if (_nonce.length == 12 && _counter.length < 4) {
26+
throw ArgumentError('The counter should be 4 bytes');
2427
}
2528
_counterSize = _nonce.length == 8 ? 8 : 4;
2629
reset();
@@ -257,9 +260,10 @@ class ChaCha20 extends SaltedCipher {
257260
}) {
258261
nonce ??= randomBytes(8);
259262
counter ??= Nonce64.int64(1);
263+
var counter8 = counter.bytes;
260264
var key8 = key is Uint8List ? key : Uint8List.fromList(key);
261265
var nonce8 = nonce is Uint8List ? nonce : Uint8List.fromList(nonce);
262-
return ChaCha20(key8, nonce8, counter.bytes);
266+
return ChaCha20(key8, nonce8, counter8);
263267
}
264268

265269
@override

lib/src/algorithms/padding.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ class _BytePadding extends Padding {
209209

210210
class _ANSIPadding extends Padding {
211211
@override
212-
final String name = "ANSI-X9.23";
212+
final String name = "ANSI";
213213

214214
const _ANSIPadding();
215215

@@ -248,7 +248,7 @@ class _ANSIPadding extends Padding {
248248

249249
class _PKCS7Padding extends Padding {
250250
@override
251-
final String name = "PKCS#7";
251+
final String name = "PKCS7";
252252

253253
const _PKCS7Padding();
254254

@@ -286,7 +286,7 @@ class _PKCS7Padding extends Padding {
286286

287287
class _PKCS5Padding extends Padding {
288288
@override
289-
final String name = "PKCS#5";
289+
final String name = "PKCS5";
290290

291291
const _PKCS5Padding();
292292

lib/src/algorithms/salsa20.dart

Lines changed: 52 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,35 @@ import 'dart:typed_data';
55

66
import 'package:cipherlib/src/core/cipher_sink.dart';
77
import 'package:cipherlib/src/core/salted_cipher.dart';
8+
import 'package:cipherlib/src/utils/nonce.dart';
9+
import 'package:hashlib/hashlib.dart' show randomBytes;
810

911
const int _mask32 = 0xFFFFFFFF;
1012

1113
/// This sink is used by the [Salsa20] algorithm.
1214
class Salsa20Sink extends CipherSink {
13-
Salsa20Sink(this._key, this._iv, this._counterStart) {
15+
Salsa20Sink(this._key, this._nonce, this._counter) {
1416
if (_key.length != 16 && _key.length != 32) {
1517
throw ArgumentError('The key should be either 16 or 32 bytes');
1618
}
17-
if (_iv.length != 8 && _iv.length != 16) {
19+
if (_nonce.length != 8 && _nonce.length != 16) {
1820
throw ArgumentError('The nonce should be either 8 or 16 bytes');
1921
}
22+
_needCounter = _nonce.length == 8;
23+
if (_needCounter && _counter.length < 8) {
24+
throw ArgumentError('The counter should be 8 bytes');
25+
}
2026
reset();
2127
}
2228

2329
int _pos = 0;
24-
int _counter = 0;
2530
bool _closed = false;
2631
final Uint8List _key;
27-
final Uint8List _iv;
28-
final int _counterStart;
32+
final Uint8List _nonce;
33+
final Uint8List _counter;
34+
final _iv = Uint8List(16);
2935
final _state = Uint32List(16);
36+
late final bool _needCounter;
3037
late final _state8 = _state.buffer.asUint8List();
3138
late final _key32 = _key.buffer.asUint32List();
3239
late final _iv32 = _iv.buffer.asUint32List();
@@ -38,8 +45,16 @@ class Salsa20Sink extends CipherSink {
3845
void reset() {
3946
_pos = 0;
4047
_closed = false;
41-
_counter = _counterStart;
42-
_block(_state, _key32, _iv32, _counter++);
48+
for (int i = 0; i < _nonce.length; ++i) {
49+
_iv[i] = _nonce[i];
50+
}
51+
if (_needCounter) {
52+
for (int i = 8; i < 16; ++i) {
53+
_iv[i] = _counter[i - 8];
54+
}
55+
}
56+
_block(_state, _key32, _iv32);
57+
_increment();
4358
}
4459

4560
@override
@@ -58,19 +73,28 @@ class Salsa20Sink extends CipherSink {
5873
var result = Uint8List(end - start);
5974
for (int i = start; i < end; i++) {
6075
if (_pos == 64) {
61-
_block(_state, _key32, _iv32, _counter++);
76+
_block(_state, _key32, _iv32);
77+
_increment();
6278
_pos = 0;
6379
}
6480
result[i] = data[i] ^ _state8[_pos++];
6581
}
6682
return result;
6783
}
6884

85+
void _increment() {
86+
if (_needCounter) {
87+
for (int i = 8; i < 16; ++i) {
88+
if ((++_iv[i]) != 0) return;
89+
}
90+
}
91+
}
92+
6993
@pragma('vm:prefer-inline')
7094
static int _rotl32(int x, int n) =>
7195
(((x << n) & _mask32) ^ ((x & _mask32) >>> (32 - n)));
7296

73-
static void _block(Uint32List B, Uint32List K, Uint32List N, int counter) {
97+
static void _block(Uint32List B, Uint32List K, Uint32List N) {
7498
int i, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15;
7599

76100
// init state
@@ -81,7 +105,6 @@ class Salsa20Sink extends CipherSink {
81105
s3 = B[3] = K[2];
82106
s4 = B[4] = K[3];
83107
s5 = B[5] = 0x3120646e; // 'nd 1'
84-
// 6..9 : nonce
85108
s10 = B[10] = 0x79622d36; // '6-by'
86109
s11 = B[11] = K[0];
87110
s12 = B[12] = K[1];
@@ -95,26 +118,17 @@ class Salsa20Sink extends CipherSink {
95118
s3 = B[3] = K[2];
96119
s4 = B[4] = K[3];
97120
s5 = B[5] = 0x3320646e; // 'nd 3'
98-
// 6..9 : nonce
99121
s10 = B[10] = 0x79622d32; // '2-by'
100122
s11 = B[11] = K[4];
101123
s12 = B[12] = K[5];
102124
s13 = B[13] = K[6];
103125
s14 = B[14] = K[7];
104126
s15 = B[15] = 0x6b206574; // 'te k'
105127
}
106-
// 6..9 : nonce
107-
if (N.lengthInBytes == 8) {
108-
s6 = B[6] = N[0];
109-
s7 = B[7] = N[1];
110-
s8 = B[8] = counter;
111-
s9 = B[9] = counter >>> 32;
112-
} else {
113-
s6 = B[6] = N[0];
114-
s7 = B[7] = N[1];
115-
s8 = B[8] = N[2];
116-
s9 = B[9] = N[3];
117-
}
128+
s6 = B[6] = N[0];
129+
s7 = B[7] = N[1];
130+
s8 = B[8] = N[2];
131+
s9 = B[9] = N[3];
118132

119133
// 10 row(column) rounds
120134
for (i = 0; i < 10; i++) {
@@ -197,27 +211,29 @@ class Salsa20 extends SaltedCipher {
197211
final Uint8List key;
198212

199213
/// The initial block id
200-
final int counter;
214+
final Uint8List counter;
201215

202216
const Salsa20(
203217
this.key,
204-
Uint8List iv, [
205-
this.counter = 0,
206-
]) : super(iv);
218+
Uint8List nonce,
219+
this.counter,
220+
) : super(nonce);
207221

208222
/// Creates a [Salsa20] with List<int> [key], and [nonce].
209223
///
210224
/// Every elements of the both list is transformed to unsigned 8-bit numbers.
211225
factory Salsa20.fromList(
212-
List<int> key,
213-
List<int> nonce, [
214-
int counter = 0,
215-
]) =>
216-
Salsa20(
217-
key is Uint8List ? key : Uint8List.fromList(key),
218-
nonce is Uint8List ? nonce : Uint8List.fromList(nonce),
219-
counter,
220-
);
226+
List<int> key, {
227+
List<int>? nonce,
228+
Nonce64? counter,
229+
}) {
230+
nonce ??= randomBytes(16);
231+
counter ??= Nonce64.zero();
232+
var counter8 = counter.bytes;
233+
var key8 = key is Uint8List ? key : Uint8List.fromList(key);
234+
var nonce8 = nonce is Uint8List ? nonce : Uint8List.fromList(nonce);
235+
return Salsa20(key8, nonce8, counter8);
236+
}
221237

222238
@override
223239
@pragma('vm:prefer-inline')

0 commit comments

Comments
 (0)