securebolt

package module
v0.0.0-...-1674edc Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 27, 2024 License: MIT Imports: 11 Imported by: 0

README

# SecureBolt

SecureBolt is a Go package that provides transparent, secure encryption for your data stored in [BoltDB (bbolt)](https://github.com/etcd-io/bbolt), an embedded key-value database. It leverages strong cryptographic practices to ensure data confidentiality and integrity, making it suitable for applications that require secure data storage without the overhead of managing external databases.

## Features

- **Transparent Encryption**: Data is automatically encrypted before storage and decrypted upon retrieval.
- **Strong Cryptography**: Uses AES-GCM for encryption and Argon2id for key derivation.
- **Secure Memory Handling**: Employs [memguard](https://github.com/awnumar/memguard) to protect sensitive data in memory.
- **BoltDB Compatibility**: Provides an API similar to BoltDB for easy integration.
- **Thread Safety**: Designed with concurrency in mind using mutexes for safe access.

## Installation

To install SecureBolt, run:

```bash
go get github.com/yourusername/securebolt

Replace github.com/marcgauthier/securebolt with the actual import path of the package.

Usage

Opening a Secure Database

To start using SecureBolt, you need to open or create a database by providing a filename, file mode, and a password. The password is used to derive the encryption key securely.

package main

import (
    "log"
    "github.com/yourusername/securebolt"
    "github.com/awnumar/memguard"
)

func main() {
    // Ensure memguard catches interrupts to securely destroy sensitive data
    memguard.CatchInterrupt()

    // Use a strong, high-entropy password
    password := []byte("your-secure-password")

    // Open or create the database
    db, err := securebolt.Open("mydb.db", 0600, password)
    if err != nil {
        log.Fatal(err)
    }
    defer func() {
        // Close the database securely
        if err := db.Close(); err != nil {
            log.Fatal(err)
        }
    }()

    // Securely wipe the password from memory
    memguard.WipeBytes(password)

    // Your application logic here...
}

Storing Data

err = db.Update(func(tx *securebolt.SecureTx) error {
    // Create or retrieve a bucket
    bucket, err := tx.CreateBucketIfNotExists([]byte("MyBucket"))
    if err != nil {
        return err
    }

    // Store a key-value pair (both key and value are byte slices)
    key := []byte("username")
    value := []byte("john_doe")
    return bucket.Put(key, value)
})
if err != nil {
    log.Fatal(err)
}

Retrieving Data

err = db.View(func(tx *securebolt.SecureTx) error {
    // Retrieve the bucket
    bucket, err := tx.Bucket([]byte("MyBucket"))
    if err != nil {
        return err
    }

    // Retrieve the value for a key
    key := []byte("username")
    value, err := bucket.Get(key)
    if err != nil {
        return err
    }

    if value == nil {
        log.Println("Key not found")
    } else {
        log.Printf("Retrieved value: %s\n", value)
    }
    return nil
})
if err != nil {
    log.Fatal(err)
}

Deleting Data

err = db.Update(func(tx *securebolt.SecureTx) error {
    bucket, err := tx.Bucket([]byte("MyBucket"))
    if err != nil {
        return err
    }

    // Delete the key-value pair
    key := []byte("username")
    return bucket.Delete(key)
})
if err != nil {
    log.Fatal(err)
}

Iterating Over Data

err = db.View(func(tx *securebolt.SecureTx) error {
    bucket, err := tx.Bucket([]byte("MyBucket"))
    if err != nil {
        return err
    }

    // Iterate over all key-value pairs in the bucket
    err = bucket.ForEach(func(k, v []byte) error {
        log.Printf("Key: %s, Value: %s\n", k, v)
        return nil
    })
    return err
})
if err != nil {
    log.Fatal(err)
}

Using a Cursor

err = db.View(func(tx *securebolt.SecureTx) error {
    bucket, err := tx.Bucket([]byte("MyBucket"))
    if err != nil {
        return err
    }

    cursor := bucket.Cursor()

    for k, v, err := cursor.First(); k != nil && err == nil; k, v, err = cursor.Next() {
        if err != nil {
            return err
        }
        log.Printf("Key: %s, Value: %s\n", k, v)
    }

    return nil
})
if err != nil {
    log.Fatal(err)
}

Handling Transactions

SecureBolt supports read-only and read-write transactions similar to BoltDB.

  • Read-Only Transaction: Use db.View() to create a read-only transaction.
  • Read-Write Transaction: Use db.Update() to create a read-write transaction.

Security Considerations

  • Password Management: Use a strong, high-entropy password and securely erase it from memory after use with memguard.WipeBytes().

  • Key Derivation: SecureBolt uses Argon2id with sensible defaults for time, memory, and parallelism. Adjust these parameters in deriveKey() if needed.

  • Salt Storage: The salt used for key derivation is stored unencrypted in the database's securebolt_meta bucket. Do not modify or expose this bucket.

  • Memory Protection: Sensitive data is stored in locked buffers to prevent memory paging and unauthorized access.

  • Encryption Details: Data is encrypted using AES-GCM, which provides both confidentiality and integrity. Do not change the encryption algorithm unless necessary and you understand the implications.

Limitations

  • Single Password: The entire database uses a single password. There's no support for multiple passwords or user-specific encryption keys.

  • No Key Rotation: Changing the encryption password requires creating a new database and migrating data.

  • Concurrency: While SecureBolt uses mutexes for thread safety, high levels of concurrency may affect performance.

License

This project is licensed under the MIT License. See the LICENSE file for details.

Contributing

Contributions are welcome! Please open an issue or submit a pull request on GitHub.

Acknowledgments


Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type SecureBolt

type SecureBolt struct {
	// contains filtered or unexported fields
}

SecureBolt wraps a bbolt.DB and manages encryption for SecureBucket.

func Open

func Open(filename string, mode fs.FileMode, password []byte) (*SecureBolt, error)

func (*SecureBolt) Close

func (s *SecureBolt) Close() error

Close securely destroys the encryption key and closes the database.

func (*SecureBolt) Update

func (s *SecureBolt) Update(fn func(tx *SecureTx) error) error

func (*SecureBolt) View

func (s *SecureBolt) View(fn func(tx *SecureTx) error) error

type SecureBucket

type SecureBucket struct {
	// contains filtered or unexported fields
}

func (*SecureBucket) Cursor

func (sb *SecureBucket) Cursor() *SecureCursor

Cursor creates a new cursor associated with the bucket.

func (*SecureBucket) Delete

func (sb *SecureBucket) Delete(key []byte) error

Delete removes the key and its value from the bucket.

func (*SecureBucket) ForEach

func (sb *SecureBucket) ForEach(fn func(k, v []byte) error) error

ForEach calls the provided function with each key and decrypted value in the bucket.

func (*SecureBucket) Get

func (sb *SecureBucket) Get(key []byte) ([]byte, error)

Get retrieves the encrypted value for a given key and decrypts it.

func (*SecureBucket) Put

func (sb *SecureBucket) Put(key, value []byte) error

Put encrypts the value and stores it in the underlying bucket with the given key.

type SecureCursor

type SecureCursor struct {
	// contains filtered or unexported fields
}

func (*SecureCursor) First

func (sc *SecureCursor) First() ([]byte, []byte, error)

First moves the cursor to the first key/value pair and returns it.

func (*SecureCursor) Next

func (sc *SecureCursor) Next() ([]byte, []byte, error)

Next moves the cursor to the next key/value pair and returns it.

func (*SecureCursor) Prev

func (sc *SecureCursor) Prev() ([]byte, []byte, error)

Prev moves the cursor to the previous key/value pair and returns it.

func (*SecureCursor) Seek

func (sc *SecureCursor) Seek(seek []byte) ([]byte, []byte, error)

Seek moves the cursor to a given key and returns the associated key/value pair.

type SecureTx

type SecureTx struct {
	// contains filtered or unexported fields
}

SecureTx wraps a bbolt.Tx and provides methods to access SecureBucket.

func (*SecureTx) Bucket

func (stx *SecureTx) Bucket(name []byte) (*SecureBucket, error)

func (*SecureTx) CreateBucket

func (stx *SecureTx) CreateBucket(name []byte) (*SecureBucket, error)

func (*SecureTx) CreateBucketIfNotExists

func (stx *SecureTx) CreateBucketIfNotExists(name []byte) (*SecureBucket, error)

func (*SecureTx) DeleteBucket

func (stx *SecureTx) DeleteBucket(name []byte) error

DeleteBucket deletes the bucket with the given name.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL