在过去的几个月里,我一直在努力、离开和回到这个代码挑战,每次回来我都是从头开始,因为我真的不知道当时我的想法在哪里,是否是正确的轨道。
挑战的基本前提是要破解一个 32 位的密码,你要编写一个函数,该函数将提供一个“登录”函数作为参数,它会根据密码是否正确返回 true 或 false正确的。
使用 32 位数字任意暴力破解密码显然不是一种选择。但是,对登录功能的少量调查表明它容易受到定时攻击,它使用迭代字符串比较,当它遇到不正确的字符时会短路。
所以到目前为止我的方法是初始化一组数字代码,并运行一个循环,在这个循环中,我平均尝试使用该代码登录数千次(当前为 10,000,但该数字是任意选择的),然后对代码的平均值,并从该迭代中表现最好的代码生成新代码。
我有一个相当大的问题,即我永远不会丢弃任何代码,以防性能最佳的代码不在正确的路径上,并且只是因为执行时间中的一些噪音而成为最好的。平均值中的噪声本身就是一个问题,我认为通过平均几千个,我可以解释任何给定函数执行时的噪声,但是当查看各种迭代的结果时,我可以看到不正确的代码有时仍然会异常长。
显然,我的解决方案太慢了,无法通过挑战,我正在寻找有关如何提高其准确性和效率的建议。到目前为止,这是我的代码:
// Function that runs the login function on a given code a few thousand times and creates an average
const loginTime = (code, login) => {
const timeBefore = process.hrtime();
for (let i = 0; i < 10001; i +=1) {
login(code);
}
return process.hrtime(timeBefore)[1] / 10000;
}
// Object to avoid generating duplicate codes
const alreadyGenerated = {};
// Function that generates new codes based on a provided code snippet
const generateCodes = (code) => {
const newCodes = [];
for (let i = 0; i < 10; i += 1) {
const newCode = `${code}${i}`;
if (!alreadyGenerated[newCode]) {
alreadyGenerated[newCode] = true;
newCodes.push(newCode);
}
}
return newCodes;
}
// Function that attempts to crack the password required to login
function crack(login) {
// Initialize
let codes = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
let code = null;
// Loop until code is found
while (!code) {
// Collect time averages for each code
const codeTimes = codes.reduce((acc, code) => {
acc[code] = loginTime(code, login);
return acc;
}, {});
// Sort descending by time
codes.sort((a, b) => codeTimes[b] - codeTimes[a]);
// If the code was found we can stop
if (login(codes[0])) {
code = codes[0];
continue;
}
// Generate new codes based on the best performing code
codes = [...generateCodes(codes[0]), ...codes];
}
// Return
return code;
}
这可能更适合代码审查,但由于它还不是一个完整的解决方案,我不确定。