148 lines
3.8 KiB
Dart
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;
|
|
}
|
|
}
|
|
}
|