It seems to be XOR
'ed with number 5
const data = "64 67 66 61 60 63 62 6D 6C 6F 6E 69 68 6B 6A 75 74 77 76 71 70 73 72 7D 7C 7F";
console.log(data.split(" ").map(n => String.fromCharCode(parseInt(n, 16) ^ 5)).join(""));
Knowing the expected result, we can compare existing number with expected to see the difference and find a pattern.
Let's compare first number 64
with letter a
(61) in binary:
0x64 = 01100100
0x61 = 01100001
now the second number 67
with letter b
(62):
0x67 = 01100111
0x62 = 01100010
and third number 66
with letter c
(63):
0x66 = 01100110
0x63 = 01100011
If you look closely, you can see that there is a pattern, bit 0 and 2 (bits count from right side) are not matching. So, if we convert binary 00000101
into decimal we'll get number 5
const data = "64 67 66 61 60 63 62 6D 6C 6F 6E 69 68 6B 6A 75 74 77 76 71 70 73 72 7D 7C 7F";
data.split(" ").forEach((n,i) =>
{
const number = parseInt(n, 16),
numberExpected = "a".charCodeAt(0) + i,
char = String.fromCharCode(number),
charExpected = String.fromCharCode(numberExpected),
xor = number ^ numberExpected,
result = number ^ xor,
charResult = String.fromCharCode(result);
console.log(`${char} (${n}) | expected: ${charExpected} (${numberExpected.toString(16)}) | XOR difference: ${xor} | result: ${charResult}`);
});
.as-console-wrapper{top:0;max-height:unset!important;overflow:auto!important;}