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? workingKey1; List? workingKey2; List? 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; } }