Documentation
¶
Overview ¶
Package xipher provides a curated collection of cryptographic primitives for performing key/password-based asymmetric encryption.
Xipher allows secure data sharing between two parties over an insecure channel using asymmetric encryption. The sender encrypts data using a public key (usually derived from a password) and shares the encrypted data with the receiver. The receiver decrypts the data using the corresponding secret key or password.
Key features:
- Password-based public key generation
- Stream cipher with compression support
- Post-quantum cryptography using Kyber1024
- Stream processing for memory efficiency
Example usage:
// Create a secret key from password
secretKey, err := xipher.NewSecretKeyForPassword([]byte("mypassword"))
if err != nil {
panic(err)
}
// Generate public key
publicKey, err := secretKey.PublicKey(false)
if err != nil {
panic(err)
}
// Encrypt data
plaintext := []byte("Hello, World!")
ciphertext, err := publicKey.Encrypt(plaintext, true, true)
if err != nil {
panic(err)
}
// Decrypt data
decrypted, err := secretKey.Decrypt(ciphertext)
if err != nil {
panic(err)
}
Package xipher provides a curated collection of cryptographic primitives for performing key/password-based asymmetric encryption with support for post-quantum cryptography.
Overview ¶
Xipher enables secure data sharing between two parties over an insecure channel using asymmetric encryption. The sender encrypts data using a public key (usually derived from a password) and shares the encrypted data with the receiver. The receiver decrypts the data using the corresponding secret key or password.
Key Features ¶
• Password-based public key generation using Argon2 key derivation • Stream cipher with optional compression for memory efficiency • Post-quantum cryptography support using Kyber1024 • Stream processing for handling large files efficiently • Base32 encoding for human-readable ciphertext • Both symmetric and asymmetric encryption modes
Architecture ¶
The package is built around two main types:
SecretKey: Represents a cryptographic secret key that can be either password-based or directly generated from random data. It supports both symmetric and asymmetric encryption operations.
PublicKey: Represents a cryptographic public key for asymmetric encryption. It contains the actual public key material and associated metadata.
Key Types ¶
Xipher supports two types of keys:
Direct Keys: Generated from cryptographically secure random data (64 bytes). These provide maximum entropy and are suitable when key management is handled separately.
Password-based Keys: Derived from passwords using Argon2 key derivation function. These are more convenient for human use but require secure password practices.
Encryption Modes ¶
Symmetric Encryption: Uses the secret key directly for encryption/decryption. This is faster and suitable when the same party encrypts and decrypts.
Asymmetric Encryption: Uses public key for encryption and secret key for decryption. This enables secure communication between different parties.
Post-Quantum Cryptography ¶
Xipher supports post-quantum cryptography using the Kyber1024 algorithm, providing resistance against quantum computer attacks. This can be enabled when generating public keys by setting the pq parameter to true.
Basic Usage Examples ¶
## Password-based Encryption
// Create a secret key from password
secretKey, err := xipher.NewSecretKeyForPassword([]byte("my-secure-password"))
if err != nil {
return err
}
// Generate public key (standard ECC)
publicKey, err := secretKey.PublicKey(false)
if err != nil {
return err
}
// Encrypt data
plaintext := []byte("Hello, World!")
ciphertext, err := publicKey.Encrypt(plaintext, true, true)
if err != nil {
return err
}
// Decrypt data
decrypted, err := secretKey.Decrypt(ciphertext)
if err != nil {
return err
}
## Direct Key Generation
// Generate a random secret key
secretKey, err := xipher.NewSecretKey()
if err != nil {
return err
}
// Export key for storage
keyString, err := secretKey.String()
if err != nil {
return err
}
// Later, import the key
importedKey, err := xipher.ParseSecretKeyStr(keyString)
if err != nil {
return err
}
## Post-Quantum Encryption
// Create secret key
secretKey, err := xipher.NewSecretKeyForPassword([]byte("quantum-safe-password"))
if err != nil {
return err
}
// Generate post-quantum public key
pqPublicKey, err := secretKey.PublicKey(true) // true enables post-quantum
if err != nil {
return err
}
// Encrypt with post-quantum cryptography
ciphertext, err := pqPublicKey.Encrypt([]byte("quantum-safe message"), true, true)
if err != nil {
return err
}
## Stream Processing
// Encrypt large files efficiently
inputFile, err := os.Open("largefile.txt")
if err != nil {
return err
}
defer inputFile.Close()
outputFile, err := os.Create("encrypted.xct")
if err != nil {
return err
}
defer outputFile.Close()
// Stream encryption
err = publicKey.EncryptStream(outputFile, inputFile, true, true)
if err != nil {
return err
}
// Stream decryption
encryptedFile, err := os.Open("encrypted.xct")
if err != nil {
return err
}
defer encryptedFile.Close()
decryptedFile, err := os.Create("decrypted.txt")
if err != nil {
return err
}
defer decryptedFile.Close()
err = secretKey.DecryptStream(decryptedFile, encryptedFile)
if err != nil {
return err
}
Key Derivation Parameters ¶
For password-based keys, you can customize the Argon2 parameters:
// High-security configuration
secretKey, err := xipher.NewSecretKeyForPasswordAndSpec(
[]byte("my-password"),
32, // iterations (higher = more secure, slower)
128, // memory in MB (higher = more secure, more memory)
4, // threads (higher = faster on multi-core)
)
Format Specifications ¶
## Key Formats
Secret keys are encoded with the "XSK_" prefix followed by base32-encoded data. Public keys are encoded with the "XPK_" prefix followed by base32-encoded data.
## Ciphertext Format
Encrypted data can be output in two formats: • Binary format: Raw encrypted bytes • Encoded format: "XCT_" prefix + base32-encoded encrypted data
The encoded format is human-readable and safe for text-based transmission.
Security Considerations ¶
• Use strong passwords for password-based keys (consider using passphrases) • Store direct keys securely (they cannot be recovered if lost) • Consider using post-quantum cryptography for long-term security • Use compression carefully (it may leak information about plaintext patterns) • Validate all inputs when parsing keys or ciphertext from external sources
Error Handling ¶
The package defines several specific error types for different failure modes: • errInvalidPassword: Empty or invalid password provided • errInvalidCiphertext: Malformed ciphertext data • errInvalidPublicKey: Invalid public key format • errInvalidSecretKey: Invalid secret key format • errDecryptionFailedPwdRequired: Password required for decryption • errDecryptionFailedKeyRequired: Direct key required for decryption
Performance Notes ¶
• Stream processing is more memory-efficient for large data • Compression reduces ciphertext size but adds CPU overhead • Post-quantum cryptography increases key sizes and processing time • Password-based key derivation is intentionally slow for security
Compatibility ¶
Xipher maintains backward compatibility for encrypted data. Newer versions can decrypt data encrypted with older versions, but older versions may not support features introduced in newer versions (like post-quantum cryptography).
Example (BasicPasswordEncryption) ¶
Example_basicPasswordEncryption demonstrates basic password-based encryption and decryption.
// Create a secret key from password
secretKey, err := NewSecretKeyForPassword([]byte("my-secure-password"))
if err != nil {
log.Fatal(err)
}
// Generate public key for encryption
publicKey, err := secretKey.PublicKey(false)
if err != nil {
log.Fatal(err)
}
// Encrypt some data
plaintext := []byte("Hello, World!")
ciphertext, err := publicKey.Encrypt(plaintext, true, true)
if err != nil {
log.Fatal(err)
}
// Decrypt the data
decrypted, err := secretKey.Decrypt(ciphertext)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Original: %s\n", plaintext)
fmt.Printf("Decrypted: %s\n", decrypted)
Output: Original: Hello, World! Decrypted: Hello, World!
Example (CustomKDFParameters) ¶
Example_customKDFParameters demonstrates using custom Argon2 parameters for key derivation.
password := []byte("my-password")
// Low-security, fast configuration (for testing)
fastKey, err := NewSecretKeyForPasswordAndSpec(password, 1, 8, 1)
if err != nil {
log.Fatal(err)
}
// High-security configuration
secureKey, err := NewSecretKeyForPasswordAndSpec(password, 32, 128, 4)
if err != nil {
log.Fatal(err)
}
// Both keys work for encryption/decryption
testData := []byte("test message")
// Test fast key
fastPubKey, _ := fastKey.PublicKey(false)
fastCiphertext, _ := fastPubKey.Encrypt(testData, true, true)
fastDecrypted, _ := fastKey.Decrypt(fastCiphertext)
// Test secure key
securePubKey, _ := secureKey.PublicKey(false)
secureCiphertext, _ := securePubKey.Encrypt(testData, true, true)
secureDecrypted, _ := secureKey.Decrypt(secureCiphertext)
fmt.Printf("Fast key works: %t\n", bytes.Equal(testData, fastDecrypted))
fmt.Printf("Secure key works: %t\n", bytes.Equal(testData, secureDecrypted))
fmt.Printf("Different ciphertexts: %t\n", !bytes.Equal(fastCiphertext, secureCiphertext))
Output: Fast key works: true Secure key works: true Different ciphertexts: true
Example (DirectKeyGeneration) ¶
Example_directKeyGeneration demonstrates generating and using direct (non-password-based) keys.
// Generate a random secret key
secretKey, err := NewSecretKey()
if err != nil {
log.Fatal(err)
}
// Export key as string for storage
keyString, err := secretKey.String()
if err != nil {
log.Fatal(err)
}
fmt.Printf("Key starts with: %s\n", keyString[:4])
// Later, import the key from string
importedKey, err := ParseSecretKeyStr(keyString)
if err != nil {
log.Fatal(err)
}
// Use the imported key
publicKey, err := importedKey.PublicKey(false)
if err != nil {
log.Fatal(err)
}
// Test encryption/decryption
plaintext := []byte("Test message")
ciphertext, err := publicKey.Encrypt(plaintext, true, true)
if err != nil {
log.Fatal(err)
}
decrypted, err := importedKey.Decrypt(ciphertext)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Encryption works: %t\n", bytes.Equal(plaintext, decrypted))
Output: Key starts with: XSK_ Encryption works: true
Example (FileEncryption) ¶
Example_fileEncryption demonstrates encrypting and decrypting files.
// Create a temporary file with test data
tempFile, err := os.CreateTemp("", "xipher_test_*.txt")
if err != nil {
log.Fatal(err)
}
defer os.Remove(tempFile.Name())
testData := "This is test file content for encryption."
tempFile.WriteString(testData)
tempFile.Close()
// Create secret key
secretKey, err := NewSecretKeyForPassword([]byte("file-password"))
if err != nil {
log.Fatal(err)
}
publicKey, err := secretKey.PublicKey(false)
if err != nil {
log.Fatal(err)
}
// Encrypt file
inputFile, err := os.Open(tempFile.Name())
if err != nil {
log.Fatal(err)
}
defer inputFile.Close()
encryptedFile, err := os.CreateTemp("", "xipher_encrypted_*.xct")
if err != nil {
log.Fatal(err)
}
defer os.Remove(encryptedFile.Name())
defer encryptedFile.Close()
err = publicKey.EncryptStream(encryptedFile, inputFile, true, true)
if err != nil {
log.Fatal(err)
}
encryptedFile.Close()
// Decrypt file
encryptedFile, err = os.Open(encryptedFile.Name())
if err != nil {
log.Fatal(err)
}
defer encryptedFile.Close()
decryptedFile, err := os.CreateTemp("", "xipher_decrypted_*.txt")
if err != nil {
log.Fatal(err)
}
defer os.Remove(decryptedFile.Name())
defer decryptedFile.Close()
err = secretKey.DecryptStream(decryptedFile, encryptedFile)
if err != nil {
log.Fatal(err)
}
decryptedFile.Close()
// Verify content
decryptedContent, err := os.ReadFile(decryptedFile.Name())
if err != nil {
log.Fatal(err)
}
fmt.Printf("File encryption successful: %t\n", string(decryptedContent) == testData)
Output: File encryption successful: true
Example (KeyValidation) ¶
Example_keyValidation demonstrates validating key and ciphertext strings.
// Generate a secret key
secretKey, err := NewSecretKey()
if err != nil {
log.Fatal(err)
}
keyString, _ := secretKey.String()
publicKey, _ := secretKey.PublicKey(false)
pubKeyString, _ := publicKey.String()
// Encrypt some data
ciphertext, _ := publicKey.Encrypt([]byte("test"), true, true)
ciphertextString := string(ciphertext)
// Validate formats
fmt.Printf("Valid secret key: %t\n", IsSecretKeyStr(keyString))
fmt.Printf("Valid public key: %t\n", IsPubKeyStr(pubKeyString))
fmt.Printf("Valid ciphertext: %t\n", IsCTStr(ciphertextString))
// Test invalid formats
fmt.Printf("Invalid secret key: %t\n", IsSecretKeyStr("invalid"))
fmt.Printf("Invalid public key: %t\n", IsPubKeyStr("invalid"))
fmt.Printf("Invalid ciphertext: %t\n", IsCTStr("invalid"))
Output: Valid secret key: true Valid public key: true Valid ciphertext: true Invalid secret key: false Invalid public key: false Invalid ciphertext: false
Example (PostQuantumCryptography) ¶
Example_postQuantumCryptography demonstrates using post-quantum cryptography.
// Create secret key
secretKey, err := NewSecretKeyForPassword([]byte("quantum-safe-password"))
if err != nil {
log.Fatal(err)
}
// Generate post-quantum public key (Kyber1024)
pqPublicKey, err := secretKey.PublicKey(true) // true enables post-quantum
if err != nil {
log.Fatal(err)
}
// Generate standard ECC public key for comparison
eccPublicKey, err := secretKey.PublicKey(false) // false uses ECC
if err != nil {
log.Fatal(err)
}
// Get key sizes
pqKeyBytes, _ := pqPublicKey.Bytes()
eccKeyBytes, _ := eccPublicKey.Bytes()
fmt.Printf("Post-quantum key is larger: %t\n", len(pqKeyBytes) > len(eccKeyBytes))
// Encrypt with post-quantum cryptography
plaintext := []byte("quantum-safe message")
ciphertext, err := pqPublicKey.Encrypt(plaintext, true, true)
if err != nil {
log.Fatal(err)
}
// Decrypt with the same secret key
decrypted, err := secretKey.Decrypt(ciphertext)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Post-quantum encryption works: %t\n", bytes.Equal(plaintext, decrypted))
Output: Post-quantum key is larger: true Post-quantum encryption works: true
Example (StreamProcessing) ¶
Example_streamProcessing demonstrates efficient stream processing for large data.
// Create secret key
secretKey, err := NewSecretKeyForPassword([]byte("stream-password"))
if err != nil {
log.Fatal(err)
}
// Generate public key
publicKey, err := secretKey.PublicKey(false)
if err != nil {
log.Fatal(err)
}
// Simulate large data with a string reader
largeData := strings.Repeat("This is a large file content. ", 1000)
dataReader := strings.NewReader(largeData)
// Encrypt using stream processing
var encryptedBuffer bytes.Buffer
err = publicKey.EncryptStream(&encryptedBuffer, dataReader, true, true)
if err != nil {
log.Fatal(err)
}
// Decrypt using stream processing
var decryptedBuffer bytes.Buffer
err = secretKey.DecryptStream(&decryptedBuffer, &encryptedBuffer)
if err != nil {
log.Fatal(err)
}
// Verify the data
decryptedData := decryptedBuffer.String()
fmt.Printf("Stream processing successful: %t\n", largeData == decryptedData)
fmt.Printf("Original size: %d bytes\n", len(largeData))
fmt.Printf("Encrypted data is smaller due to compression: %t\n", encryptedBuffer.Len() < len(largeData))
Output: Stream processing successful: true Original size: 30000 bytes Encrypted data is smaller due to compression: true
Example (SymmetricEncryption) ¶
Example_symmetricEncryption demonstrates using secret keys for symmetric encryption.
// Create secret key
secretKey, err := NewSecretKeyForPassword([]byte("symmetric-password"))
if err != nil {
log.Fatal(err)
}
// Encrypt directly with secret key (symmetric mode)
plaintext := []byte("Symmetric encryption is faster!")
ciphertext, err := secretKey.Encrypt(plaintext, true, true)
if err != nil {
log.Fatal(err)
}
// Decrypt with the same secret key
decrypted, err := secretKey.Decrypt(ciphertext)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Symmetric encryption works: %t\n", bytes.Equal(plaintext, decrypted))
Output: Symmetric encryption works: true
Index ¶
- Variables
- func IsCTStr(str string) bool
- func IsPubKeyStr(pubKeyStr string) bool
- func IsSecretKeyStr(secretKeyStr string) bool
- type PublicKey
- func (publicKey *PublicKey) Bytes() ([]byte, error)
- func (publicKey *PublicKey) Encrypt(data []byte, compress, encode bool) (ciphertext []byte, err error)
- func (publicKey *PublicKey) EncryptStream(dst io.Writer, src io.Reader, compress, encode bool) (err error)
- func (publicKey *PublicKey) NewEncryptingWriter(dst io.Writer, compress, encode bool) (writer io.WriteCloser, err error)
- func (publicKey *PublicKey) String() (string, error)
- type SecretKey
- func NewSecretKey() (*SecretKey, error)
- func NewSecretKeyForPassword(password []byte) (*SecretKey, error)
- func NewSecretKeyForPasswordAndSpec(password []byte, iterations, memory, threads uint8) (*SecretKey, error)
- func ParseSecretKey(key []byte) (*SecretKey, error)
- func ParseSecretKeyStr(secretKeyStr string) (*SecretKey, error)
- func SecretKeyFromSeed(seed [secretKeyBaseLength]byte) (*SecretKey, error)
- func (secretKey *SecretKey) Bytes() ([]byte, error)
- func (secretKey *SecretKey) Decrypt(ciphertext []byte) (data []byte, err error)
- func (secretKey *SecretKey) DecryptStream(dst io.Writer, src io.Reader) (err error)
- func (secretKey *SecretKey) Encrypt(data []byte, compress, encode bool) (ciphertext []byte, err error)
- func (secretKey *SecretKey) EncryptStream(dst io.Writer, src io.Reader, compress, encode bool) (err error)
- func (secretKey *SecretKey) NewDecryptingReader(src io.Reader) (io.Reader, error)
- func (secretKey *SecretKey) NewEncryptingWriter(dst io.Writer, compress, encode bool) (writer io.WriteCloser, err error)
- func (secretKey *SecretKey) PublicKey(pq bool) (*PublicKey, error)
- func (secretKey *SecretKey) String() (string, error)
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // Info contains application metadata and build information. // This structure is populated at build time and provides runtime // access to version, build details, and platform information. Info = struct { AppName string `json:"appName"` // Application name AppNameLC string `json:"appNameLC"` // Application name in lowercase Art string `json:"art"` // ASCII art logo Description string `json:"description"` // Application description Version string `json:"version"` // Version string BuiltAt string `json:"builtAt"` // Build timestamp ReleaseURL string `json:"releaseURL"` // Release URL FullCommit string `json:"fullCommit"` // Full commit hash Web string `json:"web"` // Website URL Platform string `json:"platform"` // Target platform (OS/architecture) GoVersion string `json:"goVersion"` // Go version used for building }{ AppName: appName, AppNameLC: appNameLowerCase, Art: art, Description: description, Version: version, BuiltAt: commitDate, ReleaseURL: releaseURL, FullCommit: fullCommit, Web: web, Platform: runtime.GOOS + "/" + runtime.GOARCH, GoVersion: runtime.Version(), } )
Build-time variables set by the build system.
Functions ¶
func IsCTStr ¶ added in v1.13.0
IsCTStr validates whether a string is a properly formatted ciphertext string. It checks if the string starts with the xipher ciphertext prefix "XCT_".
Parameters:
- str: String to validate
Returns true if the string appears to be xipher-encoded ciphertext.
Example:
if xipher.IsCTStr(ciphertext) {
// This is xipher-encoded ciphertext
decrypted, err := secretKey.Decrypt([]byte(ciphertext))
}
func IsPubKeyStr ¶ added in v1.13.0
IsPubKeyStr validates whether a string is a properly formatted public key string. It checks the format but does not validate the cryptographic content.
Parameters:
- pubKeyStr: String to validate
Returns true if the string matches the expected public key format.
Example:
if xipher.IsPubKeyStr(keyString) {
publicKey, err := xipher.ParsePublicKeyStr(keyString)
// ...
}
func IsSecretKeyStr ¶ added in v1.13.0
IsSecretKeyStr validates whether a string is a properly formatted secret key string. It checks the format but does not validate the cryptographic content.
Parameters:
- secretKeyStr: String to validate
Returns true if the string matches the expected secret key format.
Example:
if xipher.IsSecretKeyStr(keyString) {
secretKey, err := xipher.ParseSecretKeyStr(keyString)
// ...
}
Types ¶
type PublicKey ¶
type PublicKey struct {
// contains filtered or unexported fields
}
PublicKey represents a cryptographic public key for asymmetric encryption. It contains the actual public key material and associated metadata.
func ParsePublicKey ¶
ParsePublicKey parses a public key from its binary representation. It supports both direct and password-based public keys.
Parameters:
- pubKeyBytes: Binary representation of the public key
Returns an error if the format is invalid or parsing fails.
Example:
publicKey, err := xipher.ParsePublicKey(keyBytes)
if err != nil {
return err
}
func ParsePublicKeyStr ¶ added in v1.13.0
ParsePublicKeyStr parses a public key from its string representation. The string must have the correct prefix and format (base32 encoded).
Parameters:
- pubKeyStr: String representation of the public key (e.g., "XPK_...")
Returns an error if the string format is invalid or decoding fails.
Example:
publicKey, err := xipher.ParsePublicKeyStr("XPK_ABCDEF...")
if err != nil {
return err
}
func (*PublicKey) Bytes ¶
Bytes returns the binary representation of the public key. The format includes version, type, and optionally KDF specification, followed by the actual public key material.
Returns an error if serialization fails.
Example:
pubKeyBytes, err := publicKey.Bytes()
if err != nil {
return err
}
// Store or transmit pubKeyBytes
func (*PublicKey) Encrypt ¶
func (publicKey *PublicKey) Encrypt(data []byte, compress, encode bool) (ciphertext []byte, err error)
Encrypt encrypts the given data using the public key in asymmetric mode. This is a convenience method for encrypting small amounts of data in memory.
Parameters:
- data: Plaintext data to encrypt
- compress: If true, compresses data before encryption (reduces size)
- encode: If true, base32-encodes the output with "XCT_" prefix
Returns the encrypted ciphertext or an error if encryption fails.
Example:
plaintext := []byte("Hello, World!")
ciphertext, err := publicKey.Encrypt(plaintext, true, true)
if err != nil {
return err
}
// ciphertext is now encrypted and optionally compressed/encoded
func (*PublicKey) EncryptStream ¶
func (publicKey *PublicKey) EncryptStream(dst io.Writer, src io.Reader, compress, encode bool) (err error)
EncryptStream encrypts data from src and writes the encrypted result to dst using the public key in asymmetric mode. This is efficient for large data streams.
Parameters:
- dst: Destination writer for encrypted output
- src: Source reader for plaintext input
- compress: If true, compresses data before encryption (reduces size)
- encode: If true, base32-encodes the output with "XCT_" prefix
Returns an error if encryption fails at any stage.
Example:
file, _ := os.Open("largefile.txt")
defer file.Close()
var encrypted bytes.Buffer
err := publicKey.EncryptStream(&encrypted, file, true, true)
func (*PublicKey) NewEncryptingWriter ¶
func (publicKey *PublicKey) NewEncryptingWriter(dst io.Writer, compress, encode bool) (writer io.WriteCloser, err error)
NewEncryptingWriter creates a streaming writer that encrypts data using the public key in asymmetric mode. The writer encrypts data as it's written and outputs the result to dst.
Parameters:
- dst: Destination writer for encrypted output
- compress: If true, compresses data before encryption (reduces size)
- encode: If true, base32-encodes the output with "XCT_" prefix
Returns a WriteCloser that must be closed to finalize encryption. The Close() method is essential for proper encryption completion.
Example:
var buf bytes.Buffer
writer, err := publicKey.NewEncryptingWriter(&buf, true, true)
if err != nil {
return err
}
writer.Write([]byte("Hello, World!"))
writer.Close() // Essential for proper encryption
ciphertext := buf.Bytes()
func (*PublicKey) String ¶ added in v1.13.0
String returns the string representation of the public key. The string format is base32-encoded with the "XPK_" prefix.
Returns an error if serialization fails.
Example:
pubKeyString, err := publicKey.String()
if err != nil {
return err
}
fmt.Println("Public key:", pubKeyString) // XPK_ABCDEF...
type SecretKey ¶
type SecretKey struct {
// contains filtered or unexported fields
}
SecretKey represents a cryptographic secret key that can be either password-based or directly generated from random data. It supports both symmetric and asymmetric encryption operations and maintains internal state for efficient key derivation.
func NewSecretKey ¶
NewSecretKey creates a new secret key from cryptographically secure random data. This type of key is not password-based and provides maximum entropy. It's suitable for applications where key management is handled separately.
The generated key is 64 bytes of cryptographically secure random data.
Returns an error if random number generation fails.
Example:
secretKey, err := xipher.NewSecretKey()
if err != nil {
return err
}
// Save the key for later use
keyString, _ := secretKey.String()
func NewSecretKeyForPassword ¶
NewSecretKeyForPassword creates a new secret key derived from the given password. It uses default KDF parameters for key derivation (16 iterations, 64MB memory, 1 thread).
This is the most common way to create a secret key for password-based encryption. The resulting key can be used for both symmetric and asymmetric operations.
Parameters:
- password: The password to derive the key from (must not be empty)
Returns an error if the password is empty or key derivation fails.
Example:
secretKey, err := xipher.NewSecretKeyForPassword([]byte("my-secure-password"))
if err != nil {
return err
}
func NewSecretKeyForPasswordAndSpec ¶
func NewSecretKeyForPasswordAndSpec(password []byte, iterations, memory, threads uint8) (*SecretKey, error)
NewSecretKeyForPasswordAndSpec creates a new secret key with custom KDF parameters. This allows fine-tuning of the key derivation process for specific security or performance requirements.
Parameters:
- password: The password to derive the key from (must not be empty)
- iterations: Number of Argon2 iterations (higher = more secure, slower)
- memory: Memory usage in MB (higher = more secure, more memory)
- threads: Number of parallel threads (higher = faster on multi-core systems)
Returns an error if any parameter is invalid or key derivation fails.
Example:
// High-security configuration: more iterations and memory
secretKey, err := xipher.NewSecretKeyForPasswordAndSpec(
[]byte("my-secure-password"), 32, 128, 4)
func ParseSecretKey ¶
ParseSecretKey parses a secret key from its binary representation. The key must be exactly secretKeyLength bytes and have the correct format.
Parameters:
- key: Binary representation of the secret key
Returns an error if the key format is invalid or the length is incorrect. Only supports direct (non-password-based) keys.
func ParseSecretKeyStr ¶ added in v1.13.0
ParseSecretKeyStr parses a secret key from its string representation. The string must have the correct prefix and format (base32 encoded).
Parameters:
- secretKeyStr: String representation of the secret key (e.g., "XSK_...")
Returns an error if the string format is invalid or decoding fails.
Example:
secretKey, err := xipher.ParseSecretKeyStr("XSK_ABCDEF...")
if err != nil {
return err
}
func SecretKeyFromSeed ¶ added in v1.16.0
SecretKeyFromSeed creates a new secret key from the given 64-byte seed. This allows creating deterministic keys from known seed material.
Parameters:
- seed: Exactly 64 bytes of seed material
The seed should be cryptographically secure random data or derived from a secure source. This function does not validate the entropy of the seed.
Example:
var seed [64]byte copy(seed[:], someSecureRandomData) secretKey, err := xipher.SecretKeyFromSeed(seed)
func (*SecretKey) Bytes ¶
Bytes returns the binary representation of the secret key. This only works for direct (non-password-based) keys, as password-based keys cannot be serialized without compromising security.
The returned bytes include version and type headers followed by the key material.
Returns an error for password-based keys.
Example:
keyBytes, err := secretKey.Bytes()
if err != nil {
// Handle password-based key or other error
return err
}
// Store keyBytes securely
func (*SecretKey) Decrypt ¶
Decrypt decrypts the given ciphertext and returns the original plaintext. This is a convenience method for decrypting small amounts of data in memory. It automatically handles both base32-encoded and binary ciphertext formats.
Parameters:
- ciphertext: Encrypted data to decrypt
Returns the decrypted plaintext or an error if decryption fails.
Example:
// Decrypt data encrypted with the corresponding public key
plaintext, err := secretKey.Decrypt(ciphertext)
if err != nil {
return err
}
fmt.Println("Decrypted:", string(plaintext))
func (*SecretKey) DecryptStream ¶
DecryptStream decrypts data from src and writes the decrypted result to dst. This is efficient for large encrypted data streams and automatically handles both base32-encoded and binary ciphertext formats.
Parameters:
- dst: Destination writer for decrypted output
- src: Source reader containing encrypted data
Returns an error if decryption fails at any stage.
Example:
encryptedFile, _ := os.Open("encrypted.txt")
defer encryptedFile.Close()
decryptedFile, _ := os.Create("decrypted.txt")
defer decryptedFile.Close()
err := secretKey.DecryptStream(decryptedFile, encryptedFile)
func (*SecretKey) Encrypt ¶
func (secretKey *SecretKey) Encrypt(data []byte, compress, encode bool) (ciphertext []byte, err error)
Encrypt encrypts the given data using the secret key in symmetric mode. This is a convenience method for encrypting small amounts of data in memory.
Parameters:
- data: Plaintext data to encrypt
- compress: If true, compresses data before encryption (reduces size)
- encode: If true, base32-encodes the output with "XCT_" prefix
Returns the encrypted ciphertext or an error if encryption fails.
Example:
plaintext := []byte("Hello, World!")
ciphertext, err := secretKey.Encrypt(plaintext, true, true)
if err != nil {
return err
}
// ciphertext is now encrypted and optionally compressed/encoded
func (*SecretKey) EncryptStream ¶
func (secretKey *SecretKey) EncryptStream(dst io.Writer, src io.Reader, compress, encode bool) (err error)
EncryptStream encrypts data from src and writes the encrypted result to dst using the secret key in symmetric mode. This is efficient for large data streams.
Parameters:
- dst: Destination writer for encrypted output
- src: Source reader for plaintext input
- compress: If true, compresses data before encryption (reduces size)
- encode: If true, base32-encodes the output with "XCT_" prefix
Returns an error if encryption fails at any stage.
Example:
file, _ := os.Open("largefile.txt")
defer file.Close()
var encrypted bytes.Buffer
err := secretKey.EncryptStream(&encrypted, file, true, true)
func (*SecretKey) NewDecryptingReader ¶
NewDecryptingReader creates a streaming reader that decrypts data from src. It automatically detects whether the input is base32-encoded (with "XCT_" prefix) or in binary format, and handles both symmetric and asymmetric decryption.
Parameters:
- src: Source reader containing encrypted data
Returns a reader that provides decrypted plaintext data.
Example:
encryptedFile, _ := os.Open("encrypted.txt")
defer encryptedFile.Close()
decryptedReader, err := secretKey.NewDecryptingReader(encryptedFile)
if err != nil {
return err
}
// Read decrypted data from decryptedReader
plaintext, _ := io.ReadAll(decryptedReader)
func (*SecretKey) NewEncryptingWriter ¶
func (secretKey *SecretKey) NewEncryptingWriter(dst io.Writer, compress, encode bool) (writer io.WriteCloser, err error)
NewEncryptingWriter creates a streaming writer that encrypts data using the secret key in symmetric mode. The writer encrypts data as it's written and outputs the result to dst.
Parameters:
- dst: Destination writer for encrypted output
- compress: If true, compresses data before encryption (reduces size)
- encode: If true, base32-encodes the output with "XCT_" prefix
Returns a WriteCloser that must be closed to finalize encryption. The Close() method is essential for proper encryption completion.
Example:
var buf bytes.Buffer
writer, err := secretKey.NewEncryptingWriter(&buf, true, true)
if err != nil {
return err
}
writer.Write([]byte("Hello, World!"))
writer.Close() // Essential for proper encryption
ciphertext := buf.Bytes()
func (*SecretKey) PublicKey ¶
PublicKey derives the public key corresponding to this secret key. The public key can be used for encryption, while the secret key is needed for decryption.
Parameters:
- pq: If true, uses post-quantum cryptography (Kyber1024); if false, uses ECC
Post-quantum cryptography provides resistance against quantum computer attacks but results in larger key sizes and ciphertext.
Returns an error if key derivation fails.
Example:
// Standard ECC public key pubKey, err := secretKey.PublicKey(false) // Post-quantum public key pqPubKey, err := secretKey.PublicKey(true)
func (*SecretKey) String ¶ added in v1.13.0
String returns the string representation of the secret key. The string format is base32-encoded with the "XSK_" prefix. This only works for direct (non-password-based) keys.
Returns an error for password-based keys.
Example:
keyString, err := secretKey.String()
if err != nil {
return err
}
fmt.Println("Secret key:", keyString) // XSK_ABCDEF...
Source Files
¶
- xipher_commons.go
- xipher_const.go
- xipher_crypto.go
- xipher_doc.go
- xipher_kdf.go
- xipher_keys.go
