可以';t在C#中验证PyOpenSSL签名

本文关键字:验证 PyOpenSSL 签名 可以 | 更新日期: 2023-09-27 18:01:05

我可以使用OpenSSL在PHP中签名和验证数据:

function generate_signature($privateKey, $data) {
    $keyData = openssl_get_privatekey($privateKey);
    openssl_sign($data, $signature, $keyData, OPENSSL_ALGO_SHA256);
    openssl_free_key($keyData);
    $sigText = base64_encode($signature);
    return $sigText;
}
function verify_signature($pubKey, $sigText, $data) {
    $signature = base64_decode($sigText);       
    $keyData = openssl_get_publickey($pubKey);
    $ok = openssl_verify($data, $signature, $keyData, "sha256WithRSAEncryption");
    openssl_free_key($keyData);
    return $ok;
}
$privateKey= file_get_contents("private.key");
$pubKey = file_get_contents("public.pem");
$data = "This is a test";
$sigText = generate_signature($privateKey, $data);
$result = verify_signature($pubKey, $sigText, $data);

这适用于我尝试的任何数据值。$result总是真的。

然而,当我尝试使用BouncyCastle API在C#中验证签名时,它总是失败:

public static bool VerifySignature(string data, string signatureText)
{
    // Using statements and error checking removed for brevity 
    var uri = new Uri("pack://application:,,,/Resources/public.pem");
    var resourceStream = Application.GetResourceStream(uri);
    var reader = new StreamReader(resourceStream.Stream);
    PemReader pemReader = new PemReader(reader);
    RsaKeyParameters parameters = (RsaKeyParameters)pemReader.ReadObject();
    RSACryptoServiceProvider provider = (RSACryptoServiceProvider)RSACryptoServiceProvider.Create();
    RSAParameters rParams = new RSAParameters();
    rParams.Modulus = parameters.Modulus.ToByteArray();
    rParams.Exponent = parameters.Exponent.ToByteArray();
    provider.ImportParameters(rParams);
    byte[] sigBytes = Convert.FromBase64String(signatureText);
    byte[] dataBytes = Encoding.UTF8.GetBytes(data);
    bool isValid = provider.VerifyData(dataBytes, CryptoConfig.MapNameToOID("SHA256"), sigBytes);
    return isValid;
}

无论我尝试什么,isValid总是错误的。我试过在两端使用SHA1而不是SHA256,我尝试过不同的编码,我试过反转各种字节数组以防出现一些endian问题,但无论我尝试什么,我都无法验证PHP签名。我显然在C#方面遗漏了一些东西,但我不知道是什么。

可以';t在C#中验证PyOpenSSL签名

嗯,我仍然不确定RSACryptoServiceProvider对我有什么不利,但我发现了另一种非常有效的方法:

public static bool VerifySignature(string data, string signatureText)
{
    // Using statements and error checking removed for brevity 
    var uri = new Uri("pack://application:,,,/Resources/public.pem");
    var resourceStream = Application.GetResourceStream(uri);
    var reader = new StreamReader(resourceStream.Stream);
    PemReader pemReader = new PemReader(reader);
    RsaKeyParameters parameters = (RsaKeyParameters)pemReader.ReadObject();
    RsaDigestSigner signer = (RsaDigestSigner)SignerUtilities.GetSigner("SHA-256withRSA");
    signer.Init(false, parameters);
    byte[] sigBytes = Convert.FromBase64String(signatureText);
    byte[] dataBytes = Encoding.UTF8.GetBytes(data);
    signer.BlockUpdate(dataBytes, 0, dataBytes.Length);
    bool isValid = signer.VerifySignature(sigBytes);
    return isValid;
}