aescbc

package module
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Apr 30, 2023 License: MIT Imports: 5 Imported by: 0

README

aescbc

A library for encrypting/decrypting data streams with AES-CBC in the Go programming language.

TL;DR

So you want to encrypt a file with AES without reading the manual. Probably not the best idea, but here you go:

src, _ := os.Open("SourceFile.txt")
dst, _ := os.Create("EncryptedFile.aes")

enc, _ := NewAESCBCEncryptor()
enc.Copy(dst, src)

aesKey := enc.AESKey
iv := enc.IV

dst.Close()
src.Close()

and to decrypt:

src, _ := os.Open("EncryptedFile.aes")
dst, _ := os.Create("DecryptedFile.txt")

dec, _ := NewAESCBCDecryptor(aesKey, iv)
dec.Copy(dst, src)

dst.Close()
src.Close()

Introduction

This README is a condensed version of an article I published on Medium at https://medium.com/p/db961e0626cc. For more context, please see that article.

The aescbc library provides high-level wrappers that implement the Reader and Writer interfaces to encrypt and decrypt data.

Disclaimer

As I stated in my linked article, cryptography is hard. There are many, many ways of doing crypto wrong, even in ways that appear right. Modern cryptography is a specialized branch of mathematics, and there are academics who study and practice crypto for a living.

I am not one of those people. I have no specialized knowledge or training in cryptography, and nothing in this article should lead you to believe otherwise. It’s entirely possible that everything I’ve shown here is one of those “looks right, but is actually wrong” instances. The cryptographic algorithm and mode are only a small part of any cryptographic application, and factors beyond the selection of an algorithm and mode (Where is the ciphertext stored? Who has access to it? How are keys distributed to participants of the system? etc.) are important to the security of any cryptosystem. If your application has real-world dependencies on strong cryptographic practices, you ABSOLUTELY MUST retain the advice of someone with training and experience in these matters and not place your trust in some random guy on the internet who happened to write an article.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Pkcs7Pad

func Pkcs7Pad(input []byte, blockSize int) []byte

func Pkcs7Unpad

func Pkcs7Unpad(input []byte) ([]byte, error)

Types

type AESCBCDecryptor

type AESCBCDecryptor struct {
	CopyBufferSize int64
	// contains filtered or unexported fields
}

func NewAESCBCDecryptor

func NewAESCBCDecryptor(aesKey []byte, iv []byte) (*AESCBCDecryptor, error)

func (*AESCBCDecryptor) Close

func (e *AESCBCDecryptor) Close() error

Close is used to signal no more data will be written to the Decryptor. After Close() is called, PKCS7 padding is removed from the buffered plaintext so that it will not be returned to the caller.

At least one more call to Read() must be performed after calling Close() to ensure all plaintext has been read.

func (*AESCBCDecryptor) Copy

func (e *AESCBCDecryptor) Copy(dst io.Writer, src io.Reader) (read int64, err error)

Copy encrypts the data read from the io.Reader and writes it to io.Writer. As part of the encryption process, the AES initialization vector (IV) is prepended to the ciphertext so that it can be recovered from the data stream by the decryptor.

When using Copy(), the IV in the AESCBCDecryptor is overwritten with the first 16 bytes of the source Reader.

The read buffer size is taken from the CopyReadBufferSizeHint member variable

func (*AESCBCDecryptor) Read

func (e *AESCBCDecryptor) Read(p []byte) (n int, err error)

Read implements io.Reader and returns plaintext that has been decrypted. Data is available on Read() after ciphertext has been written to Write().

The last 16 bytes of plaintext data are retainted internally until Close() is called, so that Close() can strip off the PKCS7 padding. The remaining plaintext becomes available to Read() after Close() is called. No more data may be written after Close() is called.

If no plaintext is available, a zero-byte slice is returned and error is nil. Error will return io.EOF after the Close() method has been called and no more data is available to read.

func (*AESCBCDecryptor) Write

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

Write implements io.Writer and accepts ciphertext to be decrypted. After writing ciphertext to Write(), plaintext will become available on the Read() method.

The Close() method should be called after the last plaintext has been written to Write().

type AESCBCEncryptor

type AESCBCEncryptor struct {
	IV             []byte
	AESKey         []byte
	CopyBufferSize int64
	// contains filtered or unexported fields
}

The AESCBCEncryptor type is used to encrypt plaintext data to AES-CBC encrypyted ciphertext.

This type should be created by NewEncryptor() rather than by directly instantiating the type in your code.

Exported fields: IV: the initialization vector used to initialize the AES cipher AESKey: the AES key used to initialize the AES cipher CopyBufferSize: the size (in bytes) of the read/write buffer that Copy() will use

func NewAESCBCEncryptor

func NewAESCBCEncryptor() (*AESCBCEncryptor, error)

NewEncrypytor returns an Encryptor instance with properly initialized member variables. The AESKey and IV are populated from crypto/rand and the internal AES cihper and CBC BlockMode are properly initialized.

After calling NewEncryptor() the calling application should copy the AESKey and the IV so that they can be provided to the decrypting application.

There is no functionality to manually set the AESKey or the IV. Writing to these values after instantiation will not change the state of the cipher or block mode.

func (*AESCBCEncryptor) Close

func (e *AESCBCEncryptor) Close()

Close is used to signal no more data will be written to the Encryptor. After Close() is called, PKCS7 padding is added to the plaintext to aid in proper decryption and the padded data is added to the ciphertext that is available on the Read() method.

At least one more call to Read() mustbe peformed after calling Close() to ensure all ciphertext has been read.

func (*AESCBCEncryptor) Copy

func (e *AESCBCEncryptor) Copy(dst io.Writer, src io.Reader) (written int64, err error)

Copy encrypts the data read from the io.Reader and writes it to io.Writer. As part of the encryption process, the AES initialization vector (IV) is prepended to the ciphertext so that it can be recovered from the data stream by the decryptor.

The read buffer size is taken from the CopyReadBufferSizeHint member variable

func (*AESCBCEncryptor) Read

func (e *AESCBCEncryptor) Read(p []byte) (n int, err error)

Read implements io.Reader and returns ciphertext that has been encrypted. Data is available on Read() after plaintext has been written to Write(). If no ciphertext is available, a zero-byte slice is returned and error is nil. Error will return io.EOF after the Close() method has been called and no more data is available to read.

The encryptor must hold on to at least 16 bytes of plaintext so that there's enough plaintext to add padding when Close() is called.

func (*AESCBCEncryptor) Write

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

Write implements io.Writer and accepts plaintext to be encrypted. After writing plaintext to Write(), ciphertext will become available on the Read() method.

The last block or partial block of plaintext is internally buffered until the Close() method is called so that padding can be added to the cipher text.

The Close() method should be called after the last plaintext has been written to Write().

Jump to

Keyboard shortcuts

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