A Go implementation of ECIES (Elliptic Curve Integrated Encryption Scheme) using modern cryptographic primitives for secure data encryption and key management.
- X25519 Key Exchange: Uses X25519 for ECDH key agreement (32-byte keys)
- ChaCha20-Poly1305: AEAD encryption with 12-byte nonce and 16-byte authentication tag
- Ed25519 Support: Generate and manage Ed25519 keys for digital signatures
- Standard PEM Format:
- Private keys saved in PKCS#8 format
- Public keys saved in X.509 SubjectPublicKeyInfo format
- Cross-language compatible formats (RFC 7468)
- Secure Key Storage: Private key files created with restrictive 0600 permissions
- Comprehensive Error Handling: Descriptive error types for all operations
go get github.com/krabt/eciespackage main
import (
"fmt"
"github.com/krabt/ecies"
)
func main() {
// Generate X25519 key pair for encryption
priv, pub, err := ecies.GenerateX25519Key()
if err != nil {
panic(err)
}
// Save to PEM files
if err := ecies.SavePrivateKeyToPEM("private.pem", priv); err != nil {
panic(err)
}
if err := ecies.SavePublicKeyToPEM("public.pem", pub); err != nil {
panic(err)
}
fmt.Println("Keys generated and saved!")
}package main
import (
"fmt"
"github.com/krabt/ecies"
)
func main() {
// Generate or load keys
priv, pub, _ := ecies.GenerateX25519Key()
// Encrypt a message
plaintext := []byte("Hello, ECIES!")
ciphertext, err := ecies.Encrypt(pub, plaintext)
if err != nil {
panic(err)
}
// Decrypt the message
decrypted, err := ecies.Decrypt(priv, ciphertext)
if err != nil {
panic(err)
}
fmt.Printf("Original: %s\n", string(plaintext))
fmt.Printf("Decrypted: %s\n", string(decrypted))
}package main
import (
"github.com/krabt/ecies"
)
func main() {
// Generate Ed25519 key pair for signatures
priv, pub, err := ecies.GenerateEd25519Key()
if err != nil {
panic(err)
}
// Save to PEM files
ecies.SavePrivateKeyToPEM("sign_private.pem", priv)
ecies.SavePublicKeyToPEM("sign_public.pem", pub)
}package main
import (
"crypto/ecdh"
"github.com/krabt/ecies"
)
func main() {
// Load private key
privRaw, err := ecies.LoadPrivateKeyFromPEM("private.pem")
if err != nil {
panic(err)
}
priv := privRaw.(*ecdh.PrivateKey)
// Load public key
pubRaw, err := ecies.LoadPublicKeyFromPEM("public.pem")
if err != nil {
panic(err)
}
pub := pubRaw.(*ecdh.PublicKey)
}GenerateX25519Key() (*ecdh.PrivateKey, *ecdh.PublicKey, error)- Generate X25519 key pairGenerateEd25519Key() (ed25519.PrivateKey, ed25519.PublicKey, error)- Generate Ed25519 key pair
SavePrivateKeyToPEM(filename string, anyPriv any) error- Save private key (PKCS#8)SavePublicKeyToPEM(filename string, anyPub any) error- Save public key (X.509)LoadPrivateKeyFromPEM(filename string) (any, error)- Load private key from PEMLoadPublicKeyFromPEM(filename string) (any, error)- Load public key from PEM
Encrypt(pub *ecdh.PublicKey, plaintext []byte) ([]byte, error)- Encrypt dataDecrypt(priv *ecdh.PrivateKey, ciphertext []byte) ([]byte, error)- Decrypt data
- Ephemeral Key Generation: Generate a random ephemeral X25519 key pair
- Shared Secret: Compute ECDH shared secret between ephemeral private key and recipient's public key
- Key Derivation: Use the shared secret as nonce input for ChaCha20-Poly1305
- Encryption: Encrypt plaintext using ChaCha20-Poly1305
- Output Format:
[ephemeral_public_key (32 bytes)][nonce (12 bytes)][ciphertext + tag]
- X25519 Public Key Size: 32 bytes
- ChaCha20 Nonce Size: 12 bytes
- Poly1305 Tag Size: 16 bytes
- Header Size: 44 bytes (32 + 12)
ErrPacketTooShort- Ciphertext packet is too shortErrInvalidPubKey- Invalid ephemeral public keyErrDecryptionFailed- Decryption failed (data may be tampered or wrong key)ErrInvalidPEM- Invalid PEM block or block type mismatch
- Key Storage: Private keys are saved with 0600 permissions (owner read/write only)
- Nonce: Each encryption operation uses a unique nonce derived from the ephemeral key
- Authentication: ChaCha20-Poly1305 provides both confidentiality and authenticity
- Constants: PEM block types follow RFC 7468 standards
Run the test suite:
go test -vThe tests cover:
- Full ECIES encryption/decryption flow
- Key generation and persistence
- PEM file I/O operations
- Cross-version key compatibility
golang.org/x/crypto- For cryptographic primitives- Standard Go
cryptolibrary - For ECDH, Ed25519, and x509/PEM support
This project is licensed under the MIT License - see the LICENSE file for details.