我需要帮助在PHP中签名字符串。我们正在构建一个能够改变外部网站上的个人资料数据的Web应用程序。我们希望实现这一目标,而无需最终用户在我们的网站上输入我们的密码。因此,外部网站创建了一个API,只要我们向他们发送由证书签名的个人资料的电子邮件地址,我们就可以编辑个人资料。这允许他们检查请求是否来自可信来源(我们)。
我们尝试使用本机PHP函数和PHPSeclib来使用证书签署电子邮件地址:
$rsa = new RSA();
$rsa->setHash("sha1");
$rsa->setSignatureMode(RSA::SIGNATURE_PKCS1);
$originalkey = file_get_contents('key.ppk');
$rsa->loadKey($originalkey);
echo bin2hex($rsa->sign("test@email.nl"));
// Using native PHP methods
$email = 'test@email.nl';
$signature = '';
$private_key = openssl_pkey_get_private(file_get_contents("key.ppk"));
var_dump(openssl_sign($email, $signature, $private_key, "sha1"));
echo bin2hex($signature);
签名很好,因为PHP能够验证已发布的签名。但是,外部网站的Web服务不接受我们的签名。它们只允许40个字符的签名长度,而我们签名的十六进制转储超过1000个字符。
他们向我们发送了这个C#示例来签署一个字符串,但我们没有足够的C#知识来查看输出不同的原因。
string Sign(string username, string thumbprint, string hasher = "SHA1")
{
var store = new
System.Security.Cryptography.X509Certificates.X509Store(System.Security.Cryptography.X509Certificates.StoreLocation.LocalMachine);
store.Open(System.Security.Cryptography.X509Certificates.OpenFlags.OpenExistingOnly |
System.Security.Cryptography.X509Certificates.OpenFlags.ReadOnly);
try
{
foreach (System.Security.Cryptography.X509Certificates.X509Certificate2 certificate in store.Certificates.Find(System.Security.Cryptography.X509Certificates.X509FindType.FindByThumbprint, thumbprint, false))
{
var privateKey = certificate.PrivateKey as System.Security.Cryptography.RSACryptoServiceProvider;
if (privateKey != null)
{
var bytes = privateKey.SignData(Encoding.UTF8.GetBytes(username),
System.Security.Cryptography.HashAlgorithm.Create(hasher));
return string.Join("", bytes.Select(b => b.ToString("x2")));
} else throw new ArgumentException("no private key");
}
}
finally
{
store.Close();
}
return null;
}
有没有人可以指出我们正确的方向?
提前致谢!