软件的关键

Nad*_*eri 0 licensing rsa license-key

我想用RSA密钥设计一个产品密钥,但我不知道我的想法
中的安全性是安全还是不安全?

我对设计产品关键的想法:

我有一对密钥,例如

公钥是:MIIBvTCCASYCCQD55fNzc0WF7TANBgkqhkiG9w0BAQUFADAjMQswCQYDVQQG ...

私钥是:MIICWwIBAAKBgQDRhGF7X4A0ZVlEg594WmODVVUIiiPQs04aLmvfg8SborHss5gQ ....

我创建这样的产品密钥:(
eaxmple的私钥开始)MIICWwIBAAKBgQDRh

并从软件中的私钥中删除它

当用户没有产品密钥时无法解码密钥

And*_*ell 9

这不是您应该如何使用公钥/私钥作为产品密钥.

更好的实施

您可以创建描述已启用功能的XML文档.或者只是简单的客户名称和日期.

<license>
    <name>Acme Co.</name>
    <expiration>20120304</expiration>
</license>
Run Code Online (Sandbox Code Playgroud)

您使用私钥对XML文档进行签名,并将哈希和签名存储在文档中.然后,您可以使用之前生成的公钥验证产品中的XML文档.

签署文件的结果:

<license>
    <name>Acme Co.</name>
    <expiration>20120304</expiration>
    <signature>
        <hash>1230u4woeifhljksdkvh23p9</hash>
        <value>sdvrrvLJbmyscoVMg2pZZAtZJbBHsZFUCwE4Udv+u3TfiAms2HpLgN3cL
      NtRlxyQpvWt1FKAB/SCk1jr0IasdfeDOOHhTUTyiv2vMJgCRecC1PLcrmR9ABhqk
      itsjzrCt7V3eF5SpObdUFqcj+n9gasdfdQtlQeWcvKEcg=</value>
    </signature>
</license>
Run Code Online (Sandbox Code Playgroud)

如果用户更改了许可证文件的内容,则签名将不再匹配.他们也无法重新签署文档,因为他们无法访问您的私钥.这很重要,您使用产品而非私钥发布PUBLIC密钥.

短密钥实施

  1. 选择产品代码(一些随机字符串以标识您的产品
  2. 在产品代码中添加已知的盐
  3. 根据用户名创建加密密钥.检查以确保它有效.
  4. 使用新密钥加密salt +产品代码
  5. 从加密结果中构建人类可读密钥.

它看起来像1234-1234-1234-1234

C#解决方案:

/// <summary>
/// Provides the ability to generate and validate license keys based
/// on a product code.
/// </summary>
public class LicenseKeyManager
{
    /// <summary>
    /// Construct a new LicenseKeyManager
    /// </summary>
    public LicenseKeyManager()
    {
        crypto = new DESCryptoServiceProvider ();
    }

    /// <summary>
    /// Set or get the product code. Once the product code
    /// is manually set it will no longer be automatically 
    /// generated for this instance. Suggested to not 
    /// set the product code unless generating keys.
    /// 
    /// In this instance the ProductCode is a string
    /// that identifies the machine that the license needs
    /// to be generated on. This prevents the distribution
    /// of keys among friends.
    /// </summary>
    public String ProductCode
    {
        set
        {
            productCode = value;
        }
        get
        {
            if (productCode == null)
                productCode = Ethernet.MacAddress.Replace (":", "");

            return productCode;
        }
    }

    /// <summary>
    /// A salt that can be added to the product code to ensure that
    /// different keys are generated for different products or
    /// companies. 
    /// Once set the salt cannot be retrieved from this object.
    /// </summary>
    public String Salt
    {
        set
        {
            salt = value;
        }
    }

    /// <summary>
    /// Validate a license key
    /// </summary>
    /// <param name="name">Name associated with the license key</param>
    /// <param name="key">The license key</param>
    /// <returns>True if the license key is valid</returns>
    public bool IsValidKey (String name, String key)
    {
        if (name == null || key == null) return false;
        String license = CreateLicense (name);
        return license.CompareTo (key) == 0;
    }

    /// <summary>
    /// Create a new license key associated with the given name. The key
    /// will be the same if this method is reinvoked with the same name and
    /// product code.
    /// </summary>
    /// <param name="name">Name to associate with the license key</param>
    /// <returns>New License Key</returns>
    public String CreateLicense (String name)
    {
        String licenseSource = ProductCode;

        if (salt != null)
            licenseSource = salt + licenseSource;

        byte[] license = Encrypt(licenseSource, name);

        if (license.Length > 16)
        {
            byte[] tmp = new byte[16];
            Array.Copy (license, tmp, 16);
            license = tmp;
        }
        else if (license.Length < 16)
        {
            byte[] tmp = 
                new byte[] {
                    36, 36, 36, 36, 36, 36, 36, 36,
                    36, 36, 36, 36, 36, 36, 36, 36};
            Array.Copy (license, tmp, license.Length);
            license = tmp;
        }

        StringBuilder sb = 
            new StringBuilder ();

        String base64License =          
            Convert.ToBase64String (license).ToUpper();
        base64License = base64License.Replace ('+', 'F');
        base64License = base64License.Replace ('/', 'A');

        // Format the license key in a human readable format.
        // We dont need all of the license key just enough
        // so that it isn't predictable. This key won't be
        // used in decrypting the license, only in comparision
        // similar to that when hasing passwords.
        sb.AppendFormat (
            "{0}{1}{2}{3}-{4}{5}{6}{7}-" +
            "{8}{9}{10}{11}-{12}{13}{14}{15}",
            base64License[0], base64License[1], 
            base64License[2], base64License[3], 
            base64License[4], base64License[5], 
            base64License[6], base64License[7], 
            base64License[8], base64License[9], 
            base64License[10],base64License[11], 
            base64License[12],base64License[13], 
            base64License[14],base64License[15]);

        return sb.ToString();
    }

    private byte[] GetLegalKey(string Key) 
    {
        string sTemp = Key;
        crypto.GenerateKey();
        byte[] bytTemp = crypto.Key;
        int KeyLength = bytTemp.Length;
        if (sTemp.Length > KeyLength)
            sTemp = sTemp.Substring(0, KeyLength);
        else if (sTemp.Length < KeyLength)
            sTemp = sTemp.PadRight(KeyLength, ' ');

        return ASCIIEncoding.ASCII.GetBytes(sTemp);
    }

    private byte[] Encrypt(string Source, string Key) 
    {
        // use UTF8 unicode conversion for two byte characters
        byte[] byteIn = UTF8Encoding.UTF8.GetBytes(Source);

        // set the private key
        crypto.Key = GetLegalKey(Key);
        crypto.IV = iv;

        // create an Encryptor from the Provider Service instance
        ICryptoTransform encryptor = crypto.CreateEncryptor();

        // convert into Base64 so that the result can be used in xml
        return encryptor.TransformFinalBlock (
                byteIn, 0, byteIn.Length);
    }

    private static byte[] iv = new byte[] {63,63,63,63,63,63,63,63};
    private String productCode;
    private String salt;
    private SymmetricAlgorithm crypto;
}
Run Code Online (Sandbox Code Playgroud)