update: updating files with detailed comments
This commit is contained in:
parent
df25885fcf
commit
ef243a6e8b
2 changed files with 68 additions and 11 deletions
|
@ -14,7 +14,7 @@
|
||||||
/// - Salt generation utilities
|
/// - Salt generation utilities
|
||||||
///
|
///
|
||||||
/// These components are essential for secure password hashing and storage.
|
/// These components are essential for secure password hashing and storage.
|
||||||
library hashing;
|
library;
|
||||||
|
|
||||||
export 'package:protevus_hashing/src/pbkdf2.dart';
|
export 'package:protevus_hashing/src/pbkdf2.dart';
|
||||||
export 'package:protevus_hashing/src/salt.dart';
|
export 'package:protevus_hashing/src/salt.dart';
|
||||||
|
|
|
@ -10,36 +10,56 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:crypto/crypto.dart';
|
import 'package:crypto/crypto.dart';
|
||||||
|
|
||||||
/// Instances of this type derive a key from a password, salt, and hash function.
|
/// Implements the PBKDF2 (Password-Based Key Derivation Function 2) algorithm.
|
||||||
|
///
|
||||||
|
/// This class is used to derive a key from a password, salt, and hash function.
|
||||||
|
/// It's particularly useful for secure password storage and key generation.
|
||||||
///
|
///
|
||||||
/// https://en.wikipedia.org/wiki/PBKDF2
|
/// https://en.wikipedia.org/wiki/PBKDF2
|
||||||
class PBKDF2 {
|
class PBKDF2 {
|
||||||
/// Creates instance capable of generating a key.
|
/// Creates an instance of PBKDF2 capable of generating a key.
|
||||||
///
|
///
|
||||||
/// [hashAlgorithm] defaults to [sha256].
|
/// [hashAlgorithm] specifies the hash function to use. Defaults to [sha256].
|
||||||
PBKDF2({Hash? hashAlgorithm}) {
|
PBKDF2({Hash? hashAlgorithm}) {
|
||||||
this.hashAlgorithm = hashAlgorithm ?? sha256;
|
this.hashAlgorithm = hashAlgorithm ?? sha256;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the current hash algorithm used by this PBKDF2 instance.
|
||||||
Hash get hashAlgorithm => _hashAlgorithm;
|
Hash get hashAlgorithm => _hashAlgorithm;
|
||||||
|
|
||||||
|
/// Sets the hash algorithm to be used by this PBKDF2 instance.
|
||||||
|
///
|
||||||
|
/// This also updates the internal block size based on the new algorithm.
|
||||||
set hashAlgorithm(Hash algorithm) {
|
set hashAlgorithm(Hash algorithm) {
|
||||||
_hashAlgorithm = algorithm;
|
_hashAlgorithm = algorithm;
|
||||||
_blockSize = _hashAlgorithm.convert([1, 2, 3]).bytes.length;
|
_blockSize = _hashAlgorithm.convert([1, 2, 3]).bytes.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The hash algorithm used for key derivation.
|
||||||
|
///
|
||||||
|
/// This is marked as 'late' because it's initialized in the constructor or
|
||||||
|
/// when the setter is called, but not at the point of declaration.
|
||||||
late Hash _hashAlgorithm;
|
late Hash _hashAlgorithm;
|
||||||
|
|
||||||
|
/// The block size used in the PBKDF2 algorithm.
|
||||||
|
///
|
||||||
|
/// This value is determined by the output size of the hash function being used.
|
||||||
|
/// It's initialized when the hash algorithm is set, either in the constructor
|
||||||
|
/// or when the hashAlgorithm setter is called.
|
||||||
late int _blockSize;
|
late int _blockSize;
|
||||||
|
|
||||||
/// Hashes a [password] with a given [salt].
|
/// Generates a key from the given password and salt.
|
||||||
///
|
///
|
||||||
/// The length of this return value will be [keyLength].
|
/// [password] is the password to hash.
|
||||||
|
/// [salt] is the salt to use in the hashing process.
|
||||||
|
/// [rounds] is the number of iterations to perform.
|
||||||
|
/// [keyLength] is the desired length of the output key in bytes.
|
||||||
///
|
///
|
||||||
/// See [generateAsBase64String] for generating a random salt.
|
/// Returns a [List<int>] representing the generated key.
|
||||||
///
|
///
|
||||||
/// See also [generateBase64Key], which base64 encodes the key returned from this method for storage.
|
/// Throws a [PBKDF2Exception] if the derived key would be too long.
|
||||||
List<int> generateKey(
|
List<int> generateKey(
|
||||||
String password,
|
String password,
|
||||||
String salt,
|
String salt,
|
||||||
|
@ -79,9 +99,16 @@ class PBKDF2 {
|
||||||
return key.buffer.asUint8List();
|
return key.buffer.asUint8List();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Hashed a [password] with a given [salt] and base64 encodes the result.
|
/// Generates a base64-encoded key from the given password and salt.
|
||||||
///
|
///
|
||||||
/// This method invokes [generateKey] and base64 encodes the result.
|
/// This method invokes [generateKey] and base64 encodes the result.
|
||||||
|
///
|
||||||
|
/// [password] is the password to hash.
|
||||||
|
/// [salt] is the salt to use in the hashing process.
|
||||||
|
/// [rounds] is the number of iterations to perform.
|
||||||
|
/// [keyLength] is the desired length of the output key in bytes.
|
||||||
|
///
|
||||||
|
/// Returns a [String] representing the base64-encoded generated key.
|
||||||
String generateBase64Key(
|
String generateBase64Key(
|
||||||
String password,
|
String password,
|
||||||
String salt,
|
String salt,
|
||||||
|
@ -94,22 +121,42 @@ class PBKDF2 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Thrown when [PBKDF2] throws an exception.
|
/// Exception thrown when an error occurs during PBKDF2 key generation.
|
||||||
class PBKDF2Exception implements Exception {
|
class PBKDF2Exception implements Exception {
|
||||||
|
/// Creates a new PBKDF2Exception with the given error message.
|
||||||
PBKDF2Exception(this.message);
|
PBKDF2Exception(this.message);
|
||||||
|
|
||||||
|
/// The error message describing the exception.
|
||||||
String message;
|
String message;
|
||||||
|
|
||||||
|
/// Returns a string representation of the PBKDF2Exception.
|
||||||
|
///
|
||||||
|
/// This method overrides the default [Object.toString] method to provide
|
||||||
|
/// a more descriptive string representation of the exception. The returned
|
||||||
|
/// string includes the exception type ("PBKDF2Exception") followed by the
|
||||||
|
/// error message.
|
||||||
|
///
|
||||||
|
/// Returns a [String] in the format "PBKDF2Exception: [error message]".
|
||||||
@override
|
@override
|
||||||
String toString() => "PBKDF2Exception: $message";
|
String toString() => "PBKDF2Exception: $message";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A helper class for XOR operations on digests during PBKDF2 key generation.
|
||||||
class _XORDigestSink implements Sink<Digest> {
|
class _XORDigestSink implements Sink<Digest> {
|
||||||
|
/// Creates a new _XORDigestSink with the given input buffer and HMAC.
|
||||||
_XORDigestSink(ByteData inputBuffer, Hmac hmac) {
|
_XORDigestSink(ByteData inputBuffer, Hmac hmac) {
|
||||||
lastDigest = hmac.convert(inputBuffer.buffer.asUint8List()).bytes;
|
lastDigest = hmac.convert(inputBuffer.buffer.asUint8List()).bytes;
|
||||||
bytes = ByteData(lastDigest.length)
|
bytes = ByteData(lastDigest.length)
|
||||||
..buffer.asUint8List().setRange(0, lastDigest.length, lastDigest);
|
..buffer.asUint8List().setRange(0, lastDigest.length, lastDigest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generates a hash by repeatedly applying HMAC and XOR operations.
|
||||||
|
///
|
||||||
|
/// [inputBuffer] is the initial input data.
|
||||||
|
/// [hmac] is the HMAC instance to use for hashing.
|
||||||
|
/// [rounds] is the number of iterations to perform.
|
||||||
|
///
|
||||||
|
/// Returns a [Uint8List] representing the generated hash.
|
||||||
static Uint8List generate(ByteData inputBuffer, Hmac hmac, int rounds) {
|
static Uint8List generate(ByteData inputBuffer, Hmac hmac, int rounds) {
|
||||||
final hashSink = _XORDigestSink(inputBuffer, hmac);
|
final hashSink = _XORDigestSink(inputBuffer, hmac);
|
||||||
|
|
||||||
|
@ -124,9 +171,15 @@ class _XORDigestSink implements Sink<Digest> {
|
||||||
return hashSink.bytes.buffer.asUint8List();
|
return hashSink.bytes.buffer.asUint8List();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Stores the intermediate XOR results.
|
||||||
late ByteData bytes;
|
late ByteData bytes;
|
||||||
|
|
||||||
|
/// Stores the last computed digest.
|
||||||
late List<int> lastDigest;
|
late List<int> lastDigest;
|
||||||
|
|
||||||
|
/// Adds a new digest to the sink by performing an XOR operation.
|
||||||
|
///
|
||||||
|
/// [digest] is the digest to add to the sink.
|
||||||
@override
|
@override
|
||||||
void add(Digest digest) {
|
void add(Digest digest) {
|
||||||
lastDigest = digest.bytes;
|
lastDigest = digest.bytes;
|
||||||
|
@ -135,6 +188,10 @@ class _XORDigestSink implements Sink<Digest> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Closes the sink and performs any necessary cleanup.
|
||||||
|
///
|
||||||
|
/// This method is required by the [Sink] interface but does not perform
|
||||||
|
/// any additional actions in this implementation.
|
||||||
@override
|
@override
|
||||||
void close() {}
|
void close() {}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue