108 lines
2.9 KiB
Dart
108 lines
2.9 KiB
Dart
import 'dart:typed_data';
|
|
|
|
import 'package:pointycastle/api.dart';
|
|
import 'package:pointycastle/block/des_base.dart';
|
|
import 'package:pointycastle/src/impl/base_block_cipher.dart';
|
|
import 'package:pointycastle/src/registry/registry.dart';
|
|
|
|
class DESedeEngine extends DesBase implements BaseBlockCipher {
|
|
static final FactoryConfig factoryConfig =
|
|
StaticFactoryConfig(BlockCipher, 'DESede', () => DESedeEngine());
|
|
|
|
static final BLOCK_SIZE = 8;
|
|
|
|
List<int>? workingKey1;
|
|
List<int>? workingKey2;
|
|
List<int>? workingKey3;
|
|
|
|
bool forEncryption = false;
|
|
|
|
@override
|
|
String get algorithmName => 'DESede';
|
|
|
|
@override
|
|
int get blockSize => BLOCK_SIZE;
|
|
|
|
@override
|
|
void init(bool forEncryption, CipherParameters? params) {
|
|
if (params is KeyParameter) {
|
|
var keyMaster = params.key;
|
|
|
|
if (keyMaster.length != 24 && keyMaster.length != 16) {
|
|
throw ArgumentError('key size must be 16 or 24 bytes.');
|
|
}
|
|
|
|
this.forEncryption = forEncryption;
|
|
|
|
var key1 = Uint8List(8);
|
|
|
|
_arrayCopy(keyMaster, 0, key1, 0, key1.length);
|
|
workingKey1 = generateWorkingKey(forEncryption, key1);
|
|
|
|
var key2 = Uint8List(8);
|
|
_arrayCopy(keyMaster, 8, key2, 0, key2.length);
|
|
workingKey2 = generateWorkingKey(!forEncryption, key2);
|
|
|
|
if (keyMaster.length == 24) {
|
|
var key3 = Uint8List(8);
|
|
_arrayCopy(keyMaster, 16, key3, 0, key3.length);
|
|
workingKey3 = generateWorkingKey(forEncryption, key3);
|
|
} else {
|
|
workingKey3 = workingKey1;
|
|
}
|
|
}
|
|
}
|
|
|
|
@override
|
|
Uint8List process(Uint8List data) {
|
|
var out = Uint8List(blockSize);
|
|
var len = processBlock(data, 0, out, 0);
|
|
return out.sublist(0, len);
|
|
}
|
|
|
|
@override
|
|
int processBlock(Uint8List inp, int inpOff, Uint8List out, int outOff) {
|
|
if (workingKey1 == null || workingKey2 == null || workingKey3 == null) {
|
|
throw ArgumentError('DESede engine not initialised');
|
|
}
|
|
|
|
if ((inpOff + BLOCK_SIZE) > inp.length) {
|
|
throw ArgumentError('input buffer too short');
|
|
}
|
|
|
|
if ((outOff + BLOCK_SIZE) > out.length) {
|
|
throw ArgumentError('output buffer too short');
|
|
}
|
|
|
|
var temp = Uint8List(BLOCK_SIZE);
|
|
|
|
if (forEncryption) {
|
|
desFunc(workingKey1!, inp, inpOff, temp, 0);
|
|
desFunc(workingKey2!, temp, 0, temp, 0);
|
|
desFunc(workingKey3!, temp, 0, out, outOff);
|
|
} else {
|
|
desFunc(workingKey3!, inp, inpOff, temp, 0);
|
|
desFunc(workingKey2!, temp, 0, temp, 0);
|
|
desFunc(workingKey1!, temp, 0, out, outOff);
|
|
}
|
|
|
|
return BLOCK_SIZE;
|
|
}
|
|
|
|
@override
|
|
void reset() {}
|
|
|
|
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];
|
|
}
|
|
}
|
|
|
|
int bitsOfSecurity() {
|
|
if (workingKey1 != null && workingKey1 == workingKey3) {
|
|
return 80;
|
|
}
|
|
return 112;
|
|
}
|
|
}
|