using System; using System.Text; using Sog; using ChewKeongTAN; using System.Collections.Generic; using System.Linq; namespace PlayerOp { public class DynamicExchangeSvc { //编码字典 private static string CHAR_INDEXS = "abcdefghijkmnpqrstuvwxyz2345678"; //现在字符集一共31个,5位就可以表示 private static int ConvertByteCount = 5; private static int MAX_LENGTH = 32; //生成时是否校验 private static bool IS_CHECK = true; //默认兑换码长度 private const int DEFAULT_CODE_LENGTH = 12; //默认密码 private const string DEFAULT_PASSWD = "arpg2020"; /// 字节:groupId(1) + id(4) + 随机码补齐 + verify(1) public static Dictionary CreateCodes(int groupId, int codeCount, int seed, string passwrod = DEFAULT_PASSWD, int codeLength = DEFAULT_CODE_LENGTH) { Dictionary dict = new Dictionary(); if (codeLength > MAX_LENGTH) { return dict; } //用伪随机做种,保证每次做出来的数据一致 var random = new SRandom(seed); //八位数据总长度 int fullLength = codeLength * ConvertByteCount / 8; //剩余长度做随机码 int randCount = fullLength - 6; if (randCount <= 0) { return dict; } Byte[] passwdBytes = Encoding.UTF8.GetBytes(passwrod); for (int i = 1; i <= codeCount; i++) { var bytes = CreateCodeBytes(groupId, randCount, i, fullLength, random, passwdBytes); BigInteger bigInteger = new BigInteger(bytes); string code = bigInteger.ToStringByCode(CHAR_INDEXS, codeLength); if (IS_CHECK) { bool ret = VerifyCode(code, out int checkGroupId, out int checkId, passwrod); if (!ret || checkGroupId != groupId || checkId != i) { TraceLog.Error("DynamicExchangeSvc.CreateCodes Verify fail groupId {0} id {1} code {2} ", checkGroupId, checkId, code); break; } } if (dict.ContainsValue(code)) { TraceLog.Error("DynamicExchangeSvc.CreateCodes repeat code {0} groupId {1} id {2} ", code, groupId, i); break; } dict.Add(i, code); } if (dict.Count != codeCount) { dict.Clear(); } return dict; } public static bool VerifyCode(string code, out int groupId, out int id, string passwrod = DEFAULT_PASSWD) { groupId = 0; id = 0; BigInteger deCodeBig = new BigInteger(code, CHAR_INDEXS); byte[] bytes = deCodeBig.getBytes(); int fullLength = code.Length * ConvertByteCount / 8; byte[] fullBytes = new byte[fullLength]; for (int i = 1; i <= fullLength; i++) { if (i <= bytes.Length) { fullBytes[fullLength - i] = bytes[bytes.Length - i]; } else { fullBytes[fullLength - i] = 0; } } int randCount = fullLength - 6; //TraceLog.Trace("VerifyCode bytelength {0} code {1}", fullLength, code); //解密 Byte[] passwdBytes = Encoding.UTF8.GetBytes(passwrod); for (int i = 0; i < fullBytes.Length; i++) { fullBytes[i] = (byte) (fullBytes[i] ^ passwdBytes[i % passwdBytes.Length]); } //异或解密 //随机码与id异或 for (int j = 0; j < 5; j++) { fullBytes[j] = (byte)(fullBytes[j] ^ fullBytes[5 + j % randCount]); } BigInteger big = new BigInteger(fullBytes); //TraceLog.Trace("VerifyCode {0}", big.ToString()); int sum = 0; for (int i = 0; i < fullBytes.Length - 1; i++) { sum += fullBytes[i]; } byte verify = (byte) (sum % Byte.MaxValue); if (verify != fullBytes[fullBytes.Length - 1]) { return false; } //解id groupId =(int)fullBytes[0]; id = (int)fullBytes[1] << 24 | (int)fullBytes[2] << 16 | (int)fullBytes[3] << 8 | (int)fullBytes[4]; return true; } private static byte[] CreateCodeBytes(int groupId, int randCount, int id, int fullLength, SRandom random, Byte[] passwdBytes) { byte[] randbytes = new byte[randCount]; for (int j = 0; j < randCount; j++) { randbytes[j] = (byte)(random.Next() % Byte.MaxValue); } ByteHapper byteHapper = ByteHapper.CreateBytes(fullLength); byteHapper.AppendNumber((byte)groupId).AppendNumber(id).AppendBytes(randbytes); byte verify = (byte)(byteHapper.GetSum() % Byte.MaxValue); byteHapper.AppendNumber(verify); BigInteger big = new BigInteger(byteHapper.bytes); //TraceLog.Trace("CreateCodeBytes {0}", big.ToString()); //随机码与id异或 for (int j = 0; j < 5; j++) { byteHapper.bytes[j] = (byte)(byteHapper.bytes[j] ^ byteHapper.bytes[5 + j % randCount]); } //异或加密 for (int j = 0; j < byteHapper.bytes.Length; j++) { byteHapper.bytes[j] = (byte)(byteHapper.bytes[j] ^ passwdBytes[j % passwdBytes.Length]); } return byteHapper.bytes; } partial class ByteHapper { public byte[] bytes; private int index; private ByteHapper(int capacity) { bytes = new byte[capacity]; index = 0; } public static ByteHapper CreateBytes(int capacity) { ByteHapper byteHapper = new ByteHapper(capacity); return byteHapper; } public ByteHapper AppendBytes(byte[] arr) { for (int i = 0; i < arr.Length; i++) { bytes[index + i] = arr[i]; } index += arr.Length; return this; } public ByteHapper AppendNumber(byte val) { bytes[index] = val; index++; return this; } public int GetSum() { int ret = 0; for (int i = 0; i < bytes.Length; i++) { ret += bytes[i]; } return ret; } public ByteHapper AppendNumber(int val) { byte[] arr = Number2byte(val); return AppendBytes(arr); } public ByteHapper AppendNumber(long val) { byte[] arr = Number2byte(val); return AppendBytes(arr); } public static byte[] Number2byte(int val) { byte[] arr = new byte[] { (byte) ((val >> 24) & 0xFF), (byte) ((val >> 16) & 0xFF), (byte) ((val >> 8) & 0xFF), (byte) (val & 0xFF), }; return arr; } public static byte[] Number2byte(long val) { byte[] arr = new byte[] { (byte) ((val >> 56) & 0xFF), (byte) ((val >> 48) & 0xFF), (byte) ((val >> 40) & 0xFF), (byte) ((val >> 32) & 0xFF), (byte) ((val >> 24) & 0xFF), (byte) ((val >> 16) & 0xFF), (byte) ((val >> 8) & 0xFF), (byte) (val & 0xFF), }; return arr; } public static byte[] Number2byte(short val) { byte[] arr = new byte[] { (byte) ((val >> 8) & 0xFF), (byte) (val & 0xFF), }; return arr; } } } }