Защита лицензионного ключа с помощью ключа RSA

уже поздно, я устал и, наверное, совсем дремлю...

Я написал приложение, которое мне нужно защитить, чтобы оно работало только на машинах, для которых я сгенерировал ключ. Что я сейчас делаю, так это получаю серийный номер 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 с помощью закрытого ключа при создании лицензии приложения, а затем поместить открытый ключ в каталог приложения и использовать его для проверки/расшифровки кода? Я могу отказаться от части шифрования, если я смогу заставить часть подписи работать правильно. Я использовал его в качестве резервной копии, чтобы скрыть происхождение лицензионного кода, из которого я ввожу ключ.

Есть ли в этом смысл? Я полный дурак?

Спасибо за любую помощь, которую кто-нибудь может дать мне в этом.


person Jesse Knott    schedule 30.03.2010    source источник


Ответы (2)


Я использовал этот метод для подписи 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
person James Westgate    schedule 30.03.2010
comment
Потрясающий! Спасибо за помощь! Это не только решило мою проблему с лицензией, но и помогло мне управлять другими ресурсами в моем приложении. - person Jesse Knott; 03.04.2010
comment
Только что заметил, что я не размещаю StreamReader там, наконец, в блоке try catch ... - person James Westgate; 03.04.2010

Думаю, проблема в том, что разные пользователи не имеют доступа к ключу, который хранится для 1-го пользователя (обратите внимание: я не эксперт по криптографии).

person Budda    schedule 14.05.2010