C# 中的 RSA 签名以获取许可

RSA signing in C# for licensing

(方法#2) 我需要做一个软件激活机制。所以我最终采用了这个方案:应用程序根据计算机的硬件创建一个唯一的 ID。买家通过电子邮件将此 ID 发给我。我用我的私钥签名,然后发回签名的字符串。应用程序验证字符串(使用包含的 public 密钥对其进行解码并将其与硬件 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 编码字符串 (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,因为它是字符串数据,您需要将其转换为二进制形式进行签名。