이 스레드의 일부 아이디어를 사용하여 JS 코드를 작성했습니다.
const BITS = 32n;
const MAX = 4294967295n;
const COPRIME = 65521n;
const INVERSE = 2166657316n;
const ROT = 6n;
const XOR1 = 10296065n;
const XOR2 = 2426476569n;
function rotRight(n, bits, size) {
const mask = (1n << bits) - 1n;
// console.log('mask',mask.toString(2).padStart(Number(size),'0'));
const left = n & mask;
const right = n >> bits;
return (left << (size - bits)) | right;
}
const pipe = fns => fns.reduce((f, g) => (...args) => g(f(...args)));
function build(...fns) {
const enc = fns.map(f => Array.isArray(f) ? f[0] : f);
const dec = fns.map(f => Array.isArray(f) ? f[1] : f).reverse();
return [
pipe(enc),
pipe(dec),
]
}
[exports.encode, exports.decode] = build(
[BigInt, Number],
[i => (i * COPRIME) % MAX, i => (i * INVERSE) % MAX],
x => x ^ XOR1,
[x => rotRight(x, ROT, BITS), x => rotRight(x, BITS-ROT, BITS)],
x => x ^ XOR2,
);
다음과 같은 멋진 결과가 생성됩니다.
1 1352888202n 1 'mdh37u'
2 480471946n 2 '7y26iy'
3 3634587530n 3 '1o3xtoq'
4 2225300362n 4 '10svwqy'
5 1084456843n 5 'hxno97'
6 212040587n 6 '3i8rkb'
7 3366156171n 7 '1jo4eq3'
8 3030610827n 8 '1e4cia3'
9 1889750920n 9 'v93x54'
10 1017334664n 10 'gtp0g8'
11 4171450248n 11 '1wzknm0'
12 2762163080n 12 '19oiqo8'
13 1621319561n 13 'qtai6h'
14 748903305n 14 'cdvlhl'
15 3903018889n 15 '1sjr8nd'
16 3567473545n 16 '1mzzc7d'
17 2426613641n 17 '144qr2h'
18 1554197390n 18 'ppbudq'
19 413345678n 19 '6u3fke'
20 3299025806n 20 '1ik5klq'
21 2158182286n 21 'zoxc3y'
22 1285766031n 22 'l9iff3'
23 144914319n 23 '2ea0lr'
24 4104336271n 24 '1vvm64v'
25 2963476367n 25 '1d0dkzz'
26 2091060108n 26 'ykyob0'
27 950208396n 27 'fpq9ho'
28 3835888524n 28 '1rfsej0'
29 2695045004n 29 '18kk618'
30 1822628749n 30 'u559cd'
31 681777037n 31 'b9wuj1'
32 346231693n 32 '5q4y31'
테스트 대상 :
const {encode,decode} = require('./obfuscate')
for(let i = 1; i <= 1000; ++i) {
const j = encode(i);
const k = decode(j);
console.log(i, j, k, j.toString(36));
}
XOR1
과 XOR2
0 사이의 무작위 숫자입니다 MAX
. MAX
이다 2**32-1
; 가장 높은 ID가 될 것이라고 생각하는 값으로 설정해야합니다.
COPRIME
는 coprime w / MAX
입니다. 나는 소수 그 자체가 다른 모든 수 (자신의 배수를 제외하고)와 공통점 이라고 생각 합니다.
INVERSE
알아 내기가 까다로운 것입니다. 이 블로그 게시물은 정확한 답변을 제공하지 않지만 WolframAlpha가 알아낼 수 있습니다 . 기본적으로, 단지 방정식 해결하기 (COPRIME * x) % MAX = 1
위한이 x
.
이 build
함수는 이러한 인코딩 / 디코딩 파이프 라인을 더 쉽게 만들 수 있도록 제가 만든 것입니다. [encode, decode]
쌍으로 원하는만큼 작업을 공급할 수 있습니다 . 이러한 기능은 동일하고 반대 여야합니다. XOR
당신이 한 쌍의가 필요하지 않도록 기능은 자신의 칭찬이다.
또 다른 재미있는 혁신이 있습니다 .
function mixHalves(n) {
const mask = 2n**12n-1n;
const right = n & mask;
const left = n >> 12n;
const mix = left ^ right;
return (mix << 12n) | right;
}
(24 비트 정수 가정-다른 크기의 숫자 만 변경)