2012-12-16 32 views
20

Tôi đang cố gắng hiểu cách xử lý và quản lý vectơ initilization và muối (khi áp dụng) khi mã hóa và giải mã dữ liệu bằng thuật toán mã hóa đối xứng, trong trường hợp này là AES.Mã hóa đối xứng (AES): Việc lưu IV và Muối cùng với dữ liệu được mã hóa có an toàn và thích hợp không?

Tôi đã suy ra từ các chủ đề SO khác nhau và các trang web khác mà không phải là IV hoặc muối cần phải bí mật, chỉ duy nhất để bảo vệ chống lại các cuộc tấn công cryptanalytic như tấn công brute-force. Với điều này trong tâm trí tôi figured rằng nó sẽ là khả thi để lưu trữ giả ngẫu nhiên IV của tôi với các dữ liệu được mã hóa. Tôi hỏi liệu phương pháp tôi đang sử dụng có phù hợp hay không, tôi có nên xử lý muối mã hóa hiện tại của mình theo cách tương tự không? Đó là viết nó vào dòng ký ức cùng bên IV

Mã của tôi:

private const ushort ITERATIONS = 300; 
private static readonly byte[] SALT = new byte[] { 0x26, 0xdc, 0xff, 0x00, 0xad, 0xed, 0x7a, 0xee, 0xc5, 0xfe, 0x07, 0xaf, 0x4d, 0x08, 0x22, 0x3c }; 

private static byte[] CreateKey(string password, int keySize) 
{ 
    DeriveBytes derivedKey = new Rfc2898DeriveBytes(password, SALT, ITERATIONS); 
    return derivedKey.GetBytes(keySize >> 3); 
} 

public static byte[] Encrypt(byte[] data, string password) 
{ 
    byte[] encryptedData = null; 
    using (AesCryptoServiceProvider provider = new AesCryptoServiceProvider()) 
    { 
     provider.GenerateIV(); 
     provider.Key = CreateKey(password, provider.KeySize); 
     provider.Mode = CipherMode.CBC; 
     provider.Padding = PaddingMode.PKCS7; 

     using (MemoryStream memStream = new MemoryStream(data.Length)) 
     { 
      memStream.Write(provider.IV, 0, 16); 
      using (ICryptoTransform encryptor = provider.CreateEncryptor(provider.Key, provider.IV)) 
      { 
       using (CryptoStream cryptoStream = new CryptoStream(memStream, encryptor, CryptoStreamMode.Write)) 
       { 
        cryptoStream.Write(data, 0, data.Length); 
        cryptoStream.FlushFinalBlock(); 
       } 
      } 
      encryptedData = memStream.ToArray(); 
     } 
    } 
    return encryptedData; 
} 

public static byte[] Decrypt(byte[] data, string password) 
{ 
    byte[] decryptedData = new byte[data.Length]; 
    using (AesCryptoServiceProvider provider = new AesCryptoServiceProvider()) 
    { 
     provider.Key = CreateKey(password, provider.KeySize); 
     provider.Mode = CipherMode.CBC; 
     provider.Padding = PaddingMode.PKCS7; 
     using (MemoryStream memStream = new MemoryStream(data)) 
     { 
      byte[] iv = new byte[16]; 
      memStream.Read(iv, 0, 16); 
      using (ICryptoTransform decryptor = provider.CreateDecryptor(provider.Key, iv)) 
      { 
       using (CryptoStream cryptoStream = new CryptoStream(memStream, decryptor, CryptoStreamMode.Read)) 
       { 
        cryptoStream.Read(decryptedData, 0, decryptedData.Length); 
       } 
      } 
     } 
    } 
    return decryptedData; 
} 

Tôi cũng mở cửa cho bất kỳ thông tin khác về mã hóa đối xứng liên quan đến thực hành đúng đắn.

+0

Nếu bạn không lưu trữ chúng với dữ liệu được mã hóa của mình, bạn cần lưu trữ chúng ở đâu đó - vì vậy YMMV. – larsw

+4

Trong chế độ CBC, mỗi khối được mã hóa hoạt động như IV của khối tiếp theo, vì vậy IV là giá trị công khai không thể bảo mật có liên quan - nếu không chế độ hoạt động CBC sẽ không an toàn. :) – vhallac

+0

@ vhallac tốt, nhiều V (vectơ) như IV (vector khởi tạo) có thể rõ ràng chỉ là cái đầu tiên. –

Trả lời

23

Lưu trữ IV và Muối bằng văn bản mã hóa là hợp lý và thực hành tốt nhất. Khó mã hóa muối không hữu ích, ngẫu nhiên là quan trọng, mã hóa cứng lặp lại là hoàn toàn ổn nhưng thường cao hơn nhiều so với 300 (trên thực tế ít nhất là 1000 và bạn thường cao hơn nhiều nếu máy/sử dụng của bạn có thể xử lý nó như trong 10 giây) trong số hàng nghìn).

Bởi vì tôi đã nhìn thấy rất nhiều ví dụ xấu (hoặc cũ) về mã hóa C# từ ngăn tràn tràn và dán vào mã nguồn mở, tôi đã viết một đoạn mã cắt và dán Modern Examples of Symmetric Authenticated Encryption of a string. mà tôi cố gắng theo kịp ngày và xem xét. Nó lưu trữ iv và muối với bản mã, nó cũng xác thực bản mã và các giá trị đi kèm với văn bản mã hóa.

Lý tưởng nhất là thực hành tốt hơn là sử dụng thư viện mã hóa cấp cao có thể xử lý các phương pháp hay nhất như iv cho bạn, tuy nhiên những điều này thường không tồn tại đối với csharp. Tôi đã làm việc trên một số csharp version của thư viện keyczar của google. Trong khi nó đã sẵn sàng để sử dụng, tôi đã muốn nhận được nhiều hơn về mã trước khi phát hành ổn định chính thức đầu tiên.

13

Có, cả IV và muối là giá trị công khai. Điều quan trọng hơn là đảm bảo đây là những giá trị ngẫu nhiên cho mỗi hoạt động mã hóa.

Để đưa ra ví dụ về điều này trong tự nhiên, hãy xem rncryptor data format. Ở đây muối và IV được đóng gói thành một định dạng dữ liệu, cùng với bản mã và giá trị MAC. (Lưu ý: đây là một ví dụ khách quan-c).

Các vấn đề liên quan