-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
alexadhy
committed
Mar 25, 2021
1 parent
c7fcff8
commit 90f0121
Showing
11 changed files
with
648 additions
and
151 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
"github.com/spf13/cobra" | ||
"go.amplifyedge.org/booty-v2/internal/repoclient" | ||
"go.amplifyedge.org/booty-v2/internal/reposerver" | ||
"net/http" | ||
) | ||
|
||
const ( | ||
defaultPort = 8085 | ||
defaultServerAddr = "http://localhost:8085" | ||
) | ||
|
||
var ( | ||
port int | ||
serverAddr string | ||
) | ||
|
||
func PkgRepoServerCmd() *cobra.Command { | ||
|
||
serveCmd := &cobra.Command{ | ||
Use: "serve", | ||
Short: "Start package repository server", | ||
} | ||
serveCmd.Flags().IntVarP(&port, "port", "p", defaultPort, "default port to run the repository package server") | ||
serveCmd.RunE = func(cmd *cobra.Command, args []string) error { | ||
r := reposerver.NewServer() | ||
return http.ListenAndServe(fmt.Sprintf(":%d", port), r) | ||
} | ||
return serveCmd | ||
} | ||
|
||
func PkgRepoClientCmd() *cobra.Command { | ||
clientCmd := &cobra.Command{ | ||
Use: "client", | ||
Short: "Run upload/download client to the server.", | ||
} | ||
clientCmd.Flags().StringVarP(&serverAddr, "server", "s", defaultServerAddr, "server address") | ||
|
||
subcmds := []*cobra.Command{ | ||
{ | ||
Use: "auth", | ||
Short: "authenticate request", | ||
Example: "auth <user> <password>", | ||
Args: cobra.ExactArgs(2), | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
return repoclient.AuthCli(serverAddr, args[0], args[1]) | ||
}, | ||
}, | ||
{ | ||
Use: "ul", | ||
Short: "upload file to repository", | ||
Example: "ul <location_to_file>", | ||
Args: cobra.ExactArgs(1), | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
name, err := repoclient.UploadCli(serverAddr, args[0]) | ||
if err != nil { | ||
return err | ||
} | ||
fmt.Println("uploaded id: " + name) | ||
return nil | ||
}, | ||
}, | ||
{ | ||
Use: "dl", | ||
Short: "download file from package repository", | ||
Example: "dl <file_id> <target_dir>", | ||
Args: cobra.ExactArgs(2), | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
return repoclient.DownloadCli(serverAddr, args[0], args[1]) | ||
}, | ||
}, | ||
} | ||
|
||
clientCmd.AddCommand(subcmds...) | ||
return clientCmd | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
// package pass | ||
// provides password generation and verification using argon2id | ||
// encoded passwords are stored in the format of: | ||
// $<ARGON_ALGO (i'm using argon2id)>$<version>:$MEM,ITER,PAR:$<SALT>:$<KEY> | ||
package pass | ||
|
||
import ( | ||
"crypto/rand" | ||
"crypto/subtle" | ||
"encoding/base64" | ||
"errors" | ||
"fmt" | ||
"strings" | ||
|
||
"golang.org/x/crypto/argon2" | ||
) | ||
|
||
var ( | ||
ErrWrongHash = errors.New("error: incorrect hash format") | ||
ErrIncompatibleVersion = errors.New("error: incompatible version of argon algorithm") | ||
) | ||
|
||
// Hashing Parameter | ||
// TODO: Parameterize this | ||
const ( | ||
MEM = 64 * 1024 | ||
ITER = 1 | ||
PAR = 2 | ||
SLENGTH = 16 | ||
KLENGTH = 32 | ||
) | ||
|
||
func GenHash(password string) (hash string, err error) { | ||
s, err := genRandBytes(SLENGTH) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
k := argon2.IDKey([]byte(password), s, ITER, MEM, PAR, KLENGTH) | ||
|
||
salt := base64.RawStdEncoding.EncodeToString(s) | ||
key := base64.RawStdEncoding.EncodeToString(k) | ||
|
||
hash = fmt.Sprintf( | ||
"$argon2id$v=%d$m=%d,t=%d,p=%d$%s$%s", | ||
argon2.Version, MEM, ITER, PAR, salt, key) | ||
return base64.RawStdEncoding.Strict().EncodeToString([]byte(hash)), nil | ||
} | ||
|
||
func VerifyHash(password, hash string) (match bool, err error) { | ||
salt, key, err := decodeHash(hash) | ||
if err != nil { | ||
return false, err | ||
} | ||
|
||
otherKey := argon2.IDKey([]byte(password), salt, ITER, MEM, PAR, KLENGTH) | ||
|
||
keyLen := int32(len(key)) | ||
otherKeyLen := int32(len(otherKey)) | ||
|
||
if subtle.ConstantTimeEq(keyLen, otherKeyLen) == 0 { | ||
return false, nil | ||
} | ||
if subtle.ConstantTimeCompare(key, otherKey) == 1 { | ||
return true, nil | ||
} | ||
return false, nil | ||
} | ||
|
||
func genRandBytes(n uint64) ([]byte, error) { | ||
b := make([]byte, n) | ||
_, err := rand.Read(b) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return b, nil | ||
} | ||
|
||
func decodeHash(hash string) (salt, key []byte, err error) { | ||
v, err := base64.RawStdEncoding.DecodeString(hash) | ||
if err != nil { | ||
return nil, nil, ErrWrongHash | ||
} | ||
vals := strings.Split(string(v), "$") | ||
if len(vals) != 6 { | ||
return nil, nil, ErrWrongHash | ||
} | ||
|
||
var version int | ||
_, err = fmt.Sscanf(vals[2], "v=%d", &version) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
if version != argon2.Version { | ||
return nil, nil, ErrIncompatibleVersion | ||
} | ||
|
||
salt, err = base64.RawStdEncoding.DecodeString(vals[4]) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
|
||
key, err = base64.RawStdEncoding.DecodeString(vals[5]) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
|
||
return salt, key, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package pass_test | ||
|
||
import ( | ||
"github.com/stretchr/testify/require" | ||
"go.amplifyedge.org/booty-v2/internal/pass" | ||
"testing" | ||
) | ||
|
||
type hashAndSalt struct { | ||
Unhashed string | ||
Hash string | ||
} | ||
|
||
func TestSec(t *testing.T) { | ||
t.Log("Given the need to produce hash and salt from plain text password, and verifies it thus.") | ||
{ | ||
hs := hashAndSalt{ | ||
Unhashed: "MostSecurePassword", | ||
} | ||
t.Log("\tHandling hashing and updating hash and salt record.") | ||
{ | ||
h, err := pass.GenHash(hs.Unhashed) | ||
require.NoError(t, err) | ||
hs.Hash = h | ||
t.Logf("Successfully created hash: %s\t from plain text password: %s\n", hs.Hash, hs.Unhashed) | ||
} | ||
t.Log("\tHandling verification of hash and salt") | ||
{ | ||
valid, err := pass.VerifyHash(hs.Unhashed, hs.Hash) | ||
require.NoError(t, err) | ||
require.True(t, valid) | ||
t.Log("Successfully verified password.") | ||
|
||
valid, err = pass.VerifyHash("RudolfTheRednoseReindeer", hs.Hash) | ||
require.NoError(t, err) | ||
require.False(t, valid) | ||
t.Log("Successfully invalidates invalid password.") | ||
} | ||
} | ||
|
||
} |
Oops, something went wrong.