decrypt method

  1. @override
void decrypt(
  1. String password
)
override

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)

  final (salt, iterationCount, ciphertext) =
      _parseSealedData(_encryptedData!);

  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');
  }
}