2017-09-01 103 views
0

在ECC加密過程中,我(作爲發送者)我假設我會做如下:如何正確準備使用.net framework 4.7進行ECC加密?

  1. 使用橢圓曲線(標識爲說,NIST P-256)以 產生短暫(臨時)公共和接收器的公共密鑰(即對方)的私鑰對
  2. 弄個一些如何
  3. 使用方案(比如橢圓曲線的Diffie-Hellman,也被稱爲 ECDH)推演共享祕密使用對方的公鑰和 上述步驟1中的臨時私鑰
  4. 使用共享密鑰 使用密鑰導出函數(KDF)推導出一個對稱密鑰(比如 NIST單步KDF作爲記錄在 http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar2.pdf
  5. 最後使用對稱密鑰使用AES對消息進行加密。

問題1:上述程序有問題嗎?

在.NET框架4.7,這是我的第一個嘗試吧:

 var curve = ECCurve.NamedCurves.nistP256; 
     var ecdhSender = ECDiffieHellman.Create(curve); 

     X509Certificate2 otherPartyPublicCert = null; //TODO: Get some how from other party and populate this variable 
     byte[] otherPartyPublicKey = otherPartyPublicCert.GetPublicKey(); 
     ECDiffieHellmanPublicKey otherPartyECDHPublicKey = ECDiffieHellmanCngPublicKey.FromByteArray(otherPartyPublicKey, CngKeyBlobFormat.GenericPublicBlob); 

     //The DeriveKeyMaterial seem to generate secret agreement, generate key and throw away the secrete agreement 
     var symmetricKey = ecdhSender.DeriveKeyMaterial(otherPartyECDHPublicKey); 
     // Or 
     //The DeriveKeyFromHash seem to generate same key as above because SHA256 was probably implicit in above call 
     var symmetricKey2 = ecdhSender.DeriveKeyFromHash(otherPartyECDHPublicKey, HashAlgorithmName.SHA256); 

     //TODO: Perform encryption with above key (either symmetricKey or symmetricKey2, depending on which call we choose) using AES etc. 

Q2:請問上面的代碼流似乎正確的(包括我的代碼中的註釋)?

問題3:使用DeriveKeyMaterial還是使用DeriveKeyFromHash有區別? (注:當我比較symmetricKey和symmetricKey2,它們是相同的)

Q4:要正確實現NIST單步KDF(這就要求KDF(Z,OtherInput)其中Z是祕密協議,OtherInput由keydatalen和OtherInfo),應該使用具有secretPrepend和secretAppend字節簽名但只填充secreteAppend字節的DeriveKeyFromHash方法?

Q5:如果答案是肯定的,以Q4,如果活動促銷包括說信息「AlgorithmIDStuff」,「PartyUInfoStuff」,「PartyVInfoStuff」(如果我選擇實現級聯格式),我應該用下列字節以下值序列(即比特串)中secretAppend參數(使用DeriveKeyFromHash方法Z字節值):無符號字節

  • 256的值(keydatalen)
  • LEN( 「AlgorithmIDStuff」),這是16,在無符號值字節
  • 「Algori無符號ASCII值中的「thmIDStuff」字節=>十進制字節值:65 108 103 111 114 105 116 104 109 73 68 83 116 117 102 102
  • 「PartyUInfoStuff」中的無符號ASCII值bytes =>十進制字節值:80 97 114 116 121 85 73 110 102 111 83 116 117 102 102
  • 「PartyVInfoStuff」 在無符號的ASCII值中的字節=>十進制字節值:80 97 114 116 121 86 73 110 102 111 83 116 117 102 102

回答

1

作爲你知道,因爲你編號了,這裏有很多問題。理想情況下,每個問題有一個問題,但我同意他們是相關的,所以我會盡量一次性回答他們。

問題1:上述程序有問題嗎?

你所描述什麼是有效的ECIES(橢圓曲線Integrated Encryption Scheme)(http://www.secg.org/sec1-v2.pdf),但是你錯過計算MAC密鑰。如果您不能使用經過身份驗證的加密模式,您可能只想關注ECIES。

如果您正在使用SP-800-56A,您也使用稍微不同的KDF,但這是一個很好的KDF。

Q2:上面的代碼流看起來是否正確(包括我在代碼中的註釋)?

雖然流程很好,但某些特定的代碼不正確。

byte[] otherPartyPublicKey = otherPartyPublicCert.GetPublicKey(); 
ECDiffieHellmanPublicKey otherPartyECDHPublicKey = 
    ECDiffieHellmanCngPublicKey.FromByteArray(
     otherPartyPublicKey, 
     CngKeyBlobFormat.GenericPublicBlob); 

「GenericPublicBlob」不是「任何通用公共斑點」,而是從CNG一種斑點。 GetPublicKey()方法返回公鑰字節,這是一個算法特定的數據blob。對於ECC密鑰,它是編碼的公鑰點Q.

除非密鑰的發送者不喜歡你,否則它將是一個奇數長度的數組,並且以0x04開頭。如果是這樣的話,您可以通過.NET將公共密鑰導入4.7 API:

private static ECDiffieHellmanPublicKey GetECDHPublicKey(X509Certificate2 cert) 
{ 
    byte[] pubKey = cert.GetPublicKey(); 

    if (pubKey.Length % 2 == 1 && pubKey[0] == 0x04) 
    { 
     byte[] qx = new byte[pubKey.Length/2]; 
     byte[] qy = new byte[qx.Length]; 
     Buffer.BlockCopy(pubKey, 1, qx, 0, qx.Length); 
     Buffer.BlockCopy(pubKey, 1 + qx.Length, qy, 0, qy.Length); 

     ECParameters ecParameters = new ECParameters 
     { 
      Curve = ECCurve.NamedCurves.nistP256, 
      Q = 
        { 
         X = qx, 
         Y = qy, 
        } 
     }; 

     using (var otherEcdh = ECDiffieHellman.Create(ecParameters)) 
     { 
      return otherEcdh.PublicKey; 
     } 
    } 

    throw new NotSupportedException(); 
}    

如果你不提前知道的時候希望你能做到這一點稍有不同是什麼曲線:

using (ECDsa ecdsa = cert.GetECDsaPublicKey()) 
using (ECDiffieHellman ecdh = ECDiffieHellman.Create(ecdsa.ExportParameters(false)) 
{ 
    // This one takes care of the curve. 
    return ecdh.PublicKey; 
} 

當然,你會那麼做你的臨時密鑰通過類似ECDiffieHellman.Create(otherPublic.ExportParameters().Curve)

Q3:有沒有使用任何DeriveKeyMaterial或DeriveKeyFromHash區別嗎? (注意:當我比較了symmetricKey和symmetricKey2,它們是相同的)

DeriveKeyMaterial來自.NET 3.5,並使用一堆屬性來控制它的。默認情況下,它使用SHA-256進行哈希派生。

0123.被添加到.NET 4.6.2或其附件中,以更清楚地瞭解正在執行的操作以及操作中涉及的屬性(現在的參數)。

我認爲沒有人再次使用DeriveKeyMaterial(而是使用新的方法),但這只是我。

Q4:要正確實現NIST單步KDF(這就要求KDF(Z,OtherInput)其中Z是祕密協議,OtherInput由keydatalen和活動促銷),應使用DeriveKeyFromHash有secretPrepend和方法secretAppend字節簽名但只填充secreteAppend字節?

OtherInfo號進入secretAppend,而是一個大端32位計數器進入secretPrepend(見5.8.1.1,過程,步驟3,4,5.1,5.2)。

Q5:如果答案是肯定的,以Q4,如果活動促銷包括說信息「AlgorithmIDStuff」,「PartyUInfoStuff」,「PartyVInfoStuff」(如果我選擇實現級聯格式),我應該用下列字節以下值序列(即比特串)(使用ž字節值由DeriveKeyFromHash法)在secretAppend論點:

號「AlgorithmIDStuff」不符合AlgorithmID值(5.8.1.2節)的定義;和PartyU/PartyV信息相似。

+0

關於對Q5的回答:5.8.1.2節中的算法ID討論並沒有說它是強制性的,而是一個建議。 PartyUInfo和PartyVInfo也是如此。我錯了嗎?如果沒有,那麼我的想法是使用這些字段的自定義字符串。假設這些字段的值是有效值,則位串序列是否正確? – Raghu

+0

AlgorithmID:一個必需的非空子字段,用於指示如何分析導出的密鑰材料以及將使用哪個或哪些算法衍生的密鑰材料。您的值不表示算法,或者如何解析密鑰。在線快速搜索不會產生任何推薦值,因此您可能需要在https://crypto.stackexchange.com上提出具體問題。 – bartonjs

+0

我明白了。如果我使用值「id-aes256-GCM」(並更改相應的字節),它會是正確的嗎? – Raghu

相關問題