@vGrabko99
html, css, js, php, golang, mysql

Безопасно ли это?

Пару дней назад на хабре написали

Можно внедрить растяжение пароля, это позволяет ещё больше затруднить брутфорс-атаки. Растяжение представляет собой итеративный, или рекурсивный, алгоритм, который раз за разом вычисляет хэш самого себя, десятки тысяч раз (а то и более).


Я подумал что для очень неэффективного брутфорса необходимо делать хеши со скоростью 1секунда +
Вот за вечер накидал пакет
package password

import (
	"crypto/rand"
	mt "math/rand"

	"crypto/md5"
	"crypto/sha256"
	"crypto/sha512"

	"encoding/base64"
	"encoding/hex"

	"io"
	"strconv"
	"strings"
)

const (
	saltSize            = 16
	delmiter            = "$$$$$$$$$$$$#######$$$$$$$$$$"
	stretching_password = 500
	salt_local_secret   = "ahfw*&TGdsfnbi*^Wt"
)

func Hash(pass string) (string, error) {

	salt_secret, err := salt_secret()
	if err != nil {
		return "", err
	}

	salt, err := salt(salt_local_secret + salt_secret)
	if err != nil {
		return "", err
	}

	interation := randInt(1, 20)

	hash, err := hash(pass, salt_secret, salt, int64(interation))
	if err != nil {
		return "", err
	}
	interation_string := strconv.Itoa(interation)
	return salt_secret + delmiter + interation_string + delmiter + hash + delmiter + salt, nil

}

func Verify(hashing string, pass string) (bool, error) {
	data := trim_salt_hash(hashing)

	interation, _ := strconv.ParseInt(data["interation_string"], 10, 64)

	has, err := hash(pass, data["salt_secret"], data["salt"], int64(interation))
	if err != nil {
		return false, err
	}

	if data["salt_secret"]+delmiter+data["interation_string"]+delmiter+has+delmiter+data["salt"] == hashing {
		return true, nil
	} else {
		return false, nil
	}

}

func hash(pass string, salt_secret string, salt string, interation int64) (string, error) {
	var pass_salt string = salt_secret + pass + salt + salt_secret + pass + salt + pass + pass + salt
	var i int

	hash_pass := salt_local_secret
	hash_start := sha512.New()
	hash_center := sha256.New()
	hash_output := sha256.New224()

	i = 0
	for i <= stretching_password {
		i = i + 1
		hash_start.Write([]byte(pass_salt + hash_pass))
		hash_pass = hex.EncodeToString(hash_start.Sum(nil))
	}

	i = 0
	for int64(i) <= interation {
		i = i + 1
		hash_pass = hash_pass + hash_pass
	}

	i = 0
	for i <= stretching_password {
		i = i + 1
		hash_center.Write([]byte(hash_pass + salt_secret))
		hash_pass = hex.EncodeToString(hash_center.Sum(nil))
	}
	hash_output.Write([]byte(hash_pass + salt_local_secret))
	hash_pass = hex.EncodeToString(hash_output.Sum(nil))

	return hash_pass, nil
}

func trim_salt_hash(hash string) map[string]string {
	str := strings.Split(hash, delmiter)
	return map[string]string{
		"salt_secret":       str[0],
		"interation_string": str[1],
		"hash":              str[2],
		"salt":              str[3],
	}
}
func salt(secret string) (string, error) {

	buf := make([]byte, saltSize, saltSize+md5.Size)
	_, err := io.ReadFull(rand.Reader, buf)
	if err != nil {
		return "", err
	}

	hash := md5.New()
	hash.Write(buf)
	hash.Write([]byte(secret))
	return hex.EncodeToString(hash.Sum(buf)), nil
}

func salt_secret() (string, error) {
	rb := make([]byte, randInt(10, 100))
	_, err := rand.Read(rb)
	if err != nil {
		return "", err
	}

	return base64.URLEncoding.EncodeToString(rb), nil
}

func randInt(min int, max int) int {
	return min + mt.Intn(max-min)
}


Стоит ли такое вообще использовать на проде ?
UPD.
Библиотека хранит соль и т.д. сама. Вам об этом беспокоиться не надо. Так что вполне заслуживает на аналог пхп password_hash
  • Вопрос задан
  • 524 просмотра
Решения вопроса 2
Denormalization
@Denormalization
Зачем велосипедить, когда есть https://godoc.org/golang.org/x/crypto/bcrypt ? Сложность настраивается в параметрах.
Ответ написан
Комментировать
sim3x
@sim3x
Нет, не безопасно
Хеш от хеша не увеличивает сложность перебора
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы