首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >软件的密钥

软件的密钥
EN

Stack Overflow用户
提问于 2012-04-06 19:39:57
回答 1查看 484关注 0票数 0

我想使用RSA密钥设计一个产品密钥,但我不知道我的想法是否安全。

我的设计产品密钥的想法:

例如,我有一对密钥

公钥为:MIIBvTCCASYCCQD55fNzc0WF7TANBgkqhkiG9w0BAQUFADAjMQswCQYDVQQG…

私钥为:MIICWwIBAAKBgQDRhGF7X4A0ZVlEg594WmODVVUIiiPQs04aLmvfg8SborHss5gQ…

我像这样创建产品密钥:

(例如私钥的开始) MIICWwIBAAKBgQDRh

并将其从软件中的私钥中删除

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-04-06 19:52:58

这不是您使用产品密钥的公钥/私钥的方式。

更好的实现

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

代码语言:javascript
复制
<license>
    <name>Acme Co.</name>
    <expiration>20120304</expiration>
</license>

您使用私钥对XML文档进行签名,并将散列和签名与文档一起存储。然后,您可以使用之前生成的公钥来验证产品中的XML文档。

签署文件的结果:

代码语言:javascript
复制
<license>
    <name>Acme Co.</name>
    <expiration>20120304</expiration>
    <signature>
        <hash>1230u4woeifhljksdkvh23p9</hash>
        <value>sdvrrvLJbmyscoVMg2pZZAtZJbBHsZFUCwE4Udv+u3TfiAms2HpLgN3cL
      NtRlxyQpvWt1FKAB/SCk1jr0IasdfeDOOHhTUTyiv2vMJgCRecC1PLcrmR9ABhqk
      itsjzrCt7V3eF5SpObdUFqcj+n9gasdfdQtlQeWcvKEcg=</value>
    </signature>
</license>

如果用户更改了许可证文件的内容,则签名将不再匹配。他们也无法重新签署文档,因为他们无法访问您的私钥。这一点很重要,你将公钥与你的产品一起发布,而不是私钥。

短键实现

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

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

C#解决方案:

代码语言:javascript
复制
/// <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;
}
票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10042957

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档