Мне нужно создать функцию сброса пароля без интернета. Мое оборудование использует веб-интерфейс (JS/HTML) и серверную часть PHP. Я видел это раньше: пользователь получает короткий ключ, который он читает ИТ-специалисту, а ИТ-специалист генерирует короткий закрытый ключ ответа. Затем пользователь использует этот ключ и может перейти к экрану смены пароля.
Да, у меня уже есть функция "контрольные вопросы". Это будет для последнего восстановления, например, если ваш последний пользователь-администратор умрет или что-то в этом роде. Кроме того, он не может быть чувствительным ко времени, как стандартный брелок RSA. Некоторые из этих устройств находятся буквально на вершине горы, поэтому у человека может быть значительная задержка между созданием открытого ключа, получением закрытого и установкой его на свое устройство.
Я думал просто взять что-то вроде серийного номера устройства и даты и запустить их через какое-то шифрование, но мне интересно, есть ли у вас, ребята, какой-нибудь более простой способ? Черт, я мог бы зашифровать его так же, как и пароли, но генерируемые строки могут быть... громоздкими. В идеале это может быть строка из 10-12 символов.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Я нашел довольно гладкий способ сделать это. Я взял набор данных ($serial, жестко запрограммированное $seed, $date и $type для типа учетной записи), сделал md5 и зашифровал их с помощью openssl, используя функцию шифрования, которую я нашел в другом ответе, а затем сделал что-то вроде первую половину контрольной суммы, чтобы сжать длинную строку до 1/3 длины. Вы просто запускаете genkey($serial,$seed,$date,$type), чтобы получить красивую короткую строку, такую как «URMYVAFYNE». Человек на другом конце делает то же самое, затем сравнивает строки, чтобы увидеть, совпадают ли они. Затем они генерируют вторую строку, используя первую в качестве $seed, и клиент вводит ее для проверки... ну вы поняли.
function genkey($serial,$seed,$date,$type) {
$fullstring = $serial.$seed.$date.$type;
$md5 = md5($fullstring);
$encrypted = encrypt_decrypt('encrypt',$md5);
return condense(condense($encrypted));
}
function encrypt_decrypt($action, $string)
{
$output = false;
$encrypt_method = "AES-256-CBC";
$secret_key = '[REDACTED]'; //32 byte
$secret_iv = '[REDACTED]'; //16 byte
// hash
$key = hash('sha256', $secret_key);
// iv - encrypt method AES-256-CBC expects 16 bytes
$iv = substr(hash('sha256', $secret_iv), 0, 16);
if ( $action == 'encrypt' ) {
$output = openssl_encrypt($string, $encrypt_method, $key, 0, $iv);
$output = base64_encode($output);
} else if ( $action == 'decrypt' ) {
$output = openssl_decrypt(base64_decode($string), $encrypt_method, $key, 0, $iv);
}
return $output;
}
function condense($str) {
$arr = str_split($str, 3);
$retstr = '';
for($i=0;$i<count($arr);$i++) {
$sum=WordSum($arr[$i]);
$letternum = $sum%26 + 65; //ascii code for capital letter
$letter = chr($letternum);
$retstr .= $letter;
}
return $retstr;
}
Просто помните, если вы используете это, чтобы заменить [УДАЛЕНО] своими собственными строками.
О, и это само собой разумеется, но я получил JS, вызывающий функцию через Ajax.
Конечно, в тот момент, когда я публикую это, я понимаю, что openssl_encrypt() - это вещь. Я попробую это утром и обновлю, если это сделает то, что мне нужно.