saltsecret

package
v0.0.0-...-744ffa8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 18, 2015 License: BSD-3-Clause, BSD-3-Clause Imports: 8 Imported by: 4

README

saltsecret (golang package)

Saltsecret provides a simple way to encrypt or decrypt a message using NaCl secret key cryptography. Optionally it can compress the data before encrypting them.

The encryption key is created anew for each message by a key derivation function (scrypt) using the user provided secret and a random salt. The salt is used as NaCl's nonce, so the receiver may decrypt the message having a priori only the user provided secret.

Saltsecret is more secure than padsecret but also very slow due to scrypt. Thus is better used for applications with few messages, or for very large messages, where much time is spent on the encryption itself. Benchmarks are provided (by go test -bench) to let you decide which package to use.

Beyond the default methods (Encrypt(msg []byte), Decrypt(msg []byte)), it also provides an io.Reader and an io.Writer interface to decrypt or encrypt data. Since we don't have a stream cipher, these methods need to have available all the data before they make available their output. For Writer this means you have to Flush() or Close() before you can read the io.Writer you passed to the Writer. For Reader it means it will block until it reads all the data from the io.Reader you passed to it.

I use it for symmetric-key encryption schemes. Depending on your usage it may or may not be a safe option. I do not claim any expertise in cryptography.

Note: The compression status is set inside the message (last bit of the nonce), thus whilst you do need to have a common key and padding between two processes exchanging messages, you do not need to have a common compression setting.

Usage

import "github.com/andmarios/crypto/nacl/saltsecret"

Example

You may find more examples in the examples directory.

package main

import (
	"github.com/andmarios/crypto/nacl/saltsecret"
	"log"
)

func main() {
    // Create a padsecret instance with "secret" key and no compression.
    key := []byte("secret")
	c := saltsecret.New(key, false)

	// Message to be encrypted
	msg := []byte("Hello World")

	// Encrypt message
	encMsg, err := c.Encrypt(msg)
	if err != nil {
		log.Fatalln(err.Error())
	}

	// Decrypt message
	decMsg, err := c.Decrypt(encMsg)
	if err != nil {
		log.Fatalln("Could not decrypt message")
	}
	log.Printf("Decrypted message is '%s'.\n", decMsg)
}

License

You can find more information inside the LICENSE file. In short this software uses a BSD 3-Clause license.

Documentation

Overview

Package saltsecret implements a simple library for on-the-fly NaCl secret key (symmetric) encryption and decryption with a scrypt derived key.

It is meant to be used for symmetric-key encryption schemes. Optionally it can (de)compress the data before (dec)encryption.

The encryption key is derived from the user provided key and a random salt for each encryption operation. The salt is used as NaCl's nonce, so that the receiver can decrypt the message. The key derivation function (scrypt) makes saltsecret more secure but also very slow. It is more useful for when you want to exchange a few messages, or for very large messages.

Beyond the recommended methods (Encrypt, Decrypt) it also implements the io.ReadWriter interface.

One bit of the NaCl's nonce is used to indicate whether the message was compressed before encrypting. Still the algorithm should remain safe since nonce collisions are again extremely rare.

Index

Examples

Constants

View Source
const (
	ENCRYPT = iota
	DECRYPT
)

Operation mode for Reader and Writer

Variables

This section is empty.

Functions

This section is empty.

Types

type Reader

type Reader struct {
	C *SaltSecret
	// contains filtered or unexported fields
}

A Reader reads data from another Reader, encrypts or decrypts and, if needed, (de)compress them into a []byte variable. A Reader may be re-used by using Reset.

func NewReader

func NewReader(r io.Reader, key []byte, mode int, compress bool) (*Reader, error)

NewReader creates a new Reader. Reads from the returned Reader read, encrypt or decrypt (and (de)compress, if needed), data from r. The implementation needs to read all data from r at once, since we do not use a stream cipher. mode is either saltsecret.ENCRYPT (0), or saltsecret.DECRYPT (1).

func (*Reader) Read

func (d *Reader) Read(p []byte) (n int, err error)

Read reads into p an encrypted or decrypted and, if needed, (de)compressed form of the bytes from the underlying Reader. Read needs to read all data from the underlying Reader before it can operate on them.

func (*Reader) Reset

func (d *Reader) Reset(r io.Reader)

Reset returns Reader to its initial state, except it now reads from r.

type SaltSecret

type SaltSecret struct {
	NPow uint
	// contains filtered or unexported fields
}

A SaltSecret holds the instance's key and the compression settings. Npow is the N power of two iterations to run the algorithm for. Default is 14 which is the recommended for interactive logins as of 2009. You have to set it explicitly, after creating a SaltSecret, Reader or Writer.

func New

func New(key []byte, compress bool) *SaltSecret

New creates a new SaltSecret instance. key is the key used for encryption. For every message the encryption key will be derived by the key and a random salt. compress indicates whether the data should be compessed (zlib) before encrypting.

func (SaltSecret) Decrypt

func (c SaltSecret) Decrypt(msg []byte) ([]byte, error)

Decrypt decrypts an encrypted message and returns it (plaintext). If you have enabled compression, it wil detect it and decompress the msg after decrypting it.

Example
package main

import (
	"fmt"
	"log"

	"github.com/andmarios/crypto/nacl/saltsecret"
)

func main() {
	// Create a saltsecret instance with "password" key and no compression.
	key := []byte("password")
	c := saltsecret.New(key, false)

	encryptedMsg := []byte{40, 145, 30, 139, 112, 75, 178, 223, 40, 199,
		146, 158, 49, 40, 197, 98, 80, 34, 74, 6, 231, 13, 250, 240, 18,
		194, 143, 4, 137, 47, 181, 95, 193, 7, 142, 148, 160, 12, 55,
		140, 229, 223, 49, 4, 115, 165, 125, 206, 187, 13, 52}

	// Decrypt message
	decryptedMsg, err := c.Decrypt(encryptedMsg)
	if err != nil {
		log.Fatalln(err)
	}
	fmt.Printf("Decrypted message is '%s'.\n", decryptedMsg)
}
Output:

Decrypted message is 'Hello World'.

func (SaltSecret) Encrypt

func (c SaltSecret) Encrypt(msg []byte) (out []byte, e error)

Encrypt encrypts a message and returns the encrypted msg (nonce + ciphertext). If you have enabled compression, it will compress the msg before encrypting it.

Example
package main

import (
	"fmt"
	"log"

	"github.com/andmarios/crypto/nacl/saltsecret"
)

func main() {
	// Create a saltsecret instance with "password" key and no compression.
	key := []byte("password")
	c := saltsecret.New(key, false)

	// Message to be encrypted
	msg := []byte("Hello World")

	// Encrypt message
	encryptedMsg, err := c.Encrypt(msg)
	if err != nil {
		log.Fatalln(err)
	}

	fmt.Println("Encrypted message:", encryptedMsg)
}
Output:

type Writer

type Writer struct {
	C *SaltSecret
	// contains filtered or unexported fields
}

A Writer takes data written to it and writes the encrypted or decrypted and, if needed, (de)compressed form of that data to an underlying writer.

func NewWriter

func NewWriter(w io.Writer, key []byte, mode int, compress bool) (*Writer, error)

NewWriter creates a new writer. Writes to the returned Writer are encrypted or decrypted and, if needed, (de)compressed and written to w.

It is the caller's responsibility to call Close() on WriteCloser when done, since we do not use a stream cipher, we need to have all the data before operating on them.

func (*Writer) Close

func (e *Writer) Close() error

Close acts as a placeholder for Flush.

func (*Writer) Flush

func (e *Writer) Flush() error

Flush encrypt or decrypts and (de)compresses, if needed, the data written to the writer. After a Flush, the writer has to be Reset in order to write to it again.

func (*Writer) Reset

func (e *Writer) Reset(w io.Writer)

Reset clears the sate of the Writer w such that it is equivalent to its initial state from NewWriter, but instead writing to w.

func (*Writer) Write

func (e *Writer) Write(p []byte) (n int, err error)

Write writes and encrypts or decrypts (and, if needed, a (de)compressed) form of p to the underlying io.Writer. The produced bytes are not written until the Writer is closed or explicitly flushed.

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL