Documentation ¶
Overview ¶
Package sio implements the DARE format. It provides an API for secure en/decrypting IO operations using io.Reader and io.Writer.
Index ¶
- Constants
- func Decrypt(dst io.Writer, src io.Reader, config Config) (n int64, err error)
- func DecryptReader(src io.Reader, config Config) (io.Reader, error)
- func DecryptWriter(dst io.Writer, config Config) (io.WriteCloser, error)
- func Encrypt(dst io.Writer, src io.Reader, config Config) (n int64, err error)
- func EncryptReader(src io.Reader, config Config) (io.Reader, error)
- func EncryptWriter(dst io.Writer, config Config) (io.WriteCloser, error)
- func Overhead(size uint64) uint64
- type Config
Examples ¶
Constants ¶
const ( // Version20 specifies version 2.0 Version20 byte = 0x20 // Version10 specifies version 1.0 Version10 byte = 0x10 )
const ( // AES_256_GCM specifies the cipher suite AES-GCM with 256 bit keys. AES_256_GCM byte = iota // CHACHA20_POLY1305 specifies the cipher suite ChaCha20Poly1305 with 256 bit keys. CHACHA20_POLY1305 )
Variables ¶
This section is empty.
Functions ¶
func Decrypt ¶
Decrypt reads from src until it encounters an io.EOF and decrypts all received data. The decrypted data is written to dst. It returns the number of bytes decrypted and the first error encountered while decrypting, if any.
Decrypt returns the number of bytes written to dst. Decrypt only writes data to dst if the data was decrypted successfully.
Example ¶
// the master key used to derive encryption keys masterkey, err := hex.DecodeString("000102030405060708090A0B0C0D0E0FF0E0D0C0B0A090807060504030201000") // use your own key here if err != nil { fmt.Printf("Cannot decode hex key: %v", err) // add error handling return } // the nonce used to derive the encryption key nonce, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000001") // use your generated nonce here if err != nil { fmt.Printf("Cannot decode hex key: %v", err) // add error handling return } // derive the encryption key from the master key and the nonce var key [32]byte kdf := hkdf.New(sha256.New, masterkey, nonce, nil) if _, err = io.ReadFull(kdf, key[:]); err != nil { fmt.Printf("Failed to derive encryption key: %v", err) // add error handling return } input := os.Stdin // customize for your needs - the encrypted data output := os.Stdout // customize from your needs - the decrypted output if _, err = Decrypt(output, input, Config{Key: key[:]}); err != nil { fmt.Printf("Failed to encrypt data: %v", err) // add error handling return }
Output:
func DecryptReader ¶
DecryptReader wraps the given src and returns an io.Reader which decrypts all received data. DecryptReader returns an error if the provided decryption configuration is invalid.
func DecryptWriter ¶
DecryptWriter wraps the given dst and returns an io.WriteCloser which decrypts all data written to it. DecryptWriter returns an error if the provided decryption configuration is invalid.
The returned io.WriteCloser must be closed successfully to finalize the decryption process.
func Encrypt ¶
Encrypt reads from src until it encounters an io.EOF and encrypts all received data. The encrypted data is written to dst. It returns the number of bytes encrypted and the first error encountered while encrypting, if any.
Encrypt returns the number of bytes written to dst.
Example ¶
// the master key used to derive encryption keys // this key must be keep secret masterkey, err := hex.DecodeString("000102030405060708090A0B0C0D0E0FF0E0D0C0B0A090807060504030201000") // use your own key here if err != nil { fmt.Printf("Cannot decode hex key: %v", err) // add error handling return } // generate a random nonce to derive an encryption key from the master key // this nonce must be saved to be able to decrypt the data again - it is not // required to keep it secret var nonce [32]byte if _, err = io.ReadFull(rand.Reader, nonce[:]); err != nil { fmt.Printf("Failed to read random data: %v", err) // add error handling return } // derive an encryption key from the master key and the nonce var key [32]byte kdf := hkdf.New(sha256.New, masterkey, nonce[:], nil) if _, err = io.ReadFull(kdf, key[:]); err != nil { fmt.Printf("Failed to derive encryption key: %v", err) // add error handling return } input := os.Stdin // customize for your needs - the plaintext output := os.Stdout // customize from your needs - the decrypted output if _, err = Encrypt(output, input, Config{Key: key[:]}); err != nil { fmt.Printf("Failed to encrypt data: %v", err) // add error handling return }
Output:
func EncryptReader ¶
EncryptReader wraps the given src and returns an io.Reader which encrypts all received data. EncryptReader returns an error if the provided encryption configuration is invalid.
Example ¶
// the master key used to derive encryption keys // this key must be keep secret masterkey, err := hex.DecodeString("000102030405060708090A0B0C0D0E0FF0E0D0C0B0A090807060504030201000") // use your own key here if err != nil { fmt.Printf("Cannot decode hex key: %v", err) // add error handling return } // generate a random nonce to derive an encryption key from the master key // this nonce must be saved to be able to decrypt the data again - it is not // required to keep it secret var nonce [32]byte if _, err = io.ReadFull(rand.Reader, nonce[:]); err != nil { fmt.Printf("Failed to read random data: %v", err) // add error handling return } // derive an encryption key from the master key and the nonce var key [32]byte kdf := hkdf.New(sha256.New, masterkey, nonce[:], nil) if _, err = io.ReadFull(kdf, key[:]); err != nil { fmt.Printf("Failed to derive encryption key: %v", err) // add error handling return } input := os.Stdin // customize for your needs - the plaintext input encrypted, err := EncryptReader(input, Config{Key: key[:]}) if err != nil { fmt.Printf("Failed to encrypted reader: %v", err) // add error handling return } // the encrypted io.Reader can be used like every other reader - e.g. for copying if _, err := io.Copy(os.Stdout, encrypted); err != nil { fmt.Printf("Failed to copy data: %v", err) // add error handling return }
Output:
func EncryptWriter ¶
EncryptWriter wraps the given dst and returns an io.WriteCloser which encrypts all data written to it. EncryptWriter returns an error if the provided decryption configuration is invalid.
The returned io.WriteCloser must be closed successfully to finalize the encryption process.
Example ¶
// the master key used to derive encryption keys // this key must be keep secret masterkey, err := hex.DecodeString("000102030405060708090A0B0C0D0E0FF0E0D0C0B0A090807060504030201000") // use your own key here if err != nil { fmt.Printf("Cannot decode hex key: %v", err) // add error handling return } // generate a random nonce to derive an encryption key from the master key // this nonce must be saved to be able to decrypt the data again - it is not // required to keep it secret var nonce [32]byte if _, err = io.ReadFull(rand.Reader, nonce[:]); err != nil { fmt.Printf("Failed to read random data: %v", err) // add error handling return } // derive an encryption key from the master key and the nonce var key [32]byte kdf := hkdf.New(sha256.New, masterkey, nonce[:], nil) if _, err = io.ReadFull(kdf, key[:]); err != nil { fmt.Printf("Failed to derive encryption key: %v", err) // add error handling return } output := os.Stdout // customize for your needs - the encrypted output encrypted, err := EncryptWriter(output, Config{Key: key[:]}) if err != nil { fmt.Printf("Failed to encrypted writer: %v", err) // add error handling return } // the encrypted io.Writer can be used now but it MUST be closed at the end to // finalize the encryption. if _, err = io.Copy(encrypted, os.Stdin); err != nil { fmt.Printf("Failed to copy data: %v", err) // add error handling return } if err = encrypted.Close(); err != nil { fmt.Printf("Failed to finalize encryption: %v", err) // add error handling return }
Output:
Types ¶
type Config ¶
type Config struct { // The minimal supported version of the format. If // not set the default value - Version10 - is used. MinVersion byte // The highest supported version of the format. If // not set the default value - Version20 - is used. MaxVersion byte // A list of supported cipher suites. If not set the // default value is used. CipherSuites []byte // The secret encryption key. It must be 32 bytes long. Key []byte // The first expected sequence number. It should only // be set manually when decrypting a range within a // stream. SequenceNumber uint32 // The RNG used to generate random values. If not set // the default value (crypto/rand.Reader) is used. Rand io.Reader // The size of the encrypted payload in bytes. The // default value is 64KB. It should be used to restrict // the size of encrypted packages. The payload size // must be between 1 and 64 KB. // // This field is specific for version 1.0 and is // deprecated. PayloadSize int }
Config contains the format configuration. The only field which must always be set manually is the secret key.