twonly-app-dependencies/pointycastle/lib/key_derivators/pkcs12_parameter_generator.dart
2025-12-07 16:10:41 +01:00

148 lines
3.8 KiB
Dart

import 'dart:typed_data';
import 'package:pointycastle/pointycastle.dart';
import 'package:pointycastle/src/registry/registry.dart';
class PKCS12ParametersGenerator implements PBEParametersGenerator {
static final FactoryConfig factoryConfig = DynamicFactoryConfig.suffix(
PBEParametersGenerator,
'/PKCS12',
(_, final Match match) => () {
var mac = Digest(match.group(1)!);
return PKCS12ParametersGenerator(mac);
});
static const int KEY_MATERIAL = 1;
static const int IV_MATERIAL = 2;
static const int MAC_MATERIAL = 3;
Digest digest;
late int u;
late int v;
late Uint8List salt;
late Uint8List password;
late int iterationCount;
PKCS12ParametersGenerator(this.digest) {
u = digest.digestSize;
v = digest.byteLength;
}
@override
void init(Uint8List password, Uint8List salt, int iterationCount) {
this.password = password;
this.salt = salt;
this.iterationCount = iterationCount;
}
///
/// Generates a derived key with the given [keySize] in bytes.
///
@override
KeyParameter generateDerivedParameters(int keySize) {
var dKey = _generateDerivedKey(KEY_MATERIAL, keySize);
return KeyParameter(dKey);
}
///
/// Generates a derived key with the given [keySize] in bytes and a derived IV with the given [ivSize].
///
@override
ParametersWithIV generateDerivedParametersWithIV(int keySize, int ivSize) {
var dKey = _generateDerivedKey(KEY_MATERIAL, keySize);
var iv = _generateDerivedKey(IV_MATERIAL, ivSize);
return ParametersWithIV(KeyParameter(dKey), iv);
}
///
/// Generates a derived key with the given [keySize] in bytes used for mac generating.
///
@override
KeyParameter generateDerivedMacParameters(int keySize) {
var dKey = _generateDerivedKey(MAC_MATERIAL, keySize);
return KeyParameter(dKey);
}
Uint8List _generateDerivedKey(int idByte, int n) {
var D = Uint8List(v);
var dKey = Uint8List(n);
for (var i = 0; i != D.length; i++) {
D[i] = idByte;
}
Uint8List S;
if (salt.isNotEmpty) {
S = Uint8List(v * (((salt.length + v) - 1) ~/ v));
for (var i = 0; i != S.length; i++) {
S[i] = salt[i % salt.length];
}
} else {
S = Uint8List(0);
}
Uint8List P;
if (password.isNotEmpty) {
P = Uint8List(v * (((password.length + v) - 1) ~/ v));
for (var i = 0; i != P.length; i++) {
P[i] = password[i % password.length];
}
} else {
P = Uint8List(0);
}
var I = Uint8List(S.length + P.length);
_arrayCopy(S, 0, I, 0, S.length);
_arrayCopy(P, 0, I, S.length, P.length);
var B = Uint8List(v);
var c = ((n + u) - 1) ~/ u;
var A = Uint8List(u);
for (var i = 1; i <= c; i++) {
digest.update(D, 0, D.length);
digest.update(I, 0, I.length);
digest.doFinal(A, 0);
for (var j = 1; j < iterationCount; j++) {
digest.update(A, 0, A.length);
digest.doFinal(A, 0);
}
for (var j = 0; j != B.length; j++) {
B[j] = A[j % A.length];
}
for (var j = 0; j != (I.length ~/ v); j++) {
_adjust(I, j * v, B);
}
if (i == c) {
_arrayCopy(A, 0, dKey, (i - 1) * u, dKey.length - ((i - 1) * u));
} else {
_arrayCopy(A, 0, dKey, (i - 1) * u, A.length);
}
}
return dKey;
}
void _arrayCopy(Uint8List? sourceArr, int sourcePos, Uint8List? outArr,
int outPos, int len) {
for (var i = 0; i < len; i++) {
outArr![outPos + i] = sourceArr![sourcePos + i];
}
}
void _adjust(Uint8List a, int aOff, Uint8List b) {
var x = (b[b.length - 1] & 0xff) + (a[aOff + b.length - 1] & 0xff) + 1;
a[aOff + b.length - 1] = x;
x >>>= 8;
for (var i = b.length - 2; i >= 0; i--) {
x += (b[i] & 0xff) + (a[aOff + i] & 0xff);
a[aOff + i] = x;
x >>>= 8;
}
}
}