2015-07-10 18 views
11

Tôi có một nhiệm vụ trong tay đòi hỏi phải có vật liệu chính sử dụng chức năng dẫn xuất quan trọng được mô tả trong NIST SP 800-56A, phần 5.8.1. Tôi không phải là chuyên gia về Mật mã vì vậy xin lỗi nếu câu hỏi là ngây thơ. Dưới đây là những gì tôi đã làm như vậy cho đến nay:Có phải ECDiffieHellmanCng trong .NET có chức năng dẫn xuất quan trọng thực hiện NIST SP 800-56A, phần 5.8.1

  1. Tôi có khóa công khai của bên kia và riêng tư của tôi chính
  2. Bây giờ tôi cố gắng tạo ra các bí mật chia sẻ sử dụng ECDH 1.3.132.1.12 sử dụng C# (.NET 4) lớp ECDiffieHellmanCng như vậy:

    // The GetCngKey method reads the private key from a certificate in my Personal certificate store 
    
    CngKey cngPrivateKey = GetCngKey(); 
    
    ECDiffieHellmanCng ecDiffieHellmanCng = new ECDiffieHellmanCng(cngPrivateKey); 
    
    ecDiffieHellmanCng.HashAlgorithm = CngAlgorithm.ECDiffieHellmanP256; 
    ecDiffieHellmanCng.KeyDerivationFunction = ?? // What do I set here 
    

Cuối cùng làm điều này:

ecDiffieHellmanCng.DeriveKeyMaterial(otherPartyPublicKey:); 

Ở đâu/làm cách nào để đặt các thông số khác Thuật toán ID, Thông tin bên U, Thông tin bên V?

EDIT Tôi mở để sử dụng các thư viện khác như Bouncy Castle (miễn là chúng có thể được gọi từ NET)

Trả lời

8

TL; DR; Tôi đã không tìm thấy cách lấy được khóa đối xứng bằng KDF được mô tả trong NIST SP 800-56A, mục 5.8.1 sử dụng các lớp tích hợp trong .NET 4.0. là nó có thể trong .NET 4.0 sử dụng thư viện BouncyCastle đáng yêu (NuGet: Install-Package BouncyCastle-Ext -Version "1.7.0"). Đây là cách:

Bước 1: Nhận bên kia của công chúng chính

Tùy thuộc vào kịch bản của bạn, điều này có thể được đọc từ một giấy chứng nhận hoặc đến với bạn như là một phần của thông điệp có chứa các dữ liệu được mã hóa. Một khi bạn có Base64 mã hóa khóa công khai, đọc nó vào một Org.BouncyCastle.Crypto.Parameters.ECPublicKeyParameters đối tượng như vậy:

var publicKeyBytes = Convert.FromBase64String(base64PubKeyStr); 
ECPublicKeyParameters otherPartyPublicKey = (ECPublicKeyParameters)PublicKeyFactory.CreateKey(publicKeyBytes); 

Bước 2: Đọc bạn tin-key

này sẽ most- thường liên quan đến việc đọc khóa riêng tư từ chứng chỉ PFX/P12. Tài khoản windows đang chạy mã nên có quyền truy cập vào PFX/P12 và bổ sung, nếu chứng chỉ được nhập vào một kho chứng chỉ, bạn sẽ cần cấp quyền thông qua All Tasks -> quản lý menu khóa riêng trong certmgr.msc

using (StreamReader reader = new StreamReader(path)) 
{ 
    var fs = reader.BaseStream; 
    string password = "<password for the PFX>"; 
    Pkcs12Store store = new Pkcs12Store(fs, passWord.ToCharArray()); 

    foreach (string n in store.Aliases) 
    { 
     if (store.IsKeyEntry(n)) 
     { 
      AsymmetricKeyEntry asymmetricKey = store.GetKey(n); 

      if (asymmetricKey.Key.IsPrivate) 
      { 
       ECPrivateKeyParameters privateKey = asymmetricKey.Key as ECPrivateKeyParameters; 
      } 
     } 
    } 
} 

BƯỚC 3: tính bí mật

IBasicAgreement aKeyAgree = AgreementUtilities.GetBasicAgreement("ECDH"); 
aKeyAgree.Init(privateKey); 
BigInteger sharedSecret = aKeyAgree.CalculateAgreement(otherPartyPublicKey); 
byte[] sharedSecretBytes = sharedSecret.ToByteArray(); 

BƯỚC 4 chia sẻ: Chuẩn bị thông tin cần thiết để tính toán khóa đối xứng:

byte[] algorithmId = Encoding.ASCII.GetBytes(("<prependString/Hex>" + "id-aes256-GCM")); 
byte[] partyUInfo = Encoding.ASCII.GetBytes("<as-per-agreement>"); 
byte[] partyVInfo = <as-per-agreement>; 
MemoryStream stream = new MemoryStream(algorithmId.Length + partyUInfo.Length + partyVInfo.Length); 
var sr = new BinaryWriter(stream); 
sr.Write(algorithmId); 
sr.Flush(); 
sr.Write(partyUInfo); 
sr.Flush(); 
sr.Write(partyVInfo); 
sr.Flush(); 
stream.Position = 0; 
byte[] keyCalculationInfo = stream.GetBuffer(); 

Bước 5: Rút ra các sy mmetric key

// NOTE: Use the digest/Hash function as per your agreement with the other party 
IDigest digest = new Sha256Digest(); 
byte[] symmetricKey = new byte[digest.GetDigestSize()]; 
digest.Update((byte)(1 >> 24)); 
digest.Update((byte)(1 >> 16)); 
digest.Update((byte)(1 >> 8)); 
digest.Update((byte)1); 
digest.BlockUpdate(sharedSecret, 0, sharedSecret.Length); 
digest.BlockUpdate(keyCalculationInfo, 0, keyCalculationInfo.Length); 
digest.DoFinal(symmetricKey, 0); 

Bây giờ bạn có khóa đối xứng sẵn sàng thực hiện giải mã. Để thực hiện giải mã bằng AES, BouncyCastle IWrapper có thể được sử dụng. Lấy IWrapper bằng cách sử dụng Org.BouncyCastle.Security.WrapperUtilities bằng cách gọi WrapperUtilities.GetWrapper ("AES //"), ví dụ: "AES/CBC/PKCS7". Điều này cũng sẽ phụ thuộc vào thỏa thuận giữa hai bên giao tiếp.

Khởi tạo mật mã (IWrapper) bằng khóa đối xứng và vectơ khởi tạo (IV) và gọi phương thức Unwrap để nhận byte thuần văn bản. Cuối cùng, chuyển đổi thành chuỗi ký tự bằng cách sử dụng mã hóa ký tự được sử dụng (ví dụ: UTF8/ASCII/Unicode)

+0

Về phía mã hóa, BouncyCastle có lớp ConcatenationKDFGenerator https://github.com/bcgit/bc-csharp/blob/0801c1543f0cafc79c44b225e53c973bdd1b0a0f/ crypto/src/crypto/agreement/kdf/ConcatenationKdfGenerator.cs – Sentinel

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