deriveKey method
Generates a new secret key from a secret key and a nonce.
The nonce ("salt") should be some random sequence of bytes. Nonce does not need to be protected. If possible, you should have a different nonce for each key derivation.
Implementation
@override
Future<SecretKeyData> deriveKey({
required SecretKey secretKey,
List<int> nonce = const <int>[],
List<int> info = const <int>[],
}) async {
// Calculate a pseudorandom key
final secretKeyBytes = await secretKey.extractBytes();
final nonceAsSecretKey = SecretKey(nonce);
final prkMac = await hmac.calculateMac(
secretKeyBytes,
secretKey: nonceAsSecretKey,
nonce: nonce,
);
final prk = SecretKey(prkMac.bytes);
// T(0)
var bytes = const <int>[];
// T(1), T(2), ...
final hashLength = hmac.hashAlgorithm.hashLengthInBytes;
final n = outputLength ~/ hashLength;
final result = Uint8List(outputLength);
for (var i = 0; i <= n; i++) {
final sink = await hmac.newMacSink(secretKey: prk);
sink.add(bytes);
if (info.isNotEmpty) {
sink.add(info);
}
final added = <int>[0xFF & (1 + i)];
sink.add(added);
sink.close();
final mac = await sink.mac();
bytes = mac.bytes;
final offset = i * hashLength;
if (offset + bytes.length <= result.length) {
result.setAll(offset, bytes);
} else {
result.setAll(offset, bytes.take(result.length - offset));
}
}
return SecretKeyData(result);
}