sio: github.com/minio/sio Index | Examples | Files

package sio

import "github.com/minio/sio"

Package sio implements the DARE format. It provides an API for secure en/decrypting IO operations using io.Reader and io.Writer.

Index

Examples

Package Files

dare.go generic.go reader-v1.go reader-v2.go sio.go writer-v1.go writer-v2.go

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
)

func Decrypt Uses

func Decrypt(dst io.Writer, src io.Reader, config Config) (n int64, err error)

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. It returns an error of type sio.Error if decryption fails.

Code:

// 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 {
    if _, ok := err.(Error); ok {
        fmt.Printf("Malformed encrypted data: %v", err) // add error handling - here we know that the data is malformed/not authentic.
        return
    }
    fmt.Printf("Failed to decrypt data: %v", err) // add error handling
    return
}

func DecryptReader Uses

func DecryptReader(src io.Reader, config Config) (io.Reader, error)

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. The returned io.Reader returns an error of type sio.Error if the decryption fails.

func DecryptReaderAt Uses

func DecryptReaderAt(src io.ReaderAt, config Config) (io.ReaderAt, error)

DecryptReaderAt wraps the given src and returns an io.ReaderAt which decrypts all received data. DecryptReaderAt returns an error if the provided decryption configuration is invalid. The returned io.ReaderAt returns an error of type sio.Error if the decryption fails.

func DecryptWriter Uses

func DecryptWriter(dst io.Writer, config Config) (io.WriteCloser, error)

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. The returned io.WriteCloser returns an error of type sio.Error if the decryption fails.

func DecryptedSize Uses

func DecryptedSize(size uint64) (uint64, error)

DecryptedSize computes the size of a decrypted data stream from the encrypted stream size. It is the inverse of EncryptedSize().

DecryptedSize returns an error if the provided size is to large or if the provided size is an invalid encrypted stream size.

func Encrypt Uses

func Encrypt(dst io.Writer, src io.Reader, config Config) (n int64, err error)

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.

Code:

// 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
}

func EncryptReader Uses

func EncryptReader(src io.Reader, config Config) (io.Reader, error)

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.

Code:

// 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
}

func EncryptWriter Uses

func EncryptWriter(dst io.Writer, config Config) (io.WriteCloser, error)

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.

Code:

// 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
}

func EncryptedSize Uses

func EncryptedSize(size uint64) (uint64, error)

EncryptedSize computes the size of an encrypted data stream from the plaintext size. It is the inverse of DecryptedSize().

EncryptedSize returns an error if the provided size is to large.

type Config Uses

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.

type Error Uses

type Error struct {
    // contains filtered or unexported fields
}

Error is the error returned by an io.Reader or io.Writer if the encrypted data cannot be decrypted because it is malformed or not authentic.

func (Error) Error Uses

func (e Error) Error() string

Package sio imports 13 packages (graph) and is imported by 18 packages. Updated 2019-10-13. Refresh now. Tools for package owners.