In today's digital age, managing passwords efficiently and securely is crucial. Building a password vault can help store multiple passwords securely. This guide will walk through creating a simple password vault using the Go programming language. We will cover setting up a basic command-line application, securing passwords with encryption, and ensuring data integrity.

Getting Started

Create a new directory for your project and initialize a new Go module:

mkdir gopassvault
cd gopassvault
go mod init gopassvault

Basic Command-Line Application

We'll start by setting up a basic command-line application that can accept user inputs for storing and retrieving passwords.

package main

import (
    "fmt"
    "os"
)

func main() {
    if len(os.Args) < 2 {
        fmt.Println("Usage: gopassvault command")
        return
    }

    command := os.Args[1]

    switch command {
    case "set":
        // will handle set command
    case "get":
        // will handle get command
    default:
        fmt.Println("Unknown command")
    }
}

Securing Passwords with Encryption

To secure passwords, we'll use AES encryption from the built-in crypto package. AES (Advanced Encryption Standard) is strong enough to keep your passwords safe if managed correctly.

package main

import (
    "crypto/aes"
    "crypto/cipher"
    "crypto/rand"
    "encoding/hex"
    "io"
)

func encrypt(plaintext string, key []byte) (ciphertext string, err error) {
    block, err := aes.NewCipher(key)
    if err != nil {
        return "", err
    }

    aesGCM, err := cipher.NewGCM(block)
    if err != nil {
        return "", err
    }

    nonce := make([]byte, aesGCM.NonceSize())
    if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
        return "", err
    }

    encrypted := aesGCM.Seal(nonce, nonce, []byte(plaintext), nil)
    return hex.EncodeToString(encrypted), nil
}

The encryption function takes plaintext and a key, then returns the ciphertext. Note that managing the key securely is crucial, and it should never be hard-coded into your application.

Data Storage and Management

For simplicity, we will store encrypted passwords in a local file. A more robust solution could involve using a database.

package main

import (
    "bufio"
    "fmt"
    "os"
)

func savePassword(filename, account, encryptedPassword string) error {
    file, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
    if err != nil {
        return err
    }
    defer file.Close()

    writer := bufio.NewWriter(file)
    _, err = writer.WriteString(fmt.Sprintf("%s:%s\n", account, encryptedPassword))
    if err != nil {
        return err
    }

    return writer.Flush()
}

The savePassword function writes the encrypted password to a file, associating it with a specific account identifier.

Final Considerations

Building a secure password vault involves careful handling of encryption, key management, and data storage. While this guide provides a starting point, consider adopting additional security measures such as using a dedicated encryption library, integrating environment-specific key storage solutions like AWS KMS, or seeking security audit services.