Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/332.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
使用RSASSA-PKCS1-V1_5-SIGN与C#RSACryptoServiceProvider手动签名?_C#_Encryption_Cryptography_Certificate_Rsa - Fatal编程技术网

使用RSASSA-PKCS1-V1_5-SIGN与C#RSACryptoServiceProvider手动签名?

使用RSASSA-PKCS1-V1_5-SIGN与C#RSACryptoServiceProvider手动签名?,c#,encryption,cryptography,certificate,rsa,C#,Encryption,Cryptography,Certificate,Rsa,我一直在努力了解C#如何准确地对数据进行签名,或者寻找任何关于它如何对数据进行签名的文档 我试图遵循指定的签名方案,但似乎无法生成与.NET实现匹配的签名 RSACryptoServiceProvider是如何生成签名的,或者为什么我的任何ManualSignedData都与下面示例代码中的RSACryptoServiceProviderSignedData不匹配 public void ManualSignatureTest(byte[] data, X509Certificate2

我一直在努力了解C#如何准确地对数据进行签名,或者寻找任何关于它如何对数据进行签名的文档

我试图遵循指定的签名方案,但似乎无法生成与.NET实现匹配的签名

RSACryptoServiceProvider是如何生成签名的,或者为什么我的任何ManualSignedData都与下面示例代码中的RSACryptoServiceProviderSignedData不匹配

    public void ManualSignatureTest(byte[] data, X509Certificate2 cert)
    {
        var sha256 = new SHA256CryptoServiceProvider();
        var rsa = (RSACryptoServiceProvider)cert.PrivateKey;

        var RSACryptoServiceProviderSignedData = rsa.SignData(data, "SHA256");

        var manualSignedDataLittle = ManualSignDataSha256(data, rsa, true, false);
        var manualSignedDataBig = ManualSignDataSha256(data, rsa, false, false);

        //https://msdn.microsoft.com/en-us/library/system.security.cryptography.rsacryptoserviceprovider(v=vs.110).aspx
        //the RSACryptoServiceProvider class reverses the order of an encrypted array of bytes after encryption and before decryption
        var manualSignedDataReversedLittle = ManualSignDataSha256(data, rsa, true, true);
        var manualSignedDataReversedBig = ManualSignDataSha256(data, rsa, false, true);            
    }

    public byte[] ManualSignDataSha256(byte[] data, RSACryptoServiceProvider rsa, bool littleEndian, bool reverseArray)
    {
        //https://tools.ietf.org/html/rfc8017#section-8.2.1
        //EM = EMSA-PKCS1-V1_5-ENCODE (M, k)
        var emsaEncodedMessage = EmsaPkcs1V1_5Encode_SHA256(data, 245);

        if (reverseArray) Array.Reverse(emsaEncodedMessage);
        //m = OS2IP (EM)
        var intMessageRepresentative = OS2IP(emsaEncodedMessage, littleEndian);

        //s = RSASP1 (K, m)
        var intSignatureRepresentative = RSASP1(rsa, intMessageRepresentative);

        //S = I2OSP (s, k)
        var signature = I2OSP(intSignatureRepresentative, 256, littleEndian);

        return signature;
    }

    public byte[] HexToByte(string hex)
    {
        return Enumerable.Range(0, hex.Length / 2).Select(x => Convert.ToByte(hex.Substring(x * 2, 2), 16)).ToArray();
    }

    public byte[] EmsaPkcs1V1_5Encode_SHA256(byte[] message, int emLen)
    {
        var digest = new SHA256CryptoServiceProvider().ComputeHash(message);
        var digestAlgorithm = HexToByte("3031300d060960864801650304020105000420");
        var digestInfo = digest.Concat(digestAlgorithm).ToArray();

        var paddingLength = emLen - digestInfo.Length - 3;
        var paddingHexString = "";
        for (int i = 0; i < paddingLength; i++)
        {
            paddingHexString += "FF";
        }

        return HexToByte("0001" + paddingHexString + "00").Concat(digestInfo).ToArray();
    }

    public BigInteger OS2IP(byte[] data, bool isLittleEndian)
    {
        BigInteger bi = 0;
        if (isLittleEndian)
        {
            for (int i = 0; i < data.Length; i++)
            {
                bi += BigInteger.Pow(256, i) * data[i];
            }
        }
        else
        {
            for (int i = 1; i <= data.Length; i++)
            {
                bi += BigInteger.Pow(256, i - 1) * data[data.Length - i];
            }
        }
        return bi;
    }

    public BigInteger RSASP1(RSACryptoServiceProvider rsa, BigInteger message)
    {
        var keyParameters = rsa.ExportParameters(true);
        var n = new BigInteger(keyParameters.Modulus);
        var d = new BigInteger(keyParameters.D);
        return BigInteger.ModPow(message, d, n);
        return default(BigInteger);
    }

    public byte[] I2OSP(BigInteger x, int xLen, bool makeLittleEndian)
    {
        byte[] result = new byte[xLen];
        int index = 0;
        while ((x > 0) && (index < result.Length))
        {
            result[index++] = (byte)(x % 256);
            x /= 256;
        }
        if (!makeLittleEndian)
            Array.Reverse(result);
        return result;
    }
public void ManualSignatureTest(字节[]数据,X509Certificate2证书)
{
var sha256=新的SHA256CryptoServiceProvider();
var rsa=(rsacyptoserviceprovider)cert.PrivateKey;
var rsacryptserviceprovidersigneddata=rsa.SignData(数据,“SHA256”);
var manualSignedDataLittle=ManualSignDataSha256(数据,rsa,真,假);
var manualSignedDataBig=ManualSignDataSha256(数据、rsa、假、假);
//https://msdn.microsoft.com/en-us/library/system.security.cryptography.rsacryptoserviceprovider(v=vs.110).aspx
//RSACryptServiceProvider类在加密后和解密前反转加密字节数组的顺序
var manualSignedDataReversedLittle=ManualSignDataSha256(数据,rsa,真,真);
var manualSignedDataReversedBig=ManualSignDataSha256(数据,rsa,假,真);
}
公共字节[]手动SignDataSha256(字节[]数据,RSACryptoServiceProvider rsa,bool littleEndian,bool reversearlay)
{
//https://tools.ietf.org/html/rfc8017#section-8.2.1
//EM=EMSA-PKCS1-V1_5-ENCODE(M,k)
var emsaEncodedMessage=EmsaPkcs1V1_5Encode_SHA256(数据,245);
if(reverseArray)Array.Reverse(emsaEncodedMessage);
//m=OS2IP(EM)
var intMessageRepresentative=OS2IP(emsaEncodedMessage,littleEndian);
//s=RSASP1(K,m)
var intSignatureRepresentative=rsap1(rsa,intMessageRepresentative);
//S=I2OSP(S,k)
var签名=I2OSP(intSignatureRepresentative,256,littleEndian);
返回签名;
}
公共字节[]十六进制字节(字符串十六进制)
{
返回可枚举的.Range(0,十六进制长度/2);
}
公共字节[]EmsaPkcs1V1_5Encode_SHA256(字节[]消息,int-emLen)
{
var digest=新的SHA256CryptoServiceProvider().ComputeHash(消息);
var digestAlgorithm=HexToByte(“3031300d060960864801650304020105000420”);
var digestInfo=digest.Concat(digestAlgorithm.ToArray();
var paddingLength=emLen-digestInfo.Length-3;
var paddingexstring=“”;
对于(int i=0;i
您有很多bug。首先,EmsaPkcs1V1_5Encode_SHA256函数向后构建digestInfo变量(您使用了
digestAlgorithm
作为后缀,而它应该是前缀)。您还应该在
RSASP1
中使用OS2IP,因为您向后调用了BigInteger变量

要点:

  • BigInteger需要一个小的endian字节[]
  • RSA参数使用大端字节[]s
  • OS2IP更易于使用
    • 如果需要,插入填充字节(字节[0]>=0x80)
    • 反向阵列
    • x=新的BigInteger(字节)
  • MSDN上关于RSACyptoServiceProvider“向后”的评论是…向后。CryptoEncrypt/CryptoDecrypt是向后的(little endian),RSACyptoServiceProvider将其解扭曲以匹配每个人在连线上期望的内容。(该评论是关于RSACSP数据直接与Windows CAPI交互操作)
下面是一个为您设计的示例。byte[]值是十六进制的,BigInteger值(OS2IP输出)是十进制的。使用上面的项目符号,您应该能够匹配它

Generated Key:
  n:
     C2311FC5FA31D333A409BB4CE95B20D21CFCE3753871725653A28425AF6DE97DF
     2020B23633F458DF12A63627121BFF4E23CE5787E077898057861D1AE60AC2F
  e: 010001
  d:
     0D916719EB103E24768AA3868D2B6BD0A26BDCEC9CC3F86C25ADCE33DFDCFB1A4
     D503E073D7FF5FD748E43F8DF02A60ED73053143E591E708DF72C2793E22B69
  p: F7EF37E67FA6685AC1788B01CF38DA20CA4BDE5D8B01A71BD28C65B409C36E4D
  q: C88257603FB8A5E25E9DDB553A73B647A3ECA6E9ABC6C440DBC705F82ED4DA6B
  dp: 72E79E0BA85B51FFC5AC7D17F096D398E0C87A9CF5C0655722A448BA40D01EFD
  dq: 4C0CABC954C1DB211DD3EFB1C6C6C6972B8481D65511C1B3FBE7E3CABB307E5B
  iq: B94CB9F83D4C145BE43EA96509FF187176F72E9B82F91B8BC49121FB6B9990F0



  data: 01010203
  hash (SHA256):
    9184ABD2BB318731D717E972057240EAE26CCA202A8D35DBE9D2176F526886A0
  EMSA_PKCS1_V1_5_ENCODE: T=
    3031300D0609608648016503040201050004209184ABD2BB318731D717E9720572
    40EAE26CCA202A8D35DBE9D2176F526886A0
  EMSA_PKCS1_V1_5_ENCODE: EM=
    0001FFFFFFFFFFFFFFFFFFFF003031300D060960864801650304020105000420918
    4ABD2BB318731D717E972057240EAE26CCA202A8D35DBE9D2176F526886A0
  OS2IP: x=
    4091738259870177337516485429975660299381480466173929813897514081197
    4001006075637088431241046394626562124424487751622623819494959348458
    9402025699608224
  RSASP1: n=
    1017065459787822195711481708900267786564376023809569193509899981293
    9461386629891828226910128922059886444866797206179548218910539391071
    517068232388857867311
  RSASP1: d=
    7106127440023861077197422440841549345679963704508929821447170322634
    5108395833416072981045532865581744327586076884716186753729887110610
    3233084086814911337
  RSASP1: s=
    4575492210354332473521217556428951379558271601925254480118287259959
    6454886403001827141625402256685452319478955175598933868230853388418
    44638909194871101390
  I2OSP: X=
    575C8A4109ED6EA2A7086338D150A5BB8205142E778547B50CC6019868070243BF4
    9DE7C60390160E392FACA18F4A05D3A7A88A4DE86DD99F030EB4AA755D7CE


rsa.SignHash:
  575C8A4109ED6EA2A7086338D150A5BB8205142E778547B50CC6019868070243B
  F49DE7C60390160E392FACA18F4A05D3A7A88A4DE86DD99F030EB4AA755D7CE
Manual:
  575C8A4109ED6EA2A7086338D150A5BB8205142E778547B50CC6019868070243B
  F49DE7C60390160E392FACA18F4A05D3A7A88A4DE86DD99F030EB4AA755D7CE
C#调用在哪里?你没有错将它与PSS进行比较?我没有看到任何示例输入、输出或你尝试过的东西(例如以十六进制打印中间值并验证它们)。