diff --git a/README.md b/README.md index c3f3cb0..73c4f51 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # PHC Crypto -[![GitHub release (latest SemVer including pre-releases)](https://img.shields.io/github/v/release/aldy505/phc-crypto?include_prereleases)](https://github.com/aldy505/phc-crypto/releases) [![GitHub](https://img.shields.io/github/license/aldy505/phc-crypto)](https://github.com/aldy505/phc-crypto/blob/master/LICENSE) [![Codecov](https://img.shields.io/codecov/c/gh/aldy505/phc-crypto)](https://www.codecov.io/gh/aldy505/phc-crypto) [![CodeFactor](https://www.codefactor.io/repository/github/aldy505/phc-crypto/badge)](https://www.codefactor.io/repository/github/aldy505/phc-crypto) [![Build test](https://github.com/aldy505/phc-crypto/actions/workflows/build.yml/badge.svg)](https://github.com/aldy505/phc-crypto/actions/workflows/build.yml) [![Build test](https://github.com/aldy505/phc-crypto/actions/workflows/coverage.yml/badge.svg)](https://github.com/aldy505/phc-crypto/actions/workflows/coverage.yml) +[![GitHub release (latest SemVer including pre-releases)](https://img.shields.io/github/v/release/aldy505/phc-crypto?include_prereleases)](https://github.com/aldy505/phc-crypto/releases) [![GitHub](https://img.shields.io/github/license/aldy505/phc-crypto)](https://github.com/aldy505/phc-crypto/blob/master/LICENSE) [![codecov](https://codecov.io/gh/aldy505/phc-crypto/branch/master/graph/badge.svg?token=HUTQURBZ73)](https://codecov.io/gh/aldy505/phc-crypto) [![CodeFactor](https://www.codefactor.io/repository/github/aldy505/phc-crypto/badge)](https://www.codefactor.io/repository/github/aldy505/phc-crypto) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/16c40f49aabe4e89afea7c1e1d90a483)](https://www.codacy.com/gh/aldy505/phc-crypto/dashboard?utm_source=github.com&utm_medium=referral&utm_content=aldy505/phc-crypto&utm_campaign=Badge_Grade) [![Build test](https://github.com/aldy505/phc-crypto/actions/workflows/build.yml/badge.svg)](https://github.com/aldy505/phc-crypto/actions/workflows/build.yml) [![Build test](https://github.com/aldy505/phc-crypto/actions/workflows/coverage.yml/badge.svg)](https://github.com/aldy505/phc-crypto/actions/workflows/coverage.yml) A work in progress. @@ -47,7 +47,7 @@ func main() { * Argon2 (argon2i & argon2id) * Chacha20poly1305 -## Want to contribute? +## Contribute Yes please! I'm still new to Go and I create this module (or package if you will) to help me fulfill a need on my project. Feel free to refactor, add new feature, fix unknown bugs, and have fun! diff --git a/argon2/argon2.go b/argon2/argon2.go index 02649fd..ba2d334 100644 --- a/argon2/argon2.go +++ b/argon2/argon2.go @@ -13,6 +13,7 @@ import ( "golang.org/x/crypto/argon2" ) +// Config initialize the config require to create a hash function type Config struct { Time uint32 Memory uint32 @@ -48,7 +49,7 @@ func Hash(plain string, config Config) (string, error) { } version := argon2.Version hashString := format.Serialize(format.PHCConfig{ - Id: "argon2" + config.Variant, + ID: "argon2" + config.Variant, Version: version, Params: map[string]interface{}{ "m": strconv.Itoa(int(config.Memory)), @@ -63,7 +64,7 @@ func Hash(plain string, config Config) (string, error) { func Verify(hash string, plain string) (bool, error) { deserialize := format.Deserialize(hash) - if strings.HasPrefix(deserialize.Id, "argon2") == false { + if !strings.HasPrefix(deserialize.ID, "argon2") { return false, errors.New("hashed string is not argon instance") } @@ -87,9 +88,9 @@ func Verify(hash string, plain string) (bool, error) { return false, err } - if deserialize.Id == "argon2id" { + if deserialize.ID == "argon2id" { verifyHash = argon2.IDKey([]byte(plain), []byte(deserialize.Salt), uint32(time), uint32(memory), uint8(parallelism), keyLen) - } else if deserialize.Id == "argon2i" { + } else if deserialize.ID == "argon2i" { verifyHash = argon2.Key([]byte(plain), []byte(deserialize.Salt), uint32(time), uint32(memory), uint8(parallelism), keyLen) } diff --git a/bcrypt/bcrypt.go b/bcrypt/bcrypt.go index daf5258..a0c7182 100644 --- a/bcrypt/bcrypt.go +++ b/bcrypt/bcrypt.go @@ -9,6 +9,7 @@ import ( "golang.org/x/crypto/bcrypt" ) +// Config initialize the config require to create a hash function type Config struct { Rounds int } @@ -19,7 +20,7 @@ func Hash(plain string, config Config) (string, error) { } hash, err := bcrypt.GenerateFromPassword([]byte(plain), config.Rounds) hashString := format.Serialize(format.PHCConfig{ - Id: "bcrypt", + ID: "bcrypt", Version: 0, Params: map[string]interface{}{ "r": config.Rounds, @@ -28,14 +29,13 @@ func Hash(plain string, config Config) (string, error) { }) if err != nil { return "", err - } else { - return hashString, nil } + return hashString, nil } func Verify(hash string, plain string) (bool, error) { deserialize := format.Deserialize(hash) - if !strings.HasPrefix(deserialize.Id, "bcrypt") { + if !strings.HasPrefix(deserialize.ID, "bcrypt") { return false, errors.New("hashed string is not a bcrypt instance") } decodedHash, err := hex.DecodeString(deserialize.Hash) @@ -45,7 +45,6 @@ func Verify(hash string, plain string) (bool, error) { err = bcrypt.CompareHashAndPassword(decodedHash, []byte(plain)) if err != nil { return false, nil - } else { - return true, nil } + return true, nil } diff --git a/chacha20poly1305/chacha20poly1305.go b/chacha20poly1305/chacha20poly1305.go index b538774..803d165 100644 --- a/chacha20poly1305/chacha20poly1305.go +++ b/chacha20poly1305/chacha20poly1305.go @@ -31,7 +31,7 @@ func Hash(plain string) (string, error) { Params: map[string]interface{}{ "n": hex.EncodeToString(nonce), }, - Id: "chacha20poly1305", + ID: "chacha20poly1305", }) return hashString, nil } diff --git a/format/format.go b/format/format.go index db489b2..c5bb9f5 100644 --- a/format/format.go +++ b/format/format.go @@ -5,22 +5,26 @@ import ( "strings" ) +// PHCConfig is a struct required for creating a PHC string type PHCConfig struct { - Id string + ID string Version int Params map[string]interface{} Salt string Hash string } +// Serialize converts PHCConfig struct into a PHC string. +// See https://github.com/P-H-C/phc-string-format/blob/master/phc-sf-spec.md func Serialize(config PHCConfig) string { var params []string for key, value := range config.Params { params = append(params, key+"="+strconv.Itoa(value.(int))) } - return "$" + config.Id + "$v=" + strconv.Itoa(config.Version) + "$" + strings.Join(params, ",") + "$" + config.Salt + "$" + config.Hash + return "$" + config.ID + "$v=" + strconv.Itoa(config.Version) + "$" + strings.Join(params, ",") + "$" + config.Salt + "$" + config.Hash } +// Deserialize converts a PHC string into a PHCConfig struct func Deserialize(hash string) PHCConfig { hashArray := strings.Split(hash, "$") params := make(map[string]interface{}) @@ -32,7 +36,7 @@ func Deserialize(hash string) PHCConfig { } version, _ := strconv.Atoi(hashArray[2]) return PHCConfig{ - Id: hashArray[1], + ID: hashArray[1], Version: version, Params: params, Salt: hashArray[4], diff --git a/pbkdf2/pbkdf2.go b/pbkdf2/pbkdf2.go index ff2d496..f918e47 100644 --- a/pbkdf2/pbkdf2.go +++ b/pbkdf2/pbkdf2.go @@ -14,6 +14,7 @@ import ( "golang.org/x/crypto/pbkdf2" ) +// Config initialize the config require to create a hash function type Config struct { Rounds int KeyLen int @@ -53,7 +54,7 @@ func Hash(plain string, config Config) (string, error) { } hashString := format.Serialize(format.PHCConfig{ - Id: "pbkdf2" + config.HashFunc, + ID: "pbkdf2" + config.HashFunc, Params: map[string]interface{}{ "i": config.Rounds, }, diff --git a/phc-crypto.go b/phc-crypto.go index 352d81a..178dabe 100644 --- a/phc-crypto.go +++ b/phc-crypto.go @@ -10,11 +10,13 @@ import ( "github.com/aldy505/phc-crypto/scrypt" ) +// Algo returns struct that will be use on Hash and Verify function type Algo struct { Name string Config *Config } +// Config returns the general config of the hashing function type Config struct { Cost int Rounds int @@ -24,6 +26,7 @@ type Config struct { HashFunc string } +// Use initiates the hash/verify function func Use(name string, config Config) (*Algo, error) { var algo *Algo @@ -41,6 +44,7 @@ func Use(name string, config Config) (*Algo, error) { } } +// Hash returns a PHC formatted string of a hash function (that was initiated from Use) func (a *Algo) Hash(plain string) (hash string, err error) { if a.Name == "scrypt" { hash, err = scrypt.Hash(plain, scrypt.Config{ @@ -74,13 +78,13 @@ func (a *Algo) Hash(plain string) (hash string, err error) { } else if a.Name == "chacha20poly1305" { hash, err = chacha20poly1305.Hash(plain) return - } else { - hash = "" - err = errors.New("the algorithm provided is not supported") - return } + hash = "" + err = errors.New("the algorithm provided is not supported") + return } +// Hash returns a boolean of a hash function (that was initiated from Use) func (a *Algo) Verify(hash, plain string) (bool, error) { return false, nil } diff --git a/scrypt/scrypt.go b/scrypt/scrypt.go index 445ab18..29e839e 100644 --- a/scrypt/scrypt.go +++ b/scrypt/scrypt.go @@ -13,6 +13,7 @@ import ( "golang.org/x/crypto/scrypt" ) +// Config initialize the config require to create a hash function type Config struct { Cost int Rounds int @@ -43,7 +44,7 @@ func Hash(plain string, config Config) (string, error) { } hashString := format.Serialize(format.PHCConfig{ - Id: "scrypt", + ID: "scrypt", Version: 0, Params: map[string]interface{}{ "ln": config.Cost, @@ -59,7 +60,7 @@ func Hash(plain string, config Config) (string, error) { func Verify(hash string, plain string) (bool, error) { deserialize := format.Deserialize(hash) - if !strings.HasPrefix(deserialize.Id, "scrypt") { + if !strings.HasPrefix(deserialize.ID, "scrypt") { return false, errors.New("hashed string is not scrypt instance") }