2017-09-01 82 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

相关问题