RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1023833
Accepted
XelaNimed
XelaNimed
Asked:2020-09-12 20:51:38 +0000 UTC2020-09-12 20:51:38 +0000 UTC 2020-09-12 20:51:38 +0000 UTC

可逆许可证密钥加密

  • 772

有一种算法可以为程序的离线激活生成许可证密钥。这意味着许可证信息直接编码在密钥中。要生成许可证密钥,需要使用应用程序的名称和版本,以及许可证所有者的姓名。几乎所有的代码都是从 Internet 上的各种来源收集的,并且在某种程度上适应了我的任务。我该怎么做和做什么:

许可证密钥生成

  1. 我使用程序的名称和版本创建了一个“盐”;
  2. 使用许可证所有者的名称作为解密许可证密钥的密码;
  3. 我使用先前创建的“salt”和密码创建 Rijndale - 许可证的所有者;
  4. 我将许可证信息加密为编码字节数组;
  5. 我将使用BASE36将生成的字节数组转换为人类可读的形式;

许可证解密

  1. 在程序方面,使用反射,我得到程序的名称和版本,以及许可证所有者;
  2. 根据收到的信息,我形成一个“盐”和一个密码;
  3. 我从BASE36格式的许可证密钥中取回一组编码字节;
  4. 使用之前创建的“salt”和密码创建 Rijndale ;
  5. 我将编码字节数组解码回许可证信息;

问题是我只能用这种方法加密长度在 16 到 31 个字符之间的字符串。如何针对不同长度的字符串修改现有代码?

PS:您可以在此处使用代码“玩耍” 。

BASE36 类

using System;
using System.Text;

namespace ConsoleApp1
{
    public static class BASE36
    {
        private const string _charList = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        private static readonly char[] _charArray = _charList.ToCharArray();

        public static long Decode(string input)
        {
            long _result = 0;
            double _pow = 0;
            for (int _i = input.Length - 1; _i >= 0; _i--)
            {
                char _c = input[_i];
                int pos = _charList.IndexOf(_c);
                if (pos > -1)
                {
                    _result += pos * (long)Math.Pow(_charList.Length, _pow);
                }
                else
                {
                    return -1;
                }

                _pow++;
            }
            return _result;
        }

        public static string Encode(ulong input)
        {
            var _sb = new StringBuilder();
            do
            {
                _sb.Append(_charArray[input % (ulong)_charList.Length]);
                input /= (ulong)_charList.Length;
            } while (input != 0);

            return Reverse(_sb.ToString());
        }

        private static string Reverse(string s)
        {
            char[] charArray = s.ToCharArray();
            Array.Reverse(charArray);
            return new string(charArray);
        }
    }
}

节目班

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            string saltString = GetSaltString("Blechexport", "15");
            byte[] salt = Encoding.UTF8.GetBytes(saltString);
            string pwd = "J.Doe";
            string licInfo = $"[0,{new DateTime(2019, 11, 30).Ticks},10]";
            var bytes = Encoding.UTF8.GetBytes(licInfo);
            var seconds = new DateTime(2019, 12, 31).Ticks / 10000000;
            string[] testDatas = new string[]{
                $"[0,{seconds},1]",
                $"[1,{seconds},10]",
                $"[2,{seconds},10,10]",
                $"[3,{seconds},10,10,10]",
                $"[3,{seconds},10,10,10,10]",
                $"[3,{seconds},10,10,10,10,10]"
                // throws System.Security.Cryptography.CryptographicException
                // ,$"[3,{seconds},10,10,10,10,10,10]"
            };
            foreach (string testData in testDatas)
            {
                TestLic(pwd, salt, testData);
            }
            Console.ReadKey();
        }

        static void TestLic(string pwd, byte[] salt, string phrase)
        {
            var bytes = Encoding.UTF8.GetBytes(phrase);
            Console.WriteLine("------------------------------------------");
            Console.WriteLine($"phrase: {phrase} ({phrase.Length} symbols)");
            string licKey;
            using (var rijndael = InitSymmetric(Rijndael.Create(), pwd, salt, 256))
            {
                byte[] encryptedBytes = Transform(bytes, rijndael.CreateEncryptor);
                licKey = GenerateUID(encryptedBytes);
                Console.WriteLine($"encrypted bytes: {BitConverter.ToString(encryptedBytes)}");
                Console.WriteLine($"license key: {licKey}");
                Console.WriteLine($"key length: {licKey.Length}");
            }

            using (var rijndael = InitSymmetric(Rijndael.Create(), pwd, salt, 256))
            {
                byte[] uidBytes = GetUIDInBytes(licKey);
                byte[] decryptedBytes = Transform(uidBytes, rijndael.CreateDecryptor);
                Console.WriteLine($"decrypted bytes: {BitConverter.ToString(decryptedBytes)}");
                string decryptedText = Encoding.UTF8.GetString(decryptedBytes);
                Console.WriteLine("decryptedText: {0}", decryptedText);
            }
            Console.WriteLine("------------------------------------------");
        }

        static string GetSaltString(string programmName, string programmVersion)
        {
            return $"{programmName}.{programmVersion}";
        }

        static string GenerateUID(byte[] bytes)
        {
            //Convert checksum into 4 ulong parts and use BASE36 to encode both
            string _part1Id = BASE36.Encode(BitConverter.ToUInt64(bytes, 0));
            string _part2Id = BASE36.Encode(BitConverter.ToUInt64(bytes, 8));
            string _part3Id = BASE36.Encode(BitConverter.ToUInt64(bytes, 16));
            string _part4Id = BASE36.Encode(BitConverter.ToUInt64(bytes, 24));
            //Concat these 4 part into one string
            return string.Format("{0}-{1}-{2}-{3}", _part1Id, _part2Id, _part3Id, _part4Id);
        }

        static byte[] GetUIDInBytes(string UID)
        {
            //Split 4 part Id into 4 ulong
            string[] _ids = UID.Split('-');
            //Combine 4 part Id into one byte array
            byte[] _value = new byte[32];
            Buffer.BlockCopy(BitConverter.GetBytes(BASE36.Decode(_ids[0])), 0, _value, 0, 8);
            Buffer.BlockCopy(BitConverter.GetBytes(BASE36.Decode(_ids[1])), 0, _value, 8, 8);
            Buffer.BlockCopy(BitConverter.GetBytes(BASE36.Decode(_ids[2])), 0, _value, 16, 8);
            Buffer.BlockCopy(BitConverter.GetBytes(BASE36.Decode(_ids[3])), 0, _value, 24, 8);
            return _value;
        }

        static byte[] EncryptStringToBytes_Aes(string plainText, byte[] Key, byte[] IV)
        {
            // Check arguments.
            if (string.IsNullOrEmpty(plainText))
            {
                throw new ArgumentNullException(nameof(plainText));
            }
            if (Key == null || Key.Length == 0)
            {
                throw new ArgumentNullException(nameof(Key));
            }
            if (IV == null || IV.Length == 0)
            {
                throw new ArgumentNullException(nameof(IV));
            }
            byte[] encrypted;
            // Create an AesManaged object
            // with the specified key and IV.
            using (AesManaged aesAlg = new AesManaged())
            {
                aesAlg.Key = Key;
                aesAlg.IV = IV;
                // Create an encryptor to perform the stream transform.
                ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
                // Create the streams used for encryption.
                using (MemoryStream msEncrypt = new MemoryStream())
                {
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    {
                        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                        {
                            //Write all data to the stream.
                            swEncrypt.Write(plainText);
                        }

                        encrypted = msEncrypt.ToArray();
                    }
                }
            }
            // Return the encrypted bytes from the memory stream.
            return encrypted;
        }

        static string DecryptStringFromBytes_Aes(byte[] cipherText, byte[] Key, byte[] IV)
        {
            // Check arguments.
            if (cipherText == null || cipherText.Length <= 0)
            {
                throw new ArgumentNullException(nameof(cipherText));
            }
            if (Key == null || Key.Length <= 0)
            {
                throw new ArgumentNullException(nameof(Key));
            }
            if (IV == null || IV.Length <= 0)
            {
                throw new ArgumentNullException(nameof(IV));
            }
            // Declare the string used to hold
            // the decrypted text.
            string plaintext = null;
            // Create an AesManaged object
            // with the specified key and IV.
            using (AesManaged aesAlg = new AesManaged())
            {
                aesAlg.Key = Key;
                aesAlg.IV = IV;
                // Create a decryptor to perform the stream transform.
                ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
                // Create the streams used for decryption.
                using (MemoryStream msDecrypt = new MemoryStream(cipherText))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                        {
                            // Read the decrypted bytes from the decrypting stream
                            // and place them in a string.
                            plaintext = srDecrypt.ReadToEnd();
                        }
                    }
                }
            }
            return plaintext;
        }

        static SymmetricAlgorithm InitSymmetric(SymmetricAlgorithm algorithm, string password, byte[] salt, int keyBitLength)
        {
            const int Iterations = 234;
            using (var rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, salt, Iterations))
            {
                if (!algorithm.ValidKeySize(keyBitLength))
                {
                    throw new InvalidOperationException("Invalid size key");
                }
                algorithm.Key = rfc2898DeriveBytes.GetBytes(keyBitLength / 8);
                algorithm.IV = rfc2898DeriveBytes.GetBytes(algorithm.BlockSize / 8);
                return algorithm;
            }
        }

        static byte[] Transform(byte[] bytes, Func<ICryptoTransform> selectCryptoTransform)
        {
            using (var memoryStream = new MemoryStream())
            {
                using (var cryptoStream = new CryptoStream(memoryStream, selectCryptoTransform(), CryptoStreamMode.Write))
                {
                    cryptoStream.Write(bytes, 0, bytes.Length);
                }
                return memoryStream.ToArray();
            }
        }
    }
}
c#
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    XelaNimed
    2020-09-12T23:41:47Z2020-09-12T23:41:47Z

    感谢tym32167和Zergatul的评论,该问题已得到解决,并且已修改以下方法以处理任意长度的字符串:

    static string GenerateUID(byte[] bytes)
    {
        string[] arr = new string[bytes.Length / 8];
        for (int i = 0; i < arr.Length; i++)
        {
            arr[i] = BASE36.Encode(BitConverter.ToUInt64(bytes, 8 * i));
        }
        return string.Join("-", arr);
    }
    
    static byte[] GetUIDInBytes(string UID)
    {
        string[] ids = UID.Split('-');
        byte[] val = new byte[ids.Length * 8];
        for(int i = 0; i < ids.Length; i++)
        {
            Buffer.BlockCopy(BitConverter.GetBytes(BASE36.Decode(ids[i])), 0, val, 8 * i, 8);
        }
        return val;
    }
    

    我很乐意接受任何建设性的意见和建议!

    PS:和以前一样,您可以在这里“玩”更正和工作的代码。

    • 0

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    根据浏览器窗口的大小调整背景图案的大小

    • 2 个回答
  • Marko Smith

    理解for循环的执行逻辑

    • 1 个回答
  • Marko Smith

    复制动态数组时出错(C++)

    • 1 个回答
  • Marko Smith

    Or and If,elif,else 构造[重复]

    • 1 个回答
  • Marko Smith

    如何构建支持 x64 的 APK

    • 1 个回答
  • Marko Smith

    如何使按钮的输入宽度?

    • 2 个回答
  • Marko Smith

    如何显示对象变量的名称?

    • 3 个回答
  • Marko Smith

    如何循环一个函数?

    • 1 个回答
  • Marko Smith

    LOWORD 宏有什么作用?

    • 2 个回答
  • Marko Smith

    从字符串的开头删除直到并包括一个字符

    • 2 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5