encprim

package module
v1.1.0 Latest Latest
Warning

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

Go to latest
Published: Aug 31, 2023 License: MIT Imports: 5 Imported by: 0

README

encprim

This package provides a high-level set of encryption primitives which can be used in their default configuration to securely derive encryption/decryption keys from a password or passphrase as well as to encrypt or decrypt data. The goal of this package is to ensure that anyone who wants access to secure authenticated encryption can have it without needing to worry about the details or making mistakes that ultimately compromise the security of their efforts. This code is open source so that you can learn from it if you need to incorporate similar concepts into your own code as well as to show that I have nothing to hide in making this software.

Installation

This package can be installed by running go get as follows:

go get github.com/AbishYoung/encprim

Usage

This package is made to be as user-friendly as possible so below are a few helpful examples of how to use what is provided.

Deriving a new key
import (
	"github.com/AbishYoung/encprim"
)

func main() {
	// password must be as long or longer than encprim.MinimumPassword (10 bytes)
	password := "password123" // clearly a fake password never use this
	key := encprim.Key{}      // create a new key
	err := key.FromString(password)
	if err != nil {
		panic("Uh oh something went wrong!")
	}
	
	// key is now populated with a new encryption key as well as a random salt!
	// if you plan to rederive the same key at a later point, whether you want to only
	// use a password or if you are sending a ciphertext to another party and have only
	// pre-shared a password, then you will need to preserve the salt. The salt is not
	// private and can be shared in the open, but you will need it in order to derive the
	// same key from the same password.
}
Rederiving an encryption key

THIS SHOULD ONLY BE DONE WHEN DECRYPTING AND NEVER WHEN ENCRYPTING

import (
	"github.com/AbishYoung/encprim"
)

func main() {
	// the password should never be stored alongside the ciphertext. It is, obviously, a secret.
	password := []byte{"password123"} // again, not a real password. Never use this.
	
	// the salt is not a secret and should be stored alongside the ciphertext if you plan on
	// deriving the same key that was used to encrypt from only a password/passphrase.
	salt := // some unique salt that you obtained. For a good price perhaps?
	
	// new key struct
	key := encprim.Key{}
	err := key.RederiveKey(password, salt)
	if err != nil {
		panic("Uh oh something went wrong!")
	}
	
	// key should now be populated with the same data as was used to originally derive the
	// encryption key.
}
Encrypting using a derived key
import (
	"github.com/AbishYoung/encprim"
)

func main() {
	// This can be generated using the Deriving a new key example.
	key := // some key struct
	ciphertext, err := key.Encrypt([]byte("Hello, World!"))
	if err != nil {
		panic("Uh oh something went wrong!")
	}
	
	// ciphertext will now be populated with a new encprim.CipherBlock struct.
	// The encrypted data can then be accessed through ciphertext.Bytes and the unique
	// nonce can be accessed through ciphertext.Nonce. Like the salt in the Deriving a new
	// key example it must be preserved for decryption of the ciphertext to be successful. 
	// The nonce is not private and can be shared in the open.
}
Decrypting using a derived key
import (
	"github.com/AbishYoung/encprim"
)

func main() {
	// These values should either be stored alongside each other or sent alongside each other.
	ciphertext := // some arbitrary slice of bytes that constitutes the ciphertext.
	nonce :=      // a slice of bytes that represent the nonce used to encrypt (len(nonce) == encprim.AESNonceLength).
	key :=        // the key derived using the Rederive encryption key example.
	
	// Create a new encprim.CipherBlock
	block, err := encprim.NewCipherBlock(ciphertext, nonce)
	if err != nil {
		panic("The nonce is probably not %d bytes...", encprim.AESNonceLength)
	}
	
	plaintext, err := key.Decrypt(block)
	if err != nil {
		panic("Uh oh something went wrong!")
	}
	
	// plaintext should now hold a byte slice populated with the decrypted plaintext which
	// can then be used how-so-ever you desire.
}

License

This project is licensed under the MIT OSS license. For more information see the LICENSE.md file.

Documentation

Overview

Package encprim provides simple encryption primitives that are easy to use and hard to get wrong. encprim provides one tool that can be used to securely encrypt, decrypt, and generate encryption keys. The default behavior is set up in such a way that when using the library as simply as possible is as secure as possible. When needed each function will contain warnings for behavior that is not default and which may cause the output to be insecure or less secure.

Index

Constants

View Source
const (
	AESNonceLength   = 16     // the unique nonce will always be this size (128 bits).
	AESKeyLength     = 32     // the aes key size will always be this size (256 bits).
	ScryptSaltLength = 16     // the scrypt salt size will always be this size (128 bits).
	ScryptN          = 131072 // the CPU/memory cost parameter for scrypt.
	ScryptR          = 8      // the block size parameter for scrypt.
	ScryptP          = 1      // the parallelization parameter for scrypt.
	MinimumPassword  = 10     // this is the minimum number of bytes accepted for key derivation.
)

Variables

This section is empty.

Functions

This section is empty.

Types

type CipherBlock

type CipherBlock struct {
	Bytes []byte               // an arbitrary slice of bytes representing a ciphertext.
	Nonce [AESNonceLength]byte // the nonce that was generated and used when performing encryption.
}

CipherBlock provides a structured representation of a ciphertext and it's parts.

NOTE: When encryption is performed a random nonce is generated. This must be included with the ciphertext in order for decryption to be performed successfully.

It is a good idea, if you are using a shared password/passphrase, to include the random salt that was used to generate the key as well so that the recipient/user can use the same password to generate the same key needed to perform the decryption of the ciphertext.

func NewCipherBlock

func NewCipherBlock(bytes []byte, nonce []byte) (CipherBlock, error)

NewCipherBlock creates a new encprim.CipherBlock given a ciphertext and a nonce.

type Key

type Key struct {
	Key  [AESKeyLength]byte     // the key used for encryption/decryption operations.
	Salt [ScryptSaltLength]byte // the salt used to derive the key (encryption only)
}

Key provides a structured representation of an encryption/decryption key.

NOTE: NEVER REUSE A SALT FOR ENCRYPTION!

A salt must always be cryptographically random when derivation for encryption is performed otherwise it greatly reduces the security afforded by the operation. The ability to specify a salt when deriving is only provided to ease the ability to test the code predictably and should never appear in use outside of testing.

func (*Key) Decrypt

func (k *Key) Decrypt(ciphertext CipherBlock) ([]byte, error)

Decrypt provides a way to decrypt an arbitrary slice of bytes given a known nonce.

The nonce provided should always be the nonce that was used to encrypt the ciphertext otherwise this function will fail to produce a plaintext and will instead return an error.

It is important that the nonce be included when distributing the ciphertext and the nonce does not need to be kept secret and can be shared in the clear.

func (*Key) Encrypt

func (k *Key) Encrypt(plaintext []byte) (CipherBlock, error)

Encrypt provides a way to encrypt an arbitrary slice of bytes using a given key.

The key should be derived from the FromString function and NEVER from the RederiveKey function!

func (*Key) FromString

func (k *Key) FromString(password string) error

FromString provides a way to generate a new key from a password/passphrase.

This function should only ever be used when deriving a key for encryption. To rederive a key from a known salt and a pre-shared or otherwise already known password/passphrase please use the RederiveKey method. The salt does not need to be kept secret.

func (*Key) RederiveKey

func (k *Key) RederiveKey(password string, salt []byte) error

RederiveKey provides a way to rederive a key from a known salt and a known password/passphrase

This function SHOULD ONLY BE USED FOR DECRYPTION as reusing a salt reduces the security of the generated key. If you are using this for encryption outside unit testing you need to stop and rethink what you are doing because I promise you that you don't want to do this. Just use a new salt for every new key **unless** you are trying to rederive a key from a known password/passphrase and a salt.

Jump to

Keyboard shortcuts

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