From b586d1e8ee5b382a55acf85e1617074ee985f87f Mon Sep 17 00:00:00 2001 From: Robert Date: Sat, 5 Jul 2025 09:55:37 -0400 Subject: [PATCH] aes/chacha20 --- .gitignore | 2 + README | 5 +- chaKey.go | 17 +++ client.go | 147 +++++++++++++++++++++++- default.yaml | 3 + go.mod | 5 +- go.sum | 3 + keygen.go | 157 ++++++++++++++++++++++--- server.go | 315 ++++++++++++++++++++++++++++++++++++++++++++++----- 9 files changed, 605 insertions(+), 49 deletions(-) create mode 100644 chaKey.go create mode 100644 default.yaml diff --git a/.gitignore b/.gitignore index bc9b288..0fb8b14 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ *.db vaultClient +config.yaml +*.pem diff --git a/README b/README index 96d28bd..fba88ae 100644 --- a/README +++ b/README @@ -5,8 +5,9 @@ go mod download golang.org/x/term go mod tidy go run keygen.go -nano server.go -REPLACE old key with new key! +go run chaKey.go +nano default.yaml +cp default.yaml config.yaml sudo apt install gcc CGO_ENABLED=1 go build -o cliVault server.go diff --git a/chaKey.go b/chaKey.go new file mode 100644 index 0000000..15739a1 --- /dev/null +++ b/chaKey.go @@ -0,0 +1,17 @@ +package main + +import ( + "crypto/rand" + "fmt" + "golang.org/x/crypto/chacha20poly1305" +) + +func main() { + // Generate or use a pre-shared key (in real code, this should be properly managed) + key := make([]byte, chacha20poly1305.KeySize) + if _, err := rand.Read(key); err != nil { + // handle error + return + } + fmt.Printf("%x", key) +} diff --git a/client.go b/client.go index f17c1d0..b76b094 100644 --- a/client.go +++ b/client.go @@ -1,7 +1,10 @@ package main import ( + "crypto/sha256" "crypto/rand" + "golang.org/x/crypto/chacha20poly1305" + "encoding/base64" "encoding/gob" "encoding/hex" "fmt" @@ -9,9 +12,23 @@ import ( "time" "golang.org/x/term" "syscall" + "flag" + "os" + "log" + "bytes" + "io/ioutil" + "gopkg.in/yaml.v2" ) +var ChaKey = []byte("") +type Config struct { + Auth struct { + ChaKey string `yaml:"ChaKey"` + } `yaml:"auth"` +} + type Request struct { + KeyPwd string Username string Password string Operation string @@ -23,6 +40,7 @@ type Request struct { type Response struct { Message string + Enc string } func generateNonce() (string, error) { @@ -34,7 +52,106 @@ func generateNonce() (string, error) { return hex.EncodeToString(b), nil } +func getKey()([]byte) { + // Hash it to 32 bytes using SHA-256 + hashedKey := sha256.Sum256(ChaKey) + theKey := hashedKey[:] // Convert [32]byte to []byte + return theKey +} + +func chEnc(p string)(string) { + // Create cipher + aead, err := chacha20poly1305.NewX(getKey()) + if err != nil { + log.Fatalf("ChaKey enc error") + return "" + } + // Create nonce + nonce := make([]byte, aead.NonceSize()) + if _, err := rand.Read(nonce); err != nil { + log.Fatalf("Cha Nonce Error") + return "" + } + // Encode with gob first + var buf bytes.Buffer + tempEnc := gob.NewEncoder(&buf) + if err := tempEnc.Encode(p); err != nil { + log.Fatalf("gob encode first error") + return "" + } + + // Encrypt the encoded data + encrypted := aead.Seal(nil, nonce, buf.Bytes(), nil) + + // Send nonce + encrypted data + fullMessage := append(nonce, encrypted...) + + encoded := base64.StdEncoding.EncodeToString(fullMessage) + return encoded +} + +func chDec(eText string)(string) { + if eText == "" { + return "" + } + + // Decoding from base64 + decoded, err := base64.StdEncoding.DecodeString(eText) + if err != nil { + log.Fatal("Base64 decoding error:", err) + } + + // Create cipher instance (XChaCha20-Poly1305 for longer nonces) + aead, err := chacha20poly1305.NewX(getKey()) + if err != nil { + log.Fatalf("Client: ChaKey failed") + return "" + } + + encryptedMsg := decoded + + // Decrypt: Split nonce and ciphertext + decryptedNonce := encryptedMsg[:aead.NonceSize()] + decryptedCiphertext := encryptedMsg[aead.NonceSize():] + + decrypted, err := aead.Open(nil, decryptedNonce, decryptedCiphertext, nil) + if err != nil { + log.Fatalf("Client decryption failed") + return "" + } + + return string(decrypted) +} + func main() { + configFilePtr := flag.String("config", "config.yaml", "Path to the YAML configuration file") + flag.Parse() + + if *configFilePtr == "" { + fmt.Println("Please specify a configuration file using -config") + flag.Usage() + os.Exit(1) + } + + // Read the config file + yamlFile, err := ioutil.ReadFile(*configFilePtr) + if err != nil { + log.Fatalf("Error reading YAML file: %v\n", err) + } + + // Parse the YAML + var config Config + err = yaml.Unmarshal(yamlFile, &config) + if err != nil { + log.Fatalf("Error parsing YAML file: %v\n", err) + } + + // Print the ChaKey + if config.Auth.ChaKey == "" { + fmt.Println("Warning: ChaKey not found in configuration file") + } + ChaKey = []byte(config.Auth.ChaKey) + var host string fmt.Print("Enter host or IP: ") fmt.Scanln(&host) @@ -44,6 +161,14 @@ func main() { panic(err) } defer conn.Close() + + fmt.Print("Key Passphrase: ") + byteKeyPwd, err := term.ReadPassword(int(syscall.Stdin)) + fmt.Println() + if err != nil { + panic(err) + } + keypassphrase := string(byteKeyPwd) var username, op, site, vaultData string fmt.Print("Username: ") @@ -74,12 +199,20 @@ func main() { panic(err) } + var myPwd string + if vaultData == "" { + myPwd = "" + } else { + myPwd = chEnc(vaultData) + } + req := Request{ - Username: username, - Password: password, + KeyPwd: chEnc(keypassphrase), + Username: chEnc(username), + Password: chEnc(password), Operation: op, - Site: site, - VaultData: vaultData, + Site: chEnc(site), + VaultData: myPwd, Timestamp: time.Now().Unix(), Nonce: nonce, } @@ -98,5 +231,9 @@ func main() { return } - fmt.Println("Server response:", res.Message) + if res.Message != "" { + fmt.Println("Server response:", res.Message) + } else { + fmt.Println("Server response:", chDec(res.Enc)) + } } diff --git a/default.yaml b/default.yaml new file mode 100644 index 0000000..17e97ed --- /dev/null +++ b/default.yaml @@ -0,0 +1,3 @@ +auth: + ChaKey: "b107568bf716da40f5f17fea0e6608816020118d2c10b488ef9777b3d626126f" + PEM: "encrypted_aes_key.pem" diff --git a/go.mod b/go.mod index 0c2de43..201d71b 100644 --- a/go.mod +++ b/go.mod @@ -8,4 +8,7 @@ require ( golang.org/x/term v0.32.0 ) -require golang.org/x/sys v0.33.0 // indirect +require ( + golang.org/x/sys v0.33.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect +) diff --git a/go.sum b/go.sum index e7717c7..45ea190 100644 --- a/go.sum +++ b/go.sum @@ -6,3 +6,6 @@ golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= diff --git a/keygen.go b/keygen.go index 77ace22..f34030d 100644 --- a/keygen.go +++ b/keygen.go @@ -1,25 +1,152 @@ package main import ( - "crypto/rand" - "encoding/hex" - "fmt" + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "encoding/pem" + "errors" + "fmt" + "os" + "flag" + + "golang.org/x/crypto/ssh/terminal" + "golang.org/x/crypto/scrypt" ) -func generateKey() ([]byte, error) { - key := make([]byte, 16) - _, err := rand.Read(key) - if err != nil { - return nil, err +func main() { + keyPtr := flag.String("keyfile", "encrypted_aes_key.pem", "Enter keyfile") + flag.Parse() + + if *keyPtr == "" { + fmt.Print("Please enter a keyfile") + return } - return key, nil + + // Generate a new AES-256 key + key, err := generateAESKey(32) // 32 bytes = 256 bits + if err != nil { + fmt.Printf("Error generating AES key: %v\n", err) + return + } + + // Prompt for passphrase + print("Enter passphrase: ") + pass, _ := terminal.ReadPassword(0) // Hides input + password := string(pass) + + // Encrypt and PEM encode the key + pemBlock, err := encryptKeyToPEM(key, password) + if err != nil { + fmt.Printf("Error encrypting key: %v\n", err) + return + } + + // Save to file + err = os.WriteFile(*keyPtr, pem.EncodeToMemory(pemBlock), 0600) + if err != nil { + fmt.Printf("Error writing PEM file: %v\n", err) + return + } + + fmt.Printf("Successfully generated and password-protected AES key in %s", *keyPtr) } -func main() { - key, err := generateKey() - if err != nil { - panic(err) - } +// generateAESKey creates a new random AES key of specified size +func generateAESKey(size int) ([]byte, error) { + key := make([]byte, size) + _, err := rand.Read(key) + if err != nil { + return nil, err + } + return key, nil +} + +// encryptKeyToPEM encrypts the key with a password and returns a PEM block +func encryptKeyToPEM(key []byte, password string) (*pem.Block, error) { + // Convert password to suitable encryption key + salt := make([]byte, 16) + if _, err := rand.Read(salt); err != nil { + return nil, err + } + + // Use scrypt for key derivation (better than PBKDF2) + // N: CPU/memory cost, r: block size, p: parallelization + encryptionKey, err := scrypt.Key([]byte(password), salt, 32768, 8, 1, 32) + if err != nil { + return nil, err + } + + // Generate a random IV + iv := make([]byte, aes.BlockSize) + if _, err := rand.Read(iv); err != nil { + return nil, err + } + + // Encrypt the key + block, err := aes.NewCipher(encryptionKey) + if err != nil { + return nil, err + } + + encrypted := make([]byte, len(key)) + stream := cipher.NewCFBEncrypter(block, iv) + stream.XORKeyStream(encrypted, key) + + // Create PEM block + pemBlock := &pem.Block{ + Type: "ENCRYPTED AES KEY", + Headers: map[string]string{ + "Key-Derivation": "scrypt", + "SALT": fmt.Sprintf("%x", salt), + "IV": fmt.Sprintf("%x", iv), + "Key-Size": fmt.Sprintf("%d", len(key)*8), + }, + Bytes: encrypted, + } + + return pemBlock, nil +} + +// hexStringToBytes converts a hex string to bytes +func hexStringToBytes(hexStr string) ([]byte, error) { + if len(hexStr)%2 != 0 { + return nil, errors.New("hex string length must be even") + } + bytes := make([]byte, len(hexStr)/2) + for i := 0; i < len(hexStr); i += 2 { + b, err := hexByte(hexStr[i], hexStr[i+1]) + if err != nil { + return nil, err + } + bytes[i/2] = b + } + return bytes, nil +} + +// hexByte converts two hex characters to a byte +func hexByte(a, b byte) (byte, error) { + high, err := hexDigitToByte(a) + if err != nil { + return 0, err + } + low, err := hexDigitToByte(b) + if err != nil { + return 0, err + } + return (high << 4) | low, nil +} - fmt.Println("Generated 32-byte key (hex):", hex.EncodeToString(key)) +// hexDigitToByte converts a single hex character to its byte value +func hexDigitToByte(c byte) (byte, error) { + switch { + case '0' <= c && c <= '9': + return c - '0', nil + case 'a' <= c && c <= 'f': + return c - 'a' + 10, nil + case 'A' <= c && c <= 'F': + return c - 'A' + 10, nil + default: + return 0, fmt.Errorf("invalid hex digit %c", c) + } } diff --git a/server.go b/server.go index b74f475..cfdf9b2 100644 --- a/server.go +++ b/server.go @@ -2,20 +2,42 @@ package main import ( "golang.org/x/crypto/bcrypt" + "golang.org/x/crypto/chacha20poly1305" + "golang.org/x/crypto/scrypt" + "crypto/sha256" + "crypto/rand" "crypto/aes" "crypto/cipher" "database/sql" + "encoding/base64" + "encoding/pem" "encoding/gob" "fmt" "net" "sync" "time" - + "bytes" + "errors" + "flag" + "os" + "log" + "io/ioutil" + "gopkg.in/yaml.v2" + _ "github.com/mattn/go-sqlite3" ) const AllowRegistration = true // Disable after users are added! -var key = []byte("2f5680a7fb57ce83e8e83dbb1114ee31") // 32 bytes +var ChaKey = []byte("") + +type Config struct { + Auth struct { + ChaKey string `yaml:"ChaKey"` + PEM string `yaml:"PEM"` + } `yaml:"auth"` +} + +var config Config var nonceStore = struct { sync.Mutex @@ -24,7 +46,9 @@ var nonceStore = struct { const nonceExpiry = 30 * time.Second +var key []byte type Request struct { + KeyPwd string Username string Password string Operation string @@ -36,6 +60,7 @@ type Request struct { type Response struct { Message string + Enc string } var ipAttempts = struct { @@ -81,6 +106,106 @@ func isValidNonce(nonce string, timestamp int64) bool { return true } +// decryptPEMToKey decrypts a PEM block with the given password +func decryptPEMToKey(filename string, password string) ([]byte, error) { + // Read the entire file + pemData, err := os.ReadFile(filename) + if err != nil { + return nil, fmt.Errorf("failed to read PEM file: %v", err) + } + + // Decode the PEM block + pemBlock, _ := pem.Decode(pemData) + if pemBlock == nil { + return nil, errors.New("failed to decode PEM block") + } + + // Check if the PEM block is encrypted + if pemBlock.Headers["Key-Derivation"] == "" { + return nil, errors.New("PEM block is not password-protected") + } + + // Get salt and IV from headers + salt, err := hexStringToBytes(pemBlock.Headers["SALT"]) + if err != nil { + return nil, fmt.Errorf("invalid salt: %v", err) + } + + iv, err := hexStringToBytes(pemBlock.Headers["IV"]) + if err != nil { + return nil, fmt.Errorf("invalid IV: %v", err) + } + + // Derive encryption key + var encryptionKey []byte + switch pemBlock.Headers["Key-Derivation"] { + case "scrypt": + encryptionKey, err = scrypt.Key([]byte(password), salt, 32768, 8, 1, 32) + //case "pbkdf2": + //encryptionKey = pbkdf2.Key([]byte(password), salt, 10000, 32, sha256.New) + default: + return nil, errors.New("unsupported key derivation function") + } + if err != nil { + return nil, err + } + + // Decrypt the key + block, err := aes.NewCipher(encryptionKey) + if err != nil { + return nil, err + } + + decrypted := make([]byte, len(pemBlock.Bytes)) + stream := cipher.NewCFBDecrypter(block, iv) + stream.XORKeyStream(decrypted, pemBlock.Bytes) + + return decrypted, nil +} + +// hexStringToBytes converts a hex string to bytes +func hexStringToBytes(hexStr string) ([]byte, error) { + if len(hexStr)%2 != 0 { + return nil, errors.New("hex string length must be even") + } + bytes := make([]byte, len(hexStr)/2) + for i := 0; i < len(hexStr); i += 2 { + b, err := hexByte(hexStr[i], hexStr[i+1]) + if err != nil { + return nil, err + } + bytes[i/2] = b + } + return bytes, nil +} + +// hexByte converts two hex characters to a byte +func hexByte(a, b byte) (byte, error) { + high, err := hexDigitToByte(a) + if err != nil { + return 0, err + } + low, err := hexDigitToByte(b) + if err != nil { + return 0, err + } + return (high << 4) | low, nil +} + +// hexDigitToByte converts a single hex character to its byte value +func hexDigitToByte(c byte) (byte, error) { + switch { + case '0' <= c && c <= '9': + return c - '0', nil + case 'a' <= c && c <= 'f': + return c - 'a' + 10, nil + case 'A' <= c && c <= 'F': + return c - 'A' + 10, nil + default: + return 0, fmt.Errorf("invalid hex digit %c", c) + } +} + func hashPassword(pw string) (string, error) { bytes, err := bcrypt.GenerateFromPassword([]byte(pw), 12) return string(bytes), err @@ -121,94 +246,232 @@ func decrypt(data []byte) (string, error) { return string(plaintext), nil } +func getKey()([]byte) { + // Hash it to 32 bytes using SHA-256 + hashedKey := sha256.Sum256(ChaKey) + theKey := hashedKey[:] // Convert [32]byte to []byte + return theKey +} + +func chEnc(pwd string)(string, error) { + // Create cipher + aead, err := chacha20poly1305.NewX(getKey()) + if err != nil { + return "", err + } + // Create nonce + nonce := make([]byte, aead.NonceSize()) + if _, err := rand.Read(nonce); err != nil { + return "", err + } + // Encode with gob first + var buf bytes.Buffer + tempEnc := gob.NewEncoder(&buf) + if err := tempEnc.Encode(pwd); err != nil { + return "", err + } + + // Encrypt the encoded data + encrypted := aead.Seal(nil, nonce, buf.Bytes(), nil) + + // Send nonce + encrypted data + fullMessage := append(nonce, encrypted...) + encoded := base64.StdEncoding.EncodeToString(fullMessage) + + return encoded, nil +} + +func chDec(eText string)(string) { + if eText == "" { + log.Fatalf("Error: Blank") + } + + // Decoding from base64 + decoded, err := base64.StdEncoding.DecodeString(eText) + if err != nil { + log.Fatalf("Error: Base64 decode") + } + + // Create cipher instance (XChaCha20-Poly1305 for longer nonces) + aead, err := chacha20poly1305.NewX(getKey()) + if err != nil { + log.Fatalf("Error: Cha20 key") + } + + encryptedMsg := decoded + + // Decrypt: Split nonce and ciphertext + decryptedNonce := encryptedMsg[:aead.NonceSize()] + decryptedCiphertext := encryptedMsg[aead.NonceSize():] + + decrypted, err := aead.Open(nil, decryptedNonce, decryptedCiphertext, nil) + if err != nil { + log.Fatalf("Error: aead open") + } + return string(decrypted) +} + func handleConnection(conn net.Conn, db *sql.DB) { defer conn.Close() dec := gob.NewDecoder(conn) enc := gob.NewEncoder(conn) - remoteAddr := conn.RemoteAddr().String() var req Request if err := dec.Decode(&req); err != nil { return } + + username := chDec(req.Username) + keypwd := chDec(req.KeyPwd) + password := chDec(req.Password) + + if username == "" { + enc.Encode(Response{Message: "Required username, blank found!", Enc: ""}) + return + } + if keypwd == "" { + enc.Encode(Response{Message: "Required key passphrase, blank found!", Enc: ""}) + return + } + if password == "" { + enc.Encode(Response{Message: "Required user password, blank found!", Enc: ""}) + return + } + + k, err := decryptPEMToKey(config.Auth.PEM, keypwd) + if err != nil { + enc.Encode(Response{Message: "Unable to decode data!", Enc: ""}) + return + } + key = k if isRateLimited(remoteAddr) { - enc.Encode(Response{"Too many requests. Try later."}) + enc.Encode(Response{Message: "Too many requests. Try later.", Enc: ""}) return } if !isValidNonce(req.Nonce, req.Timestamp) { - enc.Encode(Response{"Invalid or replayed request"}) + enc.Encode(Response{Message: "Invalid or replayed request", Enc: ""}) return } if req.Operation == "register" { if AllowRegistration == false { - enc.Encode(Response{"Registration Disabled!"}) + enc.Encode(Response{Message: "Registration Disabled!", Enc: ""}) return } - hashed, err := hashPassword(req.Password) + hashed, err := hashPassword(password) if err != nil { - enc.Encode(Response{"Failed to hash password"}) + enc.Encode(Response{Message: "Failed to hash password", Enc: ""}) return } - _, err = db.Exec("INSERT INTO users (username, password) VALUES (?, ?)", req.Username, hashed) + _, err = db.Exec("INSERT INTO users (username, password) VALUES (?, ?)", username, hashed) if err != nil { - enc.Encode(Response{"Registration failed (user exists?)"}) + enc.Encode(Response{Message: "Registration failed (user exists?)", Enc: ""}) } else { - enc.Encode(Response{"Registration successful"}) + enc.Encode(Response{Message: "Registration successful", Enc: ""}) } return } + + site := chDec(req.Site) + if site == "" { + enc.Encode(Response{Message: "Required site name, blank found!", Enc: ""}) + return + } + // Authenticate all other operations var storedHash string - err := db.QueryRow("SELECT password FROM users WHERE username = ?", req.Username).Scan(&storedHash) - if err != nil || checkPassword(storedHash, req.Password) != nil { - enc.Encode(Response{"Authentication failed"}) + err = db.QueryRow("SELECT password FROM users WHERE username = ?", username).Scan(&storedHash) + if err != nil || checkPassword(storedHash, password) != nil { + enc.Encode(Response{Message: "Authentication failed", Enc: ""}) return } switch req.Operation { case "store": - encrypted, err := encrypt(req.VaultData) + vaultdata := chDec(req.VaultData) + encrypted, err := encrypt(vaultdata) if err != nil { - enc.Encode(Response{"Encryption failed"}) + enc.Encode(Response{Message: "Encryption failed", Enc: ""}) return } _, err = db.Exec("INSERT OR REPLACE INTO accounts (user, site, password) VALUES (?, ?, ?)", - req.Username, req.Site, encrypted) + username, site, encrypted) if err != nil { - enc.Encode(Response{"Database error"}) + enc.Encode(Response{Message: "Database error", Enc: ""}) return } - enc.Encode(Response{"Password stored successfully"}) + enc.Encode(Response{Message: "Password stored successfully", Enc: ""}) case "get": var encrypted []byte - err := db.QueryRow("SELECT password FROM accounts WHERE user = ? AND site = ?", req.Username, req.Site).Scan(&encrypted) + err := db.QueryRow("SELECT password FROM accounts WHERE user = ? AND site = ?", username, site).Scan(&encrypted) if err == sql.ErrNoRows { - enc.Encode(Response{"Site not found"}) + enc.Encode(Response{Message: "Site not found", Enc: ""}) return } else if err != nil { - enc.Encode(Response{"Database error"}) + enc.Encode(Response{Message: "Database error", Enc: ""}) return } pwd, err := decrypt(encrypted) if err != nil { - enc.Encode(Response{"Decryption failed"}) + enc.Encode(Response{Message: "Decryption failed", Enc: ""}) return } - enc.Encode(Response{pwd}) + ePwd, err := chEnc(pwd) + if err != nil { + enc.Encode(Response{Message: "Encryption failed", Enc: ""}) + return + } + enc.Encode(Response{Message: "", Enc: ePwd}) default: - enc.Encode(Response{"Unknown operation"}) + enc.Encode(Response{Message: "Unknown operation", Enc: ""}) } } func main() { - db, err := sql.Open("sqlite3", "vault.db") + vaultPtr := flag.String("dbfile", "vault.db", "Enter dbfile") + configFilePtr := flag.String("config", "config.yaml", "Path to the YAML configuration file") + flag.Parse() + + if *vaultPtr == "" { + fmt.Println("Please specify a db file using -dbfile") + flag.Usage() + os.Exit(1) + } + + if *configFilePtr == "" { + fmt.Println("Please specify a configuration file using -config") + flag.Usage() + os.Exit(1) + } + + // Read the config file + yamlFile, err := ioutil.ReadFile(*configFilePtr) + if err != nil { + log.Fatalf("Error reading YAML file: %v\n", err) + } + + // Parse the YAML + err = yaml.Unmarshal(yamlFile, &config) + if err != nil { + log.Fatalf("Error parsing YAML file: %v\n", err) + } + + // Print the ChaKey + if config.Auth.ChaKey == "" { + fmt.Println("Warning: ChaKey not found in configuration file") + } + ChaKey = []byte(config.Auth.ChaKey) + if config.Auth.PEM == "" { + fmt.Println("Warning: PEM file not found in configuration file") + } + + db, err := sql.Open("sqlite3", *vaultPtr) if err != nil { panic(err) }