RSA 在 C# 中签名以进行许可
Posted
技术标签:
【中文标题】RSA 在 C# 中签名以进行许可【英文标题】:RSA signing in C# for licensing 【发布时间】:2015-01-22 21:39:48 【问题描述】:(方法 #2) 我需要做一个软件激活机制。所以我最终采用了这个方案:应用程序根据计算机的硬件创建一个唯一的 id。买家通过电子邮件将此 ID 发送给我。我用我的私钥对其进行签名,然后将签名的字符串发回。应用验证字符串(使用包含的公钥对其进行解码并与硬件 id 进行比较)。
到目前为止,我已经完成了硬件 ID,并且我已经使用 openssl 创建了密钥(1024 位),这是两个文件 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";
【问题讨论】:
没有深入研究这一点,但是您的代码在切换到 UTF-8 或存储在文本框中似乎比较随意,这意味着您可能在不知不觉中更改了字节。除非您非常小心,否则从字符串到byte[]
来回切换是危险的。如果可能,请尝试将数据保留为byte[]
。
并非所有字节序列都是有效的 UTF-8 编码。通过Convert.To/FromBase64String
使用Base64编码处理SignedData
。
@mikez 非常感谢!我错过了。成功了!
@LynnCrumbling 感谢您指出正确的方向。
我会将其添加为答案,您可以将其标记为已接受。
【参考方案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
。 CompID 可以使用 UTF-8,因为它是字符串数据,您需要将其转换为二进制形式进行签名。
【讨论】:
以上是关于RSA 在 C# 中签名以进行许可的主要内容,如果未能解决你的问题,请参考以下文章
使用 mbedtls 生成的 RSA 签名,无法使用 C# (bouncycastle) 应用程序进行验证