Saya telah mencari secara online apa arti pengecualian ini sehubungan dengan program saya tetapi tidak dapat menemukan solusi atau alasan mengapa hal itu terjadi pada program khusus saya. Saya telah menggunakan contoh yang disediakan msdn saya untuk mengenkripsi dan mendekripsi XmlDocument menggunakan algoritma Rijndael. Enkripsi berfungsi dengan baik tetapi ketika saya mencoba mendekripsi, saya mendapatkan pengecualian berikut:
Padding tidak valid dan tidak dapat dilepas
Adakah yang bisa memberi tahu saya apa yang dapat saya lakukan untuk mengatasi masalah ini? Kode saya di bawah ini adalah tempat saya mendapatkan kunci dan data lainnya. Jika cryptoMode salah, itu akan memanggil metode dekripsi, di mana pengecualian terjadi:
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);
}
c#
cryptography
Brown Love
sumber
sumber
Jawaban:
Rijndael / AES adalah block cypher. Ini mengenkripsi data dalam blok 128 bit (16 karakter). Padding kriptografi digunakan untuk memastikan bahwa blok pesan terakhir selalu berukuran benar.
Metode dekripsi Anda mengharapkan apa pun pengisi defaultnya, dan tidak menemukannya. Seperti yang dikatakan @NetSquirrel, Anda perlu secara eksplisit menyetel padding untuk enkripsi dan dekripsi. Kecuali jika Anda memiliki alasan untuk melakukan sebaliknya, gunakan padding PKCS # 7.
sumber
alg.Padding = PaddingMode.PKCS7;
Pastikan bahwa kunci Anda gunakan untuk mengenkripsi dan mendekripsi yang sama . Metode padding bahkan jika tidak secara eksplisit disetel harus tetap memungkinkan dekripsi / enkripsi yang tepat (jika tidak disetel, keduanya akan sama). Namun jika Anda karena alasan tertentu menggunakan sekumpulan kunci yang berbeda untuk dekripsi daripada yang digunakan untuk enkripsi, Anda akan mendapatkan kesalahan ini:
Jika Anda menggunakan beberapa algoritme untuk secara dinamis menghasilkan kunci yang tidak akan berfungsi. Keduanya harus sama untuk enkripsi dan dekripsi. Salah satu cara yang umum adalah meminta pemanggil menyediakan kunci dalam konstruktor kelas metode enkripsi, untuk mencegah proses enkripsi / dekripsi terlibat dalam pembuatan item ini. Ini berfokus pada tugas yang ada (mengenkripsi dan mendekripsi data) dan memerlukan
iv
dankey
harus disediakan oleh pemanggil.sumber
Untuk kepentingan orang-orang yang mencari, mungkin ada baiknya memeriksa input yang sedang didekripsi. Dalam kasus saya, info yang dikirim untuk dekripsi (salah) masuk sebagai string kosong. Ini mengakibatkan kesalahan padding.
Ini mungkin terkait dengan jawaban rossum, tetapi menurut saya itu layak untuk disebutkan.
sumber
Jika kunci dan vektor inisialisasi yang sama digunakan untuk encoding dan decoding, masalah ini tidak berasal dari decoding data tetapi dari encoding data.
Setelah Anda memanggil metode Write pada objek CryptoStream, Anda harus SELALU memanggil metode FlushFinalBlock sebelum metode Tutup.
Dokumentasi MSDN pada metode CryptoStream.FlushFinalBlock mengatakan:
" Memanggil metode Tutup akan memanggil FlushFinalBlock ... "
https://msdn.microsoft.com/en-US/library/system.security.cryptography.cryptostream.flushfinalblock(v=vs .110) .aspx
Ini salah. Memanggil metode Tutup hanya menutup CryptoStream dan Aliran keluaran.
Jika Anda tidak memanggil FlushFinalBlock sebelum Tutup setelah Anda menulis data untuk dienkripsi, saat mendekripsi data, panggilan ke metode Read atau CopyTo pada objek CryptoStream Anda akan memunculkan pengecualian CryptographicException (pesan: "Padding tidak valid dan tidak dapat dihapus").
Ini mungkin benar untuk semua algoritma enkripsi yang diturunkan dari SymmetricAlgorithm (Aes, DES, RC2, Rijndael, TripleDES), meskipun saya baru saja memverifikasi itu untuk AesManaged dan MemoryStream sebagai Output Stream.
Jadi, jika Anda menerima pengecualian CryptographicException ini pada dekripsi, baca nilai properti Stream Length Anda setelah Anda menulis data untuk dienkripsi, lalu panggil FlushFinalBlock dan baca nilainya lagi. Jika sudah berubah, Anda tahu bahwa memanggil FlushFinalBlock TIDAK opsional.
Dan Anda tidak perlu melakukan padding secara terprogram, atau memilih nilai properti Padding lainnya. Padding adalah tugas metode FlushFinalBlock.
.........
Komentar tambahan untuk Kevin:
Ya, CryptoStream memanggil FlushFinalBlock sebelum memanggil Tutup, tetapi sudah terlambat: ketika metode Tutup CryptoStream dipanggil, aliran keluaran juga ditutup.
Jika aliran keluaran Anda adalah MemoryStream, Anda tidak dapat membaca datanya setelah ditutup. Jadi, Anda perlu memanggil FlushFinalBlock di CryptoStream sebelum menggunakan data terenkripsi yang tertulis di MemoryStream.
Jika aliran keluaran Anda adalah FileStream, segalanya menjadi lebih buruk karena penulisan di-buffer. Konsekuensinya adalah byte tertulis terakhir mungkin tidak ditulis ke file jika Anda menutup aliran keluaran sebelum memanggil Flush di FileStream. Jadi sebelum memanggil Tutup di CryptoStream, Anda harus terlebih dahulu memanggil FlushFinalBlock di CryptoStream, lalu memanggil Flush di FileStream Anda.
sumber
Stream.Close()
panggilanthis.Dispose(true)
. Kode untukCryptoStream.Dispose(bool)
:if (disposing) { if (!this._finalBlockTransformed) { this.FlushFinalBlock(); } this._stream.Close(); }
Saat pertempuran serval, saya akhirnya memecahkan masalah.
(Catatan: Saya menggunakan AES standar sebagai algoritme simetris. Jawaban ini mungkin tidak cocok untuk semua orang.)
RijndaelManaged
kelas menjadiAESManaged
satu.KeySize
kelas algoritma, biarkan default.(Ini adalah langkah yang sangat penting. Saya rasa ada bug di properti KeySize.)
Berikut adalah daftar yang ingin Anda periksa argumen mana yang mungkin Anda lewatkan:
(array byte, panjang harus tepat salah satu dari 16, 24, 32 byte untuk ukuran kunci yang berbeda.)
(array byte, 16 byte)
(Salah satu CBC, CFB, CTS, ECB, OFB)
(Salah satu ANSIX923, ISO10126, Tidak Ada, PKCS7, Nol)
sumber
KeySize
langsung untuk saya. Oh, keunikan .NET :-(Masalah saya adalah bahwa passPhrase enkripsi tidak cocok dengan passPhrase dekripsi ... jadi kesalahan ini muncul .. sedikit menyesatkan.
sumber
Solusi yang memperbaiki milik saya adalah bahwa saya secara tidak sengaja telah menerapkan kunci yang berbeda ke metode Enkripsi dan Dekripsi.
sumber
Saya menemukan kesalahan ini ketika mencoba melewati jalur file yang tidak dienkripsi ke metode Decrypt. Solusinya adalah memeriksa apakah file yang dilewati dienkripsi terlebih dahulu sebelum mencoba mendekripsi
sumber
Skenario lain, sekali lagi untuk kepentingan orang yang mencari.
Bagi saya kesalahan ini terjadi selama metode Dispose () yang menutupi kesalahan sebelumnya yang tidak terkait dengan enkripsi.
Setelah komponen lain diperbaiki, pengecualian ini hilang.
sumber
Saya mengalami kesalahan padding ini ketika saya mengedit string terenkripsi secara manual dalam file (menggunakan notepad) karena saya ingin menguji bagaimana fungsi dekripsi akan berperilaku jika konten terenkripsi saya diubah secara manual.
Solusi bagi saya adalah menempatkan file
Seperti yang saya katakan, kesalahan padding saya adalah karena saya mengetik secara manual di atas teks yang didekripsi menggunakan notepad. Semoga jawaban saya dapat memandu Anda untuk solusi Anda.
sumber
Saya mengalami kesalahan yang sama. Dalam kasus saya itu karena saya telah menyimpan data terenkripsi dalam Database SQL. Tabel tempat penyimpanan data, memiliki tipe data biner (1000). Saat mengambil data dari database, itu akan mendekripsi 1000 byte ini, sementara sebenarnya ada 400 byte. Jadi menghapus nol trailing (600) dari hasil itu memperbaiki masalah.
sumber
Saya mengalami kesalahan ini dan secara eksplisit mengatur blocksize:
aesManaged.BlockSize = 128;
Setelah saya menghapusnya, itu berhasil.
sumber
Saya mengalami masalah yang sama saat mencoba memindahkan program Go ke C #. Ini berarti banyak data telah dienkripsi dengan program Go. Data ini sekarang harus didekripsi dengan C #.
Solusi terakhir adalah
PaddingMode.None
atau lebih tepatnyaPaddingMode.Zeros
.Metode kriptografi di Go:
... dan ...
Sekarang, dekripsi di C #:
Bagaimana masalah padding bisa dijelaskan? Tepat sebelum enkripsi, program Go memeriksa padding:
Bagian pentingnya adalah ini:
Sebuah array baru dibuat dengan panjang yang sesuai, sehingga panjangnya adalah kelipatan dari ukuran blok. Array baru ini diisi dengan angka nol. Metode salin kemudian menyalin data yang ada ke dalamnya. Dipastikan bahwa larik baru lebih besar dari data yang ada. Karenanya, ada nol di akhir larik.
Dengan demikian, kode C # dapat digunakan
PaddingMode.Zeros
. AlternatifnyaPaddingMode.None
hanya mengabaikan padding apa pun, yang juga berfungsi. Saya harap jawaban ini bermanfaat bagi siapa saja yang harus mem-port kode dari Go to C #, dll.sumber
Saya melaporkan kesalahan yang sama oleh klien. Saya pribadi tidak bisa menegurnya. Melihat kode metode Enkripsi dan Dekripsi , keduanya memiliki Padding yang disetel ke PaddingMode.PKCS7 . Dekripsi terlihat seperti ini dan saya tidak dapat melihat masalah terkait dengan ' FlushFinalBlock '. Bisakah seseorang menjelaskannya?
sumber
Saya mengalami kesalahan yang sama. Dalam kasus saya kata sandi yang diberikan lebih besar dari 16 berarti dienkripsi tetapi saat dekripsi saya mendapatkan kesalahan ini. Enkripsi:
Dekripsi:
sumber