-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f011d73
commit 39aad85
Showing
24 changed files
with
2,047 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
import 'dart:async'; | ||
import 'dart:typed_data'; | ||
|
||
import 'package:meta/meta.dart'; | ||
|
||
import 'helpers/validations.dart'; | ||
import 'secure_key.dart'; | ||
|
||
/// A typed [StreamConsumer], which is used to generate a hash from a stream of | ||
/// data. | ||
/// | ||
/// See [GenericHash.createConsumer] for more details. | ||
abstract class GenericHashConsumer implements StreamConsumer<Uint8List> { | ||
const GenericHashConsumer._(); // coverage:ignore-line | ||
|
||
/// A future that resolves to the hash of the data. | ||
/// | ||
/// This is the same future as returned by [close]. It will be resolved as | ||
/// soon as the consumer is closed and will either produce the actual | ||
/// hash of the consumed data, or an error if something went wrong. | ||
Future<Uint8List> get hash; | ||
|
||
/// Closes the consumer and calculates the hash. | ||
/// | ||
/// This internally finalizes the consumer and calculates the hash over all | ||
/// the received data. Once done, the hash is returned, or an error thrown, if | ||
/// it failed. The returned future is the same as the on provided via [hash]. | ||
/// | ||
/// After having been closed, no more streams can be added to the consumer. | ||
/// See [StreamConsumer.close] for more details. | ||
@override | ||
Future<Uint8List> close(); | ||
} | ||
|
||
/// A meta class that provides access to all libsodium generichash APIs. | ||
/// | ||
/// This class provides the dart interface for the crypto operations documented | ||
/// in https://libsodium.gitbook.io/doc/hashing/generic_hashing. | ||
/// Please refer to that documentation for more details about these APIs. | ||
abstract class GenericHash { | ||
const GenericHash._(); // coverage:ignore-line | ||
|
||
/// Provides crypto_generichash_BYTES. | ||
/// | ||
/// See https://libsodium.gitbook.io/doc/hashing/generic_hashing#constants | ||
int get bytes; | ||
|
||
/// Provides crypto_generichash_BYTES_MIN. | ||
/// | ||
/// See https://libsodium.gitbook.io/doc/hashing/generic_hashing#constants | ||
int get bytesMin; | ||
|
||
/// Provides crypto_generichash_BYTES_MAX. | ||
/// | ||
/// See https://libsodium.gitbook.io/doc/hashing/generic_hashing#constants | ||
int get bytesMax; | ||
|
||
/// Provides crypto_generichash_KEYBYTES. | ||
/// | ||
/// See https://libsodium.gitbook.io/doc/hashing/generic_hashing#constants | ||
int get keyBytes; | ||
|
||
/// Provides crypto_generichash_KEYBYTES_MIN. | ||
/// | ||
/// See https://libsodium.gitbook.io/doc/hashing/generic_hashing#constants | ||
int get keyBytesMin; | ||
|
||
/// Provides crypto_generichash_KEYBYTES_MAX. | ||
/// | ||
/// See https://libsodium.gitbook.io/doc/hashing/generic_hashing#constants | ||
int get keyBytesMax; | ||
|
||
/// Provides crypto_generichash_keygen. | ||
/// | ||
/// See https://libsodium.gitbook.io/doc/hashing/generic_hashing#usage | ||
SecureKey keygen(); | ||
|
||
/// Provides crypto_generichash. | ||
/// | ||
/// See https://libsodium.gitbook.io/doc/hashing/generic_hashing#usage | ||
Uint8List call({ | ||
required Uint8List message, | ||
int? outLen, | ||
SecureKey? key, | ||
}); | ||
|
||
/// Creates a [StreamConsumer] for generating a hash from a stream. | ||
/// | ||
/// The returned [GenericHashConsumer] is basically a typed [StreamConsumer], | ||
/// that wraps the generichash streaming APIs. Creating the consumer will call | ||
/// crypto_generichash_init, adding messages to it via | ||
/// [GenericHashConsumer.addStream] will call crypto_generichash_update for | ||
/// every event in the stream. After you are done adding messages, you can | ||
/// [GenericHashConsumer.close] it, which will call crypto_generichash_final | ||
/// internally and return the hash of the data. | ||
/// | ||
/// Optionally, you can pass [outLen] to modify the length of the generated | ||
/// hash and [key] if you want to use the hash as MAC. | ||
/// | ||
/// For simpler usage, if you only have a single input [Stream] and simply | ||
/// want to get the hash from it, you ca use [stream] instead. | ||
/// | ||
/// See https://libsodium.gitbook.io/doc/hashing/generic_hashing#usage | ||
GenericHashConsumer createConsumer({ | ||
int? outLen, | ||
SecureKey? key, | ||
}); | ||
|
||
/// Get the hash from an aynchronous stream of data. | ||
/// | ||
/// This is a shortcut for [createConsumer], which simply calls [Stream.pipe] | ||
/// on the [messages] stream and pipes it into the consumer. The returned | ||
/// result is the hash over all the data in the [messages] stream, optionally | ||
/// with a modified [outLen] or a [key]. | ||
/// | ||
/// See https://libsodium.gitbook.io/doc/hashing/generic_hashing#usage | ||
Future<Uint8List> stream({ | ||
required Stream<Uint8List> messages, | ||
int? outLen, | ||
SecureKey? key, | ||
}); | ||
} | ||
|
||
@internal | ||
mixin GenericHashValidations implements GenericHash { | ||
void validateOutLen(int outLen) => Validations.checkInRange( | ||
outLen, | ||
bytesMin, | ||
bytesMax, | ||
'outLen', | ||
); | ||
|
||
void validateKey(SecureKey key) => Validations.checkInRange( | ||
key.length, | ||
keyBytesMin, | ||
keyBytesMax, | ||
'key', | ||
); | ||
|
||
@override | ||
Future<Uint8List> stream({ | ||
required Stream<Uint8List> messages, | ||
int? outLen, | ||
SecureKey? key, | ||
}) => | ||
messages | ||
.pipe(createConsumer( | ||
outLen: outLen, | ||
key: key, | ||
)) | ||
.then((dynamic value) => value as Uint8List); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
import 'dart:ffi'; | ||
import 'dart:typed_data'; | ||
|
||
import '../../api/generic_hash.dart'; | ||
import '../../api/secure_key.dart'; | ||
import '../../api/sodium_exception.dart'; | ||
import '../bindings/libsodium.ffi.dart'; | ||
import '../bindings/memory_protection.dart'; | ||
import '../bindings/secure_key_native.dart'; | ||
import '../bindings/sodium_pointer.dart'; | ||
import 'helpers/generic_hash/generic_hash_consumer_ffi.dart'; | ||
import 'helpers/keygen_mixin.dart'; | ||
|
||
class GenericHashFFI | ||
with GenericHashValidations, KeygenMixin | ||
implements GenericHash { | ||
final LibSodiumFFI sodium; | ||
|
||
GenericHashFFI(this.sodium); | ||
|
||
@override | ||
int get bytes => sodium.crypto_generichash_bytes(); | ||
|
||
@override | ||
int get bytesMin => sodium.crypto_generichash_bytes_min(); | ||
|
||
@override | ||
int get bytesMax => sodium.crypto_generichash_bytes_max(); | ||
|
||
@override | ||
int get keyBytes => sodium.crypto_generichash_keybytes(); | ||
|
||
@override | ||
int get keyBytesMin => sodium.crypto_generichash_keybytes_min(); | ||
|
||
@override | ||
int get keyBytesMax => sodium.crypto_generichash_keybytes_max(); | ||
|
||
@override | ||
SecureKey keygen() => keygenImpl( | ||
sodium: sodium, | ||
keyBytes: keyBytes, | ||
implementation: sodium.crypto_generichash_keygen, | ||
); | ||
|
||
@override | ||
Uint8List call({ | ||
required Uint8List message, | ||
int? outLen, | ||
SecureKey? key, | ||
}) { | ||
if (outLen != null) { | ||
validateOutLen(outLen); | ||
} | ||
if (key != null) { | ||
validateKey(key); | ||
} | ||
|
||
SodiumPointer<Uint8>? outPtr; | ||
SodiumPointer<Uint8>? inPtr; | ||
try { | ||
outPtr = SodiumPointer.alloc( | ||
sodium, | ||
count: outLen ?? bytes, | ||
); | ||
inPtr = message.toSodiumPointer( | ||
sodium, | ||
memoryProtection: MemoryProtection.readOnly, | ||
); | ||
|
||
final result = key.runMaybeUnlockedNative( | ||
sodium, | ||
(keyPtr) => sodium.crypto_generichash( | ||
outPtr!.ptr, | ||
outPtr.count, | ||
inPtr!.ptr, | ||
inPtr.count, | ||
keyPtr?.ptr ?? nullptr, | ||
keyPtr?.count ?? 0, | ||
), | ||
); | ||
SodiumException.checkSucceededInt(result); | ||
|
||
return outPtr.copyAsList(); | ||
} finally { | ||
outPtr?.dispose(); | ||
inPtr?.dispose(); | ||
} | ||
} | ||
|
||
@override | ||
GenericHashConsumer createConsumer({ | ||
int? outLen, | ||
SecureKey? key, | ||
}) { | ||
if (outLen != null) { | ||
validateOutLen(outLen); | ||
} | ||
if (key != null) { | ||
validateKey(key); | ||
} | ||
|
||
return GenericHashConsumerFFI( | ||
sodium: sodium, | ||
outLen: outLen ?? bytes, | ||
key: key, | ||
); | ||
} | ||
} |
Oops, something went wrong.