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
273 lines
8.6 KiB
1 month ago
|
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;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|