Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.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/3/heroku/2.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# ECC p-128未在c中生成32字节数组签名#_C#_.net_Cryptography_Bouncycastle_Elliptic Curve - Fatal编程技术网

C# ECC p-128未在c中生成32字节数组签名#

C# ECC p-128未在c中生成32字节数组签名#,c#,.net,cryptography,bouncycastle,elliptic-curve,C#,.net,Cryptography,Bouncycastle,Elliptic Curve,signature1值在转换为十六进制时始终为39字节[]数组,长度大于64。 我想从c#中的P-128 ECC算法生成精确的64长度十六进制签名值 让我解释一下下面的代码: 对我必须签名的纯文本消息进行哈希 从本地文件夹读取128位PEM密钥 传递密钥并生成签名 public static string GenerateSignature(string message, string privateKeyPath) { string hashMessage;

signature1值在转换为十六进制时始终为39字节[]数组,长度大于64。 我想从c#中的P-128 ECC算法生成精确的64长度十六进制签名值

让我解释一下下面的代码:

  • 对我必须签名的纯文本消息进行哈希

  • 从本地文件夹读取128位PEM密钥

  • 传递密钥并生成签名

    public static string GenerateSignature(string message, string privateKeyPath) { string hashMessage; using (SHA256 sha256 = SHA256.Create()) { byte[] data = sha256.ComputeHash(Encoding.Default.GetBytes(message)); hashMessage = convertByteArrayToHexString(data); Console.WriteLine("Signing message: {0}", message); Console.WriteLine("Hash of the signing message: {0}", hashMessage); } byte[] hashMessageBytes = Encoding.UTF8.GetBytes(hashMessage); ISigner signer = SignerUtilities.GetSigner("SHA256withECDSA"); AsymmetricCipherKeyPair publicKey = getPrivateKeyFromPemFile(privateKeyPath); signer.Init(true, publicKey.Private); signer.BlockUpdate(hashMessageBytes, 0, hashMessageBytes.Length); byte[] signature1 = signer.GenerateSignature(); }
  • 公共静态字符串生成器签名(字符串消息、字符串privateKeyPath) { 字符串哈希消息; 使用(SHA256 SHA256=SHA256.Create()) { byte[]data=sha256.ComputeHash(Encoding.Default.GetBytes(message)); hashMessage=convertbytearraytohextstring(数据); WriteLine(“签名消息:{0}”,消息); WriteLine(“签名消息的哈希:{0}”,hashMessage); } byte[]hashMessageBytes=Encoding.UTF8.GetBytes(hashMessage); ISigner signer=SignerUtilities.GetSigner(“SHA256withECDSA”); AsymmetricipherKeyPair publicKey=GetPrivateKeyFrompFile(privateKeyPath); signer.Init(true,publicKey.Private); signer.BlockUpdate(hashMessageBytes,0,hashMessageBytes.Length); 字节[]signature1=signer.GenerateSignature(); }
    有不同的签名格式,一种是ASN.1 DER格式,在代码中使用,并对其进行了说明。对于曲线secp128r1(P-128),生成的签名长度在38到40字节之间

    您似乎期望的格式是r | s(请参阅),对于曲线secp128r1,其长度为32字节

    您可以轻松地手动在这两种格式之间进行转换

    更新版本的BouncyCastle for C#还允许直接生成r|s格式的签名,请参见,例如,使用
    SHA-256withPLAIN-ECDSA
    (而不是
    SHA-256withECDSA

    请注意:

    • 根据NIST,128位的密钥大小同时太小(相反,2019-2030年建议至少224位)。secp128r1仍在(从2000年起)中推荐,但在(从2010年起)中不再推荐
    • SHA-256withECDSA
      SHA-256withPLAIN-ECDSA
      )隐式散列消息(使用SHA-256),即不需要显式散列,并导致双重(冗余)散列
    • 此外,在显式散列中,传递给签名者的不是实际的二进制散列,而是UTF-8编码的十六进制编码散列
    • secp128r1对应于128位(16字节)的密钥大小(基点顺序)。但是对于SHA256,您使用的摘要是两倍大(32字节)。在这种情况下,根据NIST FIPS 186-4,使用散列的最左边n位
    编辑:

    为了具体说明目前为止所说的内容:以下代码UTF-8对字符串
    消息进行编码,并根据曲线secp128r1和摘要SHA256生成r|s格式的ECDSA签名(对应于IEEE P1363):

    public static string GenerateSignature(string message, string privateKeyPath)
    {
        byte[] messageBytes = Encoding.UTF8.GetBytes(message);
        ISigner signer = SignerUtilities.GetSigner("SHA-256withPLAIN-ECDSA");
        AsymmetricCipherKeyPair keyPair = getPrivateKeyFromPemFile(privateKeyPath); // get secp128r1 key pair
        signer.Init(true, keyPair.Private);
        signer.BlockUpdate(messageBytes, 0, messageBytes.Length);
        byte[] signature = signer.GenerateSignature();
        return ByteArrayToString(signature); // https://stackoverflow.com/a/311179/9014097
    }
    
    请注意与您最初发布的代码相比的差异:

    • 由于(
      Org.BouncyCastle.Crypto.
      ISigner#GenerateSignature()
      隐式散列,因此不执行显式散列
    • SHA-256withPLAIN-ECDSA
      直接以r|s格式生成签名,自v1.8.4(bccrypto-csharp-1.8.4,2018年10月27日发布)起存在
    如果是较旧的BouncyCastle版本(仅提供带有ECDSA的SHA-256
    ),则必须手动将签名从ASN.1 DER转换为r | s格式。这很容易,因为r和s可以直接从ASN.1 DER格式中提取,请参阅

    如果客户端的验证仍然未能通过上述代码,请检查两侧的键、曲线和摘要是否匹配以及验证过程本身


    为了完整性:
    当然,也可以使用(
    Org.BouncyCastle.Crypto.Signers.
    ECDsaSigner.GenerateSignature(byte[]msg)
    生成签名。重要的是,此方法不会隐式散列,即这里确实必须显式散列。这个方法返回r和s作为(
    Org.BouncyCastle.Math.
    biginger[]
    ,这样这两部分都可以很容易地用十六进制编码,例如
    toString(16)
    ,然后连接到r | s。

    Tapaco,我需要IEEE P1363输出64长度的单个十六进制字符串,我得到签名(r,s)如果我加入它,它将转换为64长度的十六进制。但它仍然没有在我的客户处验证。请帮助曲线secp128r1(P-128)生成的签名长度在38到40字节之间。我需要精确的32字节(使用IEEE P1363),然后它将转换为64个字节。您如何修改代码以生成r | s格式的签名,您是否将
    SHA-256替换为ECDSA
    ?对于更复杂的更改,例如,如果您手动从ASN.1 DER格式派生r|s格式,请编辑您的答案并添加当前代码以创建r|s签名(请不要更改已发布的代码,而是添加新代码)。您的代码中还有其他问题,特别是我列表底部的第2点和第3点:
    ISigner#GenerateSignature()
    隐式地进行哈希运算(这就是摘要名称包含在说明符中的原因),因此无需显式地进行哈希运算。因此,您可以尝试将
    BlockUpdate
    中的
    hashMessageBytes
    替换为
    Encoding.UTF8.GetBytes(message)
    。最后发布的代码与原始代码明显不同。使用三个代码没有什么意义,因此我在原始代码的基础上发布了一个可能的解决方案,请参阅我答案中的编辑部分。