561 Chương 14: Mật mã DES DESCryptoServiceProvider 64 TripleDES hay 3DES TripleDESCryptoServiceProvider 128, 192 RC2 RC2CryptoServiceProvider 40, 48 56, 64, 72, 80, 88, 96, 104, 112, 120, 128 Rijndael RijndaelManaged 128, 192, 256 Mặc dù bạn có thể tạo ra các thể hiện của các lớp giải thuật đối xứng một cách trực tiếp, lớp cơ sở SymmetricAlgorithm là một factory cho các lớp hiện thực cụ thể dẫn xuất từ đó. Gọi phương thức tĩnh SymmetricAlgorithm.Create với đối số là tên giải thuật sẽ trả về một đối tượng thuộc kiểu đã được chỉ định. Sử dụng factory cho phép bạn viết mã lệnh tổng quát, và mã lệnh này có thể làm việc với bất kỳ hiện thực giải thuật đối xứng nào: string algName = "3DES"; SymmetricAlgorithm alg = SymmetricAlgorithm.Create(algName); Nếu bạn gọi SymmetricAlgorithm.Create và không chỉ định tên giải thuật, SymmetricAlgorithm sẽ trả về một đối tượng RijndaelManaged . Nếu bạn chỉ định một giá trị không hợp lệ, SymmetricAlgorithm sẽ trả về null . Bạn có thể cấu hình các ánh xạ tên/lớp mới bằng file cấu hình (xem tài liệu . NET Framework SDK để biết thêm chi tiết). Trước khi mật hóa dữ liệu với một trong các lớp giải thuật đối xứng, bạn cần một khóa (key) và một vectơ khởi động (initialization vector). Khóa là thông tin bí mật dùng để mật hóa và giải mật hóa dữ liệu. Vectơ khởi động là dữ liệu ngẫu nhiên được truyền cho giải thuật mật hóa. Bạn phải sử dụng cùng khóa và vectơ khởi động cho cả mật hóa và giải mật hóa dữ liệu. Tuy nhiên, chỉ có khóa là cần phải được giữ bí mật, bạn có thể lưu trữ hay gửi vectơ khởi động cùng với dữ liệu đã-được-mật-hóa. Khóa cho mỗi lớp dẫn xuất từ SymmetricAlgorithm có thể được truy xuất thông qua thuộc tính Key , và vectơ khởi động có thể được truy xuất thông qua thuộc tính IV . Cách đơn giản nhất và ít lỗi nhất để tạo khóa và vectơ khởi động mới là để lớp tự tạo chúng giùm bạn. Sau khi đã tạo một đối tượng giải thuật đối xứng, nếu bạn không thiết lập các thuộc tính Key và IV cho nó, đối tượng này sẽ tự động tạo ra các giá trị mới ngay khi bạn cho gọi một thành viên có sử dụng các giá trị Key và IV . Một khi đã được thiết lập, đối tượng giải thuật đối xứng sẽ tiếp tục sử dụng các giá trị Key và IV này. Để thay đổi giá trị của Key và IV , bạn có thể gán trực tiếp các giá trị mới hoặc gọi phương thức GenerateKey và GenerateIV (buộc đối tượng giải thuật đối xứng tạo ra các giá trị ngẫu nhiên mới). Bạn không thể trực tiếp thực hiện mật hóa và giải mật hóa với một đối tượng giải thuật đối xứng. Một khi đã tạo và cấu hình đối tượng giải thuật đối xứng, bạn phải gọi phương thức CreateEncryptor hay CreateDecryptor của nó để thu lấy một đối tượng có hiện thực giao diện System.Security.Cryptography.ICryptoTransform . Kế đó, bạn có thể sử dụng các phương thức của đối tượng ICryptoTransform này để mật hóa và giải mật hóa dữ liệu. Tuy nhiên, đối tượng ICryptoTransform yêu cầu bạn truyền dữ liệu theo từng khối (có kích thước cố định) và lấp (bằng tay) khối dữ liệu cuối cùng vì khối này ít khi có kích thước đúng. 562 Chương 14: Mật mã Giao diện ICryptoTransform không quá khó sử dụng, nhưng không mấy thân thiện; do vậy .NET Framework kèm thêm lớp System.Security.Cryptography.CryptoStream . Đây là lớp dẫn xuất từ System.IO.Stream , dùng để đơn giản hóa việc mật hóa và giải mật hóa dữ liệu được đọc từ các đối tượng Stream khác. Lớp này cho phép bạn mật hóa và giải mật hóa dữ liệu từ các file và các kết nối mạng một cách dễ dàng bằng một mô hình xử lý quen thuộc, và nó cung cấp cho bạn tất cả các tiện ích quen thuộc khi truy xuất dữ liệu dựa-vào- Stream . Phương thức khởi dựng của CryptoStream yêu cầu ba đối số: một Stream nằm dưới, một thể hiện của ICryptoTransform , và một giá trị thuộc kiểu liệt kê System.Security.Cryptography.CryptoStreamMode . Giá trị CryptoStreamMode cho biết chế độ của đối tượng CryptoStream mới; các giá trị hợp lệ là Read và Write . Khi bạn gọi phương thức Read hay Write của CryptoStream , CryptoStream sẽ sử dụng thể hiện ICryptoTransform để mật hóa và giải mật hóa dữ liệu đang truyền qua CryptoStream . Đối tượng CryptoStream bảo đảm kích thước khối dùng cho thể hiện ICryptoTransform luôn đúng. Cấu hình của một đối tượng CryptoStream có tính linh hoạt cao, nhưng có thể hơi khó hiểu. Bảng 14.4 mô tả hoạt động của một đối tượng CryptoStream dựa trên chế độ của CryptoStream và kiểu thể hiện ICryptoTransform được sử dụng trong phương thức khởi dựng của CryptoStream . Bảng 14.4 Hoạt động của đối tượng CryptoStream Chế độ của CryptoStream Chỉ thị của ICryptoTransform Mô tả Read Mật hóa Stream nằm dưới chứa plaintext nguồn. CryptoStream.Read ghi ciphertext ra bộ đệm xuất. Read Giải mật hóa Stream nằm dưới chứa ciphertext nguồn. CryptoStream.Read ghi plaintext ra bộ đệm xuất. Write Mật hóa CryptoStream.Write chỉ định plaintext cần mật hóa. Stream nằm dưới nhận ciphertext đã-được-mật-hóa. Write Giải mật hóa CryptoStream.Write chỉ định ciphertext cần giải mật hóa. Stream nằm dưới nhận plaintext đã-được-giải- mật-hóa. Lớp SymmetricEncryptionExample dưới đây trình bày cách sử dụng giải thuật Triple DES để mật hóa một file và rồi giải mật hóa file đó. Phương thức Main nhận tên của file cần mật hóa làm đối số dòng lệnh. Trước tiên, nó sẽ tạo khóa và vectơ khởi động; sau đó, gọi phương thức EncryptFile , kế tiếp là phương thức DecryptFile , và sinh ra hai file: file thứ nhất chứa phiên bản đã-được-mật-hóa của file nguồn, file thứ hai chứa phiên bản đã-được-giải-mật-hóa của file đã-được-mật-hóa (giống file nguồn). using System; using System.IO; using System.Security.Cryptography; 563 Chương 14: Mật mã public class SymmetricEncryptionExample { public static void Main(string[] args) { // Tạo một giải thuật Triple DES mới để thu lấy khóa dùng cho // ví dụ này. Khóa này sẽ được dùng chung trong các phương thức // EncryptFile và DecryptFile. Bình thường, khóa được // thỏa thuận giữa người gửi và người nhận, hoặc được gửi // (bởi người gửi) cùng với file đã-được-mật-hóa. byte[] key; byte[] iv; using(SymmetricAlgorithm alg = SymmetricAlgorithm.Create("3DES")){ key = alg.Key; iv = alg.IV; } // Mật hóa file. Tiền tố "encrypted" sẽ được thêm vào tên file // nguồn và được sử dụng làm tên của file đã-được-mật-hóa. EncryptFile(args[0], "encrypted"+args[0], (byte[])key.Clone(), (byte[])iv.Clone()); // Giải mật hóa file đã-được-mật-hóa. Tiền tố "decrypted" sẽ được // thêm vào tên file gốc và được sử dụng làm tên của file // đã-được-giải-mật-hóa. DecryptFile("encrypted"+args[0], "decrypted"+args[0], key, iv); } // Phương thức dùng để mật hóa một file (bằng giải thuật Triple DES) // với key và iv cho trước. private static void EncryptFile(string srcFileName, string destFileName, byte[] key, byte[] iv) { // Tạo các stream để truy xuất file nguồn và file đích. Stream srcFile = new FileStream(srcFileName, FileMode.Open, FileAccess.Read); 564 Chương 14: Mật mã Stream destFile = new FileStream(destFileName, FileMode.Create, FileAccess.Write); // Tạo một giải thuật Triple DES mới để mật hóa file. using(SymmetricAlgorithm alg = SymmetricAlgorithm.Create("3DES")){ // Cấu hình thuộc tính Key và IV của giải thuật. alg.Key = key; alg.IV = iv; // Tạo một CryptoStream để mật hóa nội dung của // Stream nguồn khi nó được đọc. Gọi phương thức // CreateEncryptor của SymmetricAlgorithm // để nhận thể hiện ICryptoTransform và // truyền nó cho CryptoStream. CryptoStream cryptoStream = new CryptoStream(srcFile, alg.CreateEncryptor(), CryptoStreamMode.Read); // Khai báo bộ đệm dùng để đọc dữ liệu từ file nguồn // thông qua CryptoStream và ghi nó ra file đích. int bufferLength; byte[] buffer = new byte[1024]; // Đọc file nguồn (từng khối 1024 byte) và ghi phiên bản // đã-được-mật-hóa ra file đích. do { bufferLength = cryptoStream.Read(buffer, 0, 1024); destFile.Write(buffer, 0, bufferLength); } while (bufferLength > 0); // Đóng stream và xóa các dữ liệu bí mật. destFile.Flush(); Array.Clear(key,0,key.Length); 565 Chương 14: Mật mã Array.Clear(iv,0,iv.Length); cryptoStream.Clear(); cryptoStream.Close(); srcFile.Close(); destFile.Close(); } } // Phương thức dùng để giải mật hóa một file đã-được-mật-hóa bằng // giải thuật Triple DES với key và iv cho trước. private static void DecryptFile(string srcFileName, string destFileName, byte[] key, byte[] iv) { // Tạo các stream để truy xuất file nguồn và file đích. Stream srcFile = new FileStream(srcFileName, FileMode.Open, FileAccess.Read); Stream destFile = new FileStream(destFileName, FileMode.Create, FileAccess.Write); // Tạo một giải thuật Triple DES mới để giải mật hóa file. using(SymmetricAlgorithm alg = SymmetricAlgorithm.Create("3DES")){ // Cấu hình thuộc tính Key và IV của giải thuật. alg.Key = key; alg.IV = iv; // Tạo một CryptoStream để giải mật hóa nội dung của dữ liệu // đã-được-mật-hóa khi nó được ghi. Gọi phương thức // CreateDecryptor của SymmetricAlgorithm để nhận thể hiện // ICryptoTransform và truyền nó cho CryptoStream. CryptoStream cryptoStream = new CryptoStream(destFile, alg.CreateDecryptor(), CryptoStreamMode.Write); // Khai báo bộ đệm dùng để đọc dữ liệu từ file đã-được- // mật-hóa và ghi ra file đích thông qua CryptoStream. 566 Chương 14: Mật mã int bufferLength; byte[] buffer = new byte[1024]; // Đọc file đã-được-mật-hóa (từng khối 1024 byte) và ghi // phiên bản đã-được-giải-mật-hóa ra file đích. do { bufferLength = srcFile.Read(buffer, 0, 1024); cryptoStream.Write(buffer, 0, bufferLength); } while (bufferLength > 0); // Đóng stream và xóa các dữ liệu bí mật. cryptoStream.FlushFinalBlock(); Array.Clear(key,0,key.Length); Array.Clear(iv,0,iv.Length); cryptoStream.Clear(); cryptoStream.Close(); srcFile.Close(); destFile.Close(); } } } 7. 7. Truy l i khóa đ i x ng t password ạ ố ứ ừ Truy l i khóa đ i x ng t password ạ ố ứ ừ Bạn cần tạo một khóa đối xứng từ một password để người dùng chỉ cần nhớ password và không cần lưu trữ khóa. Sử dụng lớp System.Security.Cryptography.PasswordDeriveBytes để tạo khóa đối xứng từ chuỗi password. Hiếm có người nào nhớ được giá trị của một khóa đối xứng, và không thực tế khi bắt người dùng nhập các số dài như thế bằng tay. Điều này nghĩa là khóa phải được lưu trữ ở một dạng an toàn sao cho ứng dụng có thể truy xuất được (trong smart card, đĩa mềm, cơ sở dữ liệu hay file). Vấn đề liên quan với việc cấp, phân bổ, truy xuất, và lưu trữ khóa là một trong những mặt khó nhất trong quá trình hiện thực bất kỳ giải pháp mật mã nào (vấn đề này được quy chung về quản lý khóa). Khi cần ghi nhớ một bí mật (khóa), bạn không chỉ lo bảo vệ dữ liệu mà còn phải lo bảo vệ các bí mật dùng để bảo vệ dữ liệu! Một cách lưu trữ khóa là cấp cho người dùng một password dễ nhớ hơn và sử dụng một giao thức truy lại khóa (key derivation protocol) để tạo một khóa đối xứng từ password. Theo đó, 567 Chương 14: Mật mã mỗi khi cần mật hóa hay giải mật hóa dữ liệu, người dùng chỉ cần nhập password và máy tính sẽ tạo ra khóa (nếu người dùng nhập cùng password, giao thức này sẽ tạo ra cùng khóa). Truy lại khóa từ những từ hay nhóm từ dễ nhớ làm giảm đáng kể tính ngẫu nhiên của khóa, dẫn đến giảm tính bảo mật được cấp bởi những hàm mật mã có sử dụng khóa đó. Trong trường hợp tồi tệ nhất, hacker có thể đoán được password, và crack dữ liệu của bạn thông qua việc giải mã mật mã ( cryptanalysis ). Thư viện lớp .NET Framework có một hiện thực truy lại khóa đối xứng: PasswordDeriveBytes . Lớp này sử dụng một giải thuật băm được áp dụng lặp đi lặp lại cho một password để tạo ra một khóa với chiều dài như mong muốn. Khi cấu hình một đối tượng PasswordDeriveBytes , bạn có thể chỉ định tên giải thuật băm cũng như số lần lặp (mặc định, SHA-1 được áp dụng 100 lần). Ngoài ra, bạn cũng cần cung cấp giá trị salt. Salt là dữ liệu ngẫu nhiên mà quá trình truy lại khóa sẽ sử dụng để làm cho khóa tìm được trở nên bền vững hơn đối với các dạng tấn công bằng mật mã. Bạn không cần giữ bí mật cho giá trị salt; bạn phải lưu trữ và sử dụng nó khi truy lại khóa từ password sau này (nếu không có giá trị salt đúng, bạn sẽ không thể truy lại khóa đúng và không thể giải mật hóa được). Bạn không thể tạo khóa bất đối xứng bằng giao thức truy lại khóa. Giải thuật mật hóa bất đối xứng ( asymmetric encryption ) dựa vào các mối liên hệ toán cụ thể giữa các thành phần khóa công khai ( public key ) và khóa riêng ( private key ). Như thế, mỗi giải thuật mật hóa bất đối xứng yêu cầu bạn phải tuân theo một quy trình riêng để có thể tạo ra các khóa mới. Ví dụ dưới đây trình bày cách sử dụng lớp PasswordDeriveBytes để tạo một khóa đối xứng gồm 64 bit từ một chuỗi password. Ví dụ này yêu cầu hai đối số dòng lệnh: tên giải thuật băm và password (tên của các giải thuật băm đã được liệt kê trong bảng 14.1). using System; using System; using System.Security.Cryptography; public class DerivedKeyExample { public static void Main(string[] args) { // Sử dụng một bộ tạo số ngẫu nhiên để tạo giá trị salt. byte[] salt = new byte[8]; RandomNumberGenerator.Create().GetBytes(salt); // Tạo một đối tượng PasswordDeriveBytes để tạo khóa từ // password. Cần cung cấp password nguồn (là đối số dòng // lệnh thứ hai) và salt. PasswordDeriveBytes pdb = 568 Chương 14: Mật mã new PasswordDeriveBytes(args[1], salt); // Thiết lập giải thuật băm dùng để tạo khóa, tên // giải thuật được chỉ định trong đối số dòng lệnh thứ nhất. // Giải thuật được sử dụng mặc định là SHA-1. pdb.HashName = args[0]; // Thiết lập số lần lặp là 200 (đây là số lần giải thuật băm // được áp dụng cho password để tạo khóa). Mặc định là 100. pdb.IterationCount = 200; // Tạo một khóa gồm 8 byte (64 bit) từ password. // Chiều dài của khóa bị giới hạn bởi chiều dài của // mã băm - 160 bit đối với SHA-1. byte[] key = pdb.GetBytes(8); // Hiển thị khóa và salt. Console.WriteLine("Key = {0}", BitConverter.ToString(key)); Console.WriteLine("Salt = {0}", BitConverter.ToString(salt)); } } Chạy lệnh DerivedKeyExample SHA1 S0meVereeStr@ngeP@$$w0rd (sử dụng giải thuật băm SHA-1 để truy lại một khóa gồm 8 byte từ chuỗi " S0meVereeStr@ngeP@$$w0rd ") sẽ sinh ra kết xuất tương tự như sau: Key = 53-72-74-5B-A4-88-A4-80 Salt = 70-82-79-F4-3B-F9-DF-D2 Chú ý rằng, mỗi khi bạn chạy cùng một lệnh, DerivedKeyExample sinh ra khóa khác nhau. Đó là do tác dụng của salt. Nếu bạn bỏ đi dòng lệnh gán một giá trị ngẫu nhiên vào salt (được in đậm trong đoạn mã trên), sau đó biên dịch lại và chạy DerivedKeyExample , bạn sẽ nhận thấy ví dụ này luôn tạo ra cùng một khóa với một password cho trước. 8. 8. G i m t bí m t b ng phép m t hóa b t đ i x ngử ộ ậ ằ ậ ấ ố ứ G i m t bí m t b ng phép m t hóa b t đ i x ngử ộ ậ ằ ậ ấ ố ứ Bạn cần sử dụng phép mật hóa bất đối xứng ( asymmetric encryption ) để gửi một bí mật. Thể hiện hóa lớp giải thuật bất đối xứng System.Security.Cryptography. RSACryptoServiceProvider . Sử dụng phương thức RSACryptoServiceProvider. 569 Chương 14: Mật mã Encrypt và khóa công khai ( public key ) của người nhận để mật hóa thông điệp. Sau đo, người nhận sẽ sử dụng phương thức RSACryptoServiceProvider.Decrypt và khóa riêng ( private key ) để giải mật hóa bí mật đã-được-mật-hóa. .NET Framework định nghĩa một hệ thống phân cấp theo lớp cho các giải thuật bất đối xứng tương tự như đã định nghĩa cho các giải thuật đối xứng (đã được thảo luận trong mục 14.6). Tất cả các giải thuật bất đối xứng phải thừa kế một lớp cơ sở trừu tượng chung có tên là System.Security.Cryptography.AsymmetricAlgorithm . Có hai hiện thực giải thuật bất đối xứng cụ thể: • System.Security.Cryptography.RSACryptoServiceProvider • System.Security.Cryptography.DSACryptoServiceProvider Vì có đuôi là CryptoServiceProvider nên cả hai lớp này đều bọc lấy các chức năng do Win32 CryptoAPI cung cấp. Tuy nhiên, chỉ có lớp RSACryptoServiceProvider là hỗ trợ việc mật hóa dữ liệu. Lớp DSACryptoServiceProvider hiện thực Digital Signature Algorithm (DSA), bạn có thể sử dụng giải thuật này chỉ để tạo chữ ký số (xem Federal Information Processing Standard [FIPS] 186-2 tại [ http://www.itl.nist.gov/fipspubs ] để biết thêm chi tiết về DSA). Mặc dù bạn có thể tạo một đối tượng giải thuật bất đối xứng bằng phương thức tĩnh Create của lớp cơ sở AsymmetricAlgorithm , nhưng bù lại bạn sẽ phải trả giá chút ít cho việc này. Lớp AsymmetricAlgorithm không khai báo các phương thức mà RSACryptoServiceProvider sử dụng để mật hóa và giải mật hóa dữ liệu. Thay vào đó, bạn phải trực tiếp thể hiện hóa lớp RSACryptoServiceProvider bằng một trong các phương thức khởi dựng của nó. Trước khi mật hóa hay giải mật hóa dữ liệu với đối tượng RSACryptoServiceProvider , bạn cần truy xuất các khóa thích hợp. Khóa của giải thuật bất đối xứng khác nhiều so với khóa của giải thuật đối xứng. Thứ nhất, nó có hai thành phần: khóa công khai (public key) và khóa riêng (private key). Thứ hai, thay vì chỉ là một dãy các byte được sinh ngẫu nhiên, khóa bất đối xứng được tạo theo một cách thức đặc biệt. Có một mối quan hệ toán đặc biệt giữa khóa công khai và khóa riêng; mối quan hệ này cho phép giải thuật bất đối xứng mật hóa dữ liệu bằng một khóa và giải mật hóa dữ liệu bằng một khóa khác. Mỗi giải thuật bất đối xứng sử dụng cách thức tạo khóa của chính nó, và các lớp hiện thực cụ thể đóng gói các chức năng cần thiết để tạo ra các khóa mới. Khóa công khai không cần được giữ bí mật và chủ sở hữu có thể tùy ý gửi nó cho bạn thông qua e-mail, hoặc post nó lên một website hay một server phân phối khóa để mọi người cùng thấy. Những ai muốn gửi bí mật thì sử dụng khóa công khai để mật hóa bí mật. Sau đó, người nhận sử dụng khóa riêng để giải mật hóa bí mật. Khóa riêng phải được giữ bí mật; những ai sở hữu khóa riêng đều có thể giải mật hóa dữ liệu đã-được-mật-hóa bằng khóa công khai. Để tạo một bí mật được-mật-hóa-bất-đối-xứng, bạn phải có khóa công khai của người nhận và nạp nó vào một đối tượng RSACryptoServiceProvider . Có hai cách nạp khóa công khai: • Sử dụng phương thức RSACryptoServiceProvider.ImportParameters để nhập một cấu trúc System.Security.Cryptography.RSAParameters , cấu trúc này chứa thông tin khóa công khai của người nhận. Chủ sở hữu có thể tạo cấu trúc RSAParameters bằng phương thức RSACryptoServiceProvider.ExportParameters và gửi nó cho bạn. Tuy nhiên, người này có thể gửi cho bạn khóa công khai ở dạng byte, và bạn phải tự nạp giá trị này vào cấu trúc RSAParameters . 570 Chương 14: Mật mã • Sử dụng phương thức RSACryptoServiceProvider.FromXmlString để nạp dữ liệu khóa công khai từ một chuỗi XML. Chủ sở hữu có thể tạo dữ liệu XML này bằng phương thức RSACryptoServiceProvider.ToXmlString và gửi nó cho bạn. Cả phương thức ExportParameters và ToXmlString của lớp RSACryptoServiceProvider đều nhận một đối số luận lý, nếu là true , đối tượng RSACryptoServiceProvider sẽ xuất cả khóa công khai và khóa riêng. Bạn chỉ định giá trị này là false khi cần xuất khóa cho mục đích phân phối hay lưu trữ. Một khi đã nạp khóa công khai của người nhận vào đối tượng RSACryptoServiceProvider , bạn có thể mật hóa dữ liệu. Giải thuật bất đối xứng chậm hơn giải thuật đối xứng khi mật hóa và giải mật hóa dữ liệu. Vì lý do này, bạn không nên sử dụng giải thuật bất đối xứng để mật hóa lượng dữ liệu lớn. Thông thường, nếu cần mật hóa lượng dữ liệu lớn, bạn nên sử dụng giải thuật đối xứng và rồi mật hóa khóa đối xứng bằng giải thuật bất đối xứng để bạn có thể gửi khóa đối xứng cùng với dữ liệu. Mục 14.10 sẽ thảo luận về vấn đề này. Để bảo đảm tính nhất quán trong việc sử dụng, lớp RSACryptoServiceProvider không hỗ trợ mô hình mật hóa và giải mật hóa dựa-trên- System.IO.Stream (đã được sử dụng trong mục 14.6). Để mật hóa dữ liệu với đối tượng RSACryptoServiceProvider , bạn hãy gọi phương thức Encrypt , truyền cho nó một mảng byte chứa plaintext; Encrypt sẽ trả về một mảng byte chứa ciphertext. Phương thức Encrypt cũng mhận một đối số luận lý cho biết kiểu padding mà đối tượng RSACryptoServiceProvider sẽ sử dụng. Padding cho biết đối tượng bất đối xứng sẽ xử lý plaintext như thế nào trước khi mật hóa. Padding bảo đảm giải thuật bất đối xứng không cần xử lý từng khối dữ liệu, và bảo vệ ciphertext đối với các dạng tấn công bằng mật mã. Diễn giải các dạng padding vượt quá phạm vi của quyển sách này. Nói chung, nếu đang sử dụng Microsoft Windows XP trở về sau, bạn nên chỉ định đối số padding là true ; nếu không, bạn phải chỉ định đối số padding là là false (nếu không thì Encrypt sẽ ném ngoại lệ System.Security.Cryptography.CryptographicException ). Giải mật hóa dữ liệu cũng đơn giản như mật hóa dữ liệu. Người nhận cần tạo một đối tượng RSACryptoServiceProvider và nạp nó cùng với khóa riêng. Thông thường, khóa này sẽ được lưu trữ trong một kho chứa khóa (key container) do CryptoAPI quản lý (sẽ được thảo luận kỹ hơn trong mục 14.9). Người nhận gọi RSACryptoServiceProvider.Decrypt và truyền cho nó ciphertext mà bạn đã gửi. Người nhận phải chỉ định cơ chế padding, và nó cũng phải giống như khi mật hóa dữ liệu. Phương thức Decrypt trả về một mảng byte chứa plaintext đã-được- giải-mật-hóa. Nếu plaintext mô tả một chuỗi, người nhận phải chuyển mảng byte thành giá trị chuỗi thích hợp bằng lớp System.Text.Encoding . Lớp RSACryptoServiceProvider thừa kế các phương thức có tên là EncryptValue và DecryptValue từ lớp cha của nó là System.Security.Cryptography.RSA . Lớp RSACryptoServiceProvider không hiện thực các phương thức này và ném ngoại lệ System.NotSupportedException nếu bạn gọi chúng. Lớp AsymmetricEncryptionExample dưới đây trình bày cách sử dụng lớp RSACryptoServiceProvider để mật hóa một chuỗi và rồi giải mật hóa: using System; . hóa việc mật hóa và giải mật hóa dữ liệu được đọc từ các đối tượng Stream khác. Lớp này cho phép bạn mật hóa và giải mật hóa dữ liệu từ các file và các kết nối mạng một cách dễ dàng bằng một. khóa và giải mật hóa dữ liệu bằng một khóa khác. Mỗi giải thuật bất đối xứng sử dụng cách thức tạo khóa của chính nó, và các lớp hiện thực cụ thể đóng gói các chức năng cần thiết để tạo ra các. 128 Rijndael RijndaelManaged 128, 192, 256 Mặc dù bạn có thể tạo ra các thể hiện của các lớp giải thuật đối xứng một cách trực tiếp, lớp cơ sở SymmetricAlgorithm là một factory cho các lớp hiện thực cụ thể dẫn xuất từ đó.