当前位置: 首页 > 知识库问答 >
问题:

用mbedtls生成的RSA签名无法用C#(bouncycastle)应用程序验证

颜宸
2023-03-14

我正在使用mbedtls与RSA签署一个32字节的挑战。

mbedtls_rsa_context rsa;

mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);

mbedtls_rsa_rsassa_pss_sign(&rsa, f_rng, &prng, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA256, 32, challenge, signature)
mbedtls_rsa_rsassa_pss_verify(&rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA256, sizeof(challenge), challenge, signature);
RsaKeyParameters key = new RsaKeyParameters(false, new Org.BouncyCastle.Math.BigInteger(Nstring, 16), new Org.BouncyCastle.Math.BigInteger(Estring, 16));

ISigner sig = SignerUtilities.GetSigner("SHA256WITHRSA/PSS");

sig.Init(false, key);

sig.BlockUpdate(challenge, 0, challenge.Length);
Console.WriteLine("result: " + sig.VerifySignature(signature));

我想我有正确格式的数据。这是C端的公钥指数和模:

unsigned char E[] = { 0x01,0x00,0x01 };
unsigned char N[] = { 0xC2,0x7E,0xC0,0xCD,0x1B,0xEA,0xE1,0x2E,0x5F,0x15,0xE3,0x9A,0xA3,0x5C,0xF2,0x0A,0xB5,0xAE,0x7F,0x22,0xE0,0x8A,0xA8,0xA7,0x44,0x8E,0xDD,0x1F,0x3C,0xDD,0xDA,0xE5,0xBB,0x23,0x8F,0xF2,0xED,0xFA,0xDF,0xC4,0x95,0x72,0x67,0x00,0x49,0xCF,0xCD,0xE7,0x35,0x56,0x49,0xE7,0x16,0xCC,0x5A,0x9A,0x37,0xFA,0x0C,0x6B,0x79,0xA5,0x5B,0x5A,0x4C,0x1F,0x48,0xE7,0x62,0x59,0xFD,0x60,0x4A,0xCC,0xFF,0xB6,0x62,0xD2,0xEB,0x41,0xF3,0xB1,0xDA,0x2F,0x61,0x55,0x68,0xD1,0x77,0x7C,0x16,0xCA,0x62,0x2F,0xF9,0x6D,0x03,0xED,0xCF,0x89,0x9D,0x1E,0x5B,0xA8,0x4D,0x90,0xDF,0x80,0x1B,0x75,0xE0,0x6D,0xAA,0x0D,0x8A,0xCC,0xA1,0x5B,0xE5,0xD8,0xA0,0x97,0xFF,0x75,0x4B,0xDA,0x39,0x7D };

这就是我在C#端使用它们的方式:

Estring = "010001";
Nstring = "C27EC0CD1BEAE12E5F15E39AA35CF20AB5AE7F22E08AA8A7448EDD1F3CDDDAE5BB238FF2EDFADFC49572670049CFCDE7355649E716CC5A9A37FA0C6B79A55B5A4C1F48E76259FD604ACCFFB662D2EB41F3B1DA2F615568D1777C16CA622FF96D03EDCF899D1E5BA84D90DF801B75E06DAA0D8ACCA15BE5D8A097FF754BDA397D";

“Challenge”和“Signature”是两边的8位(无符号字符/字节)数组,包含相同的数据。

unsigned char challenge[32] = {
0x1E,0x36,0x44,0x82,0x2A,0x60,0x79,0xDE,0x7D,0x49,0x92,0xAA,0x5E,0x25,0xB5,0x80,0x6D,0x95,0x7E,0xE9,0x3A,0x30,0x9B,0x7F,0x82,0x4B,0xB0,0x26,0x3D,0x00,0x0C,0x2E
};

unsigned char signature[128] = {
0xA7,0x64,0x07,0xD0,0x06,0x35,0x0E,0x3F,0x6C,0xFB,0xA1,0xB8,0xDC,0xC5,0x68,0x97,0x65,0xD5,0x7A,0x74,0xFC,0x96,0x01,0x53,0xE0,0x16,0xBC,0xCA,0x59,0x40,0x37,0xC8,0xC9,0x89,0xC2,0x84,0x2A,0xC6,0x51,0xCD,0xDA,0x29,0x65,0xBF,0x39,0x68,0x1E,0x3A,0x0E,0x4E,0x81,0x2E,0xBC,0x08,0x41,0x6A,0xC8,0x95,0xD1,0x43,0x35,0x7C,0x14,0xF6,0x2D,0xE8,0xDA,0x94,0x6C,0x80,0x9D,0x86,0x19,0x4B,0x16,0xD3,0x17,0xAB,0x0E,0x7F,0xE8,0x5F,0xC9,0xB5,0xCC,0x9B,0x96,0xE6,0xAB,0xB6,0x7B,0x11,0x5B,0xC8,0x01,0xD7,0x16,0x50,0xD3,0xF8,0xB4,0xF5,0xCB,0xC2,0xC4,0x70,0xCD,0x84,0x50,0xD0,0x7F,0xA9,0xC3,0x8F,0xE1,0x6B,0x54,0xF4,0x32,0xB8,0x6E,0xCD,0xD2,0xCF,0x78,0x98,0x69,0x7F
};

MBEDTLS/C++项目,有效(输出“验证成功”)

#include <stdio.h>
#include "mbedtls/config.h"
#include "mbedtls/platform.h"
#include "mbedtls/error.h"
#include "mbedtls/rsa.h"
#include "mbedtls/error.h"
#include "mbedtls/bignum.h"

int main(int argc, char* argv[])
{
    int ret;
    char errbuf[100];
    mbedtls_rsa_context ctx;

    /* Key */
    unsigned char E[] = { 0x01,0x00,0x01 };
    unsigned char N[] = { 0xC2,0x7E,0xC0,0xCD,0x1B,0xEA,0xE1,0x2E,0x5F,0x15,0xE3,0x9A,0xA3,0x5C,0xF2,0x0A,0xB5,0xAE,0x7F,0x22,0xE0,0x8A,0xA8,0xA7,0x44,0x8E,0xDD,0x1F,0x3C,0xDD,0xDA,0xE5,0xBB,0x23,0x8F,0xF2,0xED,0xFA,0xDF,0xC4,0x95,0x72,0x67,0x00,0x49,0xCF,0xCD,0xE7,0x35,0x56,0x49,0xE7,0x16,0xCC,0x5A,0x9A,0x37,0xFA,0x0C,0x6B,0x79,0xA5,0x5B,0x5A,0x4C,0x1F,0x48,0xE7,0x62,0x59,0xFD,0x60,0x4A,0xCC,0xFF,0xB6,0x62,0xD2,0xEB,0x41,0xF3,0xB1,0xDA,0x2F,0x61,0x55,0x68,0xD1,0x77,0x7C,0x16,0xCA,0x62,0x2F,0xF9,0x6D,0x03,0xED,0xCF,0x89,0x9D,0x1E,0x5B,0xA8,0x4D,0x90,0xDF,0x80,0x1B,0x75,0xE0,0x6D,0xAA,0x0D,0x8A,0xCC,0xA1,0x5B,0xE5,0xD8,0xA0,0x97,0xFF,0x75,0x4B,0xDA,0x39,0x7D };

    /* Challenge */
    unsigned char challenge[] = {
        0x1E,0x36,0x44,0x82,0x2A,0x60,0x79,0xDE,0x7D,0x49,0x92,0xAA,0x5E,0x25,0xB5,0x80,0x6D,0x95,0x7E,0xE9,0x3A,0x30,0x9B,0x7F,0x82,0x4B,0xB0,0x26,0x3D,0x00,0x0C,0x2E
    };

    /* Response */
    unsigned char responseGiven[] = {
        0xA7,0x64,0x07,0xD0,0x06,0x35,0x0E,0x3F,0x6C,0xFB,0xA1,0xB8,0xDC,0xC5,0x68,0x97,0x65,0xD5,0x7A,0x74,0xFC,0x96,0x01,0x53,0xE0,0x16,0xBC,0xCA,0x59,0x40,0x37,0xC8,0xC9,0x89,0xC2,0x84,0x2A,0xC6,0x51,0xCD,0xDA,0x29,0x65,0xBF,0x39,0x68,0x1E,0x3A,0x0E,0x4E,0x81,0x2E,0xBC,0x08,0x41,0x6A,0xC8,0x95,0xD1,0x43,0x35,0x7C,0x14,0xF6,0x2D,0xE8,0xDA,0x94,0x6C,0x80,0x9D,0x86,0x19,0x4B,0x16,0xD3,0x17,0xAB,0x0E,0x7F,0xE8,0x5F,0xC9,0xB5,0xCC,0x9B,0x96,0xE6,0xAB,0xB6,0x7B,0x11,0x5B,0xC8,0x01,0xD7,0x16,0x50,0xD3,0xF8,0xB4,0xF5,0xCB,0xC2,0xC4,0x70,0xCD,0x84,0x50,0xD0,0x7F,0xA9,0xC3,0x8F,0xE1,0x6B,0x54,0xF4,0x32,0xB8,0x6E,0xCD,0xD2,0xCF,0x78,0x98,0x69,0x7F
    };

    mbedtls_rsa_init(&ctx, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);

    /* Load public key */
    if ((ret = mbedtls_rsa_import_raw(&ctx, N, sizeof(N), NULL, 0, NULL, 0, NULL, 0, E, sizeof(E))) != 0) {
        mbedtls_strerror(ret, errbuf, sizeof(errbuf));
        mbedtls_printf("mbedtls_rsa_import_raw failed, returned %d, %s\n\n", ret, errbuf);
        return 0;
    }
    if ((ret = mbedtls_rsa_complete(&ctx)) != 0) {
        mbedtls_strerror(ret, errbuf, sizeof(errbuf));
        mbedtls_printf("mbedtls_rsa_complete failed, returned %d, %s\n\n", ret, errbuf);
        return 0;
    }

    /* Verify response */
    if ((ret = mbedtls_rsa_rsassa_pss_verify(&ctx, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA256, 32, challenge, responseGiven))) {
        mbedtls_strerror(ret, errbuf, sizeof(errbuf));
        mbedtls_printf("mbedtls_rsa_rsassa_pss_verify failed, returned %d - %s\n\n", ret, errbuf);
        return 0;
    }
    else {
        mbedtls_printf("Verification success\n");
    }

    getchar();
    return 1;
}

BouncyCastal/C#项目失败(输出“VerifySignature Failed”)

using System;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Signers;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Digests;

namespace cryptotest
{
    class Program
    {
        static void Main(string[] args)
        {
            /* Key */
            byte[] E = new byte[] { 0x01, 0x00, 0x01 };
            byte[] N = new byte[] { 0xC2, 0x7E, 0xC0, 0xCD, 0x1B, 0xEA, 0xE1, 0x2E, 0x5F, 0x15, 0xE3, 0x9A, 0xA3, 0x5C, 0xF2, 0x0A, 0xB5, 0xAE, 0x7F, 0x22, 0xE0, 0x8A, 0xA8, 0xA7, 0x44, 0x8E, 0xDD, 0x1F, 0x3C, 0xDD, 0xDA, 0xE5, 0xBB, 0x23, 0x8F, 0xF2, 0xED, 0xFA, 0xDF, 0xC4, 0x95, 0x72, 0x67, 0x00, 0x49, 0xCF, 0xCD, 0xE7, 0x35, 0x56, 0x49, 0xE7, 0x16, 0xCC, 0x5A, 0x9A, 0x37, 0xFA, 0x0C, 0x6B, 0x79, 0xA5, 0x5B, 0x5A, 0x4C, 0x1F, 0x48, 0xE7, 0x62, 0x59, 0xFD, 0x60, 0x4A, 0xCC, 0xFF, 0xB6, 0x62, 0xD2, 0xEB, 0x41, 0xF3, 0xB1, 0xDA, 0x2F, 0x61, 0x55, 0x68, 0xD1, 0x77, 0x7C, 0x16, 0xCA, 0x62, 0x2F, 0xF9, 0x6D, 0x03, 0xED, 0xCF, 0x89, 0x9D, 0x1E, 0x5B, 0xA8, 0x4D, 0x90, 0xDF, 0x80, 0x1B, 0x75, 0xE0, 0x6D, 0xAA, 0x0D, 0x8A, 0xCC, 0xA1, 0x5B, 0xE5, 0xD8, 0xA0, 0x97, 0xFF, 0x75, 0x4B, 0xDA, 0x39, 0x7D };

            /* Challenge */
            byte[] challenge = new byte[] {
                0x1E,0x36,0x44,0x82,0x2A,0x60,0x79,0xDE,0x7D,0x49,0x92,0xAA,0x5E,0x25,0xB5,0x80,0x6D,0x95,0x7E,0xE9,0x3A,0x30,0x9B,0x7F,0x82,0x4B,0xB0,0x26,0x3D,0x00,0x0C,0x2E
            };

            /* Response */
            byte[] responseGiven = new byte[]{
                0xA7,0x64,0x07,0xD0,0x06,0x35,0x0E,0x3F,0x6C,0xFB,0xA1,0xB8,0xDC,0xC5,0x68,0x97,0x65,0xD5,0x7A,0x74,0xFC,0x96,0x01,0x53,0xE0,0x16,0xBC,0xCA,0x59,0x40,0x37,0xC8,0xC9,0x89,0xC2,0x84,0x2A,0xC6,0x51,0xCD,0xDA,0x29,0x65,0xBF,0x39,0x68,0x1E,0x3A,0x0E,0x4E,0x81,0x2E,0xBC,0x08,0x41,0x6A,0xC8,0x95,0xD1,0x43,0x35,0x7C,0x14,0xF6,0x2D,0xE8,0xDA,0x94,0x6C,0x80,0x9D,0x86,0x19,0x4B,0x16,0xD3,0x17,0xAB,0x0E,0x7F,0xE8,0x5F,0xC9,0xB5,0xCC,0x9B,0x96,0xE6,0xAB,0xB6,0x7B,0x11,0x5B,0xC8,0x01,0xD7,0x16,0x50,0xD3,0xF8,0xB4,0xF5,0xCB,0xC2,0xC4,0x70,0xCD,0x84,0x50,0xD0,0x7F,0xA9,0xC3,0x8F,0xE1,0x6B,0x54,0xF4,0x32,0xB8,0x6E,0xCD,0xD2,0xCF,0x78,0x98,0x69,0x7F
            };

            /* Load public key. Modulus(N), exponent (E) */
            string Nstring = "";
            for (int i = 0; i < N.Length; i++) {
                Nstring += N[i].ToString("X2");
            }
            string Estring = "";
            for (int i = 0; i < E.Length; i++) {
                Estring += E[i].ToString("X2");
            }
            RsaKeyParameters key = new RsaKeyParameters(false, new Org.BouncyCastle.Math.BigInteger(Nstring, 16), new Org.BouncyCastle.Math.BigInteger(Estring, 16));
            PssSigner pss = new PssSigner(new RsaEngine(), new Sha256Digest(), 32, 0xBC);
            pss.Init(false, key);

            /* Verify response */
            pss.BlockUpdate(challenge, 0, challenge.Length);
            if(pss.VerifySignature(responseGiven) == false) {
                Console.WriteLine("VerifySignature failed");
            }
            else {
                Console.WriteLine("Verification success of given response");
            }

            Console.ReadKey();
        }
    }
}

共有1个答案

凤自珍
2023-03-14

C/C++代码在验证时期望消息的哈希值,因此在验证之前不进行哈希值。另一方面,C#代码在验证时期望消息本身,并在验证自身之前执行散列。

因此,如果将消息的哈希传递给C#代码而不是消息,则使用单个哈希消息的签名验证双重哈希消息,但失败。

如果在验证之前不在C#代码中执行类似于C/C++代码的散列,这个问题就可以解决。为此,例如,在.NET核心下,验证可以使用rsacng#verifyhash()执行,与rsacng#verifydata()相反,它需要类似于C/C++代码的消息哈希。

using System;
using System.Security.Cryptography;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
...
/* Key */
byte[] E = new byte[] { 0x01, 0x00, 0x01 };
byte[] N = new byte[] { 0xC2, 0x7E, 0xC0, 0xCD, 0x1B, 0xEA, 0xE1, 0x2E, 0x5F, 0x15, 0xE3, 0x9A, 0xA3, 0x5C, 0xF2, 0x0A, 0xB5, 0xAE, 0x7F, 0x22, 0xE0, 0x8A, 0xA8, 0xA7, 0x44, 0x8E, 0xDD, 0x1F, 0x3C, 0xDD, 0xDA, 0xE5, 0xBB, 0x23, 0x8F, 0xF2, 0xED, 0xFA, 0xDF, 0xC4, 0x95, 0x72, 0x67, 0x00, 0x49, 0xCF, 0xCD, 0xE7, 0x35, 0x56, 0x49, 0xE7, 0x16, 0xCC, 0x5A, 0x9A, 0x37, 0xFA, 0x0C, 0x6B, 0x79, 0xA5, 0x5B, 0x5A, 0x4C, 0x1F, 0x48, 0xE7, 0x62, 0x59, 0xFD, 0x60, 0x4A, 0xCC, 0xFF, 0xB6, 0x62, 0xD2, 0xEB, 0x41, 0xF3, 0xB1, 0xDA, 0x2F, 0x61, 0x55, 0x68, 0xD1, 0x77, 0x7C, 0x16, 0xCA, 0x62, 0x2F, 0xF9, 0x6D, 0x03, 0xED, 0xCF, 0x89, 0x9D, 0x1E, 0x5B, 0xA8, 0x4D, 0x90, 0xDF, 0x80, 0x1B, 0x75, 0xE0, 0x6D, 0xAA, 0x0D, 0x8A, 0xCC, 0xA1, 0x5B, 0xE5, 0xD8, 0xA0, 0x97, 0xFF, 0x75, 0x4B, 0xDA, 0x39, 0x7D };

/* Challenge */
byte[] challenge = new byte[] {
    0x1E,0x36,0x44,0x82,0x2A,0x60,0x79,0xDE,0x7D,0x49,0x92,0xAA,0x5E,0x25,0xB5,0x80,0x6D,0x95,0x7E,0xE9,0x3A,0x30,0x9B,0x7F,0x82,0x4B,0xB0,0x26,0x3D,0x00,0x0C,0x2E
};

/* Response */
byte[] responseGiven = new byte[]{
    0xA7,0x64,0x07,0xD0,0x06,0x35,0x0E,0x3F,0x6C,0xFB,0xA1,0xB8,0xDC,0xC5,0x68,0x97,0x65,0xD5,0x7A,0x74,0xFC,0x96,0x01,0x53,0xE0,0x16,0xBC,0xCA,0x59,0x40,0x37,0xC8,0xC9,0x89,0xC2,0x84,0x2A,0xC6,0x51,0xCD,0xDA,0x29,0x65,0xBF,0x39,0x68,0x1E,0x3A,0x0E,0x4E,0x81,0x2E,0xBC,0x08,0x41,0x6A,0xC8,0x95,0xD1,0x43,0x35,0x7C,0x14,0xF6,0x2D,0xE8,0xDA,0x94,0x6C,0x80,0x9D,0x86,0x19,0x4B,0x16,0xD3,0x17,0xAB,0x0E,0x7F,0xE8,0x5F,0xC9,0xB5,0xCC,0x9B,0x96,0xE6,0xAB,0xB6,0x7B,0x11,0x5B,0xC8,0x01,0xD7,0x16,0x50,0xD3,0xF8,0xB4,0xF5,0xCB,0xC2,0xC4,0x70,0xCD,0x84,0x50,0xD0,0x7F,0xA9,0xC3,0x8F,0xE1,0x6B,0x54,0xF4,0x32,0xB8,0x6E,0xCD,0xD2,0xCF,0x78,0x98,0x69,0x7F
};

/* Load public key. Modulus(N), exponent (E) */
string Nstring = "";
for (int i = 0; i < N.Length; i++)
{
    Nstring += N[i].ToString("X2");
}
string Estring = "";
for (int i = 0; i < E.Length; i++)
{
    Estring += E[i].ToString("X2");
}
RsaKeyParameters key = new RsaKeyParameters(false, new Org.BouncyCastle.Math.BigInteger(Nstring, 16), new Org.BouncyCastle.Math.BigInteger(Estring, 16));

/*
PssSigner pss = new PssSigner(new RsaEngine(), new Sha256Digest(), 32, 0xBC);
pss.Init(false, key);

// Verify response
pss.BlockUpdate(challenge, 0, challenge.Length);
if (pss.VerifySignature(responseGiven) == false)
{
    Console.WriteLine("VerifySignature failed");
}
else
{
    Console.WriteLine("Verification success of given response");
}

Console.ReadKey();
*/

RSA rsa = new RSACng();
RSAParameters rsaParams = DotNetUtilities.ToRSAParameters((RsaKeyParameters)key);
rsa.ImportParameters(rsaParams);
bool verified = rsa.VerifyHash(challenge, responseGiven, HashAlgorithmName.SHA256, RSASignaturePadding.Pss);
Console.WriteLine("Verified: " + verified); // Verified: True

Console.ReadKey();

使用此代码,验证是成功的。

或者,在原始C#代码中,可以传递消息本身而不是哈希。

 类似资料:
  • 我们有一个java程序,它使用私钥对xml文件进行签名,如下所示: 现在,我必须验证这个签名在C使用cryptocpp。我所尝试的: 我验证了作为xmlString传递的数据与用于在java中创建签名的数据是二进制的。签名是base64编码的,我也尝试使用它进行解码。到目前为止,我总是失败。 如果我使用cryptopp创建带有私钥的签名,那么验证创建的签名就不会有问题。 这里可能有什么问题?我确信

  • 我应该如何更改A方法?任何想法都是好的。提前谢谢。

  • 问题内容: 我正在使用和 (Bouncycastle库) 签署,然后验证。 这是我签署的: 现在,输出将在这一过程中使用的: 一切正常,直到由于以下原因: 有人可以给我提示可能发生的事情吗? PS 。如果有人要进行上述测试,则将需要我用来复制此文件的测试文件,只需从这里开始即可: https://www.dropbox.com/s/zs4jo1a86v8qamw/certificates.p12?

  • 我正在使用和(Bouncycastle库)对进行签名,然后验证。 由于以下,: 谁能给我一个可能会发生什么事的提示吗? ps.如果有人想要测试上面的您将需要我正在使用的测试文件来复制该文件,只需从此处即可: https://www.dropbox.com/s/zs4jo1a86v8qamw/certifications.p12?dl=0

  • 我正在尝试将支付网关集成到我的nodejs应用程序中。当支付完成时,网关用支付结果将用户重定向到我的站点。结果是RSA签名的,我需要用支付网关提供的公钥来验证它。 下面是支付网关为签名验证提供的示例PHP代码。 有谁知道怎么把这件事搞定吗?

  • 我需要为ant创建构建文件来构建我的,我已经搜索了很多,但没有任何帮助。它仍然显示错误并且不编译。当我尝试运行jar文件时,jar文件无法被删除。这里是 这里是错误