1
0
mirror of https://github.com/kamyu1537/eamuse-card-wasm.git synced 2024-11-27 21:10:48 +01:00
eamuse-card-wasm/main.go
2020-05-06 16:16:41 +09:00

972 lines
16 KiB
Go

package main
// https://github.com/DragonMinded/bemaniutils/blob/master/bemani/common/card.py
import (
"encoding/hex"
"strings"
"syscall/js"
)
var KEY = []int64{
0x20d0d03c,
0x868ecb41,
0xbcd89c84,
0x4c0e0d0d,
0x84fc30ac,
0x4cc1890e,
0xfc5418a4,
0x02c50f44,
0x68acb4e0,
0x06cd4a4e,
0xcc28906c,
0x4f0c8ac0,
0xb03ca468,
0x884ac7c4,
0x389490d8,
0xcf80c6c2,
0x58d87404,
0xc48ec444,
0xb4e83c50,
0x498d0147,
0x64f454c0,
0x4c4701c8,
0xec302cc4,
0xc6c949c1,
0xc84c00f0,
0xcdcc49cc,
0x883c5cf4,
0x8b0fcb80,
0x703cc0b0,
0xcb820a8d,
0x78804c8c,
0x4fca830e,
0x80d0f03c,
0x8ec84f8c,
0x98c89c4c,
0xc80d878f,
0x54bc949c,
0xc801c5ce,
0x749078dc,
0xc3c80d46,
0x2c8070f0,
0x0cce4dcf,
0x8c3874e4,
0x8d448ac3,
0x987cac70,
0xc0c20ac5,
0x288cfc78,
0xc28543c8,
0x4c8c7434,
0xc50e4f8d,
0x8468f4b4,
0xcb4a0307,
0x2854dc98,
0x48430b45,
0x6858fce8,
0x4681cd49,
0xd04808ec,
0x458d0fcb,
0xe0a48ce4,
0x880f8fce,
0x7434b8fc,
0xce080a8e,
0x5860fc6c,
0x46c886cc,
0xd01098a4,
0xce090b8c,
0x1044cc2c,
0x86898e0f,
0xd0809c3c,
0x4a05860f,
0x54b4f80c,
0x4008870e,
0x1480b88c,
0x0ac8854f,
0x1c9034cc,
0x08444c4e,
0x0cb83c64,
0x41c08cc6,
0x1c083460,
0xc0c603ce,
0x2ca0645c,
0x818246cb,
0x0408e454,
0xc5464487,
0x88607c18,
0xc1424187,
0x284c7c90,
0xc1030509,
0x40486c94,
0x4603494b,
0xe0404ce4,
0x4109094d,
0x60443ce4,
0x4c0b8b8d,
0xe054e8bc,
0x02008e89,
}
var LUT_A0 = []int64{
0x02080008,
0x02082000,
0x00002008,
0x00000000,
0x02002000,
0x00080008,
0x02080000,
0x02082008,
0x00000008,
0x02000000,
0x00082000,
0x00002008,
0x00082008,
0x02002008,
0x02000008,
0x02080000,
0x00002000,
0x00082008,
0x00080008,
0x02002000,
0x02082008,
0x02000008,
0x00000000,
0x00082000,
0x02000000,
0x00080000,
0x02002008,
0x02080008,
0x00080000,
0x00002000,
0x02082000,
0x00000008,
0x00080000,
0x00002000,
0x02000008,
0x02082008,
0x00002008,
0x02000000,
0x00000000,
0x00082000,
0x02080008,
0x02002008,
0x02002000,
0x00080008,
0x02082000,
0x00000008,
0x00080008,
0x02002000,
0x02082008,
0x00080000,
0x02080000,
0x02000008,
0x00082000,
0x00002008,
0x02002008,
0x02080000,
0x00000008,
0x02082000,
0x00082008,
0x00000000,
0x02000000,
0x02080008,
0x00002000,
0x00082008,
}
var LUT_A1 = []int64{
0x08000004,
0x00020004,
0x00000000,
0x08020200,
0x00020004,
0x00000200,
0x08000204,
0x00020000,
0x00000204,
0x08020204,
0x00020200,
0x08000000,
0x08000200,
0x08000004,
0x08020000,
0x00020204,
0x00020000,
0x08000204,
0x08020004,
0x00000000,
0x00000200,
0x00000004,
0x08020200,
0x08020004,
0x08020204,
0x08020000,
0x08000000,
0x00000204,
0x00000004,
0x00020200,
0x00020204,
0x08000200,
0x00000204,
0x08000000,
0x08000200,
0x00020204,
0x08020200,
0x00020004,
0x00000000,
0x08000200,
0x08000000,
0x00000200,
0x08020004,
0x00020000,
0x00020004,
0x08020204,
0x00020200,
0x00000004,
0x08020204,
0x00020200,
0x00020000,
0x08000204,
0x08000004,
0x08020000,
0x00020204,
0x00000000,
0x00000200,
0x08000004,
0x08000204,
0x08020200,
0x08020000,
0x00000204,
0x00000004,
0x08020004,
}
var LUT_A2 = []int64{
0x80040100,
0x01000100,
0x80000000,
0x81040100,
0x00000000,
0x01040000,
0x81000100,
0x80040000,
0x01040100,
0x81000000,
0x01000000,
0x80000100,
0x81000000,
0x80040100,
0x00040000,
0x01000000,
0x81040000,
0x00040100,
0x00000100,
0x80000000,
0x00040100,
0x81000100,
0x01040000,
0x00000100,
0x80000100,
0x00000000,
0x80040000,
0x01040100,
0x01000100,
0x81040000,
0x81040100,
0x00040000,
0x81040000,
0x80000100,
0x00040000,
0x81000000,
0x00040100,
0x01000100,
0x80000000,
0x01040000,
0x81000100,
0x00000000,
0x00000100,
0x80040000,
0x00000000,
0x81040000,
0x01040100,
0x00000100,
0x01000000,
0x81040100,
0x80040100,
0x00040000,
0x81040100,
0x80000000,
0x01000100,
0x80040100,
0x80040000,
0x00040100,
0x01040000,
0x81000100,
0x80000100,
0x01000000,
0x81000000,
0x01040100,
}
var LUT_A3 = []int64{
0x04010801,
0x00000000,
0x00010800,
0x04010000,
0x04000001,
0x00000801,
0x04000800,
0x00010800,
0x00000800,
0x04010001,
0x00000001,
0x04000800,
0x00010001,
0x04010800,
0x04010000,
0x00000001,
0x00010000,
0x04000801,
0x04010001,
0x00000800,
0x00010801,
0x04000000,
0x00000000,
0x00010001,
0x04000801,
0x00010801,
0x04010800,
0x04000001,
0x04000000,
0x00010000,
0x00000801,
0x04010801,
0x00010001,
0x04010800,
0x04000800,
0x00010801,
0x04010801,
0x00010001,
0x04000001,
0x00000000,
0x04000000,
0x00000801,
0x00010000,
0x04010001,
0x00000800,
0x04000000,
0x00010801,
0x04000801,
0x04010800,
0x00000800,
0x00000000,
0x04000001,
0x00000001,
0x04010801,
0x00010800,
0x04010000,
0x04010001,
0x00010000,
0x00000801,
0x04000800,
0x04000801,
0x00000001,
0x04010000,
0x00010800,
}
var LUT_B0 = []int64{
0x00000400,
0x00000020,
0x00100020,
0x40100000,
0x40100420,
0x40000400,
0x00000420,
0x00000000,
0x00100000,
0x40100020,
0x40000020,
0x00100400,
0x40000000,
0x00100420,
0x00100400,
0x40000020,
0x40100020,
0x00000400,
0x40000400,
0x40100420,
0x00000000,
0x00100020,
0x40100000,
0x00000420,
0x40100400,
0x40000420,
0x00100420,
0x40000000,
0x40000420,
0x40100400,
0x00000020,
0x00100000,
0x40000420,
0x00100400,
0x40100400,
0x40000020,
0x00000400,
0x00000020,
0x00100000,
0x40100400,
0x40100020,
0x40000420,
0x00000420,
0x00000000,
0x00000020,
0x40100000,
0x40000000,
0x00100020,
0x00000000,
0x40100020,
0x00100020,
0x00000420,
0x40000020,
0x00000400,
0x40100420,
0x00100000,
0x00100420,
0x40000000,
0x40000400,
0x40100420,
0x40100000,
0x00100420,
0x00100400,
0x40000400,
}
var LUT_B1 = []int64{
0x00800000,
0x00001000,
0x00000040,
0x00801042,
0x00801002,
0x00800040,
0x00001042,
0x00801000,
0x00001000,
0x00000002,
0x00800002,
0x00001040,
0x00800042,
0x00801002,
0x00801040,
0x00000000,
0x00001040,
0x00800000,
0x00001002,
0x00000042,
0x00800040,
0x00001042,
0x00000000,
0x00800002,
0x00000002,
0x00800042,
0x00801042,
0x00001002,
0x00801000,
0x00000040,
0x00000042,
0x00801040,
0x00801040,
0x00800042,
0x00001002,
0x00801000,
0x00001000,
0x00000002,
0x00800002,
0x00800040,
0x00800000,
0x00001040,
0x00801042,
0x00000000,
0x00001042,
0x00800000,
0x00000040,
0x00001002,
0x00800042,
0x00000040,
0x00000000,
0x00801042,
0x00801002,
0x00801040,
0x00000042,
0x00001000,
0x00001040,
0x00801002,
0x00800040,
0x00000042,
0x00000002,
0x00001042,
0x00801000,
0x00800002,
}
var LUT_B2 = []int64{
0x10400000,
0x00404010,
0x00000010,
0x10400010,
0x10004000,
0x00400000,
0x10400010,
0x00004010,
0x00400010,
0x00004000,
0x00404000,
0x10000000,
0x10404010,
0x10000010,
0x10000000,
0x10404000,
0x00000000,
0x10004000,
0x00404010,
0x00000010,
0x10000010,
0x10404010,
0x00004000,
0x10400000,
0x10404000,
0x00400010,
0x10004010,
0x00404000,
0x00004010,
0x00000000,
0x00400000,
0x10004010,
0x00404010,
0x00000010,
0x10000000,
0x00004000,
0x10000010,
0x10004000,
0x00404000,
0x10400010,
0x00000000,
0x00404010,
0x00004010,
0x10404000,
0x10004000,
0x00400000,
0x10404010,
0x10000000,
0x10004010,
0x10400000,
0x00400000,
0x10404010,
0x00004000,
0x00400010,
0x10400010,
0x00004010,
0x00400010,
0x00000000,
0x10404000,
0x10000010,
0x10400000,
0x10004010,
0x00000010,
0x00404000,
}
var LUT_B3 = []int64{
0x00208080,
0x00008000,
0x20200000,
0x20208080,
0x00200000,
0x20008080,
0x20008000,
0x20200000,
0x20008080,
0x00208080,
0x00208000,
0x20000080,
0x20200080,
0x00200000,
0x00000000,
0x20008000,
0x00008000,
0x20000000,
0x00200080,
0x00008080,
0x20208080,
0x00208000,
0x20000080,
0x00200080,
0x20000000,
0x00000080,
0x00008080,
0x20208000,
0x00000080,
0x20200080,
0x20208000,
0x00000000,
0x00000000,
0x20208080,
0x00200080,
0x20008000,
0x00208080,
0x00008000,
0x20000080,
0x00200080,
0x20208000,
0x00000080,
0x00008080,
0x20200000,
0x20008080,
0x20000000,
0x20200000,
0x00208000,
0x20208080,
0x00008080,
0x00208000,
0x20200080,
0x00200000,
0x20000080,
0x20008000,
0x00000000,
0x00008000,
0x00200000,
0x20200080,
0x00208080,
0x20000000,
0x20208000,
0x00000080,
0x20008080,
}
var VALID_CHARS = "0123456789ABCDEFGHJKLMNPRSTUWXYZ"
var CONV_CHARS = map[string]string{
"I": "1",
"O": "0",
}
func __typeFromCardId(cardid string) int64 {
upper := strings.ToUpper(cardid[:2])
if upper == "E0" {
return 1
}
if upper == "01" {
return 2
}
return 0
}
func __checksum(data []int64) int64 {
checksum := int64(0)
for i := int64(0); i < 15; i++ {
checksum += ((i % 3) + 1) * data[i]
}
for checksum >= 0x20 {
checksum = (checksum & 0x1f) + (checksum >> 5)
}
return checksum
}
func __ror(val, amount int64) int64 {
return ((val << (32 - amount)) & 0xffffffff) | ((val >> amount) & 0xffffffff)
}
func __operatorA(off, state int64) int64 {
v3 := (state >> 32) & 0xffffffff
v4 := state & 0xffffffff
for i := int64(0); i < 32; i += 4 {
v20 := __ror(v3^KEY[off+i+1], 28)
v4 ^=
LUT_B0[(v20>>26)&0x3f] ^
LUT_B1[(v20>>18)&0x3f] ^
LUT_B2[(v20>>10)&0x3f] ^
LUT_B3[(v20>>2)&0x3f] ^
LUT_A0[((v3^KEY[off+i])>>26)&0x3f] ^
LUT_A1[((v3^KEY[off+i])>>18)&0x3f] ^
LUT_A2[((v3^KEY[off+i])>>10)&0x3f] ^
LUT_A3[((v3^KEY[off+i])>>2)&0x3f]
v21 := __ror(v4^KEY[off+i+3], 28)
v3 ^=
LUT_B0[(v21>>26)&0x3f] ^
LUT_B1[(v21>>18)&0x3f] ^
LUT_B2[(v21>>10)&0x3f] ^
LUT_B3[(v21>>2)&0x3f] ^
LUT_A0[((v4^KEY[off+i+2])>>26)&0x3f] ^
LUT_A1[((v4^KEY[off+i+2])>>18)&0x3f] ^
LUT_A2[((v4^KEY[off+i+2])>>10)&0x3f] ^
LUT_A3[((v4^KEY[off+i+2])>>2)&0x3f]
}
return ((v3 & 0xffffffff) << 32) | (v4 & 0xffffffff)
}
func __operatorB(off, state int64) int64 {
v3 := (state >> 32) & 0xffffffff
v4 := state & 0xffffffff
for i := int64(0); i < 32; i += 4 {
v20 := __ror(v3^KEY[off+31-i], 28)
v4 ^=
LUT_A0[((v3^KEY[off+30-i])>>26)&0x3f] ^
LUT_A1[((v3^KEY[off+30-i])>>18)&0x3f] ^
LUT_A2[((v3^KEY[off+30-i])>>10)&0x3f] ^
LUT_A3[((v3^KEY[off+30-i])>>2)&0x3f] ^
LUT_B0[(v20>>26)&0x3f] ^
LUT_B1[(v20>>18)&0x3f] ^
LUT_B2[(v20>>10)&0x3f] ^
LUT_B3[(v20>>2)&0x3f]
v21 := __ror(v4^KEY[off+29-i], 28)
v3 ^=
LUT_A0[((v4^KEY[off+28-i])>>26)&0x3f] ^
LUT_A1[((v4^KEY[off+28-i])>>18)&0x3f] ^
LUT_A2[((v4^KEY[off+28-i])>>10)&0x3f] ^
LUT_A3[((v4^KEY[off+28-i])>>2)&0x3f] ^
LUT_B0[(v21>>26)&0x3f] ^
LUT_B1[(v21>>18)&0x3f] ^
LUT_B2[(v21>>10)&0x3f] ^
LUT_B3[(v21>>2)&0x3f]
}
return ((v3 & 0xffffffff) << 32) | (v4 & 0xffffffff)
}
func __toInt64(data []int64) int64 {
inX :=
(data[0] & 0xff) |
((data[1] & 0xff) << 8) |
((data[2] & 0xff) << 16) |
((data[3] & 0xff) << 24)
inY :=
(data[4] & 0xff) |
((data[5] & 0xff) << 8) |
((data[6] & 0xff) << 16) |
((data[7] & 0xff) << 24)
v7 := ((((inX ^ (inY >> 4)) & 0xf0f0f0f) << 4) ^ inY) & 0xffffffff
v8 := (((inX ^ (inY >> 4)) & 0xf0f0f0f) ^ inX) & 0xffffffff
v9 := (v7 ^ (v8 >> 16)) & 0x0000ffff
v10 := (((v7 ^ (v8 >> 16)) << 16) ^ v8) & 0xffffffff
v11 := (v9 ^ v7) & 0xffffffff
v12 := (v10 ^ (v11 >> 2)) & 0x33333333
v13 := (v11 ^ (v12 << 2)) & 0xffffffff
v14 := (v12 ^ v10) & 0xffffffff
v15 := (v13 ^ (v14 >> 8)) & 0x00ff00ff
v16 := (v14 ^ (v15 << 8)) & 0xffffffff
v17 := __ror(v15^v13, 1)
v18 := (v16 ^ v17) & 0x55555555
v3 := __ror(v18^v16, 1)
v4 := (v18 ^ v17) & 0xffffffff
return ((v3 & 0xffffffff) << (32)) | (v4 & 0xffffffff)
}
func __fromInt64(data []int64, state int64) []int64 {
v3 := (state >> 32) & 0xffffffff
v4 := state & 0xffffffff
v22 := __ror(v4, 31)
v23 := (v3 ^ v22) & 0x55555555
v24 := (v23 ^ v22) & 0xffffffff
v25 := __ror(v23^v3, 31)
v26 := (v25 ^ (v24 >> 8)) & 0x00ff00ff
v27 := (v24 ^ (v26 << 8)) & 0xffffffff
v28 := (v26 ^ v25) & 0xffffffff
v29 := ((v28 >> 2) ^ v27) & 0x33333333
v30 := ((v29 << 2) ^ v28) & 0xffffffff
v31 := (v29 ^ v27) & 0xffffffff
v32 := (v30 ^ (v31 >> 16)) & 0x0000ffff
v33 := (v31 ^ (v32 << 16)) & 0xffffffff
v34 := (v32 ^ v30) & 0xffffffff
v35 := (v33 ^ (v34 >> 4)) & 0xf0f0f0f
outY := ((v35 << 4) ^ v34) & 0xffffffff
outX := (v35 ^ v33) & 0xffffffff
data[0] = outX & 0xff
data[1] = (outX >> 8) & 0xff
data[2] = (outX >> 16) & 0xff
data[3] = (outX >> 24) & 0xff
data[4] = outY & 0xff
data[5] = (outY >> 8) & 0xff
data[6] = (outY >> 16) & 0xff
data[7] = (outY >> 24) & 0xff
return data
}
func __int64ArrayToByteArray(inp []int64) []byte {
out := make([]byte, len(inp))
for i := 0; i < len(out); i++ {
out[i] = byte(inp[i])
}
return out
}
func __byteArrayToInt64Array(inp []byte) []int64 {
out := make([]int64, len(inp))
for i := 0; i < len(out); i++ {
out[i] = int64(inp[i])
}
return out
}
func __int64ArrayReverse(inp []int64) []int64 {
for i, j := 0, len(inp)-1; i < j; i, j = i+1, j-1 {
inp[i], inp[j] = inp[j], inp[i]
}
return inp
}
func __encode(intInt64s []int64) []int64 {
if len(intInt64s) != 8 {
return make([]int64, 8)
}
inp := intInt64s
out := make([]int64, 8)
out = __fromInt64(out, __operatorA(0x00, __toInt64(inp)))
out = __fromInt64(out, __operatorB(0x20, __toInt64(out)))
out = __fromInt64(out, __operatorA(0x40, __toInt64(out)))
return out
}
func __decode(inInt64s []int64) []int64 {
if len(inInt64s) != 8 {
return make([]int64, 8)
}
inp := inInt64s
out := make([]int64, 8)
out = __fromInt64(out, __operatorB(0x40, __toInt64(inp)))
out = __fromInt64(out, __operatorA(0x20, __toInt64(out)))
out = __fromInt64(out, __operatorB(0x00, __toInt64(out)))
return out
}
func encode(cardId string) string {
if len(cardId) != 16 {
return ""
}
cardBytes, err := hex.DecodeString(cardId)
cardint64s := __byteArrayToInt64Array(cardBytes)
if err != nil {
return ""
}
reverse := __int64ArrayReverse(cardint64s)
ciphered := __encode(reverse)
bits := make([]int64, 65)
for i := 0; i < 64; i++ {
bits[i] = (ciphered[i>>3] >> (^i & 7)) & 1
}
groups := make([]int64, 16)
for i := 0; i < 13; i++ {
groups[i] =
(bits[i*5] << 4) |
(bits[i*5+1] << 3) |
(bits[i*5+2] << 2) |
(bits[i*5+3] << 1) |
(bits[i*5+4] << 0)
}
groups[13] = 1
groups[0] ^= __typeFromCardId(cardId)
for i := 0; i < 14; i++ {
index := i - 1
if index < 0 {
index = len(groups) + (i % len(groups)) - 1
}
groups[i] ^= groups[index]
}
groups[14] = __typeFromCardId(cardId)
groups[15] = __checksum(groups)
final := ""
for _, i := range groups {
final += string(VALID_CHARS[i])
}
return final
}
func decode(cardId string) string {
cardId = strings.ReplaceAll(cardId, " ", "")
cardId = strings.ReplaceAll(cardId, "-", "")
cardId = strings.ToUpper(cardId)
for o, n := range CONV_CHARS {
cardId = strings.ReplaceAll(cardId, o, n)
}
if len(cardId) != 16 {
return ""
}
for _, c := range cardId {
if !strings.Contains(cardId, string(c)) {
return ""
}
}
groups := make([]int64, 16)
for i := 0; i < 16; i++ {
for j := int64(0); j < 32; j++ {
if cardId[i] == VALID_CHARS[j] {
groups[i] = j
break
}
}
}
if groups[14] != 1 && groups[14] != 2 {
return ""
}
if groups[15] != __checksum(groups) {
return ""
}
for i := 13; i > 0; i-- {
groups[i] ^= groups[i-1]
}
groups[0] ^= groups[14]
bits := make([]int64, 64)
for i := 0; i < 64; i++ {
bits[i] = (groups[i/5] >> (4 - (i % 5))) & 1
}
ciphered := make([]int64, 8)
for i := 0; i < 64; i++ {
ciphered[i/8] |= bits[i] << (^i & 7)
}
deciphered := __decode(ciphered)
reverse := __int64ArrayReverse(deciphered)
final := strings.ToUpper(hex.EncodeToString(__int64ArrayToByteArray(reverse)))
return final
}
func jsEncode(_ js.Value, inputs []js.Value) interface{} {
callback := inputs[len(inputs)-1:][0]
inp := inputs[0].String()
return callback.Invoke(encode(inp))
}
func jsDecode(_ js.Value, inputs []js.Value) interface{} {
callback := inputs[len(inputs)-1:][0]
inp := inputs[0].String()
return callback.Invoke(decode(inp))
}
func main() {
c := make(chan bool)
js.Global().Set("KONAMI_CARD_ENCODE", js.FuncOf(jsEncode))
js.Global().Set("KONAMI_CARD_DECODE", js.FuncOf(jsDecode))
<-c
}