Как бросить при использовании CryptoStream, не вызывая CryptoGraphicException

Я читаю зашифрованный файл и хочу выдать конкретную ошибку всякий раз, когда пароль неверный. Поскольку дешифрование с использованием неверного пароля будет просто успешным, но вернет бессмысленные данные, я хотел бы определить, является ли пароль правильным.

То, как я это делаю, я записываю "магическое значение" в зашифрованный файл; скажем, я пишу значение MaGiC в файл. Всякий раз, когда я расшифровываю файл, я гарантирую, что первые 5 байтов содержат MaGiC, Если нет, пароль, используемый для расшифровки файла, должен быть неправильным, и поэтому я выбрасываю InvalidPasswordException,

MAGICHEADER = new byte[] { 0x4D, 0x61, 0x47, 0x69, 0x43 };      // "MaGiC"

using (var fs = File.OpenRead(path))
using (var algo = ...)
using (var cs = new CryptoStream(fs, algo.CreateDecryptor(), CryptoStreamMode.Read))
{
    var hdr = new byte[MAGICHEADER.Length]; // Buffer
    cryptoStream.Read(hdr, 0, hdr.Length);  // Read magic header from encrypted stream

    // If the decrypted data doesn't equal the magic header this means the password is wrong
    if (!MAGICHEADER.SequenceEqual(hdr))
        throw new InvalidPasswordException();

    // ... read rest of file
}

Для краткости я пропустил много вещей (алгоритм, ключ, IV, размер блока, отступы, режим и т. Д.). Для этого конкретного случая, что может быть важно: я использую PKCS7 для заполнения (но я уверен, что все заполнение вызовет описанную проблему).

Теперь на вызывающей стороне я написал такой код:

try {
    var data = ReadFile("C:\foo\bar", "INCORRECTPASSWORD");
    // ... Do stuff with data
} catch (InvalidPasswordException) {
    // Oh noes! Wrong password! Ask to enter password again
}

Однако, к моему удивлению, InvalidPasswordException не был пойман; Я получил исключение, но типа CryptographicException: Заполнение недопустимо и не может быть удалено.,

Когда я отлаживаю проблему, я вижу InvalidPasswordException быть брошенным Я также думаю, что знаю, что происходит: InvalidPasswordException брошен, то using вызывает CryptoStream быть утилизированным и CryptoStream определяет, что, поскольку мы не находимся в конце потока, то, что осталось, должно быть "заполнением", которое затем вызывает исключение. Или, по крайней мере, что-то в этом роде.

Чтобы "вызвать" МОЕ исключение, я могу сделать что-то вроде:

if (!MAGICHEADER.SequenceEqual(hdr)) {
    try { cs.FlushFinalBlock(); } catch { }  // YUK!!
    throw new InvalidPasswordException();
}

Или же:

if (!MAGICHEADER.SequenceEqual(hdr)) {
    try { cs.Dispose(); } catch { }  // YUK!!
    throw new InvalidPasswordException();
}

Однако я надеялся на более элегантное решение. Есть ли способ, которым я могу инициализировать CryptoStream не выбрасывать на утилизацию? Или способ "закрыть" CryptoStream чисто без этого метания? я пробовал Close(), Clear() и т.д., но все эти методы также вызывают CryptoGraphicException заставляя меня обернуть их в try { ... } catch { ... } как раз перед тем как бросить свой InvalidPasswordException,

0 ответов

Другие вопросы по тегам