This is an automated email from the ASF dual-hosted git repository.

zeroshade pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-go.git


The following commit(s) were added to refs/heads/main by this push:
     new 7ac7d2f9 fix(parquet): propagate nonce generation failures (#1045)
7ac7d2f9 is described below

commit 7ac7d2f94fa00dea4ba81d0aa9635115d5ae30f2
Author: Minh Vu <[email protected]>
AuthorDate: Wed Aug 5 19:32:56 2026 +0200

    fix(parquet): propagate nonce generation failures (#1045)
    
    ## What changed
    
    Check the secure-random read used to generate Parquet AES nonces and
    stop encryption if nonce generation fails.
    
    ## Why
    
    The encryptor previously ignored the result of `crypto/rand.Read`. On Go
    versions where that function returns an error, encryption could continue
    with an all-zero or partially filled nonce. Reusing a nonce undermines
    the security guarantees of both AES-GCM and AES-CTR.
    
    The test uses a package-local random-read seam to inject an entropy
    failure without replacing the process-wide random reader. It covers both
    supported cipher modes.
    
    ## Validation
    
    `go test ./parquet/internal/encryption`
---
 parquet/internal/encryption/aes.go      |  6 +++++-
 parquet/internal/encryption/aes_test.go | 30 ++++++++++++++++++++++++++++++
 2 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/parquet/internal/encryption/aes.go 
b/parquet/internal/encryption/aes.go
index e6bed554..327d24d5 100644
--- a/parquet/internal/encryption/aes.go
+++ b/parquet/internal/encryption/aes.go
@@ -43,6 +43,8 @@ const (
        bufferSizeLength = 4
 )
 
+var readRandom = rand.Read
+
 // Module constants for constructing the AAD bytes, the order here is
 // important as the constants are set via iota.
 const (
@@ -125,7 +127,9 @@ func (a *aesEncryptor) Encrypt(w io.Writer, src, key, aad 
[]byte) int {
        }
 
        nonce := make([]byte, NonceLength)
-       rand.Read(nonce)
+       if _, err := readRandom(nonce); err != nil {
+               panic(fmt.Errorf("parquet: failed to generate encryption nonce: 
%w", err))
+       }
 
        if a.mode == gcmMode {
                aead, err := cipher.NewGCM(block)
diff --git a/parquet/internal/encryption/aes_test.go 
b/parquet/internal/encryption/aes_test.go
index f36f0e80..712d1b90 100644
--- a/parquet/internal/encryption/aes_test.go
+++ b/parquet/internal/encryption/aes_test.go
@@ -19,12 +19,42 @@ package encryption
 import (
        "bytes"
        "encoding/binary"
+       "errors"
        "testing"
 
        "github.com/apache/arrow-go/v18/parquet"
        "github.com/stretchr/testify/assert"
+       "github.com/stretchr/testify/require"
 )
 
+type failingRandomReader struct {
+       err error
+}
+
+func (r failingRandomReader) Read([]byte) (int, error) { return 0, r.err }
+
+func TestAESEncryptRejectsNonceGenerationFailure(t *testing.T) {
+       originalReadRandom := readRandom
+       t.Cleanup(func() { readRandom = originalReadRandom })
+       failingReader := failingRandomReader{err: errors.New("entropy 
unavailable")}
+       readRandom = failingReader.Read
+
+       for _, tc := range []struct {
+               name string
+               alg  parquet.Cipher
+       }{
+               {name: "GCM", alg: parquet.AesGcm},
+               {name: "CTR", alg: parquet.AesCtr},
+       } {
+               t.Run(tc.name, func(t *testing.T) {
+                       encryptor := NewAesEncryptor(tc.alg, false)
+                       require.PanicsWithError(t,
+                               "parquet: failed to generate encryption nonce: 
entropy unavailable",
+                               func() { encryptor.Encrypt(&bytes.Buffer{}, 
[]byte("data"), make([]byte, 16), nil) })
+               })
+       }
+}
+
 func TestAESDecryptRejectsMalformedCiphertext(t *testing.T) {
        decryptor := newAesDecryptor(parquet.AesGcm, false)
        key := make([]byte, 16)

Reply via email to