Skip to content

Commit 7b55788

Browse files
committed
Import
1 parent 1a88be7 commit 7b55788

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+970
-0
lines changed

.github/workflows/go.yml

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# This workflow will build a golang project
2+
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go
3+
4+
name: CI
5+
6+
on:
7+
push:
8+
branches: [ "main" ]
9+
pull_request:
10+
branches: [ "main" ]
11+
12+
jobs:
13+
14+
build:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- uses: actions/checkout@v4
18+
with:
19+
fetch-depth: 1
20+
submodules: 'recursive'
21+
22+
- name: Set up Go
23+
uses: actions/setup-go@v4
24+
with:
25+
go-version: '1'
26+
27+
- name: Build
28+
run: go build -v ./...
29+
30+
- name: Test
31+
run: go test -v ./...

.gitignore

+6
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,9 @@ go.work.sum
2323

2424
# env file
2525
.env
26+
27+
# Zig
28+
.zig-cache
29+
30+
# temp files
31+
*~

.gitmodules

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "common/libaegis"]
2+
path = common/libaegis
3+
url = https://github.com/aegis-aead/libaegis

README.md

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# go-libaegis
2+
3+
[![Go Reference](https://pkg.go.dev/badge/github.com/jedisct1/go-libaegis.svg)](https://pkg.go.dev/github.com/jedisct1/go-libaegis)
4+
[![License](https://img.shields.io/github/license/jedisct1/go-libaegis)](https://github.com/jedisct1/go-libaegis/blob/main/LICENSE)
5+
6+
A Go binding for [libaegis](https://github.com/jedisct1/libaegis), implementing a family of fast and modern authenticated encryption algorithms designed for high performance and security.
7+
8+
## Features
9+
10+
- Provides a Go wrapper around `libaegis` for seamless integration.
11+
- Implements AEGIS-128L, AEGIS-128X, AEGIS-256 and AEGIS-256X.
12+
- Optimized for modern CPUs with hardware acceleration.
13+
- Lightweight and easy to use within Go applications.
14+
15+
## Installation
16+
17+
To install `go-libaegis`, use:
18+
19+
```sh
20+
go get github.com/jedisct1/go-libaegis
21+
```
22+
23+
## Usage
24+
25+
```go
26+
package main
27+
28+
import (
29+
"crypto/rand"
30+
"fmt"
31+
// other options:
32+
// aegis128l, aegis128x4, aegis256, aegis256x2, aegis256x4
33+
"github.com/jedisct1/go-libaegis/aegis128x2"
34+
)
35+
36+
func main() {
37+
key := make([]byte, aegis128x2.KeySize)
38+
rand.Read(key)
39+
40+
nonce := make([]byte, aegis128x2.NonceSize)
41+
rand.Read(nonce)
42+
43+
plaintext := []byte("Hello, world!")
44+
associatedData := []byte("metadata")
45+
46+
// tag size can be 16 or 32 bytes
47+
aead := aegis128x2.New(key, 16)
48+
49+
ciphertext := aead.Seal(nil, nonce, plaintext, associatedData)
50+
51+
decrypted, err := aead.Open(nil, nonce, ciphertext, associatedData)
52+
if err != nil {
53+
panic(err)
54+
}
55+
56+
fmt.Println("Decrypted message:", string(decrypted))
57+
}
58+
```
59+
60+
## API Reference
61+
62+
- `Encrypt(plaintext, associatedData, nonce, key []byte) ([]byte, error)`
63+
- `Decrypt(ciphertext, associatedData, nonce, key []byte) ([]byte, error)`
64+
- `KeySize` (constant): Size of the encryption key in bytes.
65+
- `NonceSize` (constant): Size of the nonce in bytes.
66+
67+
## Requirements
68+
69+
- Go 1.16+
70+
- A C compiler
71+
72+
## License
73+
74+
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
75+
76+
## Contributing
77+
78+
Contributions are welcome! Feel free to open an issue or submit a pull request.
79+
80+
## Security Notice
81+
82+
Always ensure that you use randomly generated keys and unique nonces when using authenticated encryption to maintain security.

aegis128l/aegis128l.go

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package aegis128l
2+
3+
// #include <aegis.h>
4+
// #cgo CFLAGS: -I../common/libaegis/src/include
5+
import "C"
6+
7+
import (
8+
"crypto/cipher"
9+
10+
"github.com/jedisct1/go-libaegis/common"
11+
)
12+
13+
const (
14+
KeySize = 16
15+
NonceSize = 16
16+
)
17+
18+
type Aegis128L struct {
19+
common.Aegis
20+
}
21+
22+
// The nonce size, in bytes.
23+
func (aead *Aegis128L) NonceSize() int {
24+
return NonceSize
25+
}
26+
27+
// New returns a new AEAD that uses the provided key and tag length.
28+
// The key must be 16 bytes long.
29+
// The tag length must be 16 or 32.
30+
func New(key []byte, tagLen int) (cipher.AEAD, error) {
31+
if len(key) != KeySize {
32+
return nil, common.ErrBadKeyLength
33+
}
34+
if tagLen != 16 && tagLen != 32 {
35+
return nil, common.ErrBadTagLength
36+
}
37+
a := new(Aegis128L)
38+
a.TagLen = tagLen
39+
a.Key = key
40+
return a, nil
41+
}
42+
43+
func (aead *Aegis128L) Seal(dst, nonce, cleartext, additionalData []byte) []byte {
44+
if len(nonce) != aead.NonceSize() {
45+
panic("aegis: invalid nonce length")
46+
}
47+
outLen := len(cleartext) + aead.TagLen
48+
var buf []byte
49+
inplace := false
50+
if cap(dst)-len(dst) >= outLen {
51+
inplace = true
52+
buf = dst[len(dst) : len(dst)+outLen]
53+
} else {
54+
buf = make([]byte, outLen)
55+
}
56+
res := C.aegis128l_encrypt((*C.uchar)(&buf[0]), C.size_t(aead.TagLen), slicePointerOrNull(cleartext),
57+
C.size_t(len(cleartext)), slicePointerOrNull(additionalData), C.size_t(len(additionalData)), (*C.uchar)(&nonce[0]), (*C.uchar)(&aead.Key[0]))
58+
if res != 0 {
59+
panic("encryption failed")
60+
}
61+
if inplace {
62+
return dst[:len(dst)+outLen]
63+
}
64+
return append(dst, buf...)
65+
}
66+
67+
func (aead *Aegis128L) Open(plaintext, nonce, ciphertext, additionalData []byte) ([]byte, error) {
68+
if len(nonce) != aead.NonceSize() {
69+
return nil, common.ErrBadNonceLength
70+
}
71+
if len(ciphertext) < aead.TagLen {
72+
return nil, common.ErrTruncated
73+
}
74+
outLen := len(ciphertext) - aead.TagLen
75+
var buf []byte
76+
inplace := false
77+
if cap(plaintext)-len(plaintext) >= outLen {
78+
inplace = true
79+
buf = plaintext[len(plaintext) : len(plaintext)+outLen]
80+
} else {
81+
buf = make([]byte, len(ciphertext)-aead.TagLen)
82+
}
83+
res := C.aegis128l_decrypt((*C.uchar)(&buf[0]), slicePointerOrNull(ciphertext),
84+
C.size_t(len(ciphertext)), C.size_t(aead.TagLen), slicePointerOrNull(additionalData), C.size_t(len(additionalData)), (*C.uchar)(&nonce[0]), (*C.uchar)(&aead.Key[0]))
85+
if res != 0 {
86+
return nil, common.ErrAuth
87+
}
88+
if inplace {
89+
return plaintext[:len(plaintext)+outLen], nil
90+
}
91+
return append(plaintext, buf...), nil
92+
}
93+
94+
func slicePointerOrNull(s []byte) (ptr *C.uchar) {
95+
if len(s) == 0 {
96+
return
97+
}
98+
return (*C.uchar)(&s[0])
99+
}

aegis128l/aegis128l_test.go

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package aegis128l
2+
3+
import (
4+
"crypto/rand"
5+
"fmt"
6+
)
7+
8+
func Example() {
9+
key := make([]byte, KeySize)
10+
rand.Read(key)
11+
aead, err := New(key, 16)
12+
if err != nil {
13+
panic(err)
14+
}
15+
16+
nonce := make([]byte, aead.NonceSize())
17+
rand.Read(nonce)
18+
19+
ciphertext := aead.Seal(nil, nonce, []byte("hello, world!"), nil)
20+
21+
plaintext, err := aead.Open(nil, nonce, ciphertext, nil)
22+
if err != nil {
23+
panic(err)
24+
}
25+
26+
fmt.Println(string(plaintext))
27+
// Output: hello, world!
28+
}

aegis128x2/aegis128x2.go

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package aegis128x2
2+
3+
// #include <aegis.h>
4+
// #cgo CFLAGS: -I../common/libaegis/src/include
5+
import "C"
6+
7+
import (
8+
"crypto/cipher"
9+
10+
"github.com/jedisct1/go-libaegis/common"
11+
)
12+
13+
const (
14+
KeySize = 16
15+
NonceSize = 16
16+
)
17+
18+
type Aegis128X2 struct {
19+
common.Aegis
20+
}
21+
22+
// The nonce size, in bytes.
23+
func (aead *Aegis128X2) NonceSize() int {
24+
return NonceSize
25+
}
26+
27+
// New returns a new AEAD that uses the provided key and tag length.
28+
// The key must be 16 bytes long.
29+
// The tag length must be 16 or 32.
30+
func New(key []byte, tagLen int) (cipher.AEAD, error) {
31+
if len(key) != KeySize {
32+
return nil, common.ErrBadKeyLength
33+
}
34+
if tagLen != 16 && tagLen != 32 {
35+
return nil, common.ErrBadTagLength
36+
}
37+
a := new(Aegis128X2)
38+
a.TagLen = tagLen
39+
a.Key = key
40+
return a, nil
41+
}
42+
43+
func (aead *Aegis128X2) Seal(dst, nonce, cleartext, additionalData []byte) []byte {
44+
if len(nonce) != aead.NonceSize() {
45+
panic("aegis: invalid nonce length")
46+
}
47+
outLen := len(cleartext) + aead.TagLen
48+
var buf []byte
49+
inplace := false
50+
if cap(dst)-len(dst) >= outLen {
51+
inplace = true
52+
buf = dst[len(dst) : len(dst)+outLen]
53+
} else {
54+
buf = make([]byte, outLen)
55+
}
56+
res := C.aegis128x2_encrypt((*C.uchar)(&buf[0]), C.size_t(aead.TagLen), slicePointerOrNull(cleartext),
57+
C.size_t(len(cleartext)), slicePointerOrNull(additionalData), C.size_t(len(additionalData)), (*C.uchar)(&nonce[0]), (*C.uchar)(&aead.Key[0]))
58+
if res != 0 {
59+
panic("encryption failed")
60+
}
61+
if inplace {
62+
return dst[:len(dst)+outLen]
63+
}
64+
return append(dst, buf...)
65+
}
66+
67+
func (aead *Aegis128X2) Open(plaintext, nonce, ciphertext, additionalData []byte) ([]byte, error) {
68+
if len(nonce) != aead.NonceSize() {
69+
return nil, common.ErrBadNonceLength
70+
}
71+
if len(ciphertext) < aead.TagLen {
72+
return nil, common.ErrTruncated
73+
}
74+
outLen := len(ciphertext) - aead.TagLen
75+
var buf []byte
76+
inplace := false
77+
if cap(plaintext)-len(plaintext) >= outLen {
78+
inplace = true
79+
buf = plaintext[len(plaintext) : len(plaintext)+outLen]
80+
} else {
81+
buf = make([]byte, len(ciphertext)-aead.TagLen)
82+
}
83+
res := C.aegis128x2_decrypt((*C.uchar)(&buf[0]), slicePointerOrNull(ciphertext),
84+
C.size_t(len(ciphertext)), C.size_t(aead.TagLen), slicePointerOrNull(additionalData), C.size_t(len(additionalData)), (*C.uchar)(&nonce[0]), (*C.uchar)(&aead.Key[0]))
85+
if res != 0 {
86+
return nil, common.ErrAuth
87+
}
88+
if inplace {
89+
return plaintext[:len(plaintext)+outLen], nil
90+
}
91+
return append(plaintext, buf...), nil
92+
}
93+
94+
func slicePointerOrNull(s []byte) (ptr *C.uchar) {
95+
if len(s) == 0 {
96+
return
97+
}
98+
return (*C.uchar)(&s[0])
99+
}

aegis128x2/aegis128x2_test.go

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package aegis128x2
2+
3+
import (
4+
"crypto/rand"
5+
"fmt"
6+
)
7+
8+
func Example() {
9+
key := make([]byte, KeySize)
10+
rand.Read(key)
11+
aead, err := New(key, 16)
12+
if err != nil {
13+
panic(err)
14+
}
15+
16+
nonce := make([]byte, aead.NonceSize())
17+
rand.Read(nonce)
18+
19+
ciphertext := aead.Seal(nil, nonce, []byte("hello, world!"), nil)
20+
21+
plaintext, err := aead.Open(nil, nonce, ciphertext, nil)
22+
if err != nil {
23+
panic(err)
24+
}
25+
26+
fmt.Println(string(plaintext))
27+
// Output: hello, world!
28+
}

0 commit comments

Comments
 (0)