122 lines
3.0 KiB
Go
122 lines
3.0 KiB
Go
package algos
|
|
|
|
import (
|
|
"crypto/md5"
|
|
"crypto/rand"
|
|
"encoding/base64"
|
|
"encoding/binary"
|
|
"encoding/hex"
|
|
"fmt"
|
|
)
|
|
|
|
// validate 验证并限制在64位范围内
|
|
func validate(num uint64) uint64 {
|
|
return num & 0xFFFFFFFFFFFFFFFF
|
|
}
|
|
|
|
// ror 右循环移位
|
|
func ror(value uint64, count int) uint64 {
|
|
nbits := 64
|
|
count %= nbits
|
|
low := (value << (nbits - count))
|
|
value = (value >> count)
|
|
value = value | low
|
|
return value
|
|
}
|
|
|
|
// encryptLadonInput 加密Ladon输入
|
|
func encryptLadonInput(hashTable []byte, inputData []byte) []byte {
|
|
data0 := binary.LittleEndian.Uint64(inputData[:8])
|
|
data1 := binary.LittleEndian.Uint64(inputData[8:])
|
|
|
|
for i := 0; i < 0x22; i++ {
|
|
hash := binary.LittleEndian.Uint64(hashTable[i*8 : (i+1)*8])
|
|
data1 = validate(hash ^ (data0 + ((data1 >> 8) | (data1 << (64 - 8)))))
|
|
data0 = validate(data1 ^ ((data0 >> 0x3D) | (data0 << (64 - 0x3D))))
|
|
}
|
|
|
|
outputData := make([]byte, 26)
|
|
binary.LittleEndian.PutUint64(outputData[:8], data0)
|
|
binary.LittleEndian.PutUint64(outputData[8:], data1)
|
|
|
|
return outputData
|
|
}
|
|
|
|
// encryptLadon 加密Ladon
|
|
func encryptLadon(md5Hex []byte, data []byte, size int) []byte {
|
|
hashTable := make([]byte, 272+16)
|
|
copy(hashTable[:32], md5Hex)
|
|
|
|
temp := make([]uint64, 0)
|
|
for i := 0; i < 4; i++ {
|
|
temp = append(temp, binary.LittleEndian.Uint64(hashTable[i*8:(i+1)*8]))
|
|
}
|
|
|
|
bufferB0 := temp[0]
|
|
bufferB8 := temp[1]
|
|
temp = temp[2:]
|
|
|
|
for i := 0; i < 0x22; i++ {
|
|
x9 := bufferB0
|
|
x8 := bufferB8
|
|
x8 = validate(ror(x8, 8))
|
|
x8 = validate(x8 + x9)
|
|
x8 = validate(x8 ^ uint64(i))
|
|
temp = append(temp, x8)
|
|
x8 = validate(x8 ^ ror(x9, 61))
|
|
binary.LittleEndian.PutUint64(hashTable[(i+1)*8:], x8)
|
|
bufferB0 = x8
|
|
bufferB8 = temp[0]
|
|
temp = temp[1:]
|
|
}
|
|
|
|
newSize := PaddingSize(size)
|
|
|
|
input := make([]byte, newSize)
|
|
copy(input[:size], data)
|
|
PKCS7PadBuffer(input, size, newSize, 16)
|
|
|
|
output := make([]byte, newSize)
|
|
for i := 0; i < newSize/16; i++ {
|
|
result := encryptLadonInput(hashTable, input[i*16:(i+1)*16])
|
|
copy(output[i*16:(i+1)*16], result)
|
|
}
|
|
|
|
return output
|
|
}
|
|
|
|
// LadonEncrypt Ladon加密主函数
|
|
func LadonEncrypt(khronos int64, lcID int, aid int, randomBytes []byte) string {
|
|
data := fmt.Sprintf("%d-%d-%d", khronos, lcID, aid)
|
|
|
|
if randomBytes == nil {
|
|
randomBytes = make([]byte, 4)
|
|
rand.Read(randomBytes)
|
|
}
|
|
|
|
keygen := append(randomBytes, []byte(fmt.Sprintf("%d", aid))...)
|
|
hasher := md5.New()
|
|
hasher.Write(keygen)
|
|
md5Hex := hex.EncodeToString(hasher.Sum(nil))
|
|
|
|
size := len(data)
|
|
newSize := PaddingSize(size)
|
|
|
|
output := make([]byte, newSize+4)
|
|
copy(output[:4], randomBytes)
|
|
|
|
encrypted := encryptLadon([]byte(md5Hex), []byte(data), size)
|
|
copy(output[4:], encrypted)
|
|
|
|
return base64.StdEncoding.EncodeToString(output)
|
|
}
|
|
|
|
// Ladon Ladon加密器
|
|
type Ladon struct{}
|
|
|
|
// Encrypt Ladon加密
|
|
func (l *Ladon) Encrypt(xKhronos int64, lcID int, aid int) string {
|
|
return LadonEncrypt(xKhronos, lcID, aid, nil)
|
|
}
|
|
|