可能我有几个误会。
AFAIK使用RSA-SHA1签署字节数组会生成与所使用的RSA密钥长度相同的字节数组(签名)。是吗?
从另一方面签名,粗略意味着使用SHA1生成哈希(因此它的长度为160比特),然后使用或不使用填充方案使用私钥加密它。是吗?
稍后,为了恢复此哈希(使用或不使用填充模式),我需要使用公钥加密签名。是吗?
我的逻辑中有些东西被破坏了,因为我无法使用公钥加密签名。
或者我的代码错了。我使用.net RSACryptoServiceProvider并且在尝试加密签名时引发了错误的数据长度错误...我假设加密意味着使用公钥应用RSA,对吧? 尝试解密时会引发Key Not found异常。正如所料,因为我只有公钥。
编辑: 给定一个字节数组和RSACryptoServiceProvider我可以加密,解密和SignData。我认为SignData(没有填充模式来简化问题)是应用SHA的快捷方式,然后是Decrypt。对于加密,我的意思是使用公钥作为输入应用RSA公式,对于解密,我的意思是使用私钥作为输入应用RSA公式(完全相同的公式)。这个定义好吗?
EDIT2: 例如,看看下一个签名的xml:http://www.facturae.gob.es/formato/Versiones/factura_ejemplo2_32v1.xml
下一个PowerShell脚本:
$signb64="oYR1T06OSaryEDv8VF9/JgWmwf0KSyOXKpBWY4uAD0YoMh7hedEj8GyRnKpVpaFanqycIAwGGCgl vtCNm+qeLvZXuI0cfl2RF421F8Ay+Q0ani/OtzUUE49wuvwTCClPaNdhv2vfUadR8ExR7e/gI/IL 51uc3mEJX+bQ8dxAQ2w=";
$certB64="MIIDtDCCAx2gAwIBAgICAIcwDQYJKoZIhvcNAQELBQAwcjELMAkGA1UEBhMCRVMxDzANBgNVBAgT Bk1hZHJpZDEPMA0GA1UEBxMGTWFkcmlkMQ4wDAYDVQQKEwVNSVR5QzEbMBkGA1UECxMSTUlUeUMg RE5JZSBQcnVlYmFzMRQwEgYDVQQDEwtDQSB1c3VhcmlvczAeFw0wOTEwMTUxNjA5MzRaFw0xMDEw MTUxNjA5MzRaMHExCzAJBgNVBAYTAkVTMQ8wDQYDVQQIEwZNYWRyaWQxDzANBgNVBAcTBk1hZHJp ZDEOMAwGA1UEChMFTUlUeUMxGzAZBgNVBAsTEk1JVHlDIEROSWUgUHJ1ZWJhczETMBEGA1UEAxMK VXN1YXJpbyA1NDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAroms65axKuQK18YDfD/x6DIn 0zKZ+6bv1K2hItJxel/JvU3JJ80/nY5o0Zbn+PrvlR2xF3poWYcPHLZpesgxhCMfnP7Jb5OUfceL g44m6T9P3PG1lSAZs3H6/TabyWGJy+cNRZMWs13KnB9fDAjJ5Jw0HVkwYNwmb1c7sHCuyxcCAwEA AaOCAVgwggFUMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBTYhqU2tppJoHl+S1py BOH+dliYhzCBmAYDVR0jBIGQMIGNgBT1oWqod09bsQSMp35I8Q6fxXaPG6FypHAwbjEPMA0GA1UE CBMGTWFkcmlkMQ8wDQYDVQQHEwZNYWRyaWQxDjAMBgNVBAoTBU1JVHlDMRswGQYDVQQLExJNSVR5 QyBETkllIFBydWViYXMxEDAOBgNVBAMTB1Jvb3QgQ0ExCzAJBgNVBAYTAkVTggEDMAkGA1UdEQQC MAAwNgYDVR0SBC8wLYYraHR0cDovL21pbmlzdGVyLThqZ3h5OS5taXR5Yy5hZ2UvUEtJL0NBLmNy dDA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vbWluaXN0ZXItOGpneHk5Lm1pdHljLmFnZS9QS0kv Y3JsLmNybDANBgkqhkiG9w0BAQsFAAOBgQAhAN/KVouQrHOgd74gBJqGXyBXfVOeTVW+UTthhfCv DatXzTcrkYPQMfBAQMgGEa5KaQXcqKKhaoCUvrzFqE0HnAGX+ytX41oxZiM2fGNxRZcyUApLEX67 m8HOA/Cs2ZDlpU2W7wiOX5qr+ToTyfXsnRwPWvJ8VUmmXwyMEKcuzg==";
$signb=[System.Convert]::FromBase64String($signB64);
$certb=[System.Convert]::FromBase64String($certB64);
$cert = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList @(,$certb)
$rsacsp = [System.Security.Cryptography.RSACryptoServiceProvider] $cert.PublicKey.Key;
$signb.Length*8;
$rsacsp;
$rsacsp.Encrypt($signb,0);
我试过了:
$rsacsp.Encrypt($signb,[System.Security.Cryptography.RSAEncryptionPadding]::Pkcs1);
而不是
$rsacsp.Encrypt($signb,0);
但我总是得到一个糟糕的长度错误:
Exception calling "Encrypt" with "2" argument(s): "Bad Length.
编辑3: 阅读之后,我可以看到我的主要问题是"从另一方面签名,粗略意味着使用SHA1生成哈希(所以它是160个咬长)然后有或没有填充方案用私钥加密它.Is那对吗?"。
RSA符号(具有n位密钥长度)可被视为采用任意字节数组并输出n位的操作。为了做到这一点,它使用像SHA1这样的散列函数,它接受任意字节数组并产生固定输出(SHA1为160位)。现在理论上我可以加密"使用私钥但然后输出也将是160位长它不是RSA的实现方式。 RSA签名需要在哈希之后应用填充函数,以便在"加密"之前生成n位文本。它
混淆的另一个原因是.NET RSACryptoProvider的加密方法的含义。事实证明,该方法有两个参数:字节数组和表示填充功能的标志。它采用字节数组,应用填充然后"加密"用公钥。签名方案没有用处。 RSACryptoProvider中的操作解密和加密不是模拟的。你可以解密"无论如何"加密",而不是相反。
最后,混淆在于" atomic"加密/解密时使用的函数和登录时使用的函数相同,但它们以不兼容的方式使用。
答案 0 :(得分:2)
AFAIK使用RSA-SHA1签署字节数组会生成与所使用的RSA密钥长度相同的字节数组(签名)。是吗?
通常是的,虽然大小当然会被编码为八位字节流(也就是字节数组),但签名的大小实际上可能大到7位。密钥大小通常是8(位)的倍数,因此不会出现太多。
从另一方面签名,粗略意味着使用SHA1生成哈希(因此它的长度为160比特),然后使用或不使用填充方案使用私钥加密它。是吗?
不,你不应该在没有填充的情况下在RSA中执行模幂运算;安全性需要填充方案。请注意,您不应在此处讨论加密。加密用于提供机密性。 RSA签名生成和加密都使用模幂运算 - 虽然使用不同的密钥 - 并不意味着一个等同于另一个。
请务必注意the padding scheme for PKCS#1 v1.5 encryption与the one used for signature generation不同。此外,还有较新的OAEP padding scheme for encryption和PSS padding scheme for signature generation相当不同。
稍后,为了恢复此哈希(使用或不使用填充模式),我需要使用公钥加密签名。是吗?
执行模幂运算,然后验证结果,是的。但是,由于验证需要以安全的方式验证填充,因此您应该让API处理此问题。
我的逻辑中有些东西被破坏了,因为我无法使用公钥加密签名。
尝试编写用于验证的内容,例如this example中所见的方法VerifyHash
。
您可以尝试查找原始RSA实现,以找出RSA签名中的内容。 您只应该这样做来分析签名。
因此,如果您使用公钥“加密”数据(即只执行模幂运算),您将得到:
0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003021300906052b0e03021a05000414a2304127e2fe3b8a8203b219feafdd9b58558310
结果。这显然是用于签名生成的PCKS#1 v1.5填充。它包含一个编码的哈希值:
SEQUENCE(2 elem)
SEQUENCE(2 elem)
OBJECT IDENTIFIER1.3.14.3.2.26
NULL
OCTET STRING(20 byte) A2304127E2FE3B8A8203B219FEAFDD9B58558310