2010-05-12 24 views
7

Tôi có mã hóa AES được thực hiện trên hai cột: một trong các cột này được lưu trữ tại cơ sở dữ liệu SQL Server ; khác được lưu trữ tại một cơ sở dữ liệu SQL Server .Làm thế nào để có được khả năng tương thích giữa mã hóa CES và SQL2k8 AES?

Khi cơ sở dữ liệu của cột đầu tiên (2000) không có chức năng gốc để mã hóa/giải mã, chúng tôi đã quyết định thực hiện logic mã hóa ở cấp ứng dụng, với các lớp .NET, cho cả hai. Tuy nhiên, khi cơ sở dữ liệu của cột thứ hai (2008) cho phép loại chức năng này, chúng tôi muốn di chuyển dữ liệu bằng cách sử dụng các hàm cơ sở dữ liệu nhanh hơn, vì việc di chuyển dữ liệu trong SQL 2k nhỏ hơn nhiều so với thứ hai này và nó sẽ kéo dài hơn 50 giờ vì được thực hiện ở cấp ứng dụng.

Vấn đề của tôi bắt đầu tại thời điểm này: sử dụng cùng một khóa, tôi không đạt được kết quả tương tự khi mã hóa giá trị, không cùng kích thước kết quả.

Dưới đây chúng tôi có logic đầy đủ ở cả hai bên .. Đương nhiên là tôi không hiển thị phím, nhưng mọi thứ khác là như nhau:

private byte[] RijndaelEncrypt(byte[] clearData, byte[] Key) 
{ 
    var memoryStream = new MemoryStream(); 

    Rijndael algorithm = Rijndael.Create(); 

    algorithm.Key = Key; 
    algorithm.IV = InitializationVector; 

    var criptoStream = new CryptoStream(memoryStream, algorithm.CreateEncryptor(), CryptoStreamMode.Write); 
    criptoStream.Write(clearData, 0, clearData.Length); 
    criptoStream.Close(); 

    byte[] encryptedData = memoryStream.ToArray(); 
    return encryptedData; 
} 

private byte[] RijndaelDecrypt(byte[] cipherData, byte[] Key) 
{ 
    var memoryStream = new MemoryStream(); 

    Rijndael algorithm = Rijndael.Create(); 

    algorithm.Key = Key; 
    algorithm.IV = InitializationVector; 

    var criptoStream = new CryptoStream(memoryStream, algorithm.CreateDecryptor(), CryptoStreamMode.Write); 

    criptoStream.Write(cipherData, 0, cipherData.Length); 

    criptoStream.Close(); 

    byte[] decryptedData = memoryStream.ToArray(); 

    return decryptedData; 
} 

Đây là mẫu mã SQL:

open symmetric key columnKey decryption by password = N'{pwd!!i_ll_not_show_it_here}' 

declare @enc varchar(max) 

set @enc = dbo.VarBinarytoBase64(EncryptByKey(Key_GUID('columnKey'), 'blablabla')) 

select LEN(@enc), @enc 

varbinaryToBase64 này là một hàm sql được thử nghiệm mà chúng tôi sử dụng để chuyển đổi varbinary thành cùng một định dạng mà chúng tôi sử dụng để lưu trữ các chuỗi trong ứng dụng .net.

Kết quả trong C# là: eg0wgTeR3noWYgvdmpzTKijkdtTsdvnvKzh + uhyN3Lo =

Các kết quả tương tự trong SQL2k8 là: AI0zI7D77EmqgTQrdgMBHAEAAACyACXb + P3HvctA0yBduAuwPS4Ah3AB4Dbdj2KBGC1Dk4b8GEbtXs5fINzvusp8FRBknF15Br2xI1CqP0Qb/M4w

Tôi chỉ không có được chưa gì tôi đang làm sai rồi.

Bạn có ý tưởng nào không?

EDIT: Một điểm tôi nghĩ là rất quan trọng: Tôi có một Vector khởi tạo tại mã C#, 16 byte. IV này không được đặt ở khóa đối xứng SQL, tôi có thể làm điều này không?

Nhưng thậm chí không làm đầy IV trong C#, tôi nhận được kết quả rất khác nhau, cả về nội dung và độ dài.

+0

Có điều gì trong tài liệu nêu rõ hai thuật toán mã hóa thực tế giống nhau không? – Joe

+0

họ nói cả hai đều là AES, đúng không? Tôi nghĩ rằng điều này là đủ để đảm bảo một số khả năng tương tác .. –

Trả lời

5

Có một vài điều tôi muốn xem xét:

  1. Hoàn toàn chắc chắn rằng bản rõ là giống hệt nhau về nội dung và mã hóa. IIRC, luồng mặc định là UTF-8 trong khi nếu hàm VarBinaryToBase64 của bạn lấy tham số nvarchar, nó sẽ là Unicode.

  2. Đảm bảo cả hai thuật toán mã hóa đều sử dụng cùng một kích thước khối. Trong SQL, bạn xác định thuật toán khi bạn gọi CREATE SYMMETRIC KEY. Nếu bạn không chỉ định một thuật toán, nó sử dụng AES256. Trong NET sử dụng RijndaelManaged, tôi tin rằng kích thước khối mặc định là 128 nhưng bạn có thể đặt nó là 256 (bạn không thể nếu bạn sử dụng lớp Aes).

  3. Điều cuối cùng tôi tìm là cách SQL Server giao dịch với Initialization Vectors như bạn đã đề cập trong bài đăng đã sửa đổi của bạn. Tôi muốn nói rằng nó sử dụng tham số authenticator cho điều này, nhưng đó là một dự đoán hoang dã.

EDIT

tôi là con đường tắt. Với những gì tôi đã phát hiện, bạn không thể sử dụng lớp .NET để giải mã văn bản được mã hóa bằng mã hóa được tích hợp của SQL Server vì SQL Server thêm một loạt các goo vào những gì được mã hóa, bao gồm cả một vector khởi tạo ngẫu nhiên. Từ cuốn sách Michael Cole của "Pro T-SQL 2005 Hướng dẫn Lập trình viên của" (mặc dù năm 2008 thực hiện điều này theo cùng một cách):

Khi SQL Server sẽ mã hóa bởi đối xứng quan trọng, nó cho biết thêm siêu dữ liệu với mã hóa kết quả, cũng như đệm, làm cho kết quả được mã hóa lớn hơn (đôi khi là lớn hơn đáng kể) so với văn bản thuần túy không được mã hóa . Định dạng cho kết quả mã hóa với siêu dữ liệu sau định dạng này:

  • 16 byte đầu tiên của kết quả mã hóa đại diện cho GUID của khóa đối xứng sử dụng để mã hóa dữ liệu
  • 4 byte tiếp theo đại diện số phiên bản, hiện được mã hóa cứng là "01000000".
  • 8 byte tiếp theo cho mã hóa DES (16 byte cho mã hóa AES) đại diện cho vector khởi tạo được tạo ngẫu nhiên.
  • 8 byte tiếp theo là thông tin tiêu đề thể hiện các tùy chọn được sử dụng để mã hóa dữ liệu. Nếu tùy chọn xác thực được sử dụng, thông tin tiêu đề này bao gồm mã băm SHA1 của trình xác thực, làm cho thông tin tiêu đề 28 byte ở độ dài .
  • Phần cuối cùng của dữ liệu được mã hóa là dữ liệu thực tế và chính đệm. Đối với thuật toán DES, độ dài của dữ liệu được mã hóa này sẽ là bội số của 8 byte. Đối với thuật toán AES, độ dài sẽ là bội số của 16 byte.
+0

Đánh giá bởi độ dài đầu ra (84 byte trước khi mã hóa base64), tôi không nghĩ rằng SQL Server đang sử dụng AES256. Nó không phải là bội số của 16 hoặc là mặc dù. Khá lạ. – Thorarin

+0

@Thorarin - Tin Coles chỉ nói rằng dữ liệu + padding sẽ là bội số của 16, không phải toàn bộ thuật toán. Vì vậy, 84 ít hơn một tiêu đề 36 byte là 48 byte mà là bội số của 16. – Thomas

+0

Ah, chỉnh sửa của bạn xóa mọi thứ lên rất nhiều, ít nhất nó giải thích tại sao 18 ký tự base64 đầu tiên giống nhau và phần còn lại liên tục thay đổi. , có thể giải mã bằng .NET. Bây giờ bạn đã biết bố cục tiêu đề. Mã hóa tôi không chắc chắn, phụ thuộc vào hàm băm SHA1 mà tôi đoán. – Thorarin

1

Không thực sự là câu trả lời nhưng quá lớn để nhận xét. Có lẽ nó sẽ giúp người khác tìm ra nó :)
SQL Server dường như làm rất nhiều đệm. Khi tôi thử ví dụ của bạn, tôi tiếp tục nhận được các kết quả khác nhau, mặc dù 18 ký tự đầu tiên dường như giống nhau mỗi lần. Tuy nhiên, điều này không có ý nghĩa với tôi ...

Bạn không hiển thị cách RijndaelEncrypt được gọi, nhưng với độ dài dữ liệu khác nhau, tôi đã suy nghĩ về unicode so với sự khác biệt về mã ANSI. Bạn dường như không được sử dụng unicode trong SQL Server tuy nhiên, do đó, sự khác biệt chiều dài sẽ là cách khác xung quanh, nếu bất cứ điều gì.

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