2009-04-13 29 views
12

Tôi đang sử dụng lớp .NET 3.0 lớp System.Security.Cryptography.MACTripleDES để tạo giá trị MAC. Thật không may, tôi đang làm việc với một thiết bị phần cứng sử dụng "1111111111111111" (dưới dạng hex) làm khóa DES một chiều. Thư viện System.Security.Cryptography thực hiện kiểm tra tính chính xác trên khóa và trả về Ngoại lệ nếu bạn cố gắng sử dụng khóa yếu mã hóa.TripleDES: Khóa được chỉ định là khóa yếu đã biết cho 'TripleDES' và không thể sử dụng

Ví dụ:

byte[] key = new byte[24]; 
for (int i = 0; i < key.Length; i++) 
    key[i] = 0x11; 

byte[] data = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 
byte[] computedMac = null; 
using (MACTripleDES mac = new MACTripleDES(key)) 
{ 
    computedMac = mac.ComputeHash(data); 
} 

ném một ngoại lệ

System.Security.Cryptography.CryptographicException : Specified key is a known weak key for 'TripleDES' and cannot be used. 

Tôi biết đây không phải là một chìa khóa an toàn. Trong quá trình sản xuất, thiết bị sẽ được chiếu bằng một khóa mới, an toàn. Trong thời gian đó, liệu có cách nào để ngăn chặn ngoại lệ này khỏi bị ném không? Có lẽ một cài đặt đăng ký app.config hoặc đăng ký?

Chỉnh sửa: Khóa thực sự là 101010 ... do thuật toán buộc chẵn lẻ lẻ. Tôi không chắc liệu đây có phải là phổ quát đối với thuật toán DES hay chỉ là một yêu cầu trong công việc xử lý thanh toán mà tôi làm.

Chỉnh sửa 2: Câu trả lời của Daniel dưới đây có một số thông tin rất tốt về hack. Thật không may, tôi đã không thể giải quyết vấn đề của tôi bằng cách sử dụng kỹ thuật này, nhưng vẫn còn một số đọc thú vị ở đó.

+0

(Re: chỉnh sửa của bạn) DES và 3DES chỉ sử dụng 7 bit đầu mỗi byte trong khóa. Bit ít quan trọng nhất thường được sử dụng như một bit chẵn lẻ. –

+0

Tôi sẽ về nhà như vậy. Có vẻ kỳ lạ rằng một cái gì đó như thế này sẽ được thực thi ở cấp thư viện. Những người sử dụng mã hóa nên biết sử dụng các khóa khó đoán và thư viện không nên thực thi những điều này. – Kibbee

+1

@Kibbee, Điểm yếu trong ngữ cảnh này không có nghĩa là "khó đoán". Nó có nghĩa là một khóa mà thuật toán được chỉ định thể hiện một số hành vi thoái hóa làm suy yếu nó. – caf

Trả lời

1

Thay vì sử dụng MACTripleDES bằng phím DES lặp đi lặp lại để giả một DES CBC-MAC, bạn chỉ có thể tự mình thực hiện CBC-MAC trên đầu trang DESCryptoServiceProvider.

< 1111111111111111> không phải là khóa DES yếu.

này sẽ tính toán một DES CBC-MAC:

public static byte[] CalcDesMac(byte[] key, byte[] data){ 
     DESCryptoServiceProvider des = new DESCryptoServiceProvider(); 
     des.Key = key; 
     des.IV = new byte[8]; 
     des.Padding = PaddingMode.Zeros; 
     MemoryStream ms = new MemoryStream(); 
     using(CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write)){ 
      cs.Write(data, 0, data.Length); 
     } 
     byte[] encryption = ms.ToArray(); 
     byte[] mac = new byte[8]; 
     Array.Copy(encryption, encryption.Length-8, mac, 0, 8); 
     PrintByteArray(encryption); 
     return mac; 
    } 
+0

Điều này hoạt động tốt. Tôi nghĩ rằng tôi chỉ tập trung vào lớp MACTripleDES, mà nếu tôi nghĩ rằng nó thông qua, thực sự được sử dụng cho Triple DES chỉ và không DES duy nhất. Tôi ước nó đã không đưa tôi một năm để tôi đọc câu trả lời của bạn! Tôi đã kết thúc việc thực hiện CBC-MAC bằng tay. –

1

Thật không may, hành vi không thể bị ghi đè.

6

tôi sẽ không thực sự khuyên bạn nên nó, nhưng bạn sẽ có thể thay đổi IL-code để kiểm tra các khóa yếu sử dụng Reflector và Add-in ReflexIL

chỉnh sửa:

Rất tiếc, mất một thời gian để tôi tải tất cả nó lên trong Máy ảo của tôi (chạy Ubuntu) và không muốn gây rối với Mono.

  • Cài đặt ReflexIL Add-in: View -> Add-ins -> Add
  • mở ReflexIL: Tools -> ReflexIL v0.9
  • Tìm IsWeakKey() chức năng. (Bạn có thể sử dụng Tìm kiếm: F3)
  • Hai chức năng sẽ xuất hiện, đôi khi có hai chức năng trong System.Security.Cryptography.TripleDES
  • ReflexIL cũng đã xuất hiện. Trong tab Hướng dẫn, cuộn xuống hết dòng 29 (bù 63).
  • Thay đổi ldc.i4.1 thành ldc.i4.0, điều này có nghĩa là hàm sẽ luôn trả về false.

Trong ngăn hội đồng của bạn (bên trái), bây giờ bạn có thể cuộn lên và nhấp vào "Thư viện thời gian ngôn ngữ chung", ô ReflexIL sẽ cung cấp cho bạn tùy chọn để lưu.

Ghi chú quan trọng:

  • LẠI UP lắp ráp ban đầu của bạn đầu tiên! (mscorlib.dll)
  • mscorlib.dll là một hội đồng có chữ ký và bạn sẽ cần .NET SDK (công cụ sn.exe) cho ReflexIL để làm cho nó bỏ qua xác minh. Tôi chỉ cần kiểm tra này bản thân mình, bạn nên đã có điều này với Visual C# được cài đặt. Chỉ cần nhấp vào "Đăng ký để bỏ qua xác minh (trên máy tính này)" khi được yêu cầu.
  • Tôi không nghĩ rằng tôi phải nói với bạn chỉ sử dụng này trên máy tính phát triển của bạn :)

Chúc may mắn! Nếu bạn cần thêm hướng dẫn, vui lòng sử dụng hộp nhận xét.

chỉnh sửa2:

Tôi nhầm lẫn!

http://i44.tinypic.com/2r6fwbo_th.png

tôi hoàn toàn loại bỏ các kiểm tra IsWeakKey từ chức năng set_Key trong lắp ráp mscorlib. Tôi hoàn toàn chắc chắn rằng tôi đã sửa đổi chức năng chính xác và tôi đã làm đúng. Bộ tách rời của Reflector không còn hiển thị kiểm tra nữa. Điều thú vị là tuy nhiên, Visual C# vẫn ném cùng một ngoại lệ.

Điều này khiến tôi tin rằng mscorlib phải bằng cách nào đó vẫn được lưu trữ ở đâu đó. Tuy nhiên, đổi tên mscorlib.dll thành mscorlib.dll_ dẫn đến lỗi MSVC#, vì vậy nó vẫn phải phụ thuộc vào dll gốc.

Đây là công cụ khá thú vị, nhưng tôi nghĩ rằng tôi đã đạt đến điểm mà tôi không biết đầu mối gì đang xảy ra, nó không có ý nghĩa gì cả! Xem hình ảnh đính kèm. :(

EDIT3:

Tôi nhận thấy trong Olly, rằng không giống như hội như mscoree, mscorsec và mscorwks; mscorlib.dll không thực sự nằm trong: c: \ WINDOWS \ Microsoft.NET \ Framework \ v2.0.50727 \

Nhưng thay vào đó, trong những gì dường như là một vị trí không tồn tại: C: \ WINDOWS \ lắp ráp \ NativeImages_v2.0.50727_32 \ mscorlib \ 6d667f19d687361886990f3ca0f49816 \ mscorlib.ni.dll

tôi nghĩ Tôi đang thiếu một cái gì đó ở đây :) Sẽ điều tra này một số chi tiết.

edit4:

Ngay cả sau khi đã vá ra tất cả mọi thứ trong IsWeakKey, và chơi xung quanh với cả hai loại bỏ và tạo ra hình ảnh mới có nguồn gốc (. X ni .dll) của mscorlib.dll sử dụng "ngen.exe", Tôi nhận được cùng một ngoại lệ. Tôi phải lưu ý rằng ngay cả sau khi gỡ bỏ cài đặt các hình ảnh mscorlib bản địa, nó vẫn còn sử dụng mscorlib.ni.dll ... Meh.

Tôi bỏ cuộc. Tôi hy vọng ai đó sẽ có thể trả lời những gì địa ngục đang xảy ra bởi vì tôi chắc chắn không biết. :)

+0

Giải pháp khá thú vị! Tôi vá mscorlib.dll của tôi, nhưng không có thay đổi trong hành vi của hàm. Dll này có được lưu trữ ở đâu đó không? Tất cả những gì tôi đang thay đổi là .... \ Microsoft.NET \ Framework \ v2.0.50737 \ mscorlib.dll. –

+0

Tôi vừa kiểm tra mã, bạn nói đúng. Tôi sẽ điều tra và báo cáo lại :) –

+0

Điều này thật kỳ lạ khi nói ít nhất. Bây giờ tôi đã sửa đổi kiểm tra IsWeakKey thực tế trên set_Key(), và nó đang làm điều tương tự. Nó phải được lưu trữ ở đâu đó.Tôi sẽ điều tra một số chi tiết :) –

0

Tôi không phải là chuyên gia bảo mật nhưng sẽ không XOR phím của bạn với giá trị khác là đủ để đáp ứng kiểm tra sanity? Bạn có thể làm điều này cho phiên bản gỡ lỗi của bạn (với IFDEF thích hợp) để bạn có thể kiểm tra thích hợp và loại bỏ nó cho phiên bản phát hành hoặc phiên bản sản xuất của bạn, nơi khóa sẽ đủ mạnh.

+0

Điều đó thực sự thỏa mãn kiểm tra sanity, nhưng thiết bị phần cứng mà anh đang làm việc vẫn sẽ sử dụng khóa gốc. –

+0

Vâng. Tôi chỉ nghĩ về điều đó. Tôi chỉ nghĩ về nó từ quan điểm mã và thậm chí không xem xét phần cứng. My Bad :) –

4

tôi phát hiện ra những gì bạn cần phải làm.May mắn là có một phương thức có sẵn để tạo ra các ICryptoTranforms không kiểm tra các khóa yếu. Bạn cũng cần phải xem ra cho các lớp cơ sở vì nó cũng kiểm tra sanity. Qua sự phản chiếu đơn giản gọi ra phương thức _NewEncryptor (bạn cần phải phản chiếu nhiều hơn một chút, nhưng đó là ý tưởng).

May mắn là MACTripleDES có trường kiểu TripleDES, do đó lấy được từ MACTripleDES và thay thế nó thông qua sự phản chiếu trong các nhà xây dựng. Tôi đã làm tất cả công việc cho bạn.

Tôi không thể xác minh rằng MAC chính xác được tạo, nhưng không có trường hợp ngoại lệ nào được ném. Hơn nữa, bạn có thể muốn doc nhận xét mã và thực hiện xử lý ngoại lệ (các lỗi phản chiếu - ví dụ: nếu các trường/phương thức không có) - nhưng đây là SO; nên tôi không bận tâm.

using System; 
using System.Reflection; 
using System.Security.Cryptography; 
using System.IO; 

namespace DesHack 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      byte[] key = new byte[24]; 
      for (int i = 0; i < key.Length; i++) 
       key[i] = 0x11; 

      byte[] data = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 
      byte[] computedMac = null; 
      using (MACTripleDES mac = new MACTripleDESHack(key)) 
      { 
       computedMac = mac.ComputeHash(data); 
      } 
     } 
    } 

    class MACTripleDESHack : MACTripleDES 
    { 
     TripleDES _desHack = new DesHack(); 

     static FieldInfo _cspField = typeof(MACTripleDES).GetField("des", BindingFlags.Instance | BindingFlags.NonPublic); 

     public MACTripleDESHack() 
      : base() 
     { 
      RewireDes(); 
     } 

     public MACTripleDESHack(byte[] rgbKey) 
      : base(rgbKey) 
     { 
      RewireDes(); 
     } 

     private void RewireDes() 
     { 
      _cspField.SetValue(this, _desHack); 
     } 

    } 

    class DesHack : TripleDES 
    { 
     TripleDESCryptoServiceProvider _backing = new TripleDESCryptoServiceProvider(); 

     static MethodInfo _newEncryptor; 
     static object _encrypt; 
     static object _decrypt; 

     public override int BlockSize 
     { 
      get 
      { 
       return _backing.BlockSize; 
      } 
      set 
      { 
       _backing.BlockSize = value; 
      } 
     } 

     public override int FeedbackSize 
     { 
      get 
      { 
       return _backing.FeedbackSize; 
      } 
      set 
      { 
       _backing.FeedbackSize = value; 
      } 
     } 

     // For these two we ALSO need to avoid 
     // the base class - it also checks 
     // for weak keys. 
     private byte[] _iv; 
     public override byte[] IV 
     { 
      get 
      { 
       return _iv; 
      } 
      set 
      { 
       _iv = value; 
      } 
     } 

     private byte[] _key; 
     public override byte[] Key 
     { 
      get 
      { 
       return _key; 
      } 
      set 
      { 
       _key = value; 
      } 
     } 

     public override int KeySize 
     { 
      get 
      { 
       return _backing.KeySize; 
      } 
      set 
      { 
       _backing.KeySize = value; 
      } 
     } 

     public override KeySizes[] LegalBlockSizes 
     { 
      get 
      { 
       return _backing.LegalBlockSizes; 
      } 
     } 

     public override KeySizes[] LegalKeySizes 
     { 
      get 
      { 
       return _backing.LegalKeySizes; 
      } 
     } 

     public override CipherMode Mode 
     { 
      get 
      { 
       return _backing.Mode; 
      } 
      set 
      { 
       _backing.Mode = value; 
      } 
     } 

     public override PaddingMode Padding 
     { 
      get 
      { 
       return _backing.Padding; 
      } 
      set 
      { 
       _backing.Padding = value; 
      } 
     } 


     static DesHack() 
     { 
      _encrypt = typeof(object).Assembly.GetType("System.Security.Cryptography.CryptoAPITransformMode").GetField("Encrypt").GetValue(null); 
      _decrypt = typeof(object).Assembly.GetType("System.Security.Cryptography.CryptoAPITransformMode").GetField("Decrypt").GetValue(null); 
      _newEncryptor = typeof(TripleDESCryptoServiceProvider).GetMethod("_NewEncryptor", BindingFlags.NonPublic | BindingFlags.Instance); 
     } 

     public DesHack() 
     {    
     } 

     public override ICryptoTransform CreateDecryptor() 
     { 
      return CreateDecryptor(_key, _iv); 
     } 

     public override ICryptoTransform CreateEncryptor() 
     { 
      return CreateEncryptor(_key, _iv); 
     } 

     public override ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[] rgbIV) 
     { 
      // return this._NewEncryptor(rgbKey, base.ModeValue, rgbIV, base.FeedbackSizeValue, CryptoAPITransformMode.Decrypt); 
      return (ICryptoTransform) _newEncryptor.Invoke(_backing, 
       new object[] { rgbKey, ModeValue, rgbIV, FeedbackSizeValue, _decrypt }); 
     } 

     public override ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[] rgbIV) 
     { 
      // return this._NewEncryptor(rgbKey, base.ModeValue, rgbIV, base.FeedbackSizeValue, CryptoAPITransformMode.Encrypt); 
      return (ICryptoTransform) _newEncryptor.Invoke(_backing, 
       new object[] { rgbKey, ModeValue, rgbIV, FeedbackSizeValue, _encrypt }); 
     } 

     public override void GenerateIV() 
     { 
      _backing.GenerateIV(); 
     } 

     public override void GenerateKey() 
     { 
      _backing.GenerateKey(); 
     } 

     protected override void Dispose(bool disposing) 
     { 
      if (disposing) 
       ((IDisposable) _backing).Dispose(); 
      base.Dispose(disposing); 
     } 
    } 
} 
-1

Các giải pháp phản ánh dựa giúp bạn có được xung quanh vấn đề này, nhưng họ là dơ bẩn và xấu xa. Không ai vẫn chưa đề cập đến một phương pháp rất hữu ích: TripleDES.IsWeakKey

Tôi đã có vấn đề này và giải quyết nó với một tiện ích rất đơn giản mà tôi sử dụng ngay lập tức trước khi tôi thiết lập các chính về CryptoServiceProvider tôi:

private void MakeSecureKey(byte[] key) 
{ 
    while(TripleDES.IsWeakKey(key)) 
    { 
     var sha = SHA256Managed.Create().ComputeHash(key); 
     Array.Copy(sha,key,key.Length); 
    } 
} 

Nếu bạn gọi nó bất cứ lúc nào bạn thực hiện một bộ mã hóa hoặc giải mã, nó sẽ ngăn chặn sự cố và luôn cung cấp cho bạn một khóa bảo mật.

+0

Điều này không thực sự hữu ích nếu người dùng phải tương thích với thiết bị yêu cầu một khóa cụ thể. –

+0

Đủ công bằng. Chỉ cần nghĩ rằng tôi muốn thêm nó ở đây kể từ khi số một của google hit cho lỗi đó, và nó có thể hữu ích cho ai đó trong một tình huống hơi khác nhau. – captncraig

-1

Khá đơn giản (Sau khi xem xét mã từ GitHub)

TripleDES.IsWeakKey bool tĩnh (Byte [] rgbKey)

Vì nó là tĩnh - nó rất dễ dàng để kiểm tra chìa khóa của bạn chống lại nó

  1. Kích phải có 16 hoặc 24 byte (???) tại sao họ không thể đặt nó trong tài liệu
  2. Vui lòng cung mã cho vài lần lặp lại đơn giản Chỉ cần tạo ngẫu nhiên enuogh giá trị

Xem mã tại: https://github.com/mono/mono/blob/master/mcs/class/corlib/System.Security.Cryptography/TripleDES.cs

Dekel

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