使用RSA密钥保护许可证密钥

5

现在已经很晚了,我很累,可能也有些迟钝...

我编写了一个应用程序,需要对其进行安全保护,以便只能在我生成密钥的机器上运行。 目前我正在获取BIOS序列号并从中生成哈希值,然后使用XML RSA私钥对其进行加密。接着我会签署XML以确保其不被篡改。 我试图打包公钥以便解密和验证签名,但每当我尝试以与生成签名的用户不同的用户身份执行代码时,签名就会失败。

我的大部分代码都是修改自我找到的示例代码,因为我对RSA加密不太熟悉。以下是我使用的代码以及我认为需要使用的代码,任何反馈将不胜感激,因为我现在非常迷茫。 我最初使用的原始代码如下,只要启动程序的用户与最初签署文档的用户相同,这段代码就可以正常工作...

 CspParameters cspParams = new CspParameters();
            cspParams.KeyContainerName = "XML_DSIG_RSA_KEY";
            cspParams.Flags = CspProviderFlags.UseMachineKeyStore;

            // Create a new RSA signing key and save it in the container. 
            RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams)
            {
                PersistKeyInCsp = true,
            };

这段代码是我认为应该做的,但无论我怎么做,无论是同一用户还是不同用户,都无法验证签名...

RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider();
            //Load the private key from xml file
            XmlDocument xmlPrivateKey = new XmlDocument();
            xmlPrivateKey.Load("KeyPriv.xml");
            rsaKey.FromXmlString(xmlPrivateKey.InnerXml);

我认为这与密钥容器名称有关(在这里我真的很蠢,请原谅我)。我相当确定这是导致第一种情况下它能够正常工作,同时阻止第二种情况下它无法正常工作的原因所在...

cspParams.KeyContainerName = "XML_DSIG_RSA_KEY";

有没有一种方法可以在应用程序许可证生成时使用私钥对XML进行签名/加密,然后将公钥放入应用程序目录中并使用其来验证/解密代码?如果我可以使签名部分正常工作,那么我可以放弃加密部分。我将其用作备份来混淆我从中提取许可证代码的源。这些都有意义吗?我是个蠢货吗?谢谢任何人能给我的帮助。
2个回答

5
我使用这种方法来使用存储在XML文件中的私钥对XML文档进行签名,然后将其作为资源嵌入应用程序的.dll文件中。我认为您可能正在努力访问密钥库的权限,这也会在将代码转移到其他服务器时创建麻烦。
以下是获取私钥作为嵌入式资源并签署文档的代码: (Sign是包含此方法的类的名称,Licensing.Private.Private.xml是资源的默认命名空间+文件夹+文件名的组合)
public static void SignDocument(XmlDocument xmldoc)
{
    //Get the XML content from the embedded XML privatekey.
    Stream s = null;
    string xmlkey = string.Empty;
    try
    {
        s = typeof(Sign).Assembly.GetManifestResourceStream("Licensing.Private.Private.xml");

        // Read-in the XML content.
        StreamReader reader = new StreamReader(s);
        xmlkey = reader.ReadToEnd();
        reader.Close();
    }
    catch (Exception e)
    {
        throw new Exception("Error: could not import key:",e);
    }

    // Create an RSA crypto service provider from the embedded
    // XML document resource (the private key).
    RSACryptoServiceProvider csp = new RSACryptoServiceProvider();
    csp.FromXmlString(xmlkey);
    //Creating the XML signing object.
    SignedXml sxml = new SignedXml(xmldoc);
    sxml.SigningKey = csp;

    //Set the canonicalization method for the document.
    sxml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigCanonicalizationUrl; // No comments.

    //Create an empty reference (not enveloped) for the XPath transformation.
    Reference r = new Reference("");

    //Create the XPath transform and add it to the reference list.
    r.AddTransform(new XmlDsigEnvelopedSignatureTransform(false));

    //Add the reference to the SignedXml object.
    sxml.AddReference(r);

    //Compute the signature.
    sxml.ComputeSignature();

    // Get the signature XML and add it to the document element.
    XmlElement sig = sxml.GetXml();
    xmldoc.DocumentElement.AppendChild(sig);
}

使用以下代码来生成private.xml和public.xml密钥。显然,保持private.xml文件的安全性。
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
File.WriteAllText(@"C:\privateKey.xml", rsa.ToXmlString(true));  // Private Key
File.WriteAllText(@"C:\publicKey.xml", rsa.ToXmlString(false));  // Public Key

太棒了!感谢您的帮助!这不仅解决了我的许可问题,还帮助我管理应用程序中的其他资源。 - Jesse Knott
刚刚注意到在try catch块中没有在finally中处理StreamReader的释放... - James Westgate

0

猜测,问题在于不同的用户无法访问存储在第1个用户处的密钥(请注意:我不是加密专家)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接