You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

273 lines
8.6 KiB

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<int, string> CreateCodes(int groupId, int codeCount, int seed, string passwrod = DEFAULT_PASSWD, int codeLength = DEFAULT_CODE_LENGTH)
{
Dictionary<int, string> dict = new Dictionary<int, string>();
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;
}
}
}
}