Repository navigation
Expand file tree
/
Copy pathpseudo-shuffle.ts
More file actions
126 lines (115 loc) · 2.97 KB
/
Copy pathpseudo-shuffle.ts
File metadata and controls
126 lines (115 loc) · 2.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import fe1 from "node-fe1-fpe";
export interface IPsuedoShuffleOption {
/**
* The starting value of the shuffleable range.
*/
min: number;
/**
* The ending value of the shuffleable range.
*
* Algorithm can be applied only when the difference
* between the min and max values is at least 4.
*/
max: number;
/**
* The index value to be shuffled.
*/
index: number;
/**
* The private key used to encrypt the index value.
*
* If not specified, the default value is used.
* (**Default value:** `psuedo-shuffle`)
*/
privateKey?: string;
/**
* The public key used to encrypt the index value.
*
* If not specified, the default value is used.
* (**Default value:** `psuedo-shuffle`)
*/
publicKey?: string;
}
const defaultKey = "psuedo-shuffle";
export const encode = ({
index,
min,
max,
privateKey,
publicKey,
}: IPsuedoShuffleOption): number => {
// Algorithm can be applied only when the difference
// between the min and max values is at least 4.
if (max - min < 3) return index;
// Algorithms can only be applied when the
// range difference between min and max is prime number.
// Therefore, when the range difference is not prime number,
// the algorithm is applied while leaving the last index intact.
// if ((max - min) % 2 === 0) {
// if (index === max) return index
// --max
// }
if ((max - min) % 2 === 0) {
const middle = Math.ceil(min + (max - min) / 2);
if (index === middle) return max;
if (index === max) index = middle;
--max;
}
// Algorithm does not apply to index
// values that are not in the range.
if (index < min || index > max) return index;
return (
fe1.encrypt(
max - min + 1,
index - min,
privateKey ?? defaultKey,
publicKey ?? defaultKey
) + min
);
};
export const decode = ({
index,
min,
max,
privateKey,
publicKey,
}: IPsuedoShuffleOption): number => {
// Algorithm can be applied only when the difference
// between the min and max values is at least 4.
if (max - min < 3) return index;
// Algorithms can only be applied when the
// range difference between min and max is prime number.
// Therefore, when the range difference is not prime number,
// the algorithm is applied while leaving the last index intact.
const isNonPrime = (max - min) % 2 === 0;
if (isNonPrime) {
if (index > max - 1) {
return Math.ceil(min + (max - min) / 2);
}
--max;
}
// Algorithm does not apply to index
// values that are not in the range.
if (index < min || index > max) return index;
if (isNonPrime) {
if (
index ===
encode({
index: Math.ceil(min + (max - min) / 2),
max,
min,
privateKey: privateKey ?? defaultKey,
publicKey: publicKey ?? defaultKey,
})
)
return max + 1;
}
return (
fe1.decrypt(
max - min + 1,
index - min,
privateKey ?? defaultKey,
publicKey ?? defaultKey
) + min
);
};