Skip to content

Commit b05e0ed

Browse files
authored
Merge pull request #160 from terrier989/master
Fixes Blake2b/Blake2s issues.
2 parents 0152865 + a28c393 commit b05e0ed

27 files changed

+1362
-256
lines changed

cryptography/CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
## 2.6.0
2+
* Improves Blake2b/Blake2s support:
3+
* Adds support for using as a MAC algorithm
4+
* Adds support for custom output lengths
5+
* Improves test coverage
6+
* Fixes bugs
7+
* Removes long-deprecated `newSink()` methods in `HashAlgorithm` and `MacAlgorithm` (so Blake2
8+
classes can implement both interfaces).
9+
* Raises Dart SDK minimum to 3.1.0 and other small changes related to dependency constraints.
10+
* Improves documentation.
11+
112
## 2.5.0
213
* Adds enough DER encoding/decoding support for us to use Apple's CryptoKit ECDH/ECDSA functions.
314
* Improves BrowserHmac/etc. parameter checks.

cryptography/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,8 @@ The following implementations are available:
177177
The following [MacAlgorithm](https://pub.dev/documentation/cryptography/latest/cryptography/MacAlgorithm-class.html)
178178
implementations are available:
179179
180+
* [Blake2b](https://pub.dev/documentation/cryptography/latest/cryptography/Blake2b-class.html)
181+
* [Blake2s](https://pub.dev/documentation/cryptography/latest/cryptography/Blake2s-class.html)
180182
* [Hmac](https://pub.dev/documentation/cryptography/latest/cryptography/Hmac-class.html)
181183
* [Poly1305](https://pub.dev/documentation/cryptography/latest/cryptography/Poly1305-class.html)
182184

cryptography/lib/src/browser/browser_cryptography.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import 'hkdf.dart';
3131
import 'hmac.dart';
3232
import 'pbkdf2.dart';
3333

34-
class BrowserCryptography extends DartCryptography {
34+
base class BrowserCryptography extends DartCryptography {
3535
// Documented in browser_cryptography_when_not_browser.dart
3636
static final Cryptography defaultInstance =
3737
isSupported ? BrowserCryptography() : DartCryptography();

cryptography/lib/src/cryptography/algorithms.dart

Lines changed: 126 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -548,11 +548,20 @@ abstract class Argon2id extends KdfAlgorithm {
548548
')';
549549
}
550550

551-
/// _BLAKE2B_ ([RFC 7693](https://tools.ietf.org/html/rfc7693)) [HashAlgorithm].
551+
/// _BLAKE2B_ ([RFC 7693](https://tools.ietf.org/html/rfc7693)), which can be
552+
/// used both as [HashAlgorithm] and [MacAlgorithm].
552553
///
553554
/// By default, [DartBlake2b] will be used.
554555
///
555-
/// ## Asynchronous usage
556+
/// ## Things to know
557+
/// * The default [hashLengthInBytes] / [macLength] is 64 bytes. You can
558+
/// choose a shorter hash length when you call the constructor. You should
559+
/// NOT truncate the hash yourself.
560+
/// * The algorithm was designed to be used directly as [MacAlgorithm] (no
561+
/// [Hmac] needed). Maximum secret key size is 64 bytes.
562+
/// * Blake2 hash/MAC function family includes also [Blake2s].
563+
///
564+
/// ## Example: Hashing a byte list
556565
/// ```
557566
/// import 'package:cryptography/cryptography.dart';
558567
///
@@ -566,7 +575,7 @@ abstract class Argon2id extends KdfAlgorithm {
566575
///
567576
/// If you need synchronous computations, use [DartBlake2b].
568577
///
569-
/// ## Streaming usage
578+
/// ## Example: Hashing a sequence of chunks
570579
/// ```
571580
/// import 'package:cryptography/cryptography.dart';
572581
///
@@ -587,14 +596,47 @@ abstract class Argon2id extends KdfAlgorithm {
587596
/// print('Hash: ${hash.bytes}');
588597
/// }
589598
/// ```
590-
abstract class Blake2b extends HashAlgorithm {
591-
factory Blake2b() {
592-
return Cryptography.instance.blake2b();
599+
abstract class Blake2b extends HashAlgorithm implements MacAlgorithm {
600+
/// Default value of [hashLengthInBytes] and [macLength].
601+
static const int defaultHashLengthInBytes = 64;
602+
603+
factory Blake2b({
604+
int hashLengthInBytes = defaultHashLengthInBytes,
605+
}) {
606+
if (hashLengthInBytes < 1 || hashLengthInBytes > defaultHashLengthInBytes) {
607+
throw ArgumentError.value(hashLengthInBytes);
608+
}
609+
return Cryptography.instance.blake2b(
610+
hashLengthInBytes: hashLengthInBytes,
611+
);
593612
}
594613

595-
/// Constructor for classes that extend this class.
614+
/// Constructor for subclasses.
615+
const Blake2b.constructor({
616+
this.hashLengthInBytes = defaultHashLengthInBytes,
617+
}) : assert(hashLengthInBytes > 0),
618+
assert(hashLengthInBytes <= defaultHashLengthInBytes);
596619

597-
const Blake2b.constructor();
620+
@override
621+
void checkParameters({
622+
int? length,
623+
required SecretKey secretKey,
624+
required int nonceLength,
625+
required int aadLength,
626+
required int keyStreamIndex,
627+
}) {}
628+
629+
@override
630+
int get keyStreamUsed => 0;
631+
632+
@override
633+
int get macLength => hashLengthInBytes;
634+
635+
@override
636+
bool get supportsAad => false;
637+
638+
@override
639+
bool get supportsKeyStreamIndex => false;
598640

599641
@override
600642
int get blockLengthInBytes => 64;
@@ -603,20 +645,39 @@ abstract class Blake2b extends HashAlgorithm {
603645
int get hashCode => (Blake2b).hashCode;
604646

605647
@override
606-
int get hashLengthInBytes => 64;
648+
final int hashLengthInBytes;
607649

608650
@override
609651
bool operator ==(other) => other is Blake2b;
610652

611653
@override
612-
DartHashAlgorithm toSync() => const DartBlake2b();
654+
DartBlake2b toSync() => DartBlake2b(
655+
hashLengthInBytes: hashLengthInBytes,
656+
);
657+
658+
@override
659+
String toString() {
660+
if (hashLengthInBytes == defaultHashLengthInBytes) {
661+
return 'Blake2b()';
662+
}
663+
return 'Blake2b(hashLengthInBytes: $hashLengthInBytes)';
664+
}
613665
}
614666

615-
/// _BLAKE2S_ ([RFC 7693](https://tools.ietf.org/html/rfc7693)) [HashAlgorithm].
667+
/// _BLAKE2S_ ([RFC 7693](https://tools.ietf.org/html/rfc7693)), which can be
668+
/// used both as [HashAlgorithm] and [MacAlgorithm].
616669
///
617-
/// By default, [DartBlake2s], our pure Dart implementation, will be used.
670+
/// By default, [DartBlake2s] will be used.
618671
///
619-
/// ## Asynchronous usage
672+
/// ## Things to know
673+
/// * The default [hashLengthInBytes] / [macLength] is 32 bytes. You can
674+
/// choose a shorter hash length when you call the constructor. You should
675+
/// NOT truncate the hash yourself.
676+
/// * The algorithm was designed to be used directly as [MacAlgorithm] (no
677+
/// [Hmac] needed). Maximum secret key size is 32 bytes.
678+
/// * Blake2 hash/MAC function family includes also [Blake2b].
679+
///
680+
/// ## Example: Hashing a byte list
620681
/// ```dart
621682
/// import 'package:cryptography/cryptography.dart';
622683
///
@@ -628,7 +689,7 @@ abstract class Blake2b extends HashAlgorithm {
628689
/// }
629690
/// ```
630691
///
631-
/// ## Streaming usage
692+
/// ## Example: Hashing a sequence of chunks
632693
/// ```dart
633694
/// import 'package:cryptography/cryptography.dart';
634695
///
@@ -650,14 +711,26 @@ abstract class Blake2b extends HashAlgorithm {
650711
/// }
651712
/// ```
652713
///
653-
abstract class Blake2s extends HashAlgorithm {
654-
factory Blake2s() {
655-
return Cryptography.instance.blake2s();
656-
}
714+
abstract class Blake2s extends HashAlgorithm implements MacAlgorithm {
715+
/// Default value of [hashLengthInBytes] and [macLength].
716+
static const int defaultHashLengthInBytes = 32;
657717

658-
/// Constructor for classes that extend this class.
718+
factory Blake2s({
719+
int hashLengthInBytes = defaultHashLengthInBytes,
720+
}) {
721+
if (hashLengthInBytes < 1 || hashLengthInBytes > defaultHashLengthInBytes) {
722+
throw ArgumentError.value(hashLengthInBytes);
723+
}
724+
return Cryptography.instance.blake2s(
725+
hashLengthInBytes: hashLengthInBytes,
726+
);
727+
}
659728

660-
const Blake2s.constructor();
729+
/// Constructor for subclasses.
730+
const Blake2s.constructor({
731+
this.hashLengthInBytes = defaultHashLengthInBytes,
732+
}) : assert(hashLengthInBytes > 0),
733+
assert(hashLengthInBytes <= defaultHashLengthInBytes);
661734

662735
@override
663736
int get blockLengthInBytes => 32;
@@ -666,13 +739,44 @@ abstract class Blake2s extends HashAlgorithm {
666739
int get hashCode => (Blake2s).hashCode;
667740

668741
@override
669-
int get hashLengthInBytes => 32;
742+
final int hashLengthInBytes;
743+
744+
@override
745+
void checkParameters({
746+
int? length,
747+
required SecretKey secretKey,
748+
required int nonceLength,
749+
required int aadLength,
750+
required int keyStreamIndex,
751+
}) {}
752+
753+
@override
754+
int get keyStreamUsed => 0;
755+
756+
@override
757+
int get macLength => hashLengthInBytes;
758+
759+
@override
760+
bool get supportsAad => false;
761+
762+
@override
763+
bool get supportsKeyStreamIndex => false;
670764

671765
@override
672766
bool operator ==(other) => other is Blake2s;
673767

674768
@override
675-
DartHashAlgorithm toSync() => const DartBlake2s();
769+
String toString() {
770+
if (hashLengthInBytes == defaultHashLengthInBytes) {
771+
return 'Blake2s()';
772+
}
773+
return 'Blake2s(hashLengthInBytes: $hashLengthInBytes)';
774+
}
775+
776+
@override
777+
DartBlake2s toSync() => DartBlake2s(
778+
hashLengthInBytes: hashLengthInBytes,
779+
);
676780
}
677781

678782
/// _ChaCha20_ ([RFC 7539](https://tools.ietf.org/html/rfc7539))

cryptography/lib/src/cryptography/cipher.dart

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ import '../../dart.dart';
5959
/// print('MAC: ${secretBox.mac.bytes}')
6060
///
6161
/// // Decrypt
62-
/// final clearText = await algorithm.encrypt(
62+
/// final clearText = await algorithm.decrypt(
6363
/// secretBox,
6464
/// secretKey: secretKey,
6565
/// );
@@ -443,8 +443,9 @@ abstract class Cipher {
443443
/// It will have the correct length ([nonceLength]).
444444
///
445445
/// The source of random bytes is [Random.secure] (a cryptographically secure
446-
/// random number generator) unless specified another random number generator
447-
/// when you constructed the cipher (or your [Cryptography]).
446+
/// random number generator) unless a custom random number generator was
447+
/// specified when you constructed the cipher (or your [Cryptography]
448+
/// instance).
448449
List<int> newNonce() {
449450
final bytes = Uint8List(nonceLength);
450451
fillBytesWithSecureRandom(
@@ -459,8 +460,9 @@ abstract class Cipher {
459460
/// It will have the correct length ([secretKeyLength]).
460461
///
461462
/// The source of random bytes is [Random.secure] (a cryptographically secure
462-
/// random number generator) unless specified another random number generator
463-
/// when you constructed the cipher (or your [Cryptography]).
463+
/// random number generator) unless a custom random number generator was
464+
/// specified when you constructed the cipher (or your [Cryptography]
465+
/// instance).
464466
Future<SecretKey> newSecretKey() async {
465467
return SecretKeyData.random(
466468
length: secretKeyLength,
@@ -497,7 +499,7 @@ abstract class Cipher {
497499
/// import 'package:cryptography/cryptography.dart';
498500
///
499501
/// void main() {
500-
/// final cipher = Chacha20.poly1305().toSync();
502+
/// final cipher = Chacha20.poly1305Aead().toSync();
501503
/// final secretKey = cipher.newSecretKeySync();
502504
/// final secretBox = cipher.encryptSync(
503505
/// [1,2,3],

cryptography/lib/src/cryptography/cryptography.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,10 @@ abstract class Cryptography {
115115
});
116116

117117
/// A factory used by [Blake2b].
118-
Blake2b blake2b();
118+
Blake2b blake2b({int hashLengthInBytes = 64});
119119

120120
/// A factory used by [Blake2s].
121-
Blake2s blake2s();
121+
Blake2s blake2s({int hashLengthInBytes = 32});
122122

123123
/// A factory used by [Chacha20].
124124
Chacha20 chacha20({required MacAlgorithm macAlgorithm});

cryptography/lib/src/cryptography/hash_algorithm.dart

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import 'dart:typed_data';
1717

1818
import 'package:cryptography/cryptography.dart';
1919
import 'package:cryptography/dart.dart';
20-
import 'package:meta/meta.dart';
2120

2221
/// A hash algorithm that produces a [Hash].
2322
///
@@ -105,11 +104,6 @@ abstract class HashAlgorithm {
105104
/// ```
106105
HashSink newHashSink() => _HashSink(this);
107106

108-
/// {@nodoc}
109-
@nonVirtual
110-
@Deprecated('Use newHashSink() instead')
111-
HashSink newSink() => newHashSink();
112-
113107
@override
114108
String toString() => '$runtimeType()';
115109

cryptography/lib/src/cryptography/mac_algorithm.dart

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ import 'package:cryptography/dart.dart';
2424
/// You can compute a [Mac] by calling [calculateMac] or [newMacSink].
2525
///
2626
/// ## Available algorithms
27-
/// * [Hmac]
27+
/// * [Blake2b]
28+
/// * [Blake2s]
29+
/// * [Hmac] (with any hash algorithm)
2830
/// * [Poly1305]
2931
///
3032
/// ## Not using MAC?
@@ -143,20 +145,6 @@ abstract class MacAlgorithm {
143145
);
144146
}
145147

146-
/// {@nodoc}
147-
@Deprecated('Use newMacSink()')
148-
Future<MacSink> newSink({
149-
required SecretKey secretKey,
150-
List<int> nonce = const <int>[],
151-
List<int> aad = const <int>[],
152-
}) {
153-
return newMacSink(
154-
secretKey: secretKey,
155-
nonce: nonce,
156-
aad: aad,
157-
);
158-
}
159-
160148
@override
161149
String toString() => '$runtimeType()';
162150

cryptography/lib/src/dart/blake2b.dart

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,36 @@ import 'blake2b_impl_vm.dart'
2222
///
2323
/// For examples and more information about the algorithm, see documentation for
2424
/// the class [Blake2b].
25-
class DartBlake2b extends Blake2b with DartHashAlgorithmMixin {
26-
const DartBlake2b() : super.constructor();
25+
class DartBlake2b extends Blake2b
26+
with DartHashAlgorithmMixin, DartMacAlgorithmMixin {
27+
const DartBlake2b({
28+
super.hashLengthInBytes = Blake2b.defaultHashLengthInBytes,
29+
}) : super.constructor();
30+
31+
@override
32+
DartBlake2b toSync() {
33+
return this;
34+
}
35+
36+
@override
37+
DartMacSinkMixin newMacSinkSync({
38+
required SecretKeyData secretKeyData,
39+
List<int> nonce = const <int>[],
40+
List<int> aad = const <int>[],
41+
}) {
42+
return Blake2bSink(
43+
hashLengthInBytes: hashLengthInBytes,
44+
)..initializeSync(
45+
secretKey: secretKeyData,
46+
nonce: nonce,
47+
aad: aad,
48+
);
49+
}
2750

2851
@override
2952
DartHashSink newHashSink() {
30-
return Blake2bSink();
53+
return Blake2bSink(
54+
hashLengthInBytes: hashLengthInBytes,
55+
);
3156
}
3257
}

0 commit comments

Comments
 (0)