2010-07-21 30 views
8

Bất kỳ ai đã tìm ra cách tốt để kéo các giá trị được mã hóa từ db qua khung thực thể 4?Các cột được mã hóa với Khung thực thể

Tôi có một db MySql với một số cột được mã hóa bằng des_encrypt và cần có khả năng nhận các giá trị đó dễ dàng nhất có thể, và dĩ nhiên, cập nhật và chèn chúng.

Tôi nghĩ rằng nó khá kỳ lạ có vẻ như không được hỗ trợ xây dựng cho điều này trong EF. Ngay cả hệ thống ORM được xây dựng của chúng tôi cũng hỗ trợ cho điều này. Chúng tôi chỉ cần thêm một bình luận "mã hóa" cho mỗi trường được mã hóa và công cụ ORM sẽ thêm des_decrypt (cột) và des_encrypt (cột) trong các truy vấn.

Bất kỳ ai?

Trả lời

2

IMO bạn nên mã hóa trước khi đặt nó vào cơ sở dữ liệu và lưu trữ dưới dạng dữ liệu nhị phân. Sau đó, bạn có thể dễ dàng nhận được byte[] với EF.

EDIT: Điều gì xảy ra nếu bạn đã sử dụng quy trình được lưu trữ để thực hiện tất cả các des_encryptdes_decrypt cũng như selects/inserts/deletes cho bạn. Sau đó, EF sẽ vẫn lập bản đồ cho bạn?

+0

Có vẻ như một giải pháp tốt và tôi có thể sẽ làm với điều đó nếu tôi tạo cơ sở dữ liệu mới. Vấn đề là, cơ sở dữ liệu khá lớn và được sử dụng bởi rất nhiều dự án vì vậy nó sẽ là một công việc rất lớn để đi qua mã và thay đổi điều này. – Andreas

+0

@Andreas - Xem chỉnh sửa của tôi ở trên. – TheCloudlessSky

+0

Cảm ơn bạn đã đề xuất. Điều này trông giống như một ý tưởng thực sự tốt và tôi đã thử nó. thật không may nếu tôi muốn có thể thực hiện truy vấn LINQ trên tất cả dữ liệu được giải mã của tôi từ bảng, thủ tục được lưu trữ trước tiên phải thực thi. Điều này mất mãi mãi vì nó là 250 000+ hàng với 5 cột mỗi được giải mã. Vì vậy, làm điều này: context.AllMembers(). Trường hợp (x => x.MemberId == 1) sẽ mất quá nhiều thời gian. Chắc chắn tôi có thể làm một SP mà có một đối số của memberid, nhưng nếu tôi muốn tìm kiếm trên ví dụ tên đầu tiên với LINQ? Có lẽ tôi đang thiếu một số thứ quan trọng ở đây ... – Andreas

1

Bạn có thể sử dụng Mã hóa AES (mã hóa 2 chiều). Khi bạn cần truy vấn db, bạn có thể gửi chuỗi được mã hóa có thể biểu diễn giá trị đích.

Bạn có thể tạo Tiện ích mở rộng để Giải mã thực thể.

MyTableEntitiesSet.Where(c=>c.MyField == MySeekValue.Encrypt()).First().Decrypt(); 

Điều này có thể thực hiện truy vấn cơ sở dữ liệu.

Lưu ý về kích thước dữ liệu, dữ liệu được mã hóa lớn hơn ...

+4

Câu hỏi và trả lời cũ, nhưng chỉ cần lưu ý rằng nếu bạn cố gắng làm điều này, nó sẽ chỉ hoạt động nếu bạn sử dụng một Init Vector cố định, mà không được khuyến khích, vì nó sẽ có khả năng cho phép kẻ tấn công tìm hiểu về dữ liệu. Một IV ngẫu nhiên với mỗi mã hóa nên được sử dụng, có nghĩa là bạn sẽ nhận được một giá trị khác nhau mỗi khi bạn mã hóa một cái gì đó. –

-3

Trong trường hợp cụ thể, tôi cần mã hóa số thẻ tín dụng, luôn là 16 ký tự; vì vậy tôi chỉ cần thêm một điều kiện trong get (nếu lenght! = 16 sau đó giải mã) và trong tập hợp (nếu lenght == 16 sau đó mã hóa) của thuộc tính. Nó hoạt động và tránh cho tôi rất nhiều công việc.

12

Đây là ví dụ triển khai câu trả lời được đề xuất bởi @TheCloudlessSky. Tôi nghĩ rằng nó sẽ giúp đỡ bất cứ ai đang tự hỏi làm thế nào để đi về việc thực hiện nó.

Tôi đã làm việc với một cơ sở dữ liệu hiện có, do đó, lớp mô hình cơ bản được tạo tự động cho tôi.

User.cs Auto tạo:

namespace MyApp.Model 
{ 
    public partial class User 
    { 
     public int UserId { get; set; } 
     public byte[] SSN { get; set; } 
     ... 
    } 
} 

Tôi tạo ra User.cs. của riêng tôi (Lưu ý nó nằm trong cùng một không gian tên như User.cs được tạo tự động và không có lỗi trình biên dịch do User.cs được tạo tự động được khai báo là một phần lớp! Ngoài ra, User.cs của riêng tôi không thể nằm trong cùng thư mục với User.cs tự động tạo ra vì tên tập tin xung đột!)

namespace MyApp.Model 
{ 
    public partial class User 
    { 
     public string DecryptedSSN { get; set; } 
     ... 
    } 
} 

Bây giờ bất cứ khi nào tôi được lấy tài từ DbContext của tôi, tôi sẽ thấy tất cả các thuộc tính được định nghĩa trong lớp tự động tạo ra cũng như những quy định tại lớp nâng cao của tôi.

Dưới đây là triển khai UserRepository của tôi.cs:

namespace MyApp.Model 
{ 
    public interface IUserRepository 
    { 
     User Get(int userId); 
     ... 
    } 

    public class UserRepository : IUserRepository 
    { 
     public User GetById(int userId) 
     { 
      using (var dataContext = MyDbContext()) 
      { 
       var user = dataContext.Users.Find(u => u.UserId == userId); 
       var decryptedSSNResult = dataContext.Decrypt(u.SSN); 
       user.DecryptedSSN = decryptedSSNResult.FirstOrDefault(); 
       return user; 
      } 
     } 
    } 
} 

Bây giờ bạn có thể tự hỏi làm cách nào/ở đâu tôi nhận được MyDbContext.Decrypt() từ?

Điều này KHÔNG được tạo tự động cho bạn. Tuy nhiên, bạn có thể nhập thủ tục được lưu trữ này vào tệp Model.Context.cs được tạo tự động của bạn. (Quy trình này được viết rất rõ trong bài viết EntityFramework chính thức: Cách: Nhập một Quy trình được Lưu trữ (Công cụ Mô hình Dữ liệu Thực thể) tại http://msdn.microsoft.com/en-us/library/vstudio/bb896231(v=vs.100).aspx)

Chỉ trong trường hợp bạn không biết kết quả cuối cùng sẽ trông như thế nào, đây là những gì đã tự động tạo ra trong Model.Context.cs tôi:

namespace MyApp.Model 
{ 
    // using statements found here 

    public partial class MyDbContext : DbContext 
    { 
     public MyDbContext() 
      : base("name = MyDbContext") 
     { } 

     public virtual ObjectResult<string> Decrypt(byte[] encryptedData) 
     { 
      var encryptedDataParameter = encryptedData != null ? 
          new ObjectParameter("encryptedData", encryptedData) : 
          new ObjectParameter("encryptedData", typeof(byte[])); 

      return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<string>("Decrypt", encryptedDataParameter); 
     } 

     // similar function for Encrypt 
    } 
} 

Đây là cách Decrypt tôi Stored Procedure trông giống như:

CREATE PROCEDURE decrypt 
    @encryptedData VARBINARY(8000) 
AS 
BEGIN 
    OPEN SYMMETRIC KEY xxx_Key DECRYPTION BY CERTIFICATE xxx_Cert; 

    SELECT CAST(DECRYPTIONBYKEY(@encryptedData) AS NVARCHAR(MAX)) AS data; 

    CLOSE ALL SYMMETRIC KEYS; 
END; 
GO 

Cân nhắc hiệu suất

Bây giờ tôi đã cho bạn thấy một câu trả lời được đưa ra bởi @TheCloudlessSky, tôi sẽ nhanh chóng làm nổi bật một số điểm liên quan đến hiệu suất.

1) Mỗi ​​khi bạn truy xuất đối tượng người dùng, có 2 chuyến đi được thực hiện cho cơ sở dữ liệu thay vì 1. Chuyến đi đầu tiên để truy xuất đối tượng; chuyến đi thứ hai để giải mã SSN. Điều này có thể gây ra vấn đề hiệu suất nếu bạn không cẩn thận.

Đề xuất: KHÔNG tự động giải mã các trường được mã hóa! Trong ví dụ của tôi được hiển thị ở trên, tôi đã giải mã SSN khi tôi đang truy xuất đối tượng người dùng. Tôi đã làm điều đó chỉ nhằm mục đích trình diễn! Hãy tự hỏi nếu bạn thực sự cần SSN mỗi lần người dùng được truy xuất. Nếu có thể, hãy chọn giải mã lười biếng qua giải mã háo hức!

2) Trong khi tôi chưa chứng minh điều này, mỗi lần bạn tạo/cập nhật đối tượng người dùng, cũng sẽ có 2 chuyến đi được thực hiện cho cơ sở dữ liệu. Chuyến đi đầu tiên để mã hóa SSN; chuyến đi thứ hai để chèn đối tượng. Một lần nữa điều này có thể gây ra vấn đề hiệu suất nếu bạn không cẩn thận.

Đề xuất: Hãy ý thức về hiệu suất này nhưng không ủy quyền mã hóa và lưu SSN làm phương pháp khác. Giữ tất cả trong một hoạt động nếu không bạn có thể quên lưu nó hoàn toàn. Vì vậy, các khuyến nghị cho việc tạo/cập nhật là đối diện của lấy: chọn mã hóa háo hức trên mã hóa lười biếng!

+0

Tôi cung cấp cho bạn một phiếu bầu cho nỗ lực. Nhưng tôi không đồng ý với cách tiếp cận của bạn một chút. Tôi không muốn cơ sở dữ liệu của mình giải mã các giá trị. Tôi có thể lưu trữ tất cả thông tin đó trong đơn của tôi và không phải thực hiện hai chuyến đi đến cơ sở dữ liệu. – mac10688

+0

@ mac10688 Tôi đồng ý với bạn về hiệu suất đạt được liên quan đến nhiều chuyến đi đến cơ sở dữ liệu.Nói chung, viết các thủ tục lưu trữ dành riêng cho các hoạt động CUD và liên kết chúng với mô hình thông qua khung thực thể hiệu quả hơn việc lưu trữ các thủ tục như mã hóa/giải mã. Nhưng tôi muốn chứng minh một phương pháp để đạt được mã hóa/giải mã bằng cách sử dụng các khóa được quản lý bởi cơ sở dữ liệu thay vì ứng dụng. –

+0

Tôi đang cung cấp liên kết đến cách kết nối các thủ tục lưu trữ CUD với các hoạt động CUD theo khung pháp nhân trong trường hợp ai đó tò mò về cách đạt được điều này: https://msdn.microsoft.com/en-us/data/jj593489. Tôi biết các liên kết thường được tán thành nhưng vì điều này là đến trang tài liệu MSDN Entity Framework, tôi hy vọng mọi người sẽ không quan tâm đến nó. –

1

Bạn có thể sử dụng tính năng bảo mật mã hóa tự làm/cuộn của riêng mình nhưng mọi chuyên gia bảo mật sẽ cho bạn biết never, ever, do that. Phần khó nhất của bảo mật và mã hóa dữ liệu thực sự không phải là "AES" hoặc một số thuật toán. Đó là quản lý chủ chốt. Sớm hay muộn, bạn sẽ phải đối mặt với con thú này và nó là cách khó hơn.

May mắn thay, có một công cụ gọi là Crypteron CipherDb để đảm bảo điều đó. Trong thực tế, nó vượt quá mã hóa khung thực thể, cũng cung cấp bảo vệ chống giả mạo tự động, lưu trữ khóa bảo mật, phân phối khóa bảo mật, cuộn khóa chính, bộ nhớ đệm chính, danh sách kiểm soát truy cập và hơn thế nữa. Có phiên bản cộng đồng miễn phí và chỉ mất vài phút để thêm vào ứng dụng của bạn.

Khi tích hợp với Entity Framework, bạn chỉ cần chú thích các mô hình dữ liệu với [Secure] hoặc tên một tài sản để một cái gì đó giống như Secure_SocialSecurityNumber (các Secure_ là phần quan trọng) và CipherDb sẽ chăm sóc phần còn lại.

Ví dụ, mô hình dữ liệu của bạn sẽ là:

public class Patient 
{ 
    public int Id {get; set;} 

    [Secure] 
    public string FullName {get; set;} 

    [Secure] 
    public string SocialSecurityNumber {get; set;} 
} 

Và web.config của bạn sẽ là

<configuration> 
    <configSections> 
    <section 
     name="crypteronConfig" 
     type="Crypteron.CrypteronConfig, CipherCore, Version=2017, Culture=neutral, PublicKeyToken=e0287981ec67bb47" 
     requirePermission="false" /> 
    </configSections> 

    <crypteronConfig> 
    <myCrypteronAccount appSecret="Get_this_from_http://my.crypteron.com" /> 
    </crypteronConfig> 
</configuration> 

Đó là khuyến cáo để bảo đảm web.config của bạn HOẶC cắm chìa khóa API Crypteron (AppSecret) theo chương trình (documentation)

Bạn có thể tìm ứng dụng mẫu trên GitHub tại https://github.com/crypteron/crypteron-sample-apps. .

Nhân tiện, phiên bản miễn phí có lợi từ các dịch vụ thương mại, ngoài ra, bạn cũng có thể bảo mật luồng, tệp, đối tượng, hàng đợi tin nhắn, cơ sở dữ liệu NoSQL, tất cả từ một nơi.

Tuyên bố từ chối: Tôi làm việc ở đó và chúng tôi có phiên bản cộng đồng miễn phí mà mọi người đều có thể sử dụng (và chúng tôi không kiếm tiền). Nếu bạn nghĩ nó thật tuyệt, hãy nói với chúng tôi, hãy nói với bạn bè của bạn. Nếu bạn có ngân sách, hãy lấy giấy phép thương mại. Nó giúp chúng tôi cung cấp phiên bản miễn phí cho tất cả mọi người :)

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