Senior
Podmínka Máme databázi uživatelských hesel, hesla jsou hashována (funkce hashPassword), a také je znám soubor znaků, které mohou být použity v heslech (proměnná alphabet). Naším úkolem je implementovat funkci RecoverPassword tak, aby obnovila heslo podle známého hashe a TestRecoverPassword úspěšně proběhl. Základní požadavky: Libovolná metoda je povolena package main import ( "crypto/md5" "fmt" ) var alphabet = []rune{'a', 'b', 'c', 'd', '1', '2', '3'} func RecoverPassword(h []byte) string { return "" } func hashPassword(in string) []byte { h := md5.Sum([]byte(in)) return h[:] } func main() { tests := []string{"a", "12", "abc333d"} ok := true for _, exp := range tests { h := hashPassword(exp) act := RecoverPassword(h) if act != exp { fmt.Printf("Chyba: očekáváno %q, získáno %q\n", exp, act) ok = false } } if ok { fmt.Println("Všechny testy úspěšně prošly") } }
sobes.tech AI
Odpověď od AI
Задача — по известному MD5-хэшу восстановить исходный пароль, используя заданный алфавит. Поскольку MD5 — односторонняя функция, единственный практический способ — перебор всех возможных комбинаций из alphabet, пока не найдём совпадение.
Реализация:
- Перебираем пароли разной длины (например, от 1 до некоторого максимума).
- Для каждой длины генерируем все возможные строки из alphabet.
- Для каждой строки считаем MD5 и сравниваем с заданным хэшем.
- Если совпало — возвращаем найденный пароль.
Пример кода на Go:
package main
import (
"crypto/md5"
"fmt"
)
var alphabet = []rune{'a', 'b', 'c', 'd', '1', '2', '3'}
func hashPassword(in string) []byte {
h := md5.Sum([]byte(in))
return h[:]
}
func RecoverPassword(h []byte) string {
maxLen := 7 // максимальная длина пароля (по условию теста)
var helper func(pos int, current []rune) string
helper = func(pos int, current []rune) string {
if pos == len(current) {
if string(current) != "" && equalSlices(hashPassword(string(current)), h) {
return string(current)
}
return ""
}
for _, c := range alphabet {
current[pos] = c
res := helper(pos+1, current)
if res != "" {
return res
}
}
return ""
}
for length := 1; length <= maxLen; length++ {
res := helper(0, make([]rune, length))
if res != "" {
return res
}
}
return ""
}
func equalSlices(a, b []byte) bool {
if len(a) != len(b) {
return false
}
for i := range a {
if a[i] != b[i] {
return false
}
}
return true
}
func main() {
tests := []string{"a", "12", "abc333d"}
ok := true
for _, exp := range tests {
h := hashPassword(exp)
act := RecoverPassword(h)
if act != exp {
fmt.Printf("Ошибка: ожидалось %q, получено %q\n", exp, act)
ok = false
}
}
if ok {
fmt.Println("Все тесты пройдены успешно")
}
}
Этот код перебирает все варианты паролей длиной от 1 до 7 символов из заданного алфавита и сравнивает их хэш с заданным. При совпадении возвращает найденный пароль.
Важно: такой перебор работает только при небольшом размере алфавита и ограниченной длине пароля, иначе время выполнения будет экспоненциально расти.