rsacryptoserviceprovider.VerifyData始终返回false

rsacryptoserviceprovider.VerifyData始终返回false

问题描述:

下面是我的一个验证这是使用phpseclibrsacryptoserviceprovider.VerifyData始终返回false

static void Main(string[] args) 
     { 

      var payment = 
       "VUQxMzE1MTg0OTk0MDM2MzIyMDJ8VDAwMDAxN0kxMFVEMTMxNTE4NDk5NDAzNjMyMjAyfDIwMTctMTAtMDd8MHxwYXltZW50IHN1Y2Nlc3NmdWx8MjAyNTQ="; 
      var signature = 
       "V0T9ZedZW8oB9uy4PazRIxWHvJ7rR+FVtnGjUy30mSKqgmEceZWE1aBvkQWeG4ERjAXHjsRge0D0MlHd9zvXjrLog+G5nWBHIu52O0srCd9d71JVztMQy8fV5oSnRPtlUpgdmn8QDnJ27XrbaHzNxnFyybTQhmbfxkT0oJ0MEOk="; 

      var sigByte = Convert.FromBase64String(signature); 
      var payBite = Convert.FromBase64String(payment); 

      Verify(payBite, sigByte); 
     } 

     public static bool Verify(byte[] payment, byte[] signature) 
     { 
      var key = Resources.PublicKey; 
      var cipher = Crypto.DecodeX509PublicKey(key); 

      var res = cipher.VerifyData(payment, "SHA256", signature); 
      return res; 
     } 

使用的公钥低于从PHP脚本的响应C#程序:

-----BEGIN PUBLIC KEY----- 
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDSiXzUuH9ePZgSLYrzZ0qhta25 
HCb+WG48wIKUl+cQNC/Fl/KZG2cSwRXdo8KZLVWWO5qwzplfTWEylg4IqRA48rYY 
f/b+Y7QhORKeAws4pttLZJBbh1mIbZ9HXfQ+zBjP+zfJZ1YjSFs2uZdwSt1itUcJ 
/GQFct8GoUevNELG7wIDAQAB 
-----END PUBLIC KEY----- 

但验证方法似乎总是返回false。任何想法为什么会发生。

在PHP代码相同内容的作品,卖方给我

<?php 
//load RSA library 
include 'Crypt/RSA.php'; 
//initialize RSA 
$rsa = new Crypt_RSA(); 
//decode & get POST parameters 
$payment = base64_decode("VUQxMzE1MTg0OTk0MDM2MzIyMDJ8VDAwMDAxN0kxMFVEMTMxNTE4NDk5NDAzNjMyMjAyfDIwMTctMTAtMDd8MHxwYXltZW50IHN1Y2Nlc3NmdWx8MjAyNTQ="); 
$signature = base64_decode("V0T9ZedZW8oB9uy4PazRIxWHvJ7rR+FVtnGjUy30mSKqgmEceZWE1aBvkQWeG4ERjAXHjsRge0D0MlHd9zvXjrLog+G5nWBHIu52O0srCd9d71JVztMQy8fV5oSnRPtlUpgdmn8QDnJ27XrbaHzNxnFyybTQhmbfxkT0oJ0MEOk="); 

//load public key for signature matching 
$publickey = "-----BEGIN PUBLIC KEY----- 
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDSiXzUuH9ePZgSLYrzZ0qhta25 
HCb+WG48wIKUl+cQNC/Fl/KZG2cSwRXdo8KZLVWWO5qwzplfTWEylg4IqRA48rYY 
f/b+Y7QhORKeAws4pttLZJBbh1mIbZ9HXfQ+zBjP+zfJZ1YjSFs2uZdwSt1itUcJ 
/GQFct8GoUevNELG7wIDAQAB 
-----END PUBLIC KEY-----"; 
$rsa->loadKey($publickey); 
//verify signature 
$signature_status = $rsa->verify($payment, $signature); 
//get payment response in segments 
//payment format: order_id|order_refference_number|date_time_transaction|payment_gateway_used|status_code|comment; 
$responseVariables = explode('|', $payment);  


    //display values 
    echo $signature_status; 

    echo '<br/>'; 
    var_dump($responseVariables); 


?> 

任何想法,我在做什么错在这里。我尝试在C#代码中传递“SHA512”,“MD5”,并仍然返回false。

+1

根据phpseclib文档,默认的散列算法是sha1。你有没有在C#中试过这个? – Michael

+0

@Michael yeap。这也给出了相同的结果 – Aneef

+0

我想知道你是否也可能需要做(在PHP中)'$ rsa-> setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);'。 OAEP加密是默认情况下phpseclib使用的。它比PKCS1更安全但不常用。 – neubert

好吧,好像供应商不使用PKCS1,他使用PSS。验证这种方式(需要充气城堡!):

public static bool Verify(byte[] payment, byte[] signature) 
    { 
     var pub = @"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDSiXzUuH9ePZgSLYrzZ0qhta25HCb+WG48wIKUl+cQNC/Fl/KZG2cSwRXdo8KZLVWWO5qwzplfTWEylg4IqRA48rYYf/b+Y7QhORKeAws4pttLZJBbh1mIbZ9HXfQ+zBjP+zfJZ1YjSFs2uZdwSt1itUcJ/GQFct8GoUevNELG7wIDAQAB"; 

     byte[] raw = Convert.FromBase64String(pub); 
     AsymmetricKeyParameter aKey = PublicKeyFactory.CreateKey(raw); 
     RsaKeyParameters rKey = (RsaKeyParameters)aKey; 

     PssSigner pss = new PssSigner(new RsaEngine(), new Sha1Digest(), 20); 
     pss.Init(false, rKey); 
     pss.BlockUpdate(payment, 0, payment.Length); 
     var res = pss.VerifySignature(signature); 

     return res; 
    } 
+0

是的..我猜他们的文档和实现似乎是差异。非常感谢这个想法。 – Aneef

PSS的支持,开箱即用的.NET 4.6+,但需要使用RSACng类(CAPI,它的RSACryptoServiceProvider是基于,不提供它)。

public static bool Verify(byte[] payment, byte[] signature) 
{ 
    var key = Resources.PublicKey; 
    // Change the function this calls to return RSACng instead of RSACryptoServiceProvider. 
    RSA cipher = Crypto.DecodeX509PublicKey(key); 

    // or, failing being able to change it: 
    RSA tmp = new RSACng(); 
    tmp.ImportParameters(cipher.ExportParameters(false)); 
    cipher = tmp; 

    return cipher.VerifyData(
     payment, 
     signature, 
     HashAlgorithmName.SHA256, 
     RSASignaturePadding.Pss); 
}