Skip to content

Commit

Permalink
Normalize line endings
Browse files Browse the repository at this point in the history
  • Loading branch information
tfabritius committed May 7, 2023
1 parent f7e8ff0 commit 0418ccc
Show file tree
Hide file tree
Showing 69 changed files with 6,994 additions and 6,976 deletions.
18 changes: 18 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
; editorconfig.org
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[{Makefile,go.mod,go.sum,*.go,.gitmodules}]
indent_style = tab
indent_size = 4

[*.md]
indent_size = 4
trim_trailing_whitespace = false
32 changes: 16 additions & 16 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
version: 2
updates:
- package-ecosystem: "gomod"
directory: "/backend"
schedule:
interval: "weekly"
day: "saturday"
- package-ecosystem: "npm"
directory: "/frontend"
schedule:
interval: "weekly"
day: "saturday"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"
version: 2
updates:
- package-ecosystem: "gomod"
directory: "/backend"
schedule:
interval: "weekly"
day: "saturday"
- package-ecosystem: "npm"
directory: "/frontend"
schedule:
interval: "weekly"
day: "saturday"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"
90 changes: 45 additions & 45 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,45 +1,45 @@
name: CI

on:
push:
branches:
- main
pull_request:
branches:
- main
workflow_dispatch:

jobs:
build-frontend:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./frontend
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- uses: pnpm/action-setup@v2
with:
version: 8
- run: pnpm install --frozen-lockfile
- run: pnpm typecheck
- run: pnpm lint
- run: pnpm generate

build-backend:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./backend
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
version: "1.20"
- run: go build -v ./...
- run: go test -v ./... -cover -covermode=atomic -coverpkg=./... -coverprofile=coverage.txt
- uses: codecov/codecov-action@v3
with:
token: ${{secrets.CODECOV_TOKEN}}
name: CI

on:
push:
branches:
- main
pull_request:
branches:
- main
workflow_dispatch:

jobs:
build-frontend:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./frontend
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- uses: pnpm/action-setup@v2
with:
version: 8
- run: pnpm install --frozen-lockfile
- run: pnpm typecheck
- run: pnpm lint
- run: pnpm generate

build-backend:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./backend
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
version: "1.20"
- run: go build -v ./...
- run: go test -v ./... -cover -covermode=atomic -coverpkg=./... -coverprofile=coverage.txt
- uses: codecov/codecov-action@v3
with:
token: ${{secrets.CODECOV_TOKEN}}
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1 @@
.env
.env
4 changes: 2 additions & 2 deletions backend/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
/data
/test/data
/data
/test/data
44 changes: 22 additions & 22 deletions backend/frontend.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
package main

import (
"embed"
"io/fs"
"log"
"net/http"
)

//go:generate rm -r ./static/*
//go:generate cp -r ../frontend/.output/public/* ./static/
//go:embed all:static
var frontendFs embed.FS

func getStaticFrontend() http.FileSystem {
fsys, err := fs.Sub(frontendFs, "static")
if err != nil {
log.Fatal(err)
}

return http.FS(fsys)
}
package main

import (
"embed"
"io/fs"
"log"
"net/http"
)

//go:generate rm -r ./static/*
//go:generate cp -r ../frontend/.output/public/* ./static/
//go:embed all:static
var frontendFs embed.FS

func getStaticFrontend() http.FileSystem {
fsys, err := fs.Sub(frontendFs, "static")
if err != nil {
log.Fatal(err)
}

return http.FS(fsys)
}
186 changes: 93 additions & 93 deletions backend/libs/argon2/argon2.go
Original file line number Diff line number Diff line change
@@ -1,93 +1,93 @@
package argon2

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

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

// Inspired by https://www.alexedwards.net/blog/how-to-hash-and-verify-passwords-with-argon2-in-go

// HashPasswordDefault returns hash using argon2id and default parameters
func HashPasswordDefault(password string) (string, error) {
return HashPassword(password, 32, 16, 1, 65536, 2)
}

// HashPassword returns hash using argon2id and the provided parameters
func HashPassword(password string, keyLength, saltLength, iterations, memory uint32, parallelism uint8) (string, error) {
salt := make([]byte, saltLength)
_, err := rand.Read(salt)
if err != nil {
return "", fmt.Errorf("could not create salt: %w", err)
}

key := argon2.IDKey([]byte(password), salt, iterations, memory, parallelism, keyLength)

hash := fmt.Sprintf("$argon2id$v=%d$m=%d,t=%d,p=%d$%s$%s",
argon2.Version,
memory,
iterations,
parallelism,
base64.RawStdEncoding.EncodeToString(salt),
base64.RawStdEncoding.EncodeToString(key))

return hash, nil
}

// VerifyPassword checks if password matches the hash, supports argon2id and argon2i
func VerifyPassword(password, hash string) (match bool, err error) {
hashParts := strings.Split(hash, "$")
if len(hashParts) != 6 {
return false, errors.New("invalid hash format")
}

variant := hashParts[1]

var version int
_, err = fmt.Sscanf(hashParts[2], "v=%d", &version)
if err != nil {
return false, fmt.Errorf("could not parse version: %w", err)
}
if version != argon2.Version {
return false, fmt.Errorf("incompatible version: %d", version)
}

var memory uint32
var iterations uint32
var parallelism uint8

_, err = fmt.Sscanf(hashParts[3], "m=%d,t=%d,p=%d", &memory, &iterations, &parallelism)
if err != nil {
return false, fmt.Errorf("could not parse parameters: %w", err)
}

salt, err := base64.RawStdEncoding.Strict().DecodeString(hashParts[4])
if err != nil {
return false, fmt.Errorf("could not decode salt: %w", err)
}

key, err := base64.RawStdEncoding.Strict().DecodeString(hashParts[5])
if err != nil {
return false, fmt.Errorf("could not decode key: %w", err)
}

var derivedKey []byte
switch variant {
case "argon2id":
derivedKey = argon2.IDKey([]byte(password), salt, iterations, memory, parallelism, uint32(len(key)))
case "argon2i":
derivedKey = argon2.Key([]byte(password), salt, iterations, memory, parallelism, uint32(len(key)))
default:
return false, fmt.Errorf("unknown variant: %s", variant)
}

if subtle.ConstantTimeEq(int32(len(key)), int32(len(derivedKey))) == 0 {
return false, nil
}
return subtle.ConstantTimeCompare(key, derivedKey) == 1, nil
}
package argon2

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

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

// Inspired by https://www.alexedwards.net/blog/how-to-hash-and-verify-passwords-with-argon2-in-go

// HashPasswordDefault returns hash using argon2id and default parameters
func HashPasswordDefault(password string) (string, error) {
return HashPassword(password, 32, 16, 1, 65536, 2)
}

// HashPassword returns hash using argon2id and the provided parameters
func HashPassword(password string, keyLength, saltLength, iterations, memory uint32, parallelism uint8) (string, error) {
salt := make([]byte, saltLength)
_, err := rand.Read(salt)
if err != nil {
return "", fmt.Errorf("could not create salt: %w", err)
}

key := argon2.IDKey([]byte(password), salt, iterations, memory, parallelism, keyLength)

hash := fmt.Sprintf("$argon2id$v=%d$m=%d,t=%d,p=%d$%s$%s",
argon2.Version,
memory,
iterations,
parallelism,
base64.RawStdEncoding.EncodeToString(salt),
base64.RawStdEncoding.EncodeToString(key))

return hash, nil
}

// VerifyPassword checks if password matches the hash, supports argon2id and argon2i
func VerifyPassword(password, hash string) (match bool, err error) {
hashParts := strings.Split(hash, "$")
if len(hashParts) != 6 {
return false, errors.New("invalid hash format")
}

variant := hashParts[1]

var version int
_, err = fmt.Sscanf(hashParts[2], "v=%d", &version)
if err != nil {
return false, fmt.Errorf("could not parse version: %w", err)
}
if version != argon2.Version {
return false, fmt.Errorf("incompatible version: %d", version)
}

var memory uint32
var iterations uint32
var parallelism uint8

_, err = fmt.Sscanf(hashParts[3], "m=%d,t=%d,p=%d", &memory, &iterations, &parallelism)
if err != nil {
return false, fmt.Errorf("could not parse parameters: %w", err)
}

salt, err := base64.RawStdEncoding.Strict().DecodeString(hashParts[4])
if err != nil {
return false, fmt.Errorf("could not decode salt: %w", err)
}

key, err := base64.RawStdEncoding.Strict().DecodeString(hashParts[5])
if err != nil {
return false, fmt.Errorf("could not decode key: %w", err)
}

var derivedKey []byte
switch variant {
case "argon2id":
derivedKey = argon2.IDKey([]byte(password), salt, iterations, memory, parallelism, uint32(len(key)))
case "argon2i":
derivedKey = argon2.Key([]byte(password), salt, iterations, memory, parallelism, uint32(len(key)))
default:
return false, fmt.Errorf("unknown variant: %s", variant)
}

if subtle.ConstantTimeEq(int32(len(key)), int32(len(derivedKey))) == 0 {
return false, nil
}
return subtle.ConstantTimeCompare(key, derivedKey) == 1, nil
}
Loading

0 comments on commit 0418ccc

Please sign in to comment.