decrypt method
Decrypts this entry using the given password.
Implementation
@override
void decrypt(String password) {
if (isDecrypted()) return;
// BKS Sealed Key structure:
// Salt (20 bytes)
// Iteration Count (4 bytes)
// Ciphertext (Rest)
if (_encryptedData == null || _encryptedData!.length < 24) {
throw DecryptionFailureException('Invalid sealed key data length');
}
final data = ByteData.sublistView(_encryptedData!);
int pos = 0;
// Read salt (20 bytes)
// Note: BKS V2 sometimes stores salt length?
// BC implementation usually fixed 20 bytes for this specific internal structure
final salt = _encryptedData!.sublist(pos, pos + 20);
pos += 20;
// Read iteration count
final iterationCount = data.getUint32(pos);
pos += 4;
final ciphertext = _encryptedData!.sublist(pos);
try {
// Derive Key (192 bits = 24 bytes) and IV (64 bits = 8 bytes)
// Actually BKS uses separate calls for Key and IV with different ID byte
final key =
BksKeyStore._derivePkcs12Key(password, salt, iterationCount, 24, 1);
final iv =
BksKeyStore._derivePkcs12Key(password, salt, iterationCount, 8, 2);
// Decrypt 3DES-CBC
final params = ParametersWithIV<KeyParameter>(KeyParameter(key), iv);
final cipher = CBCBlockCipher(DESedeEngine())..init(false, params);
final paddedCipher = PaddedBlockCipherImpl(PKCS7Padding(), cipher);
final plaintext = paddedCipher.process(ciphertext);
// Parse nested entry
// The plaintext contains the BksKeyEntry fields
// We can use _readBksKey but we need to match the signature
// _readBksKey expects `data, pos`.
// Note: _readBksKey reads keyType etc.
// The sealed object content is usually the BksKeyEntry data starting AFTER the type/alias/timestamp?
// No, it's the `SecretKey` or `PrivateKey` object serialization.
// If it's BksKeyEntry, it includes type etc.
// Let's assume it starts with KeyType (1 byte).
// Warning: _readBksKey reads keyType then format then algorithm...
// Let's try to parse it.
final (nested, _) = BksKeyStore._readBksKey(plaintext, 0, storeType);
nested.certChain = certChain;
nested.alias = alias;
nested.timestamp = timestamp;
_nestedEntry = nested;
_encryptedData = null; // Decrypted
} catch (e) {
if (e is KeystoreException) rethrow;
throw DecryptionFailureException('BKS decryption failed: $e');
}
}