仅仅是将已有的注册机go语言版本转换为js版本。
go代码来自 www.zzzmode.com/mytools/cha...
代码中大量使用 int32ToInt32 函数主要为了防止数值超出 int32 类型可表示的范围。
1.主函数
ts
import crypto from "crypto";
import { bigIntUnsignedRightShift, byte, int32ToInt32, rotateLeft, transform } from "./utils.js";
import ckCipher from "./ckCipher.js";
function main() {
const name = "charles";
console.log(`name: ${name} key: ${crack(name)}`);
console.log("程序正在运行,按任意键退出...");
process.stdin.setRawMode(true);
process.stdin.resume();
process.stdin.on("data", () => process.exit());
}
function crack(text: string) {
const name = byte(Buffer.from(text, "ascii"));
const length = name.length + 4;
const padded = length + (-length & (8 - 1));
const bs = byte(4);
const _bs = Buffer.from(bs);
_bs.writeUInt32BE(transform(BigInt(name.length), "int64", "uint32"), 0);
bs.set(_bs);
const buff = byte(Buffer.concat([bs, name]));
const ckName = BigInt("0x7a21c951691cd470");
const ckKey = BigInt("-5408575981733630035");
const ck = new ckCipher(ckName);
let outBuff = byte(padded);
for (let i = 0; i < padded; i += 8) {
const bf = buff.subarray(i, i + 8);
let fixBf = byte(0);
if (bf.byteLength < 8) fixBf = byte(8 - bf.byteLength);
const buf = Buffer.concat([Buffer.from(bf), Buffer.from(fixBf)]);
const nowVar = buf.readBigInt64BE() as Int64;
const dd: Int64 = ck.encrypt(nowVar);
outBuff[i] = transform(dd >> 56n, "int64", "uint8");
outBuff[i + 1] = transform(dd >> 48n, "int64", "uint8");
outBuff[i + 2] = transform(dd >> 40n, "int64", "uint8");
outBuff[i + 3] = transform(dd >> 32n, "int64", "uint8");
outBuff[i + 4] = transform(dd >> 24n, "int64", "uint8");
outBuff[i + 5] = transform(dd >> 16n, "int64", "uint8");
outBuff[i + 6] = transform(dd >> 8n, "int64", "uint8");
outBuff[i + 7] = transform(dd, "int64", "uint8");
}
let n = 0 as Int32;
for (const b of outBuff) {
const signedB: Int32 = transform(transform(b, "uint8", "int8"), "int8", "int32");
n = rotateLeft(int32ToInt32(n ^ signedB), 0x3);
}
const prefix: Int32 = int32ToInt32(n ^ 0x54882f8a);
const suffixBuffer = crypto.randomBytes(4);
const suffix: Int32 = suffixBuffer.readInt32LE();
let inVal: Int64 = transform(prefix, "int32", "int64") << 32n;
const s: Int64 = transform(suffix, "int32", "int64");
const suffixHigh: Int32 = suffix >> 16;
if (suffixHigh === 0x0401 || suffixHigh === 0x0402 || suffixHigh === 0x0403) {
inVal |= s;
} else {
inVal |= 0x01000000n | (s & 0xffffffn);
}
const out: Int64 = new ckCipher(ckKey).decrypt(inVal);
let n2: Int64 = 0n;
for (let i = 56; i >= 0; i -= 8) {
n2 ^=
transform(
bigIntUnsignedRightShift(transform(inVal, "int64", "uint64"), BigInt(i)),
"uint64",
"int64"
) & 0xffn;
}
let vv: Int32 = transform(n2 & 0xffn, "int64", "int32");
if (vv < 0) vv = -vv;
return `${vv.toString(16).padStart(2, "0")}${BigInt.asUintN(64, out)
.toString(16)
.padStart(16, "0")}`;
}
main();
2.工具函数
rotateLeft、rotateRight、pkLong 为原来代码中的辅助函数。
transform 函数实现了简单的 int64、uint64、int32、uint32、int8、uint8 数据类型互转功能。
byte、int32ToInt32 为工具函数。
bigIntUnsignedRightShift 函数让 bigint 类型支持无符号右移。
ts
// utils.ts
export function rotateLeft(x: Int32, y: Int32): Int32 {
return int32ToInt32(
int32ToInt32(x << int32ToInt32(y & 31)) |
int32ToInt32(transform(x, "int32", "uint32") >>> int32ToInt32(32 - int32ToInt32(y & 31)))
);
}
export function rotateRight(x: Int32, y: Int32): Int32 {
return int32ToInt32(
int32ToInt32(transform(x, "int32", "uint32") >>> int32ToInt32(y & 31)) |
int32ToInt32(x << int32ToInt32(32 - int32ToInt32(y & 31)))
);
}
export function pkLong(a: Int32, b: Int32): Int64 {
return (BigInt(a) & 0xffffffffn) | (BigInt(b) << 32n);
}
/**数据类型转换
* @param num 要转换的数字
* @param type 转换类型
*/
export function transform(num: Int8, originType: "int8", type: "int8"): Int8;
export function transform(num: Int8, originType: "int8", type: "uint8"): UInt8;
export function transform(num: Int8, originType: "int8", type: "int32"): Int32;
export function transform(num: Int8, originType: "int8", type: "uint32"): UInt32;
export function transform(num: Int8, originType: "int8", type: "int64"): Int64;
export function transform(num: Int8, originType: "int8", type: "uint64"): UInt64;
export function transform(num: UInt8, originType: "uint8", type: "int8"): Int8;
export function transform(num: UInt8, originType: "uint8", type: "uint8"): UInt8;
export function transform(num: UInt8, originType: "uint8", type: "int32"): Int32;
export function transform(num: UInt8, originType: "uint8", type: "uint32"): UInt32;
export function transform(num: UInt8, originType: "uint8", type: "int64"): Int64;
export function transform(num: UInt8, originType: "uint8", type: "uint64"): UInt64;
export function transform(num: Int32, originType: "int32", type: "int8"): Int8;
export function transform(num: Int32, originType: "int32", type: "uint8"): UInt8;
export function transform(num: Int32, originType: "int32", type: "int32"): Int32;
export function transform(num: Int32, originType: "int32", type: "uint32"): UInt32;
export function transform(num: Int32, originType: "int32", type: "int64"): Int64;
export function transform(num: Int32, originType: "int32", type: "uint64"): UInt64;
export function transform(num: UInt32, originType: "uint32", type: "int8"): Int8;
export function transform(num: UInt32, originType: "uint32", type: "uint8"): UInt8;
export function transform(num: UInt32, originType: "uint32", type: "int32"): Int32;
export function transform(num: UInt32, originType: "uint32", type: "uint32"): UInt32;
export function transform(num: UInt32, originType: "uint32", type: "int64"): Int64;
export function transform(num: UInt32, originType: "uint32", type: "uint64"): UInt64;
export function transform(num: Int64, originType: "int64", type: "int8"): Int8;
export function transform(num: Int64, originType: "int64", type: "uint8"): UInt8;
export function transform(num: Int64, originType: "int64", type: "int32"): Int32;
export function transform(num: Int64, originType: "int64", type: "uint32"): UInt32;
export function transform(num: Int64, originType: "int64", type: "int64"): Int64;
export function transform(num: Int64, originType: "int64", type: "uint64"): UInt64;
export function transform(num: UInt64, originType: "uint64", type: "int8"): Int8;
export function transform(num: UInt64, originType: "uint64", type: "uint8"): UInt8;
export function transform(num: UInt64, originType: "uint64", type: "int32"): Int32;
export function transform(num: UInt64, originType: "uint64", type: "uint32"): UInt32;
export function transform(num: UInt64, originType: "uint64", type: "int64"): Int64;
export function transform(num: UInt64, originType: "uint64", type: "uint64"): UInt64;
export function transform(
num: Int8 | UInt8 | Int32 | UInt32 | Int64 | UInt64,
originType: "int8" | "uint8" | "int32" | "uint32" | "int64" | "uint64",
type: "int8" | "uint8" | "int32" | "uint32" | "int64" | "uint64"
): Int8 | UInt8 | Int32 | UInt32 | Int64 | UInt64 | undefined {
const buffer = Buffer.alloc(8);
if (originType === "int8" || originType === "int32" || originType === "int64")
buffer.writeBigInt64LE(typeof num === "bigint" ? num : BigInt(num));
else if (originType === "uint8" || originType === "uint32" || originType === "uint64")
buffer.writeBigUInt64LE(typeof num === "bigint" ? num : BigInt(num));
if (type === "int32") return buffer.readInt32LE();
else if (type === "uint32") return buffer.readUInt32LE();
else if (type === "int8") return buffer.readInt8();
else if (type === "uint8") return buffer.readUInt8();
else if (type === "int64") return buffer.readBigInt64LE();
else if (type === "uint64") return buffer.readBigUInt64LE();
}
export function byte(length: number): Uint8Array<ArrayBuffer>;
export function byte(buffer: Buffer<ArrayBuffer>): Uint8Array<ArrayBuffer>;
export function byte(arg: Buffer<ArrayBuffer> | number) {
if (typeof arg === "number") return new Uint8Array(arg);
else if (arg instanceof Buffer) return new Uint8Array(arg);
}
/**bigint类型无符号右移
* @param bigIntValue 要执行无符号右移的 BigInt 值
* @param shiftAmount 右移的位数
*/
export function bigIntUnsignedRightShift(bigIntValue: bigint, shiftAmount: bigint) {
// 将 shiftAmount 转换为 BigInt 类型
const shift = BigInt(shiftAmount);
// 执行右移操作
const result = bigIntValue >> shift;
// 处理负数情况,如果是负数则需要额外处理
if (bigIntValue < 0n) {
// 计算掩码,用于清除高位的符号扩展
const mask = (1n << (64n - shift)) - 1n;
return result & mask;
}
return result;
}
export function int32ToInt32(num: Int32) {
return transform(num, "int32", "int32");
}
3.ckCipher类的封装
ts
// ckCipher.ts
import {
bigIntUnsignedRightShift,
int32ToInt32,
pkLong,
rotateLeft,
rotateRight,
transform,
} from "./utils.js";
export default class ckCipher {
rk: Int32[];
rounds = 12;
roundKeys = 2 * (this.rounds + 1);
constructor(ckKey: bigint) {
this.rk = [this.roundKeys];
const ld = new Int32Array(2);
ld[0] = transform(ckKey, "int64", "int32");
ld[1] = transform(
bigIntUnsignedRightShift(transform(ckKey, "int64", "uint64"), 32n),
"uint64",
"int32"
);
this.rk[0] = -1209970333;
for (let i = 1; i < this.roundKeys; i++) {
this.rk[i] = int32ToInt32(this.rk[i - 1]! + -1640531527);
}
let a = 0;
let b = 0;
let i = 0;
let j = 0;
for (let k = 0; k < 3 * this.roundKeys; k++) {
this.rk[i] = rotateLeft(this.rk[i]! + (a + b), 3);
a = this.rk[i]!;
ld[j] = rotateLeft(ld[j]! + (a + b), a + b);
b = ld[j]!;
i = (i + 1) % this.roundKeys;
j = (j + 1) % 2;
}
}
encrypt(num: Int64): Int64 {
let a: Int32 = transform(
BigInt(transform(num, "int64", "int32") + this.rk[0]!),
"int64",
"int32"
);
let b: Int32 = int32ToInt32(
transform(
bigIntUnsignedRightShift(transform(num, "int64", "uint64"), 32n),
"uint64",
"int32"
) + this.rk[1]!
);
for (let r = 1; r <= this.rounds; r++) {
a = int32ToInt32(rotateLeft(int32ToInt32(a ^ b), b) + this.rk[2 * r]!);
b = int32ToInt32(rotateLeft(int32ToInt32(b ^ a), a) + this.rk[2 * r + 1]!);
}
return pkLong(a, b);
}
decrypt(num: Int64): Int64 {
let a: Int32 = transform(num, "int64", "int32");
let b: Int32 = transform(
bigIntUnsignedRightShift(transform(num, "int64", "uint64"), 32n),
"uint64",
"int32"
);
for (let i = this.rounds; i > 0; i--) {
b = int32ToInt32(rotateRight(int32ToInt32(b - this.rk[2 * i + 1]!), a) ^ a);
a = int32ToInt32(rotateRight(int32ToInt32(a - this.rk[2 * i]!), b) ^ b);
}
a = int32ToInt32(a - this.rk[0]!);
b = int32ToInt32(b - this.rk[1]!);
return pkLong(a, b);
}
}
4.其他
类型别名
ts
type Int32 = number;
type Int64 = bigint;
type UInt32 = number;
type UInt64 = bigint;
type Int8 = number;
type UInt8 = number;