Skip to content

aegis-aead/go-libaegis

Repository files navigation

go-libaegis

Go Reference License

A Go binding for libaegis, implementing the AEGIS family of modern authenticated encryption algorithms designed for high performance and security.

Features

  • Provides a Go wrapper around libaegis for seamless integration.
  • Implements AEGIS-128L, AEGIS-128X, AEGIS-256 and AEGIS-256X.
  • Supports both one-shot and incremental (streaming) encryption/decryption.
  • Random-access encrypted file I/O (RAF) with per-chunk authentication.
  • Optimized for modern CPUs with hardware acceleration.
  • Lightweight and easy to use within Go applications.

Installation

To install go-libaegis, use:

go get github.com/aegis-aead/go-libaegis

Usage

package main

import (
    "crypto/rand"
    "fmt"
    // other options:
    // aegis128l, aegis128x4, aegis256, aegis256x2, aegis256x4    
    "github.com/aegis-aead/go-libaegis/aegis128x2"
)

func main() {
    key := make([]byte, aegis128x2.KeySize)
    rand.Read(key)

    nonce := make([]byte, aegis128x2.NonceSize)
    rand.Read(nonce)

    plaintext := []byte("Hello, world!")
    associatedData := []byte("metadata")

    // tag size can be 16 or 32 bytes
    aead, err := aegis128x2.New(key, 16)
    if err != nil {
        panic(err)
    }

    ciphertext := aead.Seal(nil, nonce, plaintext, associatedData)

    decrypted, err := aead.Open(nil, nonce, ciphertext, associatedData)
    if err != nil {
        panic(err)
    }

    fmt.Println("Decrypted message:", string(decrypted))
}

Incremental encryption/decryption

For large messages or streaming scenarios, use the incremental API to process data in chunks:

package main

import (
    "crypto/rand"
    "fmt"
    "github.com/aegis-aead/go-libaegis/aegis128l"
)

func main() {
    key := make([]byte, aegis128l.KeySize)
    rand.Read(key)

    nonce := make([]byte, aegis128l.NonceSize)
    rand.Read(nonce)

    associatedData := []byte("metadata")
    tagLen := 16

    // Incremental encryption
    enc, err := aegis128l.NewEncrypter(key, nonce, associatedData, tagLen)
    if err != nil {
        panic(err)
    }

    // Encrypt data in chunks - ciphertext is output immediately
    ciphertext1 := enc.Encrypt([]byte("Hello, "))
    ciphertext2 := enc.Encrypt([]byte("world!"))
    tag := enc.Final()

    // Incremental decryption
    dec, err := aegis128l.NewDecrypter(key, nonce, associatedData, tagLen)
    if err != nil {
        panic(err)
    }

    // Decrypt chunks - but don't use plaintext until Final succeeds!
    plaintext1 := dec.Decrypt(ciphertext1)
    plaintext2 := dec.Decrypt(ciphertext2)

    // Verify authentication tag
    if err := dec.Final(tag); err != nil {
        // Authentication failed - discard all decrypted data
        panic("authentication failed")
    }

    // Now it's safe to use the plaintext
    fmt.Println("Decrypted:", string(plaintext1)+string(plaintext2))
}

The incremental API is interoperable with the one-shot API: ciphertext || tag from incremental encryption equals the output of Seal().

Random-access encrypted files (RAF)

The raf package provides random-access read/write on encrypted files. Data is split into independently authenticated chunks, so you can read or write at any offset without decrypting the entire file.

package main

import (
    "crypto/rand"
    "fmt"
    "os"

    "github.com/aegis-aead/go-libaegis/raf"
)

func main() {
    key := make([]byte, 32) // AEGIS-256 uses 32-byte keys
    rand.Read(key)

    f, _ := os.Create("secret.raf")
    defer f.Close()

    store := raf.NewFileStore(f)
    ef, _ := raf.Create(store, key, &raf.Options{
        Algorithm: raf.AEGIS256,
        ChunkSize: 65536,
    })

    ef.WriteAt([]byte("hello, world"), 0)

    buf := make([]byte, 12)
    ef.ReadAt(buf, 0)
    fmt.Println(string(buf)) // "hello, world"

    ef.Close()
}

Opening an existing file auto-detects the algorithm and chunk size from the header:

store := raf.NewFileStore(f)
ef, _ := raf.Open(store, key, nil)
defer ef.Close()

You can also inspect the header without a key using raf.Probe(store).

The raf.File type implements io.ReaderAt, io.WriterAt, and io.Closer. It is not safe for concurrent use; callers needing concurrent access must synchronize externally.

Requirements

  • Go 1.19+
  • A C toolchain

License

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

Contributing

Contributions are welcome! Feel free to open an issue or submit a pull request.

Security Notice

Always ensure that you use randomly generated keys and unique nonces when using authenticated encryption to maintain security.

Alternatives in Go

About

The AEGIS family of authenticated encryption algorithms for Go.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors