(方法#2) 我需要制作一个软件激活机制。所以我最终得到了这个方案:App根据计算机的硬件创建了一个唯一的ID。买方通过电子邮件将此ID发送给我。我用我的私钥签名,然后发回签名的字符串。应用程序验证字符串(使用包含的公钥对其进行解码并将其与硬件ID进行比较)。
到目前为止,我完成了硬件ID,我已经用openssl创建了密钥(1024bit),这两个文件是private.pem和public.pem。
我尝试应用http://www.christian-etter.de/?p=771中描述的解决方案 但验证总是失败。
代码:
private void Generate_Click(object sender, EventArgs e)
{
byte[] SignedData;
byte[] UnsignedData = Encoding.UTF8.GetBytes(CompID.Text);
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.PersistKeyInCsp = false;
rsa.LoadPrivateKeyPEM(PrivateKey.Text);
using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider())
SignedData = rsa.SignData(UnsignedData, sha1);
ActCode.Text = Encoding.UTF8.GetString(SignedData, 0, SignedData.Length);
}
}
//--------------------------------------------------------------------
private void Verify_Click(object sender, EventArgs e)
{
byte[] UnsignedData = Encoding.UTF8.GetBytes(CompID.Text);
byte[] SignedData = Encoding.UTF8.GetBytes(ActCode.Text);
bool VerifOK;
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
{
rsa.PersistKeyInCsp = false;
rsa.LoadPublicKeyPEM(PublicKey.Text);
using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider())
VerifOK = rsa.VerifyData(UnsignedData, sha1, SignedData);
}
if (VerifOK) verif.Text = "verification ok";
else verif.Text = "verification error";
}
答案 0 :(得分:1)
您将某些任意字节视为UTF-8编码字符串(SignedData
)这是不正确的,因为并非所有字节序列都有效。我怀疑编码器丢失了无效字节,导致验证失败。您应该使用Base64编码以字符串格式保留二进制数据而不会丢失任何内容。所以这个:
using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider())
SignedData = rsa.SignData(UnsignedData, sha1);
ActCode.Text = Encoding.UTF8.GetString(SignedData, 0, SignedData.Length);
变为
using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider())
SignedData = rsa.SignData(UnsignedData, sha1);
ActCode.Text = Convert.ToBase64String(SignedData);
同样在验证过程中,您需要使用Convert.FromBase64String
来获取SignedData
。可以将UTF-8用于CompID,因为它是您需要转换为二进制形式进行签名的字符串数据。