Sobes.tech
Назад к вопросам
Senior
10

Условие У нас есть база данных с паролями пользователей, пароли захешированы (функция hashPassword), а так же известен набор символов которые могут быть использованы в паролях (переменная alphabet). Наша задача реализовать функцию RecoverPassword так, чтобы она восстанавливала пароль по известному хэшу и TestRecoverPassword завершился успешно Базовые требования: Решить как угодно 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 range tests { h := hashPassword(exp) act := RecoverPassword(h) if act != exp { fmt.Printf("Ошибка: ожидалось %q, получено %q\n", exp, act) ok = false } } if ok { fmt.Println("Все тесты пройдены успешно") } }

Компании, где спрашивали
Ozon ФинтехOzon Финтех

Ответ от нейросети

sobes.tech 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 символов из заданного алфавита и сравнивает их хэш с заданным. При совпадении возвращает найденный пароль.

Важно: такой перебор работает только при небольшом размере алфавита и ограниченной длине пароля, иначе время выполнения будет экспоненциально расти.