1
0
mirror of https://github.com/kamyu1537/eamuse-card-wasm.git synced 2024-11-14 07:37:36 +01:00

🎉 첫 커밋!

This commit is contained in:
Byeon seongun 2020-04-04 15:23:47 +09:00
commit 2e6cdbc344
6 changed files with 1633 additions and 0 deletions

8
.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
# JetBrains
/.idea
# Node.JS
/node_modules
# Build
/build/konami-card.wasm

24
build/konami-card.js Normal file
View File

@ -0,0 +1,24 @@
require('./wasm_exec');
const go = new Go();
const path = require('path').join(__dirname, 'konami-card.wasm');
const bytes = require('fs').readFileSync(path);
const wasmModule = new WebAssembly.Module(bytes);
const wasmInstance = new WebAssembly.Instance(wasmModule, go.importObject);
go.run(wasmInstance).then();
module.exports.encode = function (nfcId) {
return new Promise(resolve => {
KONAMI_CARD_ENCODE(nfcId, function (result) {
resolve(result)
})
})
};
module.exports.decode = function (cardId) {
return new Promise(resolve => {
KONAMI_CARD_DECODE(cardId, function (result) {
resolve(result)
})
})
};

559
build/wasm_exec.js Normal file
View File

@ -0,0 +1,559 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
(() => {
// Map multiple JavaScript environments to a single common API,
// preferring web standards over Node.js API.
//
// Environments considered:
// - Browsers
// - Node.js
// - Electron
// - Parcel
if (typeof global !== 'undefined') {
// global already exists
} else if (typeof window !== 'undefined') {
window.global = window;
} else if (typeof self !== 'undefined') {
self.global = self;
} else {
throw new Error(
'cannot export Go (neither global, window nor self is defined)'
);
}
if (!global.require && typeof require !== 'undefined') {
global.require = require;
}
if (!global.fs && global.require) {
global.fs = require('fs');
}
if (!global.fs) {
let outputBuf = '';
global.fs = {
constants: {
O_WRONLY: -1,
O_RDWR: -1,
O_CREAT: -1,
O_TRUNC: -1,
O_APPEND: -1,
O_EXCL: -1,
}, // unused
writeSync(fd, buf) {
outputBuf += decoder.decode(buf);
const nl = outputBuf.lastIndexOf('\n');
if (nl !== -1) {
console.log(outputBuf.substr(0, nl));
outputBuf = outputBuf.substr(nl + 1);
}
return buf.length;
},
write(fd, buf, offset, length, position, callback) {
if (offset !== 0 || length !== buf.length || position !== null) {
throw new Error('not implemented');
}
const n = this.writeSync(fd, buf);
callback(null, n);
},
open(path, flags, mode, callback) {
const err = new Error('not implemented');
err.code = 'ENOSYS';
callback(err);
},
read(fd, buffer, offset, length, position, callback) {
const err = new Error('not implemented');
err.code = 'ENOSYS';
callback(err);
},
fsync(fd, callback) {
callback(null);
},
};
}
if (!global.crypto) {
const nodeCrypto = require('crypto');
global.crypto = {
getRandomValues(b) {
nodeCrypto.randomFillSync(b);
},
};
}
if (!global.performance) {
global.performance = {
now() {
const [sec, nsec] = process.hrtime();
return sec * 1000 + nsec / 1000000;
},
};
}
if (!global.TextEncoder) {
global.TextEncoder = require('util').TextEncoder;
}
if (!global.TextDecoder) {
global.TextDecoder = require('util').TextDecoder;
}
// End of polyfills for common API.
const encoder = new TextEncoder('utf-8');
const decoder = new TextDecoder('utf-8');
global.Go = class {
constructor() {
this.argv = ['js'];
this.env = {};
this.exit = (code) => {
if (code !== 0) {
console.warn('exit code:', code);
}
};
this._exitPromise = new Promise((resolve) => {
this._resolveExitPromise = resolve;
});
this._pendingEvent = null;
this._scheduledTimeouts = new Map();
this._nextCallbackTimeoutID = 1;
const mem = () => {
// The buffer may change when requesting more memory.
return new DataView(this._inst.exports.mem.buffer);
};
const setInt64 = (addr, v) => {
mem().setUint32(addr + 0, v, true);
mem().setUint32(addr + 4, Math.floor(v / 4294967296), true);
};
const getInt64 = (addr) => {
const low = mem().getUint32(addr + 0, true);
const high = mem().getInt32(addr + 4, true);
return low + high * 4294967296;
};
const loadValue = (addr) => {
const f = mem().getFloat64(addr, true);
if (f === 0) {
return undefined;
}
if (!isNaN(f)) {
return f;
}
const id = mem().getUint32(addr, true);
return this._values[id];
};
const storeValue = (addr, v) => {
const nanHead = 0x7ff80000;
if (typeof v === 'number') {
if (isNaN(v)) {
mem().setUint32(addr + 4, nanHead, true);
mem().setUint32(addr, 0, true);
return;
}
if (v === 0) {
mem().setUint32(addr + 4, nanHead, true);
mem().setUint32(addr, 1, true);
return;
}
mem().setFloat64(addr, v, true);
return;
}
switch (v) {
case undefined:
mem().setFloat64(addr, 0, true);
return;
case null:
mem().setUint32(addr + 4, nanHead, true);
mem().setUint32(addr, 2, true);
return;
case true:
mem().setUint32(addr + 4, nanHead, true);
mem().setUint32(addr, 3, true);
return;
case false:
mem().setUint32(addr + 4, nanHead, true);
mem().setUint32(addr, 4, true);
return;
}
let ref = this._refs.get(v);
if (ref === undefined) {
ref = this._values.length;
this._values.push(v);
this._refs.set(v, ref);
}
let typeFlag = 0;
switch (typeof v) {
case 'string':
typeFlag = 1;
break;
case 'symbol':
typeFlag = 2;
break;
case 'function':
typeFlag = 3;
break;
}
mem().setUint32(addr + 4, nanHead | typeFlag, true);
mem().setUint32(addr, ref, true);
};
const loadSlice = (addr) => {
const array = getInt64(addr + 0);
const len = getInt64(addr + 8);
return new Uint8Array(this._inst.exports.mem.buffer, array, len);
};
const loadSliceOfValues = (addr) => {
const array = getInt64(addr + 0);
const len = getInt64(addr + 8);
const a = new Array(len);
for (let i = 0; i < len; i++) {
a[i] = loadValue(array + i * 8);
}
return a;
};
const loadString = (addr) => {
const saddr = getInt64(addr + 0);
const len = getInt64(addr + 8);
return decoder.decode(
new DataView(this._inst.exports.mem.buffer, saddr, len)
);
};
const timeOrigin = Date.now() - performance.now();
this.importObject = {
go: {
// Go's SP does not change as long as no Go code is running. Some operations (e.g. calls, getters and setters)
// may synchronously trigger a Go event handler. This makes Go code get executed in the middle of the imported
// function. A goroutine can switch to a new stack if the current stack is too small (see morestack function).
// This changes the SP, thus we have to update the SP used by the imported function.
// func wasmExit(code int32)
'runtime.wasmExit': (sp) => {
const code = mem().getInt32(sp + 8, true);
this.exited = true;
delete this._inst;
delete this._values;
delete this._refs;
this.exit(code);
},
// func wasmWrite(fd uintptr, p unsafe.Pointer, n int32)
'runtime.wasmWrite': (sp) => {
const fd = getInt64(sp + 8);
const p = getInt64(sp + 16);
const n = mem().getInt32(sp + 24, true);
fs.writeSync(
fd,
new Uint8Array(this._inst.exports.mem.buffer, p, n)
);
},
// func nanotime() int64
'runtime.nanotime': (sp) => {
setInt64(sp + 8, (timeOrigin + performance.now()) * 1000000);
},
// func walltime() (sec int64, nsec int32)
'runtime.walltime': (sp) => {
const msec = new Date().getTime();
setInt64(sp + 8, msec / 1000);
mem().setInt32(sp + 16, (msec % 1000) * 1000000, true);
},
// func scheduleTimeoutEvent(delay int64) int32
'runtime.scheduleTimeoutEvent': (sp) => {
const id = this._nextCallbackTimeoutID;
this._nextCallbackTimeoutID++;
this._scheduledTimeouts.set(
id,
setTimeout(
() => {
this._resume();
while (this._scheduledTimeouts.has(id)) {
// for some reason Go failed to register the timeout event, log and try again
// (temporary workaround for https://github.com/golang/go/issues/28975)
console.warn('scheduleTimeoutEvent: missed timeout event');
this._resume();
}
},
getInt64(sp + 8) + 1 // setTimeout has been seen to fire up to 1 millisecond early
)
);
mem().setInt32(sp + 16, id, true);
},
// func clearTimeoutEvent(id int32)
'runtime.clearTimeoutEvent': (sp) => {
const id = mem().getInt32(sp + 8, true);
clearTimeout(this._scheduledTimeouts.get(id));
this._scheduledTimeouts.delete(id);
},
// func getRandomData(r []byte)
'runtime.getRandomData': (sp) => {
crypto.getRandomValues(loadSlice(sp + 8));
},
// func stringVal(value string) ref
'syscall/js.stringVal': (sp) => {
storeValue(sp + 24, loadString(sp + 8));
},
// func valueGet(v ref, p string) ref
'syscall/js.valueGet': (sp) => {
const result = Reflect.get(loadValue(sp + 8), loadString(sp + 16));
sp = this._inst.exports.getsp(); // see comment above
storeValue(sp + 32, result);
},
// func valueSet(v ref, p string, x ref)
'syscall/js.valueSet': (sp) => {
Reflect.set(
loadValue(sp + 8),
loadString(sp + 16),
loadValue(sp + 32)
);
},
// func valueIndex(v ref, i int) ref
'syscall/js.valueIndex': (sp) => {
storeValue(
sp + 24,
Reflect.get(loadValue(sp + 8), getInt64(sp + 16))
);
},
// valueSetIndex(v ref, i int, x ref)
'syscall/js.valueSetIndex': (sp) => {
Reflect.set(
loadValue(sp + 8),
getInt64(sp + 16),
loadValue(sp + 24)
);
},
// func valueCall(v ref, m string, args []ref) (ref, bool)
'syscall/js.valueCall': (sp) => {
try {
const v = loadValue(sp + 8);
const m = Reflect.get(v, loadString(sp + 16));
const args = loadSliceOfValues(sp + 32);
const result = Reflect.apply(m, v, args);
sp = this._inst.exports.getsp(); // see comment above
storeValue(sp + 56, result);
mem().setUint8(sp + 64, 1);
} catch (err) {
storeValue(sp + 56, err);
mem().setUint8(sp + 64, 0);
}
},
// func valueInvoke(v ref, args []ref) (ref, bool)
'syscall/js.valueInvoke': (sp) => {
try {
const v = loadValue(sp + 8);
const args = loadSliceOfValues(sp + 16);
const result = Reflect.apply(v, undefined, args);
sp = this._inst.exports.getsp(); // see comment above
storeValue(sp + 40, result);
mem().setUint8(sp + 48, 1);
} catch (err) {
storeValue(sp + 40, err);
mem().setUint8(sp + 48, 0);
}
},
// func valueNew(v ref, args []ref) (ref, bool)
'syscall/js.valueNew': (sp) => {
try {
const v = loadValue(sp + 8);
const args = loadSliceOfValues(sp + 16);
const result = Reflect.construct(v, args);
sp = this._inst.exports.getsp(); // see comment above
storeValue(sp + 40, result);
mem().setUint8(sp + 48, 1);
} catch (err) {
storeValue(sp + 40, err);
mem().setUint8(sp + 48, 0);
}
},
// func valueLength(v ref) int
'syscall/js.valueLength': (sp) => {
setInt64(sp + 16, parseInt(loadValue(sp + 8).length));
},
// valuePrepareString(v ref) (ref, int)
'syscall/js.valuePrepareString': (sp) => {
const str = encoder.encode(String(loadValue(sp + 8)));
storeValue(sp + 16, str);
setInt64(sp + 24, str.length);
},
// valueLoadString(v ref, b []byte)
'syscall/js.valueLoadString': (sp) => {
const str = loadValue(sp + 8);
loadSlice(sp + 16).set(str);
},
// func valueInstanceOf(v ref, t ref) bool
'syscall/js.valueInstanceOf': (sp) => {
mem().setUint8(
sp + 24,
loadValue(sp + 8) instanceof loadValue(sp + 16)
);
},
// func copyBytesToGo(dst []byte, src ref) (int, bool)
'syscall/js.copyBytesToGo': (sp) => {
const dst = loadSlice(sp + 8);
const src = loadValue(sp + 32);
if (!(src instanceof Uint8Array)) {
mem().setUint8(sp + 48, 0);
return;
}
const toCopy = src.subarray(0, dst.length);
dst.set(toCopy);
setInt64(sp + 40, toCopy.length);
mem().setUint8(sp + 48, 1);
},
// func copyBytesToJS(dst ref, src []byte) (int, bool)
'syscall/js.copyBytesToJS': (sp) => {
const dst = loadValue(sp + 8);
const src = loadSlice(sp + 16);
if (!(dst instanceof Uint8Array)) {
mem().setUint8(sp + 48, 0);
return;
}
const toCopy = src.subarray(0, dst.length);
dst.set(toCopy);
setInt64(sp + 40, toCopy.length);
mem().setUint8(sp + 48, 1);
},
debug: (value) => {
console.log(value);
},
},
};
}
async run(instance) {
this._inst = instance;
this._values = [NaN, 0, null, true, false, global, this];
this._refs = new Map();
this.exited = false;
const mem = new DataView(this._inst.exports.mem.buffer);
// Pass command line arguments and environment variables to WebAssembly by writing them to the linear memory.
let offset = 4096;
const strPtr = (str) => {
const ptr = offset;
const bytes = encoder.encode(str + '\0');
new Uint8Array(mem.buffer, offset, bytes.length).set(bytes);
offset += bytes.length;
if (offset % 8 !== 0) {
offset += 8 - (offset % 8);
}
return ptr;
};
const argc = this.argv.length;
const argvPtrs = [];
this.argv.forEach((arg) => {
argvPtrs.push(strPtr(arg));
});
const keys = Object.keys(this.env).sort();
argvPtrs.push(keys.length);
keys.forEach((key) => {
argvPtrs.push(strPtr(`${key}=${this.env[key]}`));
});
const argv = offset;
argvPtrs.forEach((ptr) => {
mem.setUint32(offset, ptr, true);
mem.setUint32(offset + 4, 0, true);
offset += 8;
});
this._inst.exports.run(argc, argv);
if (this.exited) {
this._resolveExitPromise();
}
await this._exitPromise;
}
_resume() {
if (this.exited) {
throw new Error('Go program has already exited');
}
this._inst.exports.resume();
if (this.exited) {
this._resolveExitPromise();
}
}
_makeFuncWrapper(id) {
const go = this;
return function () {
const event = { id: id, this: this, args: arguments };
go._pendingEvent = event;
go._resume();
return event.result;
};
}
};
if (
global.require &&
global.require.main === module &&
global.process &&
global.process.versions &&
!global.process.versions.electron
) {
if (process.argv.length < 3) {
console.error('usage: go_js_wasm_exec [wasm binary] [arguments]');
process.exit(1);
}
const go = new Go();
go.argv = process.argv.slice(2);
go.env = Object.assign({ TMPDIR: require('os').tmpdir() }, process.env);
go.exit = process.exit;
WebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject)
.then((result) => {
process.on('exit', (code) => {
// Node.js exits if no event handler is pending
if (code === 0 && !go.exited) {
// deadlock, make Go print error and stack traces
go._pendingEvent = { id: 0 };
go._resume();
}
});
return go.run(result.instance);
})
.catch((err) => {
console.error(err);
process.exit(1);
});
}
})();

18
package.json Normal file
View File

@ -0,0 +1,18 @@
{
"name": "konami-card",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"private": true,
"scripts": {
"build": "cross-env GOOS=js GOARCH=wasm go build -o build/konami-card.wasm src/main.go"
},
"devDependencies": {
"cross-env": "^7.0.2",
"prettier": "^2.0.2"
},
"prettier": {
"semi": true,
"singleQuote": true
}
}

971
src/main.go Normal file
View File

@ -0,0 +1,971 @@
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
}

53
yarn.lock Normal file
View File

@ -0,0 +1,53 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
cross-env@^7.0.2:
version "7.0.2"
resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.2.tgz#bd5ed31339a93a3418ac4f3ca9ca3403082ae5f9"
integrity sha512-KZP/bMEOJEDCkDQAyRhu3RL2ZO/SUVrxQVI0G3YEQ+OLbRA3c6zgixe8Mq8a/z7+HKlNEjo8oiLUs8iRijY2Rw==
dependencies:
cross-spawn "^7.0.1"
cross-spawn@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.1.tgz#0ab56286e0f7c24e153d04cc2aa027e43a9a5d14"
integrity sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==
dependencies:
path-key "^3.1.0"
shebang-command "^2.0.0"
which "^2.0.1"
isexe@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
path-key@^3.1.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
prettier@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.2.tgz#1ba8f3eb92231e769b7fcd7cb73ae1b6b74ade08"
integrity sha512-5xJQIPT8BraI7ZnaDwSbu5zLrB6vvi8hVV58yHQ+QK64qrY40dULy0HSRlQ2/2IdzeBpjhDkqdcFBnFeDEMVdg==
shebang-command@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
dependencies:
shebang-regex "^3.0.0"
shebang-regex@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
which@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
dependencies:
isexe "^2.0.0"