Заполнение недействительно и не может быть удалено?


126

Я поискал в Интернете, что означает это исключение по отношению к моей программе, но не могу найти решения или причины, по которой это происходит с моей конкретной программой. Я использовал пример, предоставленный моим msdn, для шифрования и дешифрования XmlDocument с использованием алгоритма Rijndael. Шифрование работает нормально, но когда я пытаюсь расшифровать, я получаю следующее исключение:

Заполнение недействительно и не может быть удалено

Может ли кто-нибудь сказать мне, что я могу сделать, чтобы решить эту проблему? В приведенном ниже коде я получаю ключ и другие данные. Если cryptoMode имеет значение false, он вызовет метод дешифрования, в котором возникает исключение:

public void Cryptography(XmlDocument doc, bool cryptographyMode)
{
    RijndaelManaged key = null;
    try
    {
    // Create a new Rijndael key.
    key = new RijndaelManaged();
    const string passwordBytes = "Password1234"; //password here 

    byte[] saltBytes = Encoding.UTF8.GetBytes("SaltBytes");
    Rfc2898DeriveBytes p = new Rfc2898DeriveBytes(passwordBytes, saltBytes);
    // sizes are devided by 8 because [ 1 byte = 8 bits ] 
    key.IV = p.GetBytes(key.BlockSize/8);
    key.Key = p.GetBytes(key.KeySize/8);

    if (cryptographyMode)
    {
        Ecrypt(doc, "Content", key);
    }
    else
    {
        Decrypt(doc, key);
    }

    }
    catch (Exception ex)
    {
    MessageBox.Show(ex.Message);
    }
    finally
    {
    // Clear the key.
    if (key != null)
    {
        key.Clear();
    }
    }

}

private void Decrypt(XmlDocument doc, SymmetricAlgorithm alg)
{
    // Check the arguments.  
    if (doc == null)
    throw new ArgumentNullException("Doc");
    if (alg == null)
    throw new ArgumentNullException("alg");

    // Find the EncryptedData element in the XmlDocument.
    XmlElement encryptedElement = doc.GetElementsByTagName("EncryptedData")[0] as XmlElement;

    // If the EncryptedData element was not found, throw an exception.
    if (encryptedElement == null)
    {
    throw new XmlException("The EncryptedData element was not found.");
    }


    // Create an EncryptedData object and populate it.
    EncryptedData edElement = new EncryptedData();
    edElement.LoadXml(encryptedElement);

    // Create a new EncryptedXml object.
    EncryptedXml exml = new EncryptedXml();


    // Decrypt the element using the symmetric key.
    byte[] rgbOutput = exml.DecryptData(edElement, alg); <----  I GET THE EXCEPTION HERE
    // Replace the encryptedData element with the plaintext XML element.
    exml.ReplaceData(encryptedElement, rgbOutput);

}

12
Можете ли вы попробовать, явно установив режим заполнения, идентичный как для шифрования, так и для дешифрования, чтобы быть идентичным. Например: alg.Padding = PaddingMode.NONE;
NetSquirrel

Как выглядит метод Encrypt ()?
csharptest.net

1
Спасибо, ребята, что сработало.
Brown Love

2
@NetSquirrel: спасибо за напоминание о PaddingMode.NONE. Это выводит меня из этой ошибки (к другой) ... Выполнение AES как на Java, так и на C #, и теперь я не знаю, почему C # жалуется на заполнение Java, хотя оба используют PKCS # 7
Хоанг Лонг,

Ответы:


81

Rijndael / AES - это блочный шифр. Он шифрует данные блоками по 128 бит (16 символов). Криптографическое заполнение используется, чтобы гарантировать, что последний блок сообщения всегда имеет правильный размер.

Ваш метод дешифрования ожидает заполнения по умолчанию и не находит его. Как говорит @NetSquirrel, вам необходимо явно установить заполнение как для шифрования, так и для дешифрования. Если у вас нет причин поступить иначе, используйте заполнение PKCS # 7.


7
как установить отступы явно ??
Ахмад Хаджар

7
Спасибо, я нашел его rj.Padding = PaddingMode.none; :)
Ахмад Хаджар

7
@AhmadHajjar Никакое заполнение не влияет на безопасность, не используйте его.
deviantfan

1
Привет, я установил отступы явно, но не работает. Не знаю, какие шаги я сделал не так. Пожалуйста помоги. alg.Padding = PaddingMode.PKCS7;
Джонни

21
Я понимаю, что это старая ветка. Но для тех, кто посещает, убедитесь, что вы очистили последний блок при шифровании данных.
Маркус

53

Убедитесь, что ключи, которые вы используете для шифрования и дешифрования , одинаковы . Метод заполнения, даже если он не установлен явно, должен по-прежнему обеспечивать правильное дешифрование / шифрование (если не задано, они будут такими же). Однако , если вы по какой - то причине используют другой набор ключей для расшифровки , чем используемый для шифрования вы будете получать эту ошибку:

Заполнение недействительно и не может быть удалено

Если вы используете какой-либо алгоритм для динамической генерации ключей, это не сработает. Они должны быть одинаковыми как для шифрования, так и для дешифрования. Один из распространенных способов состоит в том, чтобы вызывающий объект предоставил ключи в конструкторе класса методов шифрования, чтобы предотвратить участие процесса шифрования / дешифрования в создании этих элементов. Он сосредоточен на задаче (шифрование и дешифрование данных) и требует ivи keyдолжны быть предоставлена вызывающим.


Этот совет был очень полезен, потому что иногда ключи хранятся в app.config, и мы всегда должны быть уверены, что ключи, используемые для шифрования, такие же, как и для дешифрования.
Mário Meyrelles

@atconway Не могли бы вы взглянуть на мой вопрос? У меня аналогичная проблема, но в C ++ / CLI: stackoverflow.com/questions/57139447/…
Simple

1
Я бы предположил, что при повседневном использовании это, вероятно, самая вероятная причина, по которой люди будут сталкиваться с этой ошибкой. Особенно, если вы не возитесь с настройками отступов.
Дэн

28

В интересах поиска людей, возможно, стоит проверить расшифровку входных данных. В моем случае информация, отправляемая для дешифрования, была (ошибочно) введена как пустая строка. Это привело к ошибке заполнения.

Это может относиться к ответу Россума, но подумал, что стоит упомянуть.


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

Пустая строка тоже была для меня виноватой.
dotNET

В моем случае кодовая фраза не была установлена ​​(да, я знаю), но этот ответ направил меня в правильном направлении.
Джим

2
Моя проблема заключалась в том, что расшифровываемая строка преобразовывалась в нижний регистр, прежде чем я попытался ее расшифровать. Я был одержим заполнением, шифрами и всем остальным, но оказалось, что это был просто плохой ввод. Иногда нужно просто сделать шаг назад!
Tom Gerken

15

Если один и тот же ключ и вектор инициализации используются для кодирования и декодирования, эта проблема возникает не из-за декодирования данных, а из-за кодирования данных.

После того, как вы вызвали метод Write для объекта CryptoStream, вы должны ВСЕГДА вызывать метод FlushFinalBlock перед методом Close.

В документации MSDN по методу CryptoStream.FlushFinalBlock говорится:
« Вызов метода Close вызовет FlushFinalBlock ... »
https://msdn.microsoft.com/en-US/library/system.security.cryptography.cryptostream.flushfinalblock(v=vs .110) .aspx
Это неверно. Вызов метода Close просто закрывает CryptoStream и выходной поток.
Если вы не вызываете FlushFinalBlock перед Close после того, как вы записали данные для шифрования, при расшифровке данных вызов метода Read или CopyTo в вашем объекте CryptoStream вызовет исключение CryptographicException (сообщение: «Заполнение недопустимо и не может быть удалено»).

Это, вероятно, верно для всех алгоритмов шифрования, производных от SymmetricAlgorithm (Aes, DES, RC2, Rijndael, TripleDES), хотя я только что проверил это для AesManaged и MemoryStream в качестве выходного потока.

Итак, если вы получаете это исключение CryptographicException при расшифровке, прочтите значение свойства Output Stream Length после того, как вы записали данные для шифрования, затем вызовите FlushFinalBlock и снова прочитайте его значение. Если он изменился, вы знаете, что вызов FlushFinalBlock НЕ является необязательным.

И вам не нужно выполнять какие-либо дополнения программно или выбирать другое значение свойства Padding. Заполнение - это задание метода FlushFinalBlock.

.........

Дополнительное замечание для Кевина:

Да, CryptoStream вызывает FlushFinalBlock перед вызовом Close, но уже слишком поздно: когда вызывается метод CryptoStream Close, выходной поток также закрывается.

Если ваш выходной поток является MemoryStream, вы не можете прочитать его данные после его закрытия. Таким образом, вам нужно вызвать FlushFinalBlock в своем CryptoStream перед использованием зашифрованных данных, записанных в MemoryStream.

Если ваш выходной поток - FileStream, дела обстоят хуже, потому что запись буферизуется. В результате последние записанные байты могут не быть записаны в файл, если вы закроете выходной поток перед вызовом Flush для FileStream. Поэтому перед вызовом Close в CryptoStream вам сначала нужно вызвать FlushFinalBlock в своем CryptoStream, а затем вызвать Flush в своем FileStream.


1
Почему ты говоришь, что это неправильно? Код для Stream.Close()звонков this.Dispose(true). Код для CryptoStream.Dispose(bool):if (disposing) { if (!this._finalBlockTransformed) { this.FlushFinalBlock(); } this._stream.Close(); }
Кевин Дойон,

1
Это решило мою проблему. Я правильно утилизировал cryptoStream, но вызов dispose произошел «слишком поздно», как вы и сказали. Это привело к ошибке «недопустимое заполнение», как описано. Добавив cryptoStream.FlushFinalBlock (), ошибка недопустимого заполнения была устранена. Спасибо!
Daniel Lambert

14

Сервал времен боев, я наконец решил проблему.
(Примечание: в качестве симметричного алгоритма я использую стандартный AES. Этот ответ может подойти не всем.)

  1. Измените класс алгоритма. Замени RijndaelManagedкласс на AESManagedодин.
  2. Не указывать явно KeySizeкласс алгоритма, оставил их по умолчанию.
    (Это очень важный шаг. Я думаю, что в свойстве KeySize есть ошибка.)

Вот список, который вы хотите проверить, какой аргумент вы могли пропустить:

  • Ключ
    (байтовый массив, длина должна быть ровно одной из 16, 24, 32 байтов для разного размера ключа.)
  • IV
    (байтовый массив, 16 байт)
  • CipherMode
    (один из CBC, CFB, CTS, ECB, OFB)
  • PaddingMode
    (один из ANSIX923, ISO10126, None, PKCS7, Zeros)

3
Неявная установка сразу KeySizeустранила это для меня. О причуды .NET :-(
Джон

Обратите внимание, что это похоже на регресс самой .NET Framework. У меня есть код, который раньше работал с RijndaelManaged, но перестал работать, и, просто изменив его на AesManaged / AesCryptoServiceProvider, он снова работает. У меня даже не было кода, явно устанавливающего KeySize. Так что, если вас это укусило, почувствуйте себя лучше - вина может лежать не на вас, а на самой .NET Framework.
Usas

6

Моя проблема заключалась в том, что passPhrase для шифрования не соответствовал passPhrase для дешифрования ... поэтому он выдал эту ошибку ... немного вводит в заблуждение.


На самом деле это правда, что мы используем PaddingMode.PKCS7 для шифрования и дешифрования, но я получил то же сообщение об ошибке. Также у нас есть среда Stage и Dev с разными ключевыми значениями. Когда я использовал соответствующий ключ -environment-key, это исключение было решено ...
Major

Хотя все вышеперечисленные ответы хороши, и вы должны использовать одно и то же заполнение для шифрования и дешифрования (ничего НЕ рекомендуется!), На самом деле этот ответ также может быть правдой. Когда я использовал правильный ключ, специфичный для среды, исключение «System.Security.Cryptography.CryptographicException: Padding недействителен и не может быть удален». было решено. Так что да, это может вводить в заблуждение.
Major

Если с помощью "passPhrase" вы говорите о точном значении для шифрования / дешифрования (не проблема с использованием неправильного ключа), то да, это была моя проблема. В моем случае исходное зашифрованное значение было длиннее, чем разрешено в моем поле таблицы базы данных, поэтому оно усекалось, чтобы соответствовать, а я этого не осознавал. Затем при расшифровке этого усеченного значения возникло это исключение.
Дэвид Гандерсон

2

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


1

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

if (Sec.IsFileEncrypted(e.File.FullName))
{
    var stream = Sec.Decrypt(e.File.FullName);
} 
else
{
    // non-encrypted scenario  
}

1
Я оспариваю всякую хитрость и бегство трусов насчет обоснованности этого решения.
полезноBee

+1, потому что это исключение возникает, когда вы дважды расшифровываете или расшифровываете что-то незашифрованное. Я прочитал этот ответ как «вы уверены, что данные действительно зашифрованы?».
Херардо Гриньоли,

0

Другой сценарий, опять же в интересах поиска людей.

Для меня эта ошибка возникла во время метода Dispose (), который замаскировал предыдущую ошибку, не связанную с шифрованием.

После исправления другого компонента это исключение исчезло.


3
Какая предыдущая ошибка не связана с шифрованием?
NStuke

0

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

Решением для меня было разместить

        try
            decryption stuff....
        catch
             inform decryption will not be carried out.
        end try

Как я уже сказал, моя ошибка заполнения была связана с тем, что я вручную набирал расшифрованный текст с помощью блокнота. Может быть, мой ответ поможет вам найти решение.


0

У меня была такая же ошибка. В моем случае это произошло потому, что я сохранил зашифрованные данные в базе данных SQL. Таблица, в которой хранятся данные, имеет двоичный (1000) тип данных. При получении данных из базы данных он расшифровывает эти 1000 байтов, тогда как на самом деле там было 400 байтов. Таким образом, удаление конечных нулей (600) из результата решило проблему.


0

У меня была эта ошибка, и я явно устанавливал размер блока: aesManaged.BlockSize = 128;

Как только я удалил это, все заработало.


0

У меня была такая же проблема при переносе программы Go на C #. Это означает, что с помощью программы Go уже было зашифровано много данных. Теперь эти данные необходимо расшифровать с помощью C #.

Окончательное решение было PaddingMode.Noneточнее PaddingMode.Zeros.

Криптографические методы в Go:

import (
    "crypto/aes"
    "crypto/cipher"
    "crypto/sha1"
    "encoding/base64"
    "io/ioutil"
    "log"

    "golang.org/x/crypto/pbkdf2"
)

func decryptFile(filename string, saltBytes []byte, masterPassword []byte) (artifact string) {

    const (
        keyLength         int = 256
        rfc2898Iterations int = 6
    )

    var (
        encryptedBytesBase64 []byte // The encrypted bytes as base64 chars
        encryptedBytes       []byte // The encrypted bytes
    )

    // Load an encrypted file:
    if bytes, bytesErr := ioutil.ReadFile(filename); bytesErr != nil {
        log.Printf("[%s] There was an error while reading the encrypted file: %s\n", filename, bytesErr.Error())
        return
    } else {
        encryptedBytesBase64 = bytes
    }

    // Decode base64:
    decodedBytes := make([]byte, len(encryptedBytesBase64))
    if countDecoded, decodedErr := base64.StdEncoding.Decode(decodedBytes, encryptedBytesBase64); decodedErr != nil {
        log.Printf("[%s] An error occur while decoding base64 data: %s\n", filename, decodedErr.Error())
        return
    } else {
        encryptedBytes = decodedBytes[:countDecoded]
    }

    // Derive key and vector out of the master password and the salt cf. RFC 2898:
    keyVectorData := pbkdf2.Key(masterPassword, saltBytes, rfc2898Iterations, (keyLength/8)+aes.BlockSize, sha1.New)
    keyBytes := keyVectorData[:keyLength/8]
    vectorBytes := keyVectorData[keyLength/8:]

    // Create an AES cipher:
    if aesBlockDecrypter, aesErr := aes.NewCipher(keyBytes); aesErr != nil {
        log.Printf("[%s] Was not possible to create new AES cipher: %s\n", filename, aesErr.Error())
        return
    } else {

        // CBC mode always works in whole blocks.
        if len(encryptedBytes)%aes.BlockSize != 0 {
            log.Printf("[%s] The encrypted data's length is not a multiple of the block size.\n", filename)
            return
        }

        // Reserve memory for decrypted data. By definition (cf. AES-CBC), it must be the same lenght as the encrypted data:
        decryptedData := make([]byte, len(encryptedBytes))

        // Create the decrypter:
        aesDecrypter := cipher.NewCBCDecrypter(aesBlockDecrypter, vectorBytes)

        // Decrypt the data:
        aesDecrypter.CryptBlocks(decryptedData, encryptedBytes)

        // Cast the decrypted data to string:
        artifact = string(decryptedData)
    }

    return
}

... и ...

import (
    "crypto/aes"
    "crypto/cipher"
    "crypto/sha1"
    "encoding/base64"
    "github.com/twinj/uuid"
    "golang.org/x/crypto/pbkdf2"
    "io/ioutil"
    "log"
    "math"
    "os"
)

func encryptFile(filename, artifact string, masterPassword []byte) (status bool) {

    const (
        keyLength         int = 256
        rfc2898Iterations int = 6
    )

    status = false
    secretBytesDecrypted := []byte(artifact)

    // Create new salt:
    saltBytes := uuid.NewV4().Bytes()

    // Derive key and vector out of the master password and the salt cf. RFC 2898:
    keyVectorData := pbkdf2.Key(masterPassword, saltBytes, rfc2898Iterations, (keyLength/8)+aes.BlockSize, sha1.New)
    keyBytes := keyVectorData[:keyLength/8]
    vectorBytes := keyVectorData[keyLength/8:]

    // Create an AES cipher:
    if aesBlockEncrypter, aesErr := aes.NewCipher(keyBytes); aesErr != nil {
        log.Printf("[%s] Was not possible to create new AES cipher: %s\n", filename, aesErr.Error())
        return
    } else {

        // CBC mode always works in whole blocks.
        if len(secretBytesDecrypted)%aes.BlockSize != 0 {
            numberNecessaryBlocks := int(math.Ceil(float64(len(secretBytesDecrypted)) / float64(aes.BlockSize)))
            enhanced := make([]byte, numberNecessaryBlocks*aes.BlockSize)
            copy(enhanced, secretBytesDecrypted)
            secretBytesDecrypted = enhanced
        }

        // Reserve memory for encrypted data. By definition (cf. AES-CBC), it must be the same lenght as the plaintext data:
        encryptedData := make([]byte, len(secretBytesDecrypted))

        // Create the encrypter:
        aesEncrypter := cipher.NewCBCEncrypter(aesBlockEncrypter, vectorBytes)

        // Encrypt the data:
        aesEncrypter.CryptBlocks(encryptedData, secretBytesDecrypted)

        // Encode base64:
        encodedBytes := make([]byte, base64.StdEncoding.EncodedLen(len(encryptedData)))
        base64.StdEncoding.Encode(encodedBytes, encryptedData)

        // Allocate memory for the final file's content:
        fileContent := make([]byte, len(saltBytes))
        copy(fileContent, saltBytes)
        fileContent = append(fileContent, 10)
        fileContent = append(fileContent, encodedBytes...)

        // Write the data into a new file. This ensures, that at least the old version is healthy in case that the
        // computer hangs while writing out the file. After a successfully write operation, the old file could be
        // deleted and the new one could be renamed.
        if writeErr := ioutil.WriteFile(filename+"-update.txt", fileContent, 0644); writeErr != nil {
            log.Printf("[%s] Was not able to write out the updated file: %s\n", filename, writeErr.Error())
            return
        } else {
            if renameErr := os.Rename(filename+"-update.txt", filename); renameErr != nil {
                log.Printf("[%s] Was not able to rename the updated file: %s\n", fileContent, renameErr.Error())
            } else {
                status = true
                return
            }
        }

        return
    }
}

Теперь расшифровка на C #:

public static string FromFile(string filename, byte[] saltBytes, string masterPassword)
{
    var iterations = 6;
    var keyLength = 256;
    var blockSize = 128;
    var result = string.Empty;
    var encryptedBytesBase64 = File.ReadAllBytes(filename);

    // bytes -> string:
    var encryptedBytesBase64String = System.Text.Encoding.UTF8.GetString(encryptedBytesBase64);

    // Decode base64:
    var encryptedBytes = Convert.FromBase64String(encryptedBytesBase64String);
    var keyVectorObj = new Rfc2898DeriveBytes(masterPassword, saltBytes.Length, iterations);
    keyVectorObj.Salt = saltBytes;
    Span<byte> keyVectorData = keyVectorObj.GetBytes(keyLength / 8 + blockSize / 8);
    var key = keyVectorData.Slice(0, keyLength / 8);
    var iv = keyVectorData.Slice(keyLength / 8);

    var aes = Aes.Create();
    aes.Padding = PaddingMode.Zeros;
    // or ... aes.Padding = PaddingMode.None;
    var decryptor = aes.CreateDecryptor(key.ToArray(), iv.ToArray());
    var decryptedString = string.Empty;

    using (var memoryStream = new MemoryStream(encryptedBytes))
    {
        using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
        {
            using (var reader = new StreamReader(cryptoStream))
            {
                decryptedString = reader.ReadToEnd();
            }
        }
    }

    return result;
}

Как можно объяснить проблему с заполнением? Непосредственно перед шифрованием программа Go проверяет заполнение:

// CBC mode always works in whole blocks.
if len(secretBytesDecrypted)%aes.BlockSize != 0 {
    numberNecessaryBlocks := int(math.Ceil(float64(len(secretBytesDecrypted)) / float64(aes.BlockSize)))
    enhanced := make([]byte, numberNecessaryBlocks*aes.BlockSize)
    copy(enhanced, secretBytesDecrypted)
    secretBytesDecrypted = enhanced
}

Важная часть заключается в следующем:

enhanced := make([]byte, numberNecessaryBlocks*aes.BlockSize)
copy(enhanced, secretBytesDecrypted)

Создается новый массив соответствующей длины, так что длина кратна размеру блока. Этот новый массив заполнен нулями. Затем метод копирования копирует в него существующие данные. Гарантируется, что новый массив больше существующих данных. Соответственно в конце массива стоят нули.

Таким образом, код C # может использовать PaddingMode.Zeros. Альтернатива PaddingMode.Noneпросто игнорирует любые отступы, что также работает. Надеюсь, этот ответ будет полезен всем, кому нужно переносить код с Go на C # и т. Д.


0

Клиент сообщил мне об этой же ошибке. Я лично не могу это воспроизвести. Если посмотреть на код методов Encrypt и Decrypt , у обоих Padding установлено значение PaddingMode.PKCS7 . Расшифровка выглядит так, и я не вижу в ней проблемы с « FlushFinalBlock ». Может кто-нибудь пролить свет на это?

public string Decrypt(string cipherText)
{
  if (string.IsNullOrEmpty(cipherText))
    return "";
  string result;
  Encoding byteEncoder = Encoding.Default;

  byte[] rijnKey = byteEncoder.GetBytes(Password);
  byte[] rijnIv = byteEncoder.GetBytes(InitialVector);
  RijndaelManaged rijn = new RijndaelManaged { Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7 };

  using (MemoryStream msDecrypt = new MemoryStream(Convert.FromBase64String(cipherText)))
  {
    using (ICryptoTransform decryptor = rijn.CreateDecryptor(rijnKey, rijnIv))
    {
      using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
      {
                    using (StreamReader swDecrypt = new StreamReader(csDecrypt))
                    {
                        result = swDecrypt.ReadToEnd();
                    }
                }
    }
  }
  rijn.Clear();      
  return result.Replace("\0", "");
}

0

У меня была такая же ошибка. В моем случае данный пароль больше 16 означает, что он зашифрован, но при расшифровке я получаю эту ошибку. Шифрование:

string keyString = "CDFUYP@ssw0rd123";
            var key = Encoding.UTF8.GetBytes(keyString);            
            using (var aesAlg = Aes.Create())
            {
                using (var encryptor = aesAlg.CreateEncryptor(key, aesAlg.IV))
                {
                    using (var msEncrypt = new MemoryStream())
                    {
                        using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                        using (var swEncrypt = new StreamWriter(csEncrypt))
                        {
                            swEncrypt.Write(text);
                        }                          
                        var iv = aesAlg.IV;

                        var decryptedContent = msEncrypt.ToArray();

                        var result = new byte[iv.Length + decryptedContent.Length];

                        Buffer.BlockCopy(iv, 0, result, 0, iv.Length);
                        Buffer.BlockCopy(decryptedContent, 0, result, iv.Length, decryptedContent.Length);

                        var encryptedString = Convert.ToBase64String(result);
                        var decryptedString = Decrypt(encryptedString);
                        if (decryptedString == null)
                        {
                            return null;
                        }
                        return encryptedString;

                    }
                }

Дешифрирование:

 string keyString = "CDFUYP@ssw0rd123";
            var fullCipher = Convert.FromBase64String(cipherText);
            var iv = new byte[16];
            var cipher = new byte[16];
            Buffer.BlockCopy(fullCipher, 0, iv, 0, iv.Length);
            Buffer.BlockCopy(fullCipher, iv.Length, cipher, 0, iv.Length);
            var key = Encoding.UTF8.GetBytes(keyString);

            using (var aesAlg = Aes.Create())
            {
                using (var decryptor = aesAlg.CreateDecryptor(key, iv))
                {
                    string result;
                    using (var msDecrypt = new MemoryStream(cipher))
                    {
                        using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                        {
                            using (var srDecrypt = new StreamReader(csDecrypt))
                            {
                                result = srDecrypt.ReadToEnd();
                            }
                        }
                    }

                    return result;
                }
            }

Привет @sundarraj, это вопрос?
Тьяго Мартинс Перес 李大仁
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.