【问题标题】:RSA signing in C# for licensingRSA 在 C# 中签名以进行许可
【发布时间】: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 感谢您指出正确的方向。
  • 我会将其添加为答案,您可以将其标记为已接受。

标签: c# rsa sign rsacryptoserviceprovider


【解决方案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,因为它是字符串数据,您需要将其转换为二进制形式进行签名。

【讨论】:

    猜你喜欢
    • 2016-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-14
    • 2012-02-08
    • 1970-01-01
    相关资源
    最近更新 更多