我可以使用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,我尝试了不同的编码,我尝试在有一些端点问题的情况下反转各种字节数组,但无论我尝试什么,我都无法验证PHP签名。我在C#方面显然遗漏了一些东西,但我不知道是什么。
答案 0 :(得分:0)
好吧,我仍然不确定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;
}