Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/273.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# .NET ECDiffieHellmancing和BouncyCastle核心兼容协议_C#_.net_.net Core_Bouncycastle_Diffie Hellman - Fatal编程技术网

C# .NET ECDiffieHellmancing和BouncyCastle核心兼容协议

C# .NET ECDiffieHellmancing和BouncyCastle核心兼容协议,c#,.net,.net-core,bouncycastle,diffie-hellman,C#,.net,.net Core,Bouncycastle,Diffie Hellman,我必须与第三方签订Diffie-Hellman协议,该第三方以.NET ECDiffieHellmancing XmlString格式传递公钥。我不能更改他们的代码。 他们发送的内容如下所示: <ECDHKeyValue xmlns="http://www.w3.org/2001/04/xmldsig-more#"> <DomainParameters> <NamedCurve URN="urn:oid:1.3.132.0.35" /> <

我必须与第三方签订Diffie-Hellman协议,该第三方以.NET ECDiffieHellmancing XmlString格式传递公钥。我不能更改他们的代码。 他们发送的内容如下所示:

<ECDHKeyValue xmlns="http://www.w3.org/2001/04/xmldsig-more#">
  <DomainParameters>
    <NamedCurve URN="urn:oid:1.3.132.0.35" />
  </DomainParameters>
  <PublicKey>
    <X Value="11" xsi:type="PrimeFieldElemType" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
    <Y Value="17" xsi:type="PrimeFieldElemType" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
  </PublicKey>
</ECDHKeyValue>
using (ECDiffieHellmanCng dhKey = new ECDiffieHellmanCng())
{
    dhKey.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
    dhKey.HashAlgorithm = CngAlgorithm.Sha256;

    Console.WriteLine(dhKey.PublicKey.ToXmlString());
}
ECDiffieHellmanCngPublicKey pbkey = ECDiffieHellmanCngPublicKey.FromXmlString(xmlHere);
    using (ECDiffieHellman dhBob = ECDiffieHellman.Create(ECCurve.CreateFromValue("1.3.132.0.35")))
    {
        using (ECDiffieHellman dhAlice = ECDiffieHellman.Create(ECCurve.CreateFromValue("1.3.132.0.35")))
        {
            byte[] b = dhAlice.DeriveKeyMaterial(dhBob.PublicKey);

            byte[] b2 = dhBob.DeriveKeyMaterial(dhAlice.PublicKey);

            Console.WriteLine(b.SequenceEqual(b2));
        }
    }
他们希望以相同的格式接收我的公钥。 他们像这样使用我的公钥:

<ECDHKeyValue xmlns="http://www.w3.org/2001/04/xmldsig-more#">
  <DomainParameters>
    <NamedCurve URN="urn:oid:1.3.132.0.35" />
  </DomainParameters>
  <PublicKey>
    <X Value="11" xsi:type="PrimeFieldElemType" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
    <Y Value="17" xsi:type="PrimeFieldElemType" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
  </PublicKey>
</ECDHKeyValue>
using (ECDiffieHellmanCng dhKey = new ECDiffieHellmanCng())
{
    dhKey.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
    dhKey.HashAlgorithm = CngAlgorithm.Sha256;

    Console.WriteLine(dhKey.PublicKey.ToXmlString());
}
ECDiffieHellmanCngPublicKey pbkey = ECDiffieHellmanCngPublicKey.FromXmlString(xmlHere);
    using (ECDiffieHellman dhBob = ECDiffieHellman.Create(ECCurve.CreateFromValue("1.3.132.0.35")))
    {
        using (ECDiffieHellman dhAlice = ECDiffieHellman.Create(ECCurve.CreateFromValue("1.3.132.0.35")))
        {
            byte[] b = dhAlice.DeriveKeyMaterial(dhBob.PublicKey);

            byte[] b2 = dhBob.DeriveKeyMaterial(dhAlice.PublicKey);

            Console.WriteLine(b.SequenceEqual(b2));
        }
    }
我在.NETCore2.1工作。不幸的是,ECDiffieHellmancing类和类似的类目前没有在.NETCore中实现。 我想我可以使用BouncyCastle for.NET核心包来实现以下目标: 我假设这两个都实现了相同的标准,并且它们是兼容的

我知道如何完全使用bouncy castle来达成协议,但是我不清楚如何从.NET ECDiffieHellmancing中的xml中的X和Y值开始,以及如何确保使用兼容的参数。 我也不清楚如何从我生成的bouncy castle公钥中获取X和Y值并发送回它们。 net api的bouncy castle与java api不完全相同,而且文档也有限,这一点也没有帮助

更新1: 在阅读了下面的一些评论之后,ECDiffieHellmancing似乎确实在.NETCore中部分实现。大多数逻辑都可以工作,但只有ToXmlString和FromXmlString不能工作。没关系,我可以解决这个问题。 然而,我现在遇到了一个不同的问题。另一侧使用的曲线为oid:1.3.132.0.35。 但是,当我尝试在.NET core中使用此功能时,即使使用了以下基本示例:

<ECDHKeyValue xmlns="http://www.w3.org/2001/04/xmldsig-more#">
  <DomainParameters>
    <NamedCurve URN="urn:oid:1.3.132.0.35" />
  </DomainParameters>
  <PublicKey>
    <X Value="11" xsi:type="PrimeFieldElemType" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
    <Y Value="17" xsi:type="PrimeFieldElemType" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
  </PublicKey>
</ECDHKeyValue>
using (ECDiffieHellmanCng dhKey = new ECDiffieHellmanCng())
{
    dhKey.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
    dhKey.HashAlgorithm = CngAlgorithm.Sha256;

    Console.WriteLine(dhKey.PublicKey.ToXmlString());
}
ECDiffieHellmanCngPublicKey pbkey = ECDiffieHellmanCngPublicKey.FromXmlString(xmlHere);
    using (ECDiffieHellman dhBob = ECDiffieHellman.Create(ECCurve.CreateFromValue("1.3.132.0.35")))
    {
        using (ECDiffieHellman dhAlice = ECDiffieHellman.Create(ECCurve.CreateFromValue("1.3.132.0.35")))
        {
            byte[] b = dhAlice.DeriveKeyMaterial(dhBob.PublicKey);

            byte[] b2 = dhBob.DeriveKeyMaterial(dhAlice.PublicKey);

            Console.WriteLine(b.SequenceEqual(b2));
        }
    }
然后我得到这个错误:

Unhandled Exception: System.PlatformNotSupportedException: The specified curve 'ECDSA_P521' or its parameters are not valid for this platform. ---> Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: The parameter is incorrect
   at System.Security.Cryptography.CngKeyLite.SetProperty(SafeNCryptHandle ncryptHandle, String propertyName, Byte[] value)
   at System.Security.Cryptography.CngKeyLite.SetCurveName(SafeNCryptHandle keyHandle, String curveName)
   at System.Security.Cryptography.CngKeyLite.GenerateNewExportableKey(String algorithm, String curveName)
   at System.Security.Cryptography.ECCngKey.GenerateKey(ECCurve curve)
   --- End of inner exception stack trace ---
   at System.Security.Cryptography.ECCngKey.GenerateKey(ECCurve curve)
   at System.Security.Cryptography.ECDiffieHellman.Create(ECCurve curve)
   at TestCore.Program.Main(String[] args) 
我不清楚错误信息。这条曲线真的不受支持吗?或者参数有问题,但具体怎么办?
如果曲线不受支持,我会感到惊讶,因为nistP521曲线是受支持的,并且根据我在网上找到的这篇IBM文档,它们是相同的:

看起来在使用ECDH处理这些OID时存在一个等价性问题(它正在将其转换为Windows ECDSA名称,而不是Windows ECDH名称)。你可以用这样的方法来解决它

private static ECCurve GetCurveByOid(string oidValue)
{
    switch (oidValue)
    {
        case "1.2.840.10045.3.1.7":
            return ECCurve.NamedCurves.nistP256;
        case "1.3.132.0.34":
            return ECCurve.NamedCurves.nistP384;
        case "1.3.132.0.35":
            return ECCurve.NamedCurves.nistP521;
    }

    return ECCurve.CreateFromValue(oidValue);
}

谢谢大家的帮助。最后,我编写了这段代码,它在.Net Core 2.1上运行,并且与.Net Framework To/FromXmlString兼容:

        using (ECDiffieHellmanCng dhBob = new ECDiffieHellmanCng())
        {
            dhBob.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
            dhBob.HashAlgorithm = CngAlgorithm.Sha256;
            string xmlBob = ToXmlString(dhBob.PublicKey);
            //Console.WriteLine(xmlBob);

            using (ECDiffieHellmanCng dhAlice = new ECDiffieHellmanCng())
            {
                dhAlice.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash;
                dhAlice.HashAlgorithm = CngAlgorithm.Sha256;
                ECDiffieHellmanPublicKey keyBob = FromXmlString(xmlBob, dhAlice.KeySize);
                byte[] b = dhAlice.DeriveKeyMaterial(keyBob);


                string xmlAlice = ToXmlString(dhAlice.PublicKey);
                ECDiffieHellmanPublicKey keyAlice = FromXmlString(xmlAlice, dhBob.KeySize);
                byte[] b2 = dhBob.DeriveKeyMaterial(keyAlice);

                Console.WriteLine(b.SequenceEqual(b2));
            }
        }

public static string ToXmlString(ECDiffieHellmanPublicKey key)
{
    // the regular ToXmlString from ECDiffieHellmanPublicKey throws PlatformNotSupportedException on .net core 2.1
    ECParameters parameters = key.ExportParameters();
    return string.Format("<ECDHKeyValue xmlns='http://www.w3.org/2001/04/xmldsig-more#'><DomainParameters><NamedCurve URN='urn:oid:{0}' />" +
                         "</DomainParameters><PublicKey><X Value='{1}' xsi:type='PrimeFieldElemType' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' />" +
                         "<Y Value='{2}' xsi:type='PrimeFieldElemType' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' /></PublicKey></ECDHKeyValue>",
        GetOid(parameters.Curve),
        new BigInteger(parameters.Q.X.Reverse().ToArray().Concat(new byte[] { 0 }).ToArray()).ToString(System.Globalization.CultureInfo.InvariantCulture), // watch out for big endian - little endian
        new BigInteger(parameters.Q.Y.Reverse().ToArray().Concat(new byte[] { 0 }).ToArray()).ToString(System.Globalization.CultureInfo.InvariantCulture));
}

public static ECDiffieHellmanPublicKey FromXmlString(string xml, int keySize)
{
    // the regular FromXmlString from ECDiffieHellmanPublicKey throws PlatformNotSupportedException on .net core 2.1
    XDocument doc = XDocument.Parse(xml);
    XNamespace nsSys = "http://www.w3.org/2001/04/xmldsig-more#";
    string xString = doc.Element(nsSys + "ECDHKeyValue").Element(nsSys + "PublicKey").Element(nsSys + "X").Attribute("Value").Value;
    string yString = doc.Element(nsSys + "ECDHKeyValue").Element(nsSys + "PublicKey").Element(nsSys + "Y").Attribute("Value").Value;
    string curve = doc.Element(nsSys + "ECDHKeyValue").Element(nsSys + "DomainParameters").Element(nsSys + "NamedCurve").Attribute("URN").Value;
    curve = curve.Replace("urn:", "").Replace("oid:", "");

    byte[] arrayX = BigInteger.Parse(xString, System.Globalization.CultureInfo.InvariantCulture).ToByteArray(false, true); // watch out for big endian - little endian
    byte[] arrayY = BigInteger.Parse(yString, System.Globalization.CultureInfo.InvariantCulture).ToByteArray(false, true);

    // make sure each part has the correct and same size
    int partSize = (int) Math.Ceiling(keySize / 8.0);
    ResizeRight(ref arrayX, partSize);
    ResizeRight(ref arrayY, partSize);

    ECParameters parameters = new ECParameters() { Q = new ECPoint() { X = arrayX, Y = arrayY }, Curve = GetCurveByOid(curve) };
    ECDiffieHellman dh = ECDiffieHellman.Create(parameters);
    return dh.PublicKey;
}

/// <summary>
/// Resize but pad zeroes to the left instead of to the right like Array.Resize
/// </summary>
public static void ResizeRight(ref byte[] b, int length)
{
    if (b.Length == length)
        return;
    if (b.Length > length)
        throw new NotSupportedException();

    byte[] newB = new byte[length];
    Array.Copy(b, 0, newB, length - b.Length, b.Length);
    b = newB;
}

private static ECCurve GetCurveByOid(string oidValue)
{
    // there are strange bugs in .net core 2.1 where the createfromvalue doesn't work for the named curves
    switch (oidValue)
    {
        case "1.2.840.10045.3.1.7":
            return ECCurve.NamedCurves.nistP256;
        case "1.3.132.0.34":
            return ECCurve.NamedCurves.nistP384;
        case "1.3.132.0.35":
            return ECCurve.NamedCurves.nistP521;
        default:
            return ECCurve.CreateFromValue(oidValue);
    }
}

private static string GetOid(ECCurve curve)
{
    // there are strange bugs in .net core 2.1 where the value of the oid of the named curves is empty
    if (curve.Oid.FriendlyName == ECCurve.NamedCurves.nistP256.Oid.FriendlyName)
        return "1.2.840.10045.3.1.7";
    else if (curve.Oid.FriendlyName == ECCurve.NamedCurves.nistP384.Oid.FriendlyName)
        return "1.3.132.0.34";
    else if (curve.Oid.FriendlyName == ECCurve.NamedCurves.nistP521.Oid.FriendlyName)
        return "1.3.132.0.35";
    else
        return curve.Oid.Value;
}
使用(ECDiffieHellmanCng dhBob=new ECDiffieHellmanCng())
{
dhBob.keydrivationfunction=ecdiffiehellmankeydrivationfunction.Hash;
dhBob.HashAlgorithm=CngAlgorithm.Sha256;
字符串xmlBob=ToXmlString(dhBob.PublicKey);
//控制台写入线(xmlBob);
使用(ecdiffiehellmancing dhAlice=new ecdiffiehellmancing())
{
dhAlice.KeyDerivationFunction=ECDiffieHellmanKeyDerivationFunction.Hash;
dhAlice.HashAlgorithm=CngAlgorithm.Sha256;
ECDiffieHellmanPublicKeyBob=FromXmlString(xmlBob,dhAlice.KeySize);
字节[]b=dhAlice.DeriveKeyMaterial(keyBob);
string xmlalise=ToXmlString(dhAlice.PublicKey);
ECDiffieHellmanPublicKeyAlice=FromXmlString(xmlAlice,dhBob.KeySize);
字节[]b2=dhBob.DeriveKeyMaterial(keyalis);
控制台写入线(b.SequenceEqual(b2));
}
}
公共静态字符串ToXmlString(ECDiffieHellman公钥)
{
//ECDiffieHellmanPublicKey中的常规ToXmlString在.NETCore2.1上抛出PlatformNotSupportedException
ECParameters=key.ExportParameters();
返回字符串。格式(“”)+
"" +
"",
GetOid(参数曲线),
新的BigInteger(parameters.Q.X.Reverse().ToArray().Concat(新字节[]{0}).ToArray()).ToString(System.Globalization.CultureInfo.InvariantCulture),//注意大端数-小端数
新的BigInteger(parameters.Q.Y.Reverse().ToArray().Concat(新字节[]{0}).ToArray()).ToString(System.Globalization.CultureInfo.InvariantCulture));
}
公共静态ECDiffieHellmanPublicKey FromXmlString(字符串xml,int-keySize)
{
//ECDiffieHellman公钥中的常规FromXmlString在.net core 2.1上抛出PlatformNotSupportedException
XDocument doc=XDocument.Parse(xml);
XNSSYS=”http://www.w3.org/2001/04/xmldsig-more#";
字符串xString=doc.Element(nsSys+“ECDHKeyValue”).Element(nsSys+“PublicKey”).Element(nsSys+“X”).Attribute(“Value”).Value;
字符串yString=doc.Element(nsSys+“ECDHKeyValue”).Element(nsSys+“PublicKey”).Element(nsSys+“Y”).Attribute(“Value”).Value;
字符串曲线=doc.Element(nsSys+“ECDHKeyValue”).Element(nsSys+“DomainParameters”).Element(nsSys+“NamedCurve”).Attribute(“URN”).Value;
曲线=曲线。替换(“urn:,”)。替换(“oid:,”);
byte[]arrayX=biginger.Parse(xString,System.Globalization.CultureInfo.InvariantCulture).ToByteArray(false,true);//注意big-endian-little endian
byte[]arrayY=biginger.Parse(yString,System.Globalization.CultureInfo.InvariantCulture).ToByteArray(false,true);
//确保每个零件的尺寸正确且相同
int partSize=(int)数学上限(keySize/8.0);
ResizeRight(参考arrayX,零件尺寸);
ResizeRight(参考阵列,零件尺寸);
ECParameters parameters=newecparameters(){Q=newecpoint(){X=arrayX,Y=arrayY},Curve=getcurvebyid(Curve)};
ECDiffieHellman dh=ECDiffieHellman.Create(参数);
返回dh.PublicKey;
}
/// 
///调整大小,但将零放在左边,而不是像数组一样放在右边。调整大小
/// 
公共静态void ResizeRight(参考字节[]b,整数长度)
{
如果(b.Length==长度)
返回;
如果(b.长度>长度)
抛出新的NotSupportedException();
字节[]新字节=新字节[长度];
数组.Copy(b,0,newB,length-b.length,b.length);
b=新的;
}
私有静态ECCurve GetCurveById(字符串值)
{
//在.NETCore2.1中有一些奇怪的bug,其中