312 lines
7.5 KiB
Go
312 lines
7.5 KiB
Go
package cdkey
|
|
|
|
import (
|
|
"math"
|
|
"math/rand"
|
|
)
|
|
|
|
const (
|
|
MAXNUM = math.MaxInt32 - 20000000
|
|
CDKEY_LENGTH = 15
|
|
MAIN_KEY_LENGTH = 40
|
|
NUM_KEY_LENGTH_BINARY = 8
|
|
MAIN_KEY_NUM_LENGTH = 32
|
|
NUM_KEY_LENGTH = 3
|
|
CHECK_LENGTH = 5
|
|
BATCH_LENGTH = 20
|
|
BATCH_KEY_LENGTH_BINARY = 32
|
|
TYPE_LENGTH_BINARY = 32
|
|
shuffleLength = 32
|
|
exceptShuffleSeedTotalLength = 70
|
|
SHUFFLE_INDEX = 14
|
|
TYPE_INDEX = 13
|
|
BATCH_NUM_BEGIN = 12
|
|
BATCH_BEGIN = 8
|
|
BATCH_END = 12
|
|
MAIN_KEY_BEGIN = 0
|
|
MAIN_KEY_END = 8
|
|
mainKeyFormat int64 = 34359738367
|
|
checkNumFormat int64 = 1065151889408
|
|
CHECK_LENGTH_BINARY = 32
|
|
)
|
|
|
|
var toBase32 = []rune{'2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}
|
|
var toBase32CToI map[rune]int
|
|
|
|
var mainKeyBatchKey = newBitmap(20, 1918215104086)
|
|
|
|
var intFormat int64 = 4294967295
|
|
var key = newBitmap(20, 1209617303503)
|
|
var shuffleMap = make(map[int][]int)
|
|
|
|
var numKey = []int64{
|
|
3000669867,
|
|
3671239387,
|
|
2526368469,
|
|
2493864681,
|
|
3604110165,
|
|
3567998377,
|
|
2763216037,
|
|
2863360677,
|
|
}
|
|
|
|
var batchKey = []*bitmap{
|
|
newBitmap(20, 31511741981182095),
|
|
newBitmap(20, 3664122353341979125),
|
|
newBitmap(20, 3024789513220408272),
|
|
newBitmap(20, 7614911559402769357),
|
|
newBitmap(20, 2108459002177461007),
|
|
newBitmap(20, -3779584974404014377),
|
|
newBitmap(20, -4708816669881919040),
|
|
newBitmap(20, -6362362468306307184),
|
|
newBitmap(20, 5237470582631498811),
|
|
newBitmap(20, 5507680150663927504),
|
|
newBitmap(20, -533592023685287698),
|
|
newBitmap(20, 5175063634818869382),
|
|
newBitmap(20, -8744795741519816883),
|
|
newBitmap(20, -4080090257317771786),
|
|
newBitmap(20, -8036132546007449313),
|
|
newBitmap(20, 202953352259602475),
|
|
newBitmap(20, 1095317292689077154),
|
|
newBitmap(20, 2991873574004670411),
|
|
newBitmap(20, -6707239314758981218),
|
|
newBitmap(20, 7712241472074747715),
|
|
newBitmap(20, -8133590642362246474),
|
|
newBitmap(20, -4968343163714505661),
|
|
newBitmap(20, -6905628074578549760),
|
|
newBitmap(20, 5195681389062354029),
|
|
newBitmap(20, -5910830154906229288),
|
|
newBitmap(20, -1676518468791541432),
|
|
newBitmap(20, -7994149653806568719),
|
|
newBitmap(20, -7378005837432330374),
|
|
newBitmap(20, 1068884024847281324),
|
|
newBitmap(20, 1945505497196485942),
|
|
newBitmap(20, -3492268017556027220),
|
|
newBitmap(20, 7364928014934311923),
|
|
}
|
|
|
|
var toNumBitSet [NUM_KEY_LENGTH_BINARY]*bitmap
|
|
var toBitSet32 [32]*bitmap
|
|
|
|
func init() {
|
|
for i := 0; i < 32; i++ {
|
|
temp := i
|
|
toBitSet32[i] = newBitmap(5, 0)
|
|
for j := 0; j < 5; j++ {
|
|
toBitSet32[i].Set(j, (temp&1) == 1)
|
|
temp >>= 1
|
|
}
|
|
}
|
|
for i := 0; i < NUM_KEY_LENGTH_BINARY; i++ {
|
|
temp := i
|
|
toNumBitSet[i] = newBitmap(NUM_KEY_LENGTH, 0)
|
|
for j := 0; j < NUM_KEY_LENGTH; j++ {
|
|
toNumBitSet[i].Set(j, (temp&1) == 1)
|
|
temp >>= 1
|
|
}
|
|
}
|
|
|
|
toBase32CToI = make(map[rune]int)
|
|
for i := 0; i < len(toBitSet32); i++ {
|
|
toBase32CToI[toBase32[i]] = i
|
|
}
|
|
for seed := 0; seed < shuffleLength; seed++ {
|
|
array := make([]int, exceptShuffleSeedTotalLength)
|
|
for i := 0; i < exceptShuffleSeedTotalLength; i++ {
|
|
array[i] = i
|
|
}
|
|
shuffle(array, rand.New(rand.NewSource(int64(seed))))
|
|
shuffleMap[seed] = array
|
|
}
|
|
}
|
|
|
|
func checkIndex(num int64, batch int, batchKeyIndex int, numKeyIndex int) bool {
|
|
return (num+int64(batch))%BATCH_KEY_LENGTH_BINARY == int64(batchKeyIndex) && (num+int64(batch))%NUM_KEY_LENGTH_BINARY == int64(numKeyIndex)
|
|
}
|
|
|
|
func numEncode(num int64, index int) int64 {
|
|
return numKey[index] ^ num
|
|
}
|
|
|
|
func getNumKeyIndex(mainKeyBitSet *bitmap) int {
|
|
bitset := newBitmap(NUM_KEY_LENGTH, 0)
|
|
for i := 0; i < bitset.GetSize(); i++ {
|
|
bitset.Set(i, mainKeyBitSet.Get(MAIN_KEY_NUM_LENGTH+i))
|
|
}
|
|
return int(bitset.toInt64())
|
|
}
|
|
|
|
func check(mainkeyBitSet *bitmap) bool {
|
|
mainkey := mainkeyBitSet.toInt64()
|
|
if mainkey <= 0 {
|
|
mainkey = -mainkey
|
|
}
|
|
beCheckNum := mainkey & mainKeyFormat
|
|
checkNum := mainkey & checkNumFormat
|
|
checkNum >>= (MAIN_KEY_NUM_LENGTH + NUM_KEY_LENGTH)
|
|
return beCheckNum%CHECK_LENGTH_BINARY == checkNum
|
|
}
|
|
|
|
func base32Decode(data string) *bitmap {
|
|
if len(data) > 63/5 {
|
|
return nil
|
|
}
|
|
bitset := newBitmap(len(data)*5, 0)
|
|
i := 0
|
|
for _, c := range data {
|
|
if _, find := toBase32CToI[c]; !find {
|
|
return nil
|
|
}
|
|
index := toBase32CToI[c]
|
|
letterBitSet := toBitSet32[index]
|
|
for j := 0; j < 5; j++ {
|
|
bitset.Set(i, letterBitSet.Get(j))
|
|
i++
|
|
}
|
|
}
|
|
return bitset
|
|
}
|
|
|
|
func recoverCDKey(cdKey string, index int) string {
|
|
array := shuffleMap[index]
|
|
if array == nil {
|
|
return ""
|
|
}
|
|
bytes := base32DecodeReturnByteArray(cdKey)
|
|
if bytes == nil {
|
|
return ""
|
|
}
|
|
if len(array) != len(bytes) {
|
|
return ""
|
|
}
|
|
resultByte := make([]byte, len(bytes))
|
|
for i := 0; i < len(array); i++ {
|
|
resultByte[array[i]] = bytes[i]
|
|
}
|
|
return base32Encode1(resultByte)
|
|
}
|
|
|
|
func shuffleCDKey(key string, index int) string {
|
|
array := shuffleMap[index]
|
|
bytes := base32DecodeReturnByteArray(key)
|
|
resultByte := make([]byte, len(bytes))
|
|
for i := 0; i < len(array); i++ {
|
|
resultByte[i] = bytes[array[i]]
|
|
}
|
|
return base32Encode1(resultByte) + string(toBase32[index])
|
|
}
|
|
|
|
func shuffle(array []int, rander *rand.Rand) {
|
|
for i := len(array); i > 1; i-- {
|
|
swap(array, i-1, rander.Intn(i))
|
|
}
|
|
}
|
|
|
|
func swap(array []int, i, j int) {
|
|
array[i], array[j] = array[j], array[i]
|
|
}
|
|
|
|
func newEncode(num int64, index int) int64 {
|
|
return numKey[index] ^ num
|
|
}
|
|
|
|
func base32Encode(m *bitmap) string {
|
|
if m.GetSize()%5 != 0 {
|
|
return ""
|
|
}
|
|
|
|
stringBuilder := ""
|
|
|
|
for i := 0; i < m.GetSize(); i += 5 {
|
|
bitset1 := newBitmap(5, 0)
|
|
for j := 0; j < 5; j++ {
|
|
bitset1.Set(j, m.Get(i+j))
|
|
}
|
|
if bitset1.toInt64() >= int64(len(toBase32)) {
|
|
return ""
|
|
}
|
|
letter := toBase32[int(bitset1.toInt64())]
|
|
stringBuilder += string(letter)
|
|
}
|
|
|
|
return stringBuilder
|
|
}
|
|
|
|
func base32Encode1(bytes []byte) string {
|
|
if len(bytes)%5 != 0 {
|
|
return ""
|
|
}
|
|
|
|
stringBuilder := ""
|
|
|
|
for i := 0; i < len(bytes); i += 5 {
|
|
bitset1 := newBitmap(5, 0)
|
|
for j := 0; j < 5; j++ {
|
|
bitset1.Set(j, bytes[i+j] > 0)
|
|
}
|
|
if bitset1.toInt64() >= int64(len(toBase32)) {
|
|
return ""
|
|
}
|
|
letter := toBase32[int(bitset1.toInt64())]
|
|
stringBuilder += string(letter)
|
|
}
|
|
|
|
return stringBuilder
|
|
}
|
|
|
|
func fakeRC4Encode(data, key *bitmap) *bitmap {
|
|
if data.GetSize() != key.GetSize() {
|
|
return nil
|
|
}
|
|
bitSet := newBitmap(data.GetSize(), 0)
|
|
for i := 0; i < data.GetSize(); i++ {
|
|
bitSet.Set(i, data.GetInt(i)^key.GetInt(i) == 1)
|
|
}
|
|
return bitSet
|
|
}
|
|
|
|
func getMainKey(batch *bitmap) *bitmap {
|
|
bitSet := newBitmap(MAIN_KEY_LENGTH, 0)
|
|
batchKey := fakeRC4Encode(batch, mainKeyBatchKey)
|
|
if batchKey == nil {
|
|
return nil
|
|
}
|
|
index := (int)(batchKey.toInt64()&intFormat) % key.GetSize()
|
|
count := 0
|
|
for i := 0; i < index; i++ {
|
|
bitSet.Set(count, key.Get(i))
|
|
count++
|
|
}
|
|
for i := 0; i < batchKey.GetSize(); i++ {
|
|
bitSet.Set(count, batchKey.Get(i))
|
|
count++
|
|
}
|
|
for i := index; i < key.GetSize(); i++ {
|
|
bitSet.Set(count, key.Get(i))
|
|
count++
|
|
}
|
|
return bitSet
|
|
}
|
|
|
|
func base32DecodeReturnByteArray(data string) []byte {
|
|
bytes := make([]byte, len(data)*5)
|
|
i := 0
|
|
for _, c := range data {
|
|
if _, find := toBase32CToI[c]; !find {
|
|
return nil
|
|
}
|
|
index := toBase32CToI[c]
|
|
letterBitSet := toBitSet32[index]
|
|
for j := 0; j < 5; j++ {
|
|
bitValue := letterBitSet.Get(j)
|
|
if bitValue {
|
|
bytes[i] = 1
|
|
} else {
|
|
bytes[i] = 0
|
|
}
|
|
i++
|
|
}
|
|
}
|
|
return bytes
|
|
}
|