Herkese merhaba!

Uzun yıllardır bol miktarda kişisel zaman ve enerji harcayarak bilgimizi hepinizle paylaşıyoruz. Ancak şu andan itibaren bu blogu çalışır durumda tutabilmek için yardımınıza ihtiyacımız var. Yapmanız gereken tek şey, sitedeki reklamlardan birine tıklamak olacaktır, aksi takdirde hosting vb. masraflar nedeniyle maalesef yayından kaldırılacaktır. Teşekkürler.

Bu yazı hazırlanırken Argon2 şifreleri karıştırma ve saklama işlemleri için ideal bir yöntemdi. Aşağıdaki örneği kullanarak şifreleri karıştırma ve doğrulama işlemlerini yapabilirsiniz.


Örnek


package main

import (
"crypto/rand"
"crypto/subtle"
"encoding/base64"
"fmt"
"log"
"strings"

"golang.org/x/crypto/argon2"
)

type Argon2ID struct {
format string
version int
time uint32
memory uint32
keyLen uint32
saltLen uint32
threads uint8
}

func main() {
argon2ID := NewArgon2ID()

plain := "inanzzz"

hash1, err := argon2ID.Hash(plain)
if err != nil {
log.Fatal(err)
}
ok1, err := argon2ID.Verify(plain, hash1)
if err != nil {
log.Fatal(err)
}

hash2, err := argon2ID.Hash(plain)
if err != nil {
log.Fatal(err)
}
ok2, err := argon2ID.Verify(plain, hash2)
if err != nil {
log.Fatal(err)
}

hash3, err := argon2ID.Hash(plain)
if err != nil {
log.Fatal(err)
}
ok3, err := argon2ID.Verify(plain, hash3+"uuu")
if err != nil {
log.Fatal(err)
}

fmt.Println("PLAIN:", plain)
fmt.Println("HASH 1:", hash1)
fmt.Println("VALID 1:", ok1)
fmt.Println("HASH 2:", hash2)
fmt.Println("VALID 2:", ok2)
fmt.Println("HASH 3:", hash3)
fmt.Println("VALID 3:", ok3)
}

func NewArgon2ID() Argon2ID {
return Argon2ID{
format: "$argon2id$v=%d$m=%d,t=%d,p=%d$%s$%s",
version: argon2.Version,
time: 1,
memory: 64 * 1024,
keyLen: 32,
saltLen: 16,
threads: 4,
}
}

func (a Argon2ID) Hash(plain string) (string, error) {
salt := make([]byte, a.saltLen)
if _, err := rand.Read(salt); err != nil {
return "", err
}

hash := argon2.IDKey([]byte(plain), salt, a.time, a.memory, a.threads, a.keyLen)

return fmt.Sprintf(
a.format,
a.version,
a.memory,
a.time,
a.threads,
base64.RawStdEncoding.EncodeToString(salt),
base64.RawStdEncoding.EncodeToString(hash),
),
nil
}

func (a Argon2ID) Verify(plain, hash string) (bool, error) {
hashParts := strings.Split(hash, "$")

_, err := fmt.Sscanf(hashParts[3], "m=%d,t=%d,p=%d", &a.memory, &a.time, &a.threads)
if err != nil {
return false, err
}

salt, err := base64.RawStdEncoding.DecodeString(hashParts[4])
if err != nil {
return false, err
}

decodedHash, err := base64.RawStdEncoding.DecodeString(hashParts[5])
if err != nil {
return false, err
}

hashToCompare := argon2.IDKey([]byte(plain), salt, a.time, a.memory, a.threads, uint32(len(decodedHash)))

return subtle.ConstantTimeCompare(decodedHash, hashToCompare) == 1, nil
}

Test


PLAIN: inanzzz
HASH 1: $argon2id$v=19$m=65536,t=1,p=4$3Ymrg20KqXd9mMawXP/YzA$nf7ubeO0tB1NDk4nBscgsHvIcDECMjIuEeEjgBRMe3s
VALID 1: true

HASH 2: $argon2id$v=19$m=65536,t=1,p=4$DneZEKdFvOarVcS5A6WsZA$dmpO4kOSbJr1ZoDWRIG+Bx8wuvpiVp9tQyyNjSwPWYk
VALID 2: true

HASH 3: $argon2id$v=19$m=65536,t=1,p=4$L/6i/DD9Ie5dKo7L6PpvVg$8OLc5G2E715nbsSgA4ZKcGngVLtAeCnB4CD76XbShic
VALID 3: false