From 014b84ec226b8a98d1aa5cfa54a847e6eae6030f Mon Sep 17 00:00:00 2001 From: Rose Hogenson Date: Sat, 4 Oct 2025 16:38:40 -0700 Subject: Allow http multipart upload --- internal/cryptoutil/oae2.go | 73 ++++++++++++++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 21 deletions(-) (limited to 'internal/cryptoutil/oae2.go') 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 { -- cgit v1.3.1