AES:Padding is invalid and cannot be removed

AES:Padding is invalid and cannot be removed
2012-06-05T10:02:26+02:00
2012-06-05T19:22:19+02:00
2022-11-25T23:40:37+01:00
spawn85
Sziasztok! Lenne egy gondom, igazából jelszót szeretnék titkosítani AES-el, és írtam egy függvényt
az MSDN-es honlap alapján, ami sztringet fogad és a titkosított byte tömböt adja vissza, illetve egy
hozzá tartozó visszafejtőt. Működik is a program mindaddig, amig mondjuk egy függvényen belül hívogatom
ezeket a függvényeket (EncryptPassword,DecryptPassword). Viszont ki szeretném szerializálni a titkosított jelszót, majd
az alkalmazás újraindítását követően a visszafejteni.
És ekkor kivételt kapok a DecryptPassword hívásokor:

at System.Security.Cryptography.RijndaelManagedTransform.DecryptData(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount, Byte[]& outputBuffer, Int32 outputOffset, PaddingMode paddingMode, Boolean fLast)
at System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
at System.Security.Cryptography.CryptoStream.FlushFinalBlock()
at System.Security.Cryptography.CryptoStream.Dispose(Boolean disposing)
at System.IO.Stream.Close()
at TrackMon.WPFApplication.Helpers.PasswordEncription.DecryptStringFromBytes(Byte[] cipherText, Byte[] Key, Byte[] IV) in C:\...PasswordEncription.cs:line 309
at TrackMon.WPFApplication.Helpers.PasswordEncription.DecryptPassword(Byte[] password) in C:\...PasswordEncription.cs:line 229
at TrackMon.WPFApplication.ViewModels.MainWindowViewModel.<InitSetupParameters>b__50() in C:\...Configuration.cs:line 434

Ha megnézem, hogy kiírás előtt mi volt a byte tömböm tartalma, és megnézem hogy visszatöltés után mi lett, akkor byte-ra pontosan megegyezik.
Olvasgattam egy kicsit a téma után, de mindenhol azt írják, hogy akkor szokott ez a hiba bekövetkezni, ha hiányzik a RijndaelManaged osztálypéldány
kezelésekor a using statement. Próbáltam vele és nélküle, próbáltam variálni a kódon, de nem segített. Sajna túl sok időm nem is volt utánaolvansi.
Van valami, amit nagyon nem látok?

A függvények:


public static RijndaelManaged myRijndael = new RijndaelManaged(); public static byte[] EncryptPassword(string password) { using (myRijndael = new RijndaelManaged()) { byte[] encrypted = EncryptStringToBytes(password, HardwareKey, myRijndael.IV); return encrypted; } } public static string DecryptPassword(byte[] password) { using (myRijndael = new RijndaelManaged()) { string decrypted = DecryptStringFromBytes(password, HardwareKey, myRijndael.IV); return decrypted; } } public static byte[] EncryptStringToBytes(string plainText, byte[] Key, byte[] IV) { // Check arguments. if (plainText == null || plainText.Length <= 0) throw new ArgumentNullException("plainText"); if (Key == null || Key.Length <= 0) throw new ArgumentNullException("Key"); if (IV == null || IV.Length <= 0) throw new ArgumentNullException("Key"); byte[] encrypted; // Create an RijndaelManaged object // with the specified key and IV. using (RijndaelManaged rijAlg = new RijndaelManaged()) { rijAlg.Key = Key; rijAlg.IV = IV; // Create a decrytor to perform the stream transform. ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV); // Create the streams used for encryption. using (MemoryStream msEncrypt = new MemoryStream()) { using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) { using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)) { //Write all data to the stream. swEncrypt.Write(plainText); } encrypted = msEncrypt.ToArray(); } } } // Return the encrypted bytes from the memory stream. return encrypted; } public static string DecryptStringFromBytes(byte[] cipherText, byte[] Key, byte[] IV) { // Check arguments. if (cipherText == null || cipherText.Length <= 0) throw new ArgumentNullException("cipherText"); if (Key == null || Key.Length <= 0) throw new ArgumentNullException("Key"); if (IV == null || IV.Length <= 0) throw new ArgumentNullException("Key"); string plaintext = null; // Create an RijndaelManaged object // with the specified key and IV. using (RijndaelManaged rijAlg = new RijndaelManaged()) { rijAlg.Key = Key; rijAlg.IV = IV; // Create a decrytor to perform the stream transform. ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV); // Create the streams used for decryption. using (MemoryStream msDecrypt = new MemoryStream(cipherText)) { using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) { using (StreamReader srDecrypt = new StreamReader(csDecrypt)) { // Read the decrypted bytes from the decrypting stream // and place them in a string. plaintext = srDecrypt.ReadToEnd(); } } } } return plaintext; }
Mutasd a teljes hozzászólást!
Érdekelt a téma és kipróbáltam a kódodat.

Én egy ilyet kaptam:

CryptographicException: Padding is invalid and cannot be removed


Úgy tűnik, hogy ha az Initialization Vector-t fixre állítod, akkor működik.

Tehát itt:

EncryptStringToBytes(password, HardwareKey, myRijndael.IV);

és itt:

DecryptStringFromBytes(password, HardwareKey, myRijndael.IV);

ha a myRijndael.IV helyett egy statikus byte array-t adsz át mentéskor ill. betöltéskor, akkor működik.

Nem mélyedtem bele a témába, így nem tudom, hogy biztonsági szempontból ez mit jelent.

Az mindenesetre kijelenthető, hogy a jelszó elkódolása helyett inkább egy salted hash-t kéne tárolnod, hiszen nincs szükség arra, hogy visszaállítsd az eredetit, csak azt szeretnéd ellenőrizni, hogy stimmel-e a beírt jelszó.

Itt egy példa, hogy hogyan kell SHA256 hash-t generálni.
Mutasd a teljes hozzászólást!

  • Én például magát az Exception-t nem látom.
    Mutasd a teljes hozzászólást!
  • Érdekelt a téma és kipróbáltam a kódodat.

    Én egy ilyet kaptam:

    CryptographicException: Padding is invalid and cannot be removed


    Úgy tűnik, hogy ha az Initialization Vector-t fixre állítod, akkor működik.

    Tehát itt:

    EncryptStringToBytes(password, HardwareKey, myRijndael.IV);

    és itt:

    DecryptStringFromBytes(password, HardwareKey, myRijndael.IV);

    ha a myRijndael.IV helyett egy statikus byte array-t adsz át mentéskor ill. betöltéskor, akkor működik.

    Nem mélyedtem bele a témába, így nem tudom, hogy biztonsági szempontból ez mit jelent.

    Az mindenesetre kijelenthető, hogy a jelszó elkódolása helyett inkább egy salted hash-t kéne tárolnod, hiszen nincs szükség arra, hogy visszaállítsd az eredetit, csak azt szeretnéd ellenőrizni, hogy stimmel-e a beírt jelszó.

    Itt egy példa, hogy hogyan kell SHA256 hash-t generálni.
    Mutasd a teljes hozzászólást!
  • Értem. Köszönöm a választ, és a privátba küldött cikket is. Jelszó tárolásához persze elég lenne hash-t tárolni, és ellenőrizni hogy stimmel-e a beírt jelszó (így működnek a MemberShipProvider-ek is), esetemben azonban nem ez volt a lényeg, hanem az, hogy konfig fájlba leszerializálódjon a titkosított jelszó, és egy runtime generált hardware infomációkat tartalmazó kulcscsal csak az adott gépben lehessen ezt visszafejteni közvetlenül programindítást követően, amely jelszóval a kliens automatikusan bejelentkezik egy szerverre https-en keresztül. Ha a teljes programot lemásolják, akkor használhatatlanná váljon egy másik gépen. Persze ez így még mindig támadható, de egy lépéssel közelebb vagyok a válaszhoz. Most már több időm lesz utánajárni a témának. Köszi mindent.
    Mutasd a teljes hozzászólást!
Tetszett amit olvastál? Szeretnél a jövőben is értesülni a hasonló érdekességekről?
abcd