加密许可证文件的有效方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/359342/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 00:27:25  来源:igfitidea点击:

An effective method for encrypting a license file?

c#encryptioncryptography

提问by David Brown

For a web application, I would like to create a simple but effective licensing system. In C#, this is a little difficult, since my decryption method could be viewed by anyone with Reflector installed.

对于 Web 应用程序,我想创建一个简单但有效的许可系统。在 C# 中,这有点困难,因为任何安装了 Reflector 的人都可以查看我的解密方法。

What are some methods for encrypting files in C# that are fairly tamper-proof?

在 C# 中加密文件的方法有哪些是相当防篡改的?

采纳答案by Wolfwyrd

It sounds like you want to be using Public/Private cryptography to sign a license token (an XML Fragment or file for example) so you can detect tampering. The simplest way to handle it is to do the following steps:

听起来您想使用公共/私有加密来签署许可证令牌(例如 XML 片段或文件),以便您可以检测篡改。处理它的最简单方法是执行以下步骤:

1) Generate a keypair for your company. You can do this in the Visual Studio command line using the SN tool. Syntax is:

1) 为您的公司生成一个密钥对。您可以使用 SN 工具在 Visual Studio 命令行中执行此操作。语法是:

sn -k c:\keypair.snk

2) Use the keypair to strongly name (i.e. sign) your client application. You can set this using the signing tab in the properties page on your application

2) 使用密钥对来强命名(即签名)您的客户端应用程序。您可以使用应用程序属性页面中的签名选项卡进行设置

3) Create a license for your client, this should be an XML document and sign it using your Private key. This involves simply computing a digital signature and steps to accomplish it can be found at:

3) 为您的客户创建一个许可证,这应该是一个 XML 文档并使用您的私钥对其进行签名。这涉及简单地计算数字签名和完成它的步骤可以在以下位置找到:

http://msdn.microsoft.com/en-us/library/ms229745.aspx

http://msdn.microsoft.com/en-us/library/ms229745.aspx

4) On the client, when checking the license you load the XmlDocument and use your Public key to verify the signature to prove the license has not been tampered with. Details on how to do this can be found at:

4) 在客户端,检查许可证时加载 XmlDocument 并使用您的公钥验证签名以证明许可证未被篡改。有关如何执行此操作的详细信息,请访问:

http://msdn.microsoft.com/en-us/library/ms229950.aspx

http://msdn.microsoft.com/en-us/library/ms229950.aspx

To get around key distribution (i.e. ensuring your client is using the correct public key) you can actually pull the public key from the signed assembly itself. Thus ensuring you dont have another key to distribute and even if someone tampers with the assembly the .net framework will die with a security exception because the strong name will no longer match the assembly itself.

为了绕过密钥分发(即确保您的客户使用正确的公钥),您实际上可以从签名的程序集本身中提取公钥。因此确保您没有另一个密钥要分发,即使有人篡改程序集,.net 框架也会因安全异常而死亡,因为强名称将不再与程序集本身匹配。

To pull the public key from the client assembly you want to use code similar to:

要从客户端程序集中提取公钥,您需要使用类似于以下代码的代码:

    /// <summary>
    /// Retrieves an RSA public key from a signed assembly
    /// </summary>
    /// <param name="assembly">Signed assembly to retrieve the key from</param>
    /// <returns>RSA Crypto Service Provider initialised with the key from the assembly</returns>
    public static RSACryptoServiceProvider GetPublicKeyFromAssembly(Assembly assembly)
    {
        if (assembly == null)
            throw new ArgumentNullException("assembly", "Assembly may not be null");

        byte[] pubkey = assembly.GetName().GetPublicKey();
        if (pubkey.Length == 0)
            throw new ArgumentException("No public key in assembly.");

        RSAParameters rsaParams = EncryptionUtils.GetRSAParameters(pubkey);
        RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
        rsa.ImportParameters(rsaParams);

        return rsa;
    }

I've uploaded a sample class with a lot of helpful Encryption Utilities on Snipt at: http://snipt.net/Wolfwyrd/encryption-utilities/to help get you on your way.

我在 Snipt 上上传了一个示例类,其中包含许多有用的加密实用程序:http://snipt.net/Wolfwyrd/encryption-utilities/以帮助您继续前进。

I have also included a sample program at: https://snipt.net/Wolfwyrd/sign-and-verify-example/. The sample requires that you add it to a solution with the encryption utils library and provide a test XML file and a SNK file for signing. The project should be set to be signed with the SNK you generate. It demonstrates how to sign the test XML file using a private key from the SNK and then verify from the public key on the assembly.

我还在以下位置包含了一个示例程序:https: //snipt.net/Wolfwyrd/sign-and-verify-example/。该示例要求您将其添加到带有加密实用程序库的解决方案中,并提供一个测试 XML 文件和一个 SNK 文件进行签名。该项目应设置为使用您生成的 SNK 进行签名。它演示了如何使用来自 SNK 的私钥对测试 XML 文件进行签名,然后从程序集上的公钥进行验证。

Update

更新

Added an up to date blog postwith a nice detailed run through on license files

添加了最新的博客文章,其中详细介绍了许可证文件

回答by Eyvind

Why would you need to encrypt it? If it is tampering you are afraid (for instance someone increasing the number of users), could you perhaps just sign it with e.g. your organization's digital certificate instead?

为什么需要加密?如果它被篡改,你害怕(例如有人增加用户数量),你是否可以只用你组织的数字证书来签名?

回答by melaos

or perhaps you want to tie a license to a particular machine, for example by generating the license key based on the md5 value of the c drive of the pc. then your license would be machine specific.

或者您可能想将许可证绑定到特定机器,例如通过根据 PC 的 c 驱动器的 md5 值生成许可证密钥。那么您的许可证将是特定于机器的。

回答by Oliver Friedrich

The only way to provide some sort of security with licensing is to force an online login against credentials hold by yourself (really abstract spoken).

通过许可提供某种安全性的唯一方法是根据您自己持有的凭据强制进行在线登录(非常抽象)。

All other methods take more time, and therefore more money, to implement, as to crack and abuse your software instead of buying a license.

所有其他方法都需要更多的时间,因此也需要更多的资金来实施,以破解和滥用您的软件而不是购买许可证。

.NET has some good cryptographic classes, but as you mentioned, if you are coding the en-/decription of the license, everyone can decompile it easily.

.NET 有一些很好的加密类,但正如你提到的,如果你正在编写许可证的编码/描述,每个人都可以轻松地反编译它。

回答by Frans Bouma

Use a signed XML file. Sign it with the private key part of a keypair and check it with the public key part in your software. This gives you the oppertunity to check whether the license has been altered and also to check if the license file is valid.

使用签名的 XML 文件。使用密钥对的私钥部分对其进行签名,并使用软件中的公钥部分对其进行检查。这使您有机会检查许可证是否已被更改以及检查许可证文件是否有效。

Signing and checking of a signed XML file is documented in the MSDN.

MSDN 中记录了对已签名 XML 文件的签名和检查。

It's of course logical that you sign the license file at your own company and send the license file to the customer who then places the license file in a folder for you to read.

您在自己的公司签署许可证文件并将许可证文件发送给客户,然后客户将许可证文件放在一个文件夹中供您阅读,这当然是合乎逻辑的。

Of course, people can cut out/hack your distributed assembly and rip out the xml sign checking, but then again, they will always be able to do so, no matter what you do.

当然,人们可以删除/破解您的分布式程序集并删除 xml 符号检查,但话又说回来,无论您做什么,他们总是能够这样做。

回答by Wolfwyrd

RE: Do not include the whole key in your code. Use sn -p to extract the public part to a file. Use that in your code you distribute to verify the license.

RE:不要在代码中包含整个密钥。使用 sn -p 将公共部分提取到文件中。在您分发的代码中使用它来验证许可证。

Using the code from the MSDN articles, I created a small app (LicMaker) to facilitate this. The app is signed with the full key pair. The input is an unsigned .XML license file. The output is the original XML + signature in a signed .LIC file. My product is also signed by the same full key pair file as well. The product verifies the .LIC file has not been tampered with. Works Great. I did not use sn -p for this solution.

使用 MSDN 文章中的代码,我创建了一个小应用程序 (LicMaker) 来简化此操作。该应用程序使用完整的密钥对进行签名。输入是一个未签名的 .XML 许可文件。输出是已签名的 .LIC 文件中的原始 XML + 签名。我的产品也由相同的完整密钥对文件签名。产品验证 .LIC 文件未被篡改。很好用。我没有将 sn -p 用于此解决方案。

回答by mark

It appears that the MSDN Samples use default parameters and this results in machine- specific signing such that you cannot sign on one machine and verify on an arbitrary other machine. I modified the logic in those samples to use the keys in my snk on the signing machine and keys from my assembly in the verifying machine. This was done using the logic from the MSDN sample and routines in the (very nicely done) ExcryptionUtils.cs sample linked above.

MSDN 示例似乎使用默认参数,这会导致特定于机器的签名,因此您无法在一台机器上签名并在任意另一台机器上进行验证。我修改了这些示例中的逻辑,以使用我在签名机上的 snk 中的密钥和在验证机中使用我的程序集的密钥。这是使用 MSDN 示例中的逻辑和上面链接的(做得非常好)ExcryptionUtils.cs 示例中的例程完成的。

For signing the file, I used this:

为了签署文件,我使用了这个:

RSACryptoServiceProvider rsaKey = EncryptionUtils.GetRSAFromSnkFile(keyFilePath);

For verifying the file, I used this:

为了验证文件,我使用了这个:

RSACryptoServiceProvider rsaKey = EncryptionUtils.GetPublicKeyFromAssembly
   (System.Reflection.Assembly.GetExecutingAssembly());

BTW: I observed that the XML signature verification ignores XML comments.

顺便说一句:我观察到 XML 签名验证忽略了 XML 注释。

回答by Cocowalla

Wolfwyrd's answer is excellent, but I just wanted to offer a muich simpler version of Wolfwyrd's GetPublicKeyFromAssemblymethod (which uses a lot of helper methods from the library Wolfwyrd graciously supplied).

Wolfwyrd 的回答非常好,但我只是想提供一个更简单的 WolfwyrdGetPublicKeyFromAssembly方法版本(它使用了 Wolfwyrd 慷慨提供的库中的许多辅助方法)。

In this version, this is all the code you need:

在这个版本中,这是你需要的所有代码:

/// <summary>
/// Extracts an RSA public key from a signed assembly
/// </summary>
/// <param name="assembly">Signed assembly to extract the key from</param>
/// <returns>RSA Crypto Service Provider initialised with the public key from the assembly</returns>
private RSACryptoServiceProvider GetPublicKeyFromAssembly(Assembly assembly)
{
    // Extract public key - note that public key stored in assembly has an extra 3 headers
    // (12 bytes) at the front that are not part of a CAPI public key blob, so they must be removed
    byte[] rawPublicKeyData = assembly.GetName().GetPublicKey();

    int extraHeadersLen = 12;
    int bytesToRead = rawPublicKeyData.Length - extraHeadersLen;
    byte[] publicKeyData = new byte[bytesToRead];
    Buffer.BlockCopy(rawPublicKeyData, extraHeadersLen, publicKeyData, 0, bytesToRead);

    RSACryptoServiceProvider publicKey = new RSACryptoServiceProvider();
    publicKey.ImportCspBlob(publicKeyData);

    return publicKey;
}

回答by Duncan Bayne

When you implement your signing / verification code, be careful not to put it in a separate assembly. Code Access Security tamper-proofing is now very easy to bypass, as explained in the article CAS Tamper-Proofing is Broken: Consequences for Software Licensing.

当你实现你的签名/验证码时,注意不要把它放在一个单独的程序集中。代码访问安全防篡改现在很容易绕过,如文章CAS 防篡改被破坏:软件许可的后果 中所述

Obligatory disclaimer & plug: the company I co-founded produces the OffByZero Cobalt licensing solution.

强制性免责声明和插件:我共同创立的公司生产OffByZero Cobalt 许可解决方案