> ## Documentation Index
> Fetch the complete documentation index at: https://docs.everabyte.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Go quickstart

> Encrypt files client-side in Go through the Everabyte Crypto SDK C ABI (cgo) — a complete zero-knowledge round trip.

Go integrates through the SDK's **C ABI** via **cgo**. The native library is `libevb_e2ee_ffi` (built from `bindings/dart/rust` of [everabyte/crypto-sdk](https://github.com/everabyte/crypto-sdk), or fetched from GitHub Releases).

## 1. Install

```bash theme={null}
git clone https://github.com/everabyte/crypto-sdk.git
cd crypto-sdk/bindings/dart/rust && cargo build --release
# → libevb_e2ee_ffi.so / .dylib
```

```go theme={null}
package evbe2ee

/*
#cgo LDFLAGS: -L/path/to/sdk -levb_e2ee_ffi
#include "evb_e2ee.h"   // from crypto-sdk/include/
*/
import "C"
```

Copy `include/evb_e2ee.h` next to your package. The Go wrappers below are the entire integration surface you need:

```go theme={null}
func generateUMK() ([]byte, error) {
	out := make([]C.uint8_t, 96)
	var l C.uint64_t
	if rc, _ := C.evb_generate_umk(&out[0], 96, &l); rc != 0 {
		return nil, lastError()
	}
	return C.GoBytes(unsafe.Pointer(&out[0]), 96), nil
}

func lastError() error {
	var buf [512]C.char
	if n, _ := C.evb_last_error(&buf[0], 512); n > 0 {
		return errors.New(C.GoString(&buf[0]))
	}
	return errors.New("unknown crypto error")
}
```

## 2. Account key (UMK) — once, kept in your secret store

```go theme={null}
umk, _ := generateUMK() // 96 bytes: X25519 secret(32) ‖ ML-KEM seed(64)

// Public keys → POST /e2ee/keys/register (+ mnemonic wrap via
// evb_wrap_umk_with_mnemonic(sk, &sk[32], phrase, salt16, nonce12, blob, cap)).
var jsonBuf [2048]C.char
C.evb_umk_public_keys((*C.uint8_t)(unsafe.Pointer(&umk[0])),
	(*C.uint8_t)(unsafe.Pointer(&umk[32])), &jsonBuf[0], 2048)
publics := string(C.GoString(&jsonBuf[0])) // {"publicKeyX25519":…,"publicKeyMlkem":…}
```

The 96 UMK bytes never leave your process; Everabyte receives only public keys and wrapped blobs.

## 3. Encrypt → upload → attach envelope

```go theme={null}
dek := randomBytes(32)      // your CSPRNG — never persisted
fileNonce := randomBytes(12)
plaintext, _ := os.ReadFile("contract.pdf")

payload := make([]C.uint8_t, len(plaintext)+65536+16)
var l C.uint64_t
rc, _ := C.evb1_seal_all((*C.uint8_t)(unsafe.Pointer(&dek[0])),
	(*C.uint8_t)(unsafe.Pointer(&fileNonce[0])),
	(*C.uint8_t)(unsafe.Pointer(&plaintext[0])), C.ulonglong(len(plaintext)),
	&payload[0], C.ulonglong(len(payload)), &l)
ciphertext := C.GoBytes(unsafe.Pointer(&payload[0]), C.int(l))

wireNameBuf := make([]C.char, 128)
realName := "contract.pdf"
C.evb_derive_wire_alias((*C.uint8_t)(unsafe.Pointer(&umk[0])),
	(*C.uint8_t)(unsafe.Pointer(&umk[32])), C.CString(realName),
	&wireNameBuf[0], 128)
wireName := C.GoString(&wireNameBuf[0]) // "evb-<hex64>"

encryptedName := make([]C.char, 512)
C.evb_encrypt_file_name((*C.uint8_t)(unsafe.Pointer(&dek[0])), C.CString(realName),
	(*C.uint8_t)(unsafe.Pointer(&fileNonce[0])), &encryptedName[0], 512)

envelopeBuf := make([]C.char, 4096)
// pass the base64-decoded PUBLIC keys from the register step here:
C.evb_wrap_dek_to_umk((*C.uint8_t)(unsafe.Pointer(&dek[0])),
	pkX25519Ptr, pkMlkemPtr, &envelopeBuf[0], 4096)
envelope := C.GoString(&envelopeBuf[0])

// POST /files/upload/{bucketId} (multipart, filename = wireName)
// POST /e2ee/files/by-path/envelope { bucketId, fileName: wireName, encryptedName, envelope }
// Check upload and attach responses. On timeout, reconcile by file ID before cleanup.
// After confirmed failure, resolve the row by bucket + wireName, confirm no envelope,
// and hard-delete through the file API as required by the E2EE upload contract.
// Handle retention blocks explicitly.
```

## 4. Download → decrypt

```go theme={null}
// GET /e2ee/files/{id}/envelope → envelope JSON
// GET /files/{id}/stream?download=true → stored ciphertext
dek := make([]C.uint8_t, 32)
C.evb_unwrap_dek_from_umk(C.CString(envelope),
	(*C.uint8_t)(unsafe.Pointer(&umk[0])),
	(*C.uint8_t)(unsafe.Pointer(&umk[32])),
	&dek[0], 32, &l)

original := make([]C.uint8_t, len(storedCiphertext))
C.evb1_open_all(&dek[0], (*C.uint8_t)(unsafe.Pointer(&storedCiphertext[0])),
	C.ulonglong(len(storedCiphertext)), &original[0],
	C.ulonglong(len(original)), &l)
plaintext := C.GoBytes(unsafe.Pointer(&original[0]), C.int(l))
// plaintext === the exact original file, decrypted on your machine
```

Error handling: every call returns `0` on success, negative otherwise; `evb_last_error(buf, cap)` reads the secret-free message (call with `cap = 0` first to get the required capacity).

## Next

* [C ABI reference](https://docs.everabyte.com/sdk/c-abi-reference.md) — every symbol and convention.
* [Node.js quickstart](https://docs.everabyte.com/sdk/quickstart-nodejs.md) — same round trip without a native library.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.