summaryrefslogtreecommitdiffstats
path: root/internal/cryptoutil
diff options
context:
space:
mode:
Diffstat (limited to 'internal/cryptoutil')
-rw-r--r--internal/cryptoutil/oae2.go73
1 files changed, 52 insertions, 21 deletions
diff --git a/internal/cryptoutil/oae2.go b/internal/cryptoutil/oae2.go
index 8eb18fb..2310039 100644
--- a/internal/cryptoutil/oae2.go
+++ b/internal/cryptoutil/oae2.go
@@ -16,14 +16,11 @@ import (
// Online Authenticated Encryption from https://eprint.iacr.org/2015/189.pdf
const (
- aeadOverhead = 16
- aesKeySize = 32
- noncePrefixSize = 3
- gcmNonceSize = 12
- headerSize = aesKeySize + noncePrefixSize
- cacheSize = 192 * 1024
- encryptedSegmentSize = cacheSize - 1
- segmentSize = encryptedSegmentSize - aeadOverhead
+ aeadOverhead = 16
+ aesKeySize = 32
+ noncePrefixSize = 3
+ gcmNonceSize = 12
+ headerSize = aesKeySize + noncePrefixSize
)
// An EncryptionKey is used for encrypting and decrypting data. A key can be any
@@ -96,30 +93,57 @@ func (o *oae2) decryptBlock(out, block []byte, lastBlock bool) ([]byte, error) {
// to the segment size, so it's important to call Close to flush the
// final segment.
type EncryptingWriter struct {
- w io.Writer
- oae2 oae2
+ w io.Writer
+ oae2 oae2
+ segmentSize int
initialized bool
err error
buf []byte
}
+type opts struct {
+ additionalData []byte
+ segmentSize int
+}
+
+var defaultOpts = opts{segmentSize: 192*1024 - 1 - aeadOverhead}
+
+type Option func(*opts)
+
+func WithAdditionalData(ad []byte) Option {
+ return func(opts *opts) {
+ opts.additionalData = ad
+ }
+}
+
+func WithSegmentSize(segmentSize int) Option {
+ return func(opts *opts) {
+ opts.segmentSize = segmentSize
+ }
+}
+
// NewWriter returns a new EncryptingWriter that writes to w. The additionalData
// will be authenticated with the first segment, but is not written to w. The
// same additional data must be provided when decrypting.
-func (k EncryptionKey) NewWriter(w io.Writer, additionalData []byte) *EncryptingWriter {
+func (k EncryptionKey) NewWriter(w io.Writer, options ...Option) *EncryptingWriter {
+ opts := defaultOpts
+ for _, o := range options {
+ o(&opts)
+ }
return &EncryptingWriter{
w: w,
oae2: oae2{
key: k,
- additionalData: additionalData,
+ additionalData: opts.additionalData,
},
+ segmentSize: opts.segmentSize,
}
}
func (w *EncryptingWriter) initialize() error {
w.initialized = true
- w.buf = make([]byte, 0, encryptedSegmentSize)
+ w.buf = make([]byte, 0, w.segmentSize+aeadOverhead)
header := make([]byte, headerSize)
rand.Read(header)
if w.err = w.oae2.initialize(header); w.err != nil {
@@ -141,7 +165,7 @@ func (w *EncryptingWriter) Write(buf []byte) (int, error) {
r := bytes.NewReader(buf)
nn := 0
for r.Len() > 0 {
- if len(w.buf) == segmentSize {
+ if len(w.buf) == w.segmentSize {
var encrypted []byte
if encrypted, w.err = w.oae2.encryptBlock(w.buf[:0], w.buf, false); w.err != nil {
return nn, w.err
@@ -151,7 +175,7 @@ func (w *EncryptingWriter) Write(buf []byte) (int, error) {
}
w.buf = w.buf[:0]
}
- n, _ := r.Read(w.buf[len(w.buf):segmentSize])
+ n, _ := r.Read(w.buf[len(w.buf):w.segmentSize])
w.buf = w.buf[:len(w.buf)+n]
nn += n
}
@@ -187,8 +211,9 @@ func (w *EncryptingWriter) Close() error {
// A DecryptingReader decrypts data using the STREAM construction.
type DecryptingReader struct {
- r *bufio.Reader
- oae2 oae2
+ r *bufio.Reader
+ oae2 oae2
+ segmentSize int
initialized bool
decryptedBuf bytes.Buffer
@@ -196,13 +221,18 @@ type DecryptingReader struct {
// NewReader returns a new DecryptingWriter that decrypts data from r. The
// additionaData must be the same that was provided when encrypting.
-func (k EncryptionKey) NewReader(r io.Reader, additionalData []byte) *DecryptingReader {
+func (k EncryptionKey) NewReader(r io.Reader, options ...Option) *DecryptingReader {
+ opts := defaultOpts
+ for _, o := range options {
+ o(&opts)
+ }
return &DecryptingReader{
- r: bufio.NewReaderSize(r, encryptedSegmentSize+1),
+ r: bufio.NewReaderSize(r, opts.segmentSize+aeadOverhead+1),
oae2: oae2{
key: k,
- additionalData: additionalData,
+ additionalData: opts.additionalData,
},
+ segmentSize: opts.segmentSize,
}
}
@@ -215,12 +245,13 @@ func (r *DecryptingReader) initialize() error {
return err
}
r.r.Discard(len(header))
- r.decryptedBuf = *bytes.NewBuffer(make([]byte, 0, segmentSize))
+ r.decryptedBuf = *bytes.NewBuffer(make([]byte, 0, r.segmentSize))
r.initialized = true
return nil
}
func (r *DecryptingReader) fillBuf() error {
+ encryptedSegmentSize := r.segmentSize + aeadOverhead
// Peek one extra byte to make sure if this is the last segment
block, readErr := r.r.Peek(encryptedSegmentSize + 1)
if len(block) == 0 {