也许我有几个误解。使用RSA加密的SHA1:长度错误错误
AFAIK使用RSA-SHA1签名一个字节数组会生成一个与使用的RSA密钥长度相同的字节数组(签名)。是对的吗?
从另一侧签名,大致意味着使用SHA1生成一个哈希(所以它是160个长),然后使用或不使用填充方案使用私钥对其进行加密。是吗?
后来,为了恢复这个散列(有或没有填充架构),我需要用公钥加密签名。是对的吗?
我的逻辑中有些东西坏了,因为我无法用公钥加密签名。
或者我的代码有误。我正在使用.net RSACryptoServiceProvider,它在尝试加密签名时引发了错误的数据长度错误...我假设加密意味着使用公钥来应用RSA,对吧? 试图解密时会引发密钥未找到异常。正如预期的那样,因为我只有公钥。
编辑: 给定一个字节数组和RSACryptoServiceProvider我可以加密,解密和SignData。我认为SignData(没有填充模式来简化问题)是应用SHA然后解密的捷径。对于加密,我的意思是应用使用公钥作为输入的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叮咬长),然后使用或不使用填充方案使用私钥进行加密。是吗?“
可以将RSA符号(具有n位密钥长度)视为采用仲裁字节数组并输出n位的操作。为了做到这一点,它使用了SHA1这样的散列函数,它接受任意字节数组并产生一个固定的输出(SHA1为160位)。现在理论上我可以用私钥“加密”,但是输出也会是160比特长,这不是实现RSA的方式。 RSA签名需要在散列之后应用填充函数,以在“加密”它之前生成n位文本。
混淆的另一个来源是.NET RSACryptoProvider的加密方法的含义。事实证明,这个方法有两个参数:一个字节数组和一个表示填充函数的标志。它需要字节数组,应用填充,然后用公钥“加密”。这对签名方案没有用处。在RSACryptoProvider中解密和加密的操作不是很简单。你可以“解密”任何“加密”,但不能反过来。
最后,混淆在于加密/解密时使用的“原子”函数和登录时使用的函数相同,但它们以不兼容的方式使用。
您使用的是什么尺寸的RSA密钥? –
你忘了告诉我们你的代码吗?寻求调试帮助的问题(“为什么这个代码不工作?”)必须包含所需的行为,特定的问题或错误以及**在问题本身**中重现它所需的最短代码。 –
我用2048长键做了测试。 – Eduard