Skip to content

Commit

Permalink
fix .fromLength() to be cryptographically secure, as I am sure any us…
Browse files Browse the repository at this point in the history
…er would assume. fixes #246 (#266)

* remove IV from fernet example, it is not used for fernet (and was not used in the example)

* fix fromLength() to be secure, add allZerosOfLength() for use where uniform 0's where needed

* added docs to IV and Key object

* added docs on primary contructors also
  • Loading branch information
timmaffett authored Apr 5, 2022
1 parent de35eef commit 3a42d25
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 14 deletions.
55 changes: 54 additions & 1 deletion lib/src/encrypted.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ part of encrypt;

/// Represents an encripted value.
class Encrypted {

/// Creates an Encrypted object from a Uint8List.
Encrypted(this._bytes);

final Uint8List _bytes;
Expand All @@ -21,7 +23,18 @@ class Encrypted {
: _bytes = Uint8List.fromList(convert.utf8.encode(input));

/// Creates an Encrypted object from a length.
Encrypted.fromLength(int length) : _bytes = Uint8List(length);
/// The key is filled with [length] bytes generated by a
/// Random.secure() generator
Encrypted.fromLength(int length) : _bytes = SecureRandom(length).bytes;

/// Creates an Encrypted object from a length.
/// The key is filled with [length] bytes generated by a
/// Random.secure() generator
Encrypted.fromSecureRandom(int length) : _bytes = SecureRandom(length).bytes;

/// Creates an Encrypted object of ALL ZEROS from a length.
/// The key is ALL ZEROS - NOT CRYPTOGRAPHICALLY SECURE!
Encrypted.allZerosOfLength(int length) : _bytes = Uint8List(length);

/// Gets the Encrypted bytes.
Uint8List get bytes => _bytes;
Expand All @@ -45,23 +58,63 @@ class Encrypted {

/// Represents an Initialization Vector.
class IV extends Encrypted {

/// Creates an Initialization Vector object from a Uint8List.
IV(Uint8List bytes) : super(bytes);

/// Creates an Initialization Vector object from a hexdecimal string.
IV.fromBase16(String encoded) : super.fromBase16(encoded);

/// Creates an Initialization Vector object from a Base64 string.
IV.fromBase64(String encoded) : super.fromBase64(encoded);

/// Creates an Initialization Vector object from a UTF-8 string.
IV.fromUtf8(String input) : super.fromUtf8(input);

/// Creates an Initialization Vector object from a length.
/// The key is filled with [length] bytes generated by a
/// Random.secure() generator
IV.fromLength(int length) : super.fromLength(length);

/// Creates an Initialization Vector object from a length.
/// The key is filled with [length] bytes generated by a
/// Random.secure() generator
IV.fromSecureRandom(int length) : super(SecureRandom(length).bytes);

/// Creates an Initialization Vector object of ALL ZEROS from a length.
/// The key is ALL ZEROS - NOT CRYPTOGRAPHICALLY SECURE!
IV.allZerosOfLength(int length) : super.allZerosOfLength(length);
}

/// Represents an Encryption Key.
class Key extends Encrypted {

/// Creates an Encryption Key object from a Uint8List.
Key(Uint8List bytes) : super(bytes);

/// Creates an Encryption Key object from a hexdecimal string.
Key.fromBase16(String encoded) : super.fromBase16(encoded);

/// Creates an Encryption Key object from a Base64 string.
Key.fromBase64(String encoded) : super.fromBase64(encoded);

/// Creates an Encryption Key object from a UTF-8 string.
Key.fromUtf8(String input) : super.fromUtf8(input);

/// Creates an Encryption Key object from a length.
/// The key is filled with [length] bytes generated by a
/// Random.secure() generator
Key.fromLength(int length) : super.fromLength(length);

/// Creates an Encryption Key object from a length.
/// The key is filled with [length] bytes generated by a
/// Random.secure() generator
Key.fromSecureRandom(int length) : super(SecureRandom(length).bytes);

/// Creates an Encryption Key object of ALL ZEROS from a length.
/// The key is ALL ZEROS - NOT CRYPTOGRAPHICALLY SECURE!
Key.allZerosOfLength(int length) : super.allZerosOfLength(length);

Key stretch(int desiredKeyLength,
{int iterationCount = 100, Uint8List? salt}) {
if (salt == null) {
Expand Down
4 changes: 2 additions & 2 deletions test/battle_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ void main() {
group('Battle test', () {
test('Emoji', () {
const encoded = 'iPC4DII05qnIJsFm6/RUp6OQEnvLSTq1pW+4/cjHf4c=';
final encrypter = Encrypter(AES(Key.fromLength(32)));
final encrypter = Encrypter(AES(Key.allZerosOfLength(32)));

expect(
Encrypted.fromBase64(encoded),
equals(
encrypter.encrypt('Text to encrypt 😀', iv: IV.fromLength(16))));
encrypter.encrypt('Text to encrypt 😀', iv: IV.allZerosOfLength(16))));
});
});
}
18 changes: 9 additions & 9 deletions test/encrypt_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ void main() {
final encrypter = Encrypter(fernet);
final encrypted = Encrypted.fromBase64(
'gAAAAABdSZ/GAAAAAAAAAAAAAAAAAAAAACxNe+/PVLJMTKmBdPrlHat3Bj32TYdt1EKCz2jlJykTrwtMgSuZdLGXAIkmResqHLA5g0k7kzOCdHe02noK7YmV75oA2sLjSTE1zao/jtEdEB/aebAOYKQW8ZEm33oyXA==');
final iv = IV.fromLength(16);
final iv = IV.allZerosOfLength(16);

test('encrypt', () {
expect(encrypter.encrypt(text, iv: iv), equals(encrypted));
Expand Down Expand Up @@ -59,12 +59,12 @@ void main() {
final encrypted = Encrypted(base64.decode(encoded));

test('encrypt', () {
expect(encrypter.encrypt(text, iv: IV.fromLength(16)),
expect(encrypter.encrypt(text, iv: IV.allZerosOfLength(16)),
equals(encrypted));
});

test('decrypt', () {
expect(encrypter.decrypt(encrypted, iv: IV.fromLength(16)),
expect(encrypter.decrypt(encrypted, iv: IV.allZerosOfLength(16)),
equals(text));
});
});
Expand All @@ -89,12 +89,12 @@ void main() {
final encrypted = Encrypted(base64.decode(encoded));

test('encrypt', () {
expect(encrypter.encrypt(text.padRight(64), iv: IV.fromLength(16)),
expect(encrypter.encrypt(text.padRight(64), iv: IV.allZerosOfLength(16)),
equals(encrypted));
});

test('decrypt', () {
expect(encrypter.decrypt(encrypted, iv: IV.fromLength(16)),
expect(encrypter.decrypt(encrypted, iv: IV.allZerosOfLength(16)),
equals(text.padRight(64)));
});
});
Expand All @@ -112,12 +112,12 @@ void main() {
final encrypted = Encrypted(base64.decode(encoded));

test('encrypt', () {
expect(encrypter.encrypt(text, iv: IV.fromLength(16)),
expect(encrypter.encrypt(text, iv: IV.allZerosOfLength(16)),
equals(encrypted));
});

test('decrypt', () {
expect(encrypter.decrypt(encrypted, iv: IV.fromLength(16)),
expect(encrypter.decrypt(encrypted, iv: IV.allZerosOfLength(16)),
equals(text));
});
});
Expand All @@ -135,12 +135,12 @@ void main() {
test(
'encrypt',
() => expect(
encrypter.encrypt(text, iv: IV.fromLength(8)), equals(encrypted)));
encrypter.encrypt(text, iv: IV.allZerosOfLength(8)), equals(encrypted)));

test(
'decrypt',
() => expect(
encrypter.decrypt(encrypted, iv: IV.fromLength(8)), equals(text)));
encrypter.decrypt(encrypted, iv: IV.allZerosOfLength(8)), equals(text)));
});

group('RSA', () {
Expand Down
21 changes: 19 additions & 2 deletions test/encrypted_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,28 @@ void main() {
expect(encrypted.bytes, equals([0, 1, 2]));
});

test('fromLength', () {
final encrypted = Encrypted.fromLength(3);
test('allZerosOfLength', () {
final encrypted = Encrypted.allZerosOfLength(3);
expect(encrypted.bytes.length, equals(3));
expect(encrypted.bytes, equals([0, 0, 0]));
});

test('fromLength', () {
final encrypted = Encrypted.fromLength(20);
final encrypted2 = Encrypted.fromLength(20);
expect(encrypted.bytes.length, equals(20));
expect(encrypted2.bytes.length, equals(20));
expect(encrypted.bytes, isNot(equals(encrypted2.bytes)));
});

test('fromSecureRandom', () {
final encrypted = Encrypted.fromSecureRandom(20);
final encrypted2 = Encrypted.fromSecureRandom(20);
expect(encrypted.bytes.length, equals(20));
expect(encrypted2.bytes.length, equals(20));
expect(encrypted.bytes, isNot(equals(encrypted2.bytes)));
});

test('fromUtf8', () {
final encrypted = Encrypted.fromUtf8('\u0000\u0001\u0002');
expect(encrypted.bytes, equals([0, 1, 2]));
Expand Down

0 comments on commit 3a42d25

Please sign in to comment.