Proč se špatné heslo příčina „Polstrování je neplatná a nelze ji odstranit?“

hlasů
39

Potřeboval jsem nějaký jednoduchý řetězec šifrování, tak jsem napsal následující kód (s velkým množstvím „inspirace“ od zde ):

    // create and initialize a crypto algorithm
    private static SymmetricAlgorithm getAlgorithm(string password) {
        SymmetricAlgorithm algorithm = Rijndael.Create();
        Rfc2898DeriveBytes rdb = new Rfc2898DeriveBytes(
            password, new byte[] {
            0x53,0x6f,0x64,0x69,0x75,0x6d,0x20,             // salty goodness
            0x43,0x68,0x6c,0x6f,0x72,0x69,0x64,0x65
        }
        );
        algorithm.Padding = PaddingMode.ISO10126;
        algorithm.Key = rdb.GetBytes(32);
        algorithm.IV = rdb.GetBytes(16);
        return algorithm;
    }

    /* 
     * encryptString
     * provides simple encryption of a string, with a given password
     */
    public static string encryptString(string clearText, string password) {
        SymmetricAlgorithm algorithm = getAlgorithm(password);
        byte[] clearBytes = System.Text.Encoding.Unicode.GetBytes(clearText);
        MemoryStream ms = new MemoryStream();
        CryptoStream cs = new CryptoStream(ms, algorithm.CreateEncryptor(), CryptoStreamMode.Write);
        cs.Write(clearBytes, 0, clearBytes.Length);
        cs.Close();
        return Convert.ToBase64String(ms.ToArray());
    }

    /*
     * decryptString
     * provides simple decryption of a string, with a given password
     */
    public static string decryptString(string cipherText, string password) {
        SymmetricAlgorithm algorithm = getAlgorithm(password);
        byte[] cipherBytes = Convert.FromBase64String(cipherText);
        MemoryStream ms = new MemoryStream();
        CryptoStream cs = new CryptoStream(ms, algorithm.CreateDecryptor(), CryptoStreamMode.Write);
        cs.Write(cipherBytes, 0, cipherBytes.Length);
        cs.Close();            
        return System.Text.Encoding.Unicode.GetString(ms.ToArray());
    }

Kód se zdá, že funguje, kromě toho, že při dešifrování dat s nesprávným klíčem, jsem si CryptographicException - „Polstrování je neplatná a nemůže být odstraněn“ - na lince cs.Close () v decryptString.

Příklad kódu:

    string password1 = password;
    string password2 = letmein;
    string startClearText = The quick brown fox jumps over the lazy dog;
    string cipherText = encryptString(startClearText, password1);
    string endClearText = decryptString(cipherText, password2);     // exception thrown

Moje otázka zní, je to, aby se dalo očekávat? Já bych si myslel, že dešifrování se špatným heslem by prostě za následek nesmysl výkonu, spíše než výjimkou.

Položena 15/08/2008 v 00:14
zdroj uživatelem
V jiných jazycích...                            


10 odpovědí

hlasů
26

Ačkoli toto bylo již odpověděl Myslím, že by bylo dobré vysvětlit, proč je třeba očekávat.

Schéma polstrování se obvykle používá, protože většina kryptografických filtry nejsou sémanticky bezpečné a aby se zabránilo některé formy cryptoatacks. Například, obvykle v RSA OAEP schéma výplň se používá, které brání některé druhy útoků (například vybraného holého útoku nebo oslepující ).

Schéma polstrování připojí nějaké (obvykle) náhodné smetí do zprávy m před odesláním zprávy. Ve způsobu OAEP, například, jsou použity dvě Věštci (to je zjednodušené vysvětlení):

  1. Vzhledem k velikosti modulu vy padd K1 bity 0 a K0 bitů s náhodným číslem.
  2. Pak použitím nějaké transformaci na zprávu, kterou získat čalouněný zpráva Wich je zašifrována a odeslána.

Který vám poskytne randomizaci zpráv a s způsob, jak otestovat, zda zpráva je odpad, či nikoliv. Vzhledem k tomu, systém polstrování je reverzibilní při dešifrování zprávy, zatímco vy nemůžete nic o integritě samotné zprávy říkají, můžete ve skutečnosti dělat nějaké tvrzení o polstrování a tak můžete zjistit, zda zpráva byla správně dešifrovat nebo děláte něco špatně (tj někdo manipuloval se zprávou nebo používáte nesprávný klíč)

Odpovězeno 25/08/2008 v 16:46
zdroj uživatelem

hlasů
16

Zažil jsem podobné „Polstrování je neplatná a nemůže být odstraněn.“ výjimka, ale v mém případě klíčovým IV a polstrování byly správné.

Ukázalo se, že proplachování šifrovací proudu je vše, co chybělo.

Takhle:

            MemoryStream msr3 = new MemoryStream();
            CryptoStream encStream = new CryptoStream(msr3, RijndaelAlg.CreateEncryptor(), CryptoStreamMode.Write);
            encStream.Write(bar2, 0, bar2.Length);
            // unless we flush the stream we would get "Padding is invalid and cannot be removed." exception when decoding
            encStream.FlushFinalBlock();
            byte[] bar3 = msr3.ToArray();
Odpovězeno 07/11/2013 v 12:44
zdroj uživatelem

hlasů
5

Pokud chcete, aby vaše používání za správné, měli byste přidat autentizaci do svého ciphertext, takže si můžete ověřit, zda se jedná o správný PASWORD nebo že ciphertext nebyl změněn. Polstrování používáte ISO10126 bude hodit pouze výjimku v případě, že poslední byte není dešifrovat jako jeden z 16 platných hodnotách polstrování (0x01-0x10). Takže máte 1/16 šanci to není házení výjimka se špatným heslem, kde, pokud si to ověřit máte deterministický způsob, jak zjistit, zda váš dešifrování je platný.

Použitím kryptografických API, zatímco zdánlivě jednoduché, ve skutečnosti je poměrně snadné udělat chybu. Například používáte pevnou sůl pro pro vás klíčem a iv odvození, to znamená, že každý ciphertext šifrované se stejným heslem bude znovu použít to IV s tím klíčem, který porušuje sémantické zabezpečení v režimu CBC IV musí být i nepředvídatelné a jedinečná daný klíč.

Z tohoto důvodu snadné udělat chybu, mám fragment kódu, který jsem se snažit, aby přezkoumala a aktuální (komentáře, otázky přivítat):

Moderní příklady Symetrické ověřený Encryption řetězce C #.

Používáte-li to AESThenHMAC.AesSimpleDecryptWithPassword(ciphertext, password)při použití nesprávné heslo, nullje vrácena, pokud ciphertext nebo iv byl změněn po šifrování nullje vrácena, budete nikdy dostat nevyžádané data zpět, nebo výjimka polstrování.

Odpovězeno 20/02/2013 v 03:01
zdroj uživatelem

hlasů
3

Pokud jste vyloučit klíčovou nesoulad, pak kromě FlushFinalBlock()(viz Yaniv odpověď), volání Close()na CryptoStreamvůli také stačit.

Pokud jste vyčištění zdrojů striktně usingbloky, ujistěte se, že hnízdo blok pro CryptoStreamsebe:

using (MemoryStream ms = new MemoryStream())
using (var enc = RijndaelAlg.CreateEncryptor())
{
  using (CryptoStream encStream = new CryptoStream(ms, enc, CryptoStreamMode.Write))
  {
    encStream.Write(bar2, 0, bar2.Length);
  } // implicit close
  byte[] encArray = ms.ToArray();
}

Byl jsem pokousán tento (nebo podobné):

using (MemoryStream ms = new MemoryStream())
using (var enc = RijndaelAlg.CreateEncryptor())
using (CryptoStream encStream = new CryptoStream(ms, enc, CryptoStreamMode.Write))
{
  encStream.Write(bar2, 0, bar2.Length);
  byte[] encArray = ms.ToArray();
} // implicit close -- too late!
Odpovězeno 13/10/2016 v 10:40
zdroj uživatelem

hlasů
3

Ano, toto je třeba očekávat, nebo alespoň jeho přesně to, co se stane, když naše šifrovací rutiny dostat non-decryptable dat

Odpovězeno 15/08/2008 v 00:25
zdroj uživatelem

hlasů
2

Dalším důvodem výjimky může být spor mezi několika nití s použitím dekódovací logiku - nativní implementací ICryptoTransform jsou není thread-safe (např SymmetricAlgorithm), takže by měl být kladen na exkluzivní části, například použitím zámku . Naleznete zde pro více informací: http://www.make-awesome.com/2011/07/system-security-cryptography-and-thread-safety/

Odpovězeno 10/10/2016 v 10:43
zdroj uživatelem

hlasů
1

Tam mohou být některé nepřečtené bytů v CryptoStream. Zavření Před úplným čtení proudu byla příčinou chyby v mém programu.

Odpovězeno 04/08/2010 v 10:16
zdroj uživatelem

hlasů
0

Měl jsem podobný problém, problém v dešifrovacím metody byla inicializace prázdnou paměťovou proudu. když to fungovalo, když jsem se inicializovat ji s šifrovaný text bytového pole, jako je tento:

MemoryStream ms = new MemoryStream(cipherText)
Odpovězeno 02/02/2015 v 12:13
zdroj uživatelem

hlasů
-1

Byl jsem také získat co Polstrování je neplatná a nelze ji odstranit zprávu. Jak již bylo řečeno někdo výše, příčinou byla některá pufrované bytů v CryptoStream. To je, jak to bylo opraveno voláním metody FlushFinalBlock ():

using (CryptoStream cryptoStream = new CryptoStream(memoryStream, algorithm.CreateDecryptor(), CryptoStreamMode.Write)) {
    cryptoStream.Write(bytes, 0, bytes.Length);
    cryptoStream.FlushFinalBlock();
    result = Encoding.UTF8.GetString(memoryStream.ToArray());
    return result;
}
Odpovězeno 08/07/2016 v 18:51
zdroj uživatelem

hlasů
-1

Odpověď aktualizovány uživatelem „atconway“ pracoval pro mě.

Problém nebyl s polstrováním, ale klíčem, který byl při šifrování a dešifrování jinak. Klíč a iv by měla být stejná v průběhu encypting a dešifrování stejnou hodnotu.

Odpovězeno 15/04/2015 v 20:12
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more