2009-06-12 33 views
12

Tôi có mục tiêu cấp cao về việc tạo một lớp tiện ích tĩnh đóng gói mã hóa cho ứng dụng .NET của tôi. Bên trong tôi muốn giảm thiểu các sáng tạo đối tượng không cần thiết.An toàn chủ đề của lớp mã hóa .NET?

Câu hỏi của tôi là: chủ đề an toàn của các lớp thực hiện mã hóa đối xứng trong .NET Framework là gì? Cụ thể là System.Security.Cryptography.RijndaelManaged và các loại ICryptoTransform mà nó tạo ra.

Ví dụ, trong hàm tạo lớp của tôi, tôi có thể đơn giản làm điều gì đó theo các dòng sau không?

static MyUtility() 
{ 
    using (RijndaelManaged rm = new RijndaelManaged()) 
    { 
     MyUtility.EncryptorTransform = rm.CreateEncryptor(MyUtility.MyKey, MyUtility.MyIV); 
     MyUtility.DecryptorTransform = rm.CreateDecryptor(MyUtility.MyKey, MyUtility.MyIV); 
    } 
} 

Side-bước vấn đề là nó an toàn để có Key và IV tồn tại trong lớp này, ví dụ khối này sẽ trả về một số câu hỏi khác:

  1. Tôi có thể tiếp tục tái sử dụng các EncryptorTransform và DecryptorTransform hơn và hơn? Các thuộc tính *.CanReuseTransform*.CanTransformMultipleBlocks ngụ ý "có", nhưng có bất kỳ cảnh báo nào mà tôi cần lưu ý không?

  2. RijndaelManaged thực hiện IDisposable độ nghiêng của tôi là đặt nó trong một khối using đặc biệt vì nó có thể gắn với libs ở cấp hệ điều hành bên ngoài. Có bất kỳ cảnh báo nào với điều này vì tôi đang giữ các đối tượng ICryptoTransform xung quanh?

  3. Có thể là câu hỏi quan trọng nhất, trong môi trường đa luồng, tôi có gặp phải vấn đề khi chia sẻ các đối tượng giữa các chủ đề không?

  4. Nếu câu trả lời cho # 3 là câu trả lời không an toàn, tôi có bị giảm hiệu năng nghiêm trọng khi khóa trong khi tôi sử dụng các đối tượng ICryptoTransform không? (Phụ thuộc vào tải tôi giả sử.)

  5. Nó có thể hoạt động hiệu quả hơn để đơn giản khởi tạo RijndaelManaged mới mỗi lần không? Hoặc lưu trữ một RijndaelManaged và tạo ra new RijndaelManaged().CreateEncryptor(...) mỗi lần?

Tôi hy vọng rằng một người nào đó ở đó biết cách hoạt động của tính năng này hoặc trải nghiệm các vấn đề từ việc triển khai tương tự. Tôi đã thấy rằng rất nhiều loại hiệu suất và các vấn đề liên quan đến chuỗi này thường không thể hiện bản thân cho đến khi có một lượng tải lớn.

Cảm ơn!

Trả lời

14

1) Có.

2) Một trong những bạn vứt bỏ nó, bạn không thể sử dụng nó. Cho đến lúc đó, bạn có thể chia sẻ/sử dụng nó (nhưng xem bên dưới)

3-4) Từ MSDN:.

"Bất cứ public static (chung trong Visual Basic) thành viên của loại này là chủ đề an toàn Bất kỳ dụ các thành viên không được bảo đảm là luồng an toàn. "

Nếu bạn muốn giữ nó và chia sẻ giữa các chủ đề, bạn sẽ cần triển khai khóa và coi nó là tài nguyên bị khóa.Nếu không, tôi khuyên bạn chỉ nên tạo các phiên bản riêng biệt nếu cần và xử lý chúng khi bạn hoàn tất.

5) Tôi khuyên bạn nên tạo chúng khi cần và sau đó cố gắng tối ưu hóa nếu sau này bạn thấy mình gặp vấn đề về hiệu suất. Đừng lo lắng về tác động của việc tạo ra một phiên bản mới cho đến khi bạn thấy đó là một vấn đề của nó sau khi lược tả.

+0

tư vấn âm thanh tốt. Tôi đoán tôi đã giả định rằng việc tạo và phá hủy một số đối tượng này có chi phí do phụ thuộc cơ bản khi các lớp SDK nền tảng định hướng. Nếu không ai nghĩ rằng đây là một mối quan tâm được bảo hành, thì có vẻ như các cơ chế đồng bộ hóa cuối cùng có thể là nút cổ chai lớn hơn. – mckamey

+2

Đúng là bạn không nên dành thời gian tối ưu hóa sớm, nhưng chỉ muốn bỏ ở đây trong trường hợp của chúng tôi, chúng tôi thấy rằng việc thực hiện ~ 500 mã hóa nhỏ (tất cả cùng một mật khẩu) mất gần 10 giây. Gần như tất cả thời gian đã được dành để tạo ra các bộ mã hóa. Tái sử dụng ICryptoTransforms là giải pháp hiển nhiên. – Bernard

+0

2cents của tôi, tôi thấy rằng _not_ sử dụng lại ICryptoTransform đã gây ra hiệu suất rất xấu của ứng dụng của chúng tôi. – gorillapower

3

Người ta có thể giải quyết vấn đề đồng thời đơn giản với một bộ nhớ cache dựa trên một chồng đồng thời:

static ConcurrentStack<ICryptoTransform> decryptors = new ConcurrentStack<ICryptoTransform>(); 

void Encrypt() 
{ 
    // Pop decryptor from cache... 
    ICryptoTransform decryptor; 
    if (!decryptors.TryPop(out decryptor)) 
    { 
     // ... or create a new one since cache is depleted 
     AesManaged aes = new AesManaged(); 
     aes.Key = key; 
     aes.IV = iv; 
     decryptor = aes.CreateDecryptor(aes.Key, aes.IV); 
    } 

    try 
    { 
     //// use decryptor 
    } 
    finally 
    { 
     decryptors.Push(decryptor); 
    } 
} 
Các vấn đề liên quan