age

package module
v0.0.0-...-af588ad Latest Latest
Warning

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

Go to latest
Published: Feb 8, 2025 License: BSD-3-Clause Imports: 3 Imported by: 0

README

age-concurrent

A concurrent, API-compatible wrapper around FiloSottile/age, providing efficient encryption and decryption using multiple workers.

Overview

age-concurrent is a drop-in replacement for age that accelerates encryption and decryption by utilizing multiple concurrent workers. It maintains full API compatibility with filippo.io/age, ensuring seamless integration while enhancing performance.

Features

  • Concurrent Encryption & Decryption: Uses runtime.NumCPU() workers by default, configurable via EncryptN and DecryptN.
  • API-Compatible: Functions and signatures match filippo.io/age.

Installation

go get github.com/bifrosta/age-concurrent

Usage

Encrypt
package main

import (
	"os"
	"github.com/bifrosta/age-concurrent"
)

func main() {
	file, _ := os.Create("encrypted.age")
	recipient, _ := age.ParseX25519Recipient("age1...")
	writer, _ := age.Encrypt(file, recipient)
	writer.Write([]byte("Hello, encrypted world!"))
	writer.Close()
}
Decrypt
package main

import (
	"os"
	"github.com/bifrosta/age-concurrent"
)

func main() {
	file, _ := os.Open("encrypted.age")
	identity, _ := age.ParseX25519Identity("AGE-SECRET-KEY-1...")
	reader, _ := age.Decrypt(file, identity)
	io.Copy(os.Stdout, reader)
}
Controlling Concurrency
writer, _ := age.EncryptN(file, 4, recipient) // Use 4 workers
reader, _ := age.DecryptN(file, 4, identity)  // Use 4 workers

Performance

Benchmark results on an AMD Ryzen 9 7950X 16-Core Processor show some speed improvements with increased concurrency:

CPU Cores Read Speed (MB/s) Write Speed (MB/s)
(upstream age) 3179 4202
1 3897 2682
2 4760 4659
4 5743 5484
8 7572 7479
16 8758 9268
32 7781 10503

Higher concurrency levels generally improve performance, particularly for encryption operations. However, performance may plateau at very high core counts due to memory bandwidth and synchronization overhead. Do your own testing to find the optimal concurrency level for your workload and hardware.

Experimental Status

Warning: This project is highly experimental and untested. While it aims to provide improved performance over age, it has not undergone rigorous security auditing or extensive testing. Use at your own risk, and do not rely on it for critical applications without performing your own verification.

License

age-concurrent is licensed under the same terms as age. See the LICENSE file for details.

Acknowledgements

Built on top of filippo.io/age with performance enhancements for concurrency.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ParseIdentities parses a file with one or more private key encodings, one per
	// line. Empty lines and lines starting with "#" are ignored.
	//
	// This is the same syntax as the private key files accepted by the CLI, except
	// the CLI also accepts SSH private keys, which are not recommended for the
	// average application.
	//
	// Currently, all returned values are of type *X25519Identity, but different
	// types might be returned in the future.
	ParseIdentities = age.ParseIdentities

	// ParseRecipients parses a file with one or more public key encodings, one per
	// line. Empty lines and lines starting with "#" are ignored.
	//
	// This is the same syntax as the recipients files accepted by the CLI, except
	// the CLI also accepts SSH recipients, which are not recommended for the
	// average application.
	//
	// Currently, all returned values are of type *X25519Recipient, but different
	// types might be returned in the future.
	ParseRecipients = age.ParseRecipients

	// NewScryptIdentity returns a new ScryptIdentity with the provided password.
	NewScryptIdentity = age.NewScryptIdentity

	// NewScryptRecipient returns a new ScryptRecipient with the provided password.
	NewScryptRecipient = age.NewScryptRecipient

	// GenerateX25519Identity randomly generates a new X25519Identity.
	GenerateX25519Identity = age.GenerateX25519Identity

	// ParseX25519Identity returns a new X25519Identity from a Bech32 private key
	// encoding with the "AGE-SECRET-KEY-1" prefix.
	ParseX25519Identity = age.ParseX25519Identity

	// ParseX25519Recipient returns a new X25519Recipient from a Bech32 public key
	// encoding with the "age1" prefix.
	ParseX25519Recipient = age.ParseX25519Recipient
)

Functions and documentation from the real age package.

View Source
var (
	ErrIncorrectIdentity = age.ErrIncorrectIdentity
)

Exported errors from the real age package.

Functions

func Decrypt

func Decrypt(src io.Reader, identities ...Identity) (io.Reader, error)

Decrypt decrypts a file encrypted to one or more identities.

It returns a Reader reading the decrypted plaintext of the age file read from src. All identities will be tried until one successfully decrypts the file.

This will use runtime.NumCPU() as the number of concurrent workers.

func DecryptN

func DecryptN(src io.Reader, concurrent int, identities ...Identity) (io.Reader, error)

DecryptN decrypts a file encrypted to one or more identities.

It behaves like Decrypt, but allows the caller to specify the number of concurrent workers to use.

func Encrypt

func Encrypt(dst io.Writer, recipients ...Recipient) (io.WriteCloser, error)

Encrypt encrypts a file to one or more recipients.

Writes to the returned WriteCloser are encrypted and written to dst as an age file. Every recipient will be able to decrypt the file.

The caller must call Close on the WriteCloser when done for the last chunk to be encrypted and flushed to dst.

This will use runtime.NumCPU() as the number of concurrent workers.

func EncryptN

func EncryptN(dst io.Writer, concurrent int, recipients ...Recipient) (io.WriteCloser, error)

EncryptN encrypts a file to one or more recipients.

It behaves like Encrypt, but allows the caller to specify the number of concurrent workers to use.

Types

type Identity

type Identity = age.Identity

An Identity is passed to Decrypt to unwrap an opaque file key from a recipient stanza. It can be for example a secret key like X25519Identity, a plugin, or a custom implementation.

Unwrap must return an error wrapping ErrIncorrectIdentity if none of the recipient stanzas match the identity, any other error will be considered fatal.

Most age API users won't need to interact with this directly, and should instead pass Recipient implementations to Encrypt and Identity implementations to Decrypt.

type NoIdentityMatchError

type NoIdentityMatchError = age.NoIdentityMatchError

NoIdentityMatchError is returned by Decrypt when none of the supplied identities match the encrypted file.

type Recipient

type Recipient = age.Recipient

A Recipient is passed to Encrypt to wrap an opaque file key to one or more recipient stanza(s). It can be for example a public key like X25519Recipient, a plugin, or a custom implementation.

Most age API users won't need to interact with this directly, and should instead pass Recipient implementations to Encrypt and Identity implementations to Decrypt.

type RecipientWithLabels

type RecipientWithLabels = age.RecipientWithLabels

RecipientWithLabels can be optionally implemented by a Recipient, in which case Encrypt will use WrapWithLabels instead of Wrap.

Encrypt will succeed only if the labels returned by all the recipients (assuming the empty set for those that don't implement RecipientWithLabels) are the same.

This can be used to ensure a recipient is only used with other recipients with equivalent properties (for example by setting a "postquantum" label) or to ensure a recipient is always used alone (by returning a random label, for example to preserve its authentication properties).

type ScryptIdentity

type ScryptIdentity = age.ScryptIdentity

ScryptIdentity is a password-based identity.

type ScryptRecipient

type ScryptRecipient = age.ScryptRecipient

ScryptRecipient is a password-based recipient. Anyone with the password can decrypt the message.

If a ScryptRecipient is used, it must be the only recipient for the file: it can't be mixed with other recipient types and can't be used multiple times for the same file.

Its use is not recommended for automated systems, which should prefer X25519Recipient.

type Stanza

type Stanza = age.Stanza

A Stanza is a section of the age header that encapsulates the file key as encrypted to a specific recipient.

Most age API users won't need to interact with this directly, and should instead pass Recipient implementations to Encrypt and Identity implementations to Decrypt.

type X25519Identity

type X25519Identity = age.X25519Identity

X25519Identity is the standard age private key, which can decrypt messages encrypted to the corresponding X25519Recipient.

type X25519Recipient

type X25519Recipient = age.X25519Recipient

X25519Recipient is the standard age public key. Messages encrypted to this recipient can be decrypted with the corresponding X25519Identity.

This recipient is anonymous, in the sense that an attacker can't tell from the message alone if it is encrypted to a certain recipient.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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