Scaffold project
This commit is contained in:
commit
b56ebf3c3d
5 changed files with 149 additions and 0 deletions
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
data/**
|
||||
.DS_Store
|
||||
Photos.code-workspace
|
||||
logs/**
|
||||
.idea/**
|
||||
.vscode/**
|
||||
tmp/**
|
||||
museum.yaml
|
8
go.mod
Normal file
8
go.mod
Normal file
|
@ -0,0 +1,8 @@
|
|||
module cli-go
|
||||
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/jamesruan/sodium v1.0.14
|
||||
golang.org/x/crypto v0.11.0
|
||||
)
|
10
go.sum
Normal file
10
go.sum
Normal file
|
@ -0,0 +1,10 @@
|
|||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
|
||||
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
70
internal/crypto/crypto.go
Normal file
70
internal/crypto/crypto.go
Normal file
|
@ -0,0 +1,70 @@
|
|||
package crypto
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
|
||||
"github.com/jamesruan/sodium"
|
||||
"golang.org/x/crypto/argon2"
|
||||
)
|
||||
|
||||
// deriveArgonKey generates a 32-bit cryptographic key using the Argon2id algorithm.
|
||||
// Parameters:
|
||||
// - password: The plaintext password to be hashed.
|
||||
// - salt: The salt as a base64 encoded string.
|
||||
// - memLimit: The memory limit in bytes.
|
||||
// - opsLimit: The number of iterations.
|
||||
//
|
||||
// Returns:
|
||||
// - A byte slice representing the derived key.
|
||||
// - An error object, which is nil if no error occurs.
|
||||
func deriveArgonKey(password, salt string, memLimit, opsLimit int) ([]byte, error) {
|
||||
if memLimit < 1024 || opsLimit < 1 {
|
||||
return nil, fmt.Errorf("invalid memory or operation limits")
|
||||
}
|
||||
|
||||
// Decode salt from base64
|
||||
saltBytes, err := base64.StdEncoding.DecodeString(salt)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid salt: %v", err)
|
||||
}
|
||||
|
||||
// Generate key using Argon2id
|
||||
// Note: We're assuming a fixed key length of 32 bytes and changing the threads
|
||||
key := argon2.IDKey([]byte(password), saltBytes, uint32(opsLimit), uint32(memLimit/1024), 1, 32)
|
||||
|
||||
return key, nil
|
||||
}
|
||||
|
||||
// decryptChaCha20poly1305 decrypts the given data using the ChaCha20-Poly1305 algorithm.
|
||||
// Parameters:
|
||||
// - data: The encrypted data as a byte slice.
|
||||
// - key: The key for decryption as a byte slice.
|
||||
// - nonce: The nonce for decryption as a byte slice.
|
||||
//
|
||||
// Returns:
|
||||
// - A byte slice representing the decrypted data.
|
||||
// - An error object, which is nil if no error occurs.
|
||||
func decryptChaCha20poly1305(data []byte, key []byte, nonce []byte) ([]byte, error) {
|
||||
reader := bytes.NewReader(data)
|
||||
header := sodium.SecretStreamXCPHeader{Bytes: nonce}
|
||||
decoder, err := sodium.MakeSecretStreamXCPDecoder(
|
||||
sodium.SecretStreamXCPKey{Bytes: key},
|
||||
reader,
|
||||
header)
|
||||
if err != nil {
|
||||
log.Println("Failed to make secret stream decoder", err)
|
||||
return nil, err
|
||||
}
|
||||
// Buffer to store the decrypted data
|
||||
decryptedData := make([]byte, len(data))
|
||||
n, err := decoder.Read(decryptedData)
|
||||
if err != nil && err != io.EOF {
|
||||
log.Println("Failed to read from decoder", err)
|
||||
return nil, err
|
||||
}
|
||||
return decryptedData[:n], nil
|
||||
}
|
53
internal/crypto/crypto_test.go
Normal file
53
internal/crypto/crypto_test.go
Normal file
|
@ -0,0 +1,53 @@
|
|||
package crypto
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const (
|
||||
password = "test_password"
|
||||
kdfSalt = "vd0dcYMGNLKn/gpT6uTFTw=="
|
||||
memLimit = 64 * 1024 * 1024 // 64MB
|
||||
opsLimit = 2
|
||||
cipherText = "kBXQ2PuX6y/aje5r22H0AehRPh6sQ0ULoeAO"
|
||||
cipherNonce = "v7wsI+BFZsRMIjDm3rTxPhmi/CaUdkdJ"
|
||||
expectedPlainText = "plain_text"
|
||||
expectedDerivedKey = "vp8d8Nee0BbIML4ab8Cp34uYnyrN77cRwTl920flyT0="
|
||||
)
|
||||
|
||||
func TestDeriveArgonKey(t *testing.T) {
|
||||
derivedKey, err := deriveArgonKey(password, kdfSalt, memLimit, opsLimit)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to derive key: %v", err)
|
||||
}
|
||||
|
||||
if base64.StdEncoding.EncodeToString(derivedKey) != expectedDerivedKey {
|
||||
t.Fatalf("Derived key does not match expected key")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecryptChaCha20poly1305(t *testing.T) {
|
||||
derivedKey, err := deriveArgonKey(password, kdfSalt, memLimit, opsLimit)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to derive key: %v", err)
|
||||
}
|
||||
|
||||
decodedCipherText, err := base64.StdEncoding.DecodeString(cipherText)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to decode cipher text: %v", err)
|
||||
}
|
||||
|
||||
decodedCipherNonce, err := base64.StdEncoding.DecodeString(cipherNonce)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to decode cipher nonce: %v", err)
|
||||
}
|
||||
|
||||
decryptedText, err := decryptChaCha20poly1305(decodedCipherText, derivedKey, decodedCipherNonce)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to decrypt: %v", err)
|
||||
}
|
||||
if string(decryptedText) != expectedPlainText {
|
||||
t.Fatalf("Decrypted text : %s does not match the expected text: %s", string(decryptedText), expectedPlainText)
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue