go-libaegis

March 19, 2026 ยท View on GitHub

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