也許我有幾個誤解。使用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