// Copyright 2024 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package cryptotestimport ()typeMakeBlockfunc(key []byte) (cipher.Block, error)// TestBlock performs a set of tests on cipher.Block implementations, checking// the documented requirements of BlockSize, Encrypt, and Decrypt.func ( *testing.T, int, MakeBlock) {// Generate random key := make([]byte, )newRandReader().Read() .Logf("Cipher key: 0x%x", ) , := ()if != nil { .Fatal() } := .BlockSize() .Run("Encryption", func( *testing.T) {testCipher(, .Encrypt, ) }) .Run("Decryption", func( *testing.T) {testCipher(, .Decrypt, ) })// Checks baseline Encrypt/Decrypt functionality. More thorough // implementation-specific characterization/golden tests should be done // for each block cipher implementation. .Run("Roundtrip", func( *testing.T) { := newRandReader()// Check Decrypt inverts Encrypt , , := make([]byte, ), make([]byte, ), make([]byte, ) .Read() .Encrypt(, ) .Decrypt(, )if !bytes.Equal(, ) { .Errorf("plaintext is different after an encrypt/decrypt cycle; got %x, want %x", , ) }// Check Encrypt inverts Decrypt (assumes block ciphers are deterministic) , , := make([]byte, ), make([]byte, ), make([]byte, ) .Read() .Decrypt(, ) .Encrypt(, )if !bytes.Equal(, ) { .Errorf("ciphertext is different after a decrypt/encrypt cycle; got %x, want %x", , ) } })}func testCipher( *testing.T, func(, []byte), int) { .Run("AlterInput", func( *testing.T) { := newRandReader()// Make long src that shouldn't be modified at all, within block // size scope or beyond it , := make([]byte, *2), make([]byte, *2) .Read()copy(, ) := make([]byte, ) (, )if !bytes.Equal(, ) { .Errorf("block cipher modified src; got %x, want %x", , ) } }) .Run("Aliasing", func( *testing.T) { := newRandReader() , := make([]byte, ), make([]byte, )// Record what output is when src and dst are different .Read() (, )// Check that the same output is generated when src=dst alias to the same // memory (, )if !bytes.Equal(, ) { .Errorf("block cipher produced different output when dst = src; got %x, want %x", , ) } }) .Run("OutOfBoundsWrite", func( *testing.T) { := newRandReader() := make([]byte, ) .Read()// Make a buffer with dst in the middle and data on either end := make([]byte, *3) , := , *2 .Read([:]) .Read([:]) := [:]// Record the prefix and suffix data to make sure they aren't written to , := make([]byte, ), make([]byte, )copy(, [:])copy(, [:])// Write to dst (the middle of the buffer) and make sure it doesn't write // beyond the dst slice (, )if !bytes.Equal([:], ) { .Errorf("block cipher did out of bounds write after end of dst slice; got %x, want %x", [:], ) }if !bytes.Equal([:], ) { .Errorf("block cipher did out of bounds write before beginning of dst slice; got %x, want %x", [:], ) }// Check that dst isn't written to beyond BlockSize even if there is room // in the slice = [:] // Extend dst to include suffix (, )if !bytes.Equal([:], ) { .Errorf("block cipher modified dst past BlockSize bytes; got %x, want %x", [:], ) } })// Check that output of cipher isn't affected by adjacent data beyond input // slice scope // For encryption, this assumes block ciphers encrypt deterministically .Run("OutOfBoundsRead", func( *testing.T) { := newRandReader() := make([]byte, ) .Read() := make([]byte, ) (, )// Make a buffer with src in the middle and data on either end := make([]byte, *3) , := , *2copy([:], ) .Read([:]) .Read([:]) := make([]byte, ) (, [:])if !bytes.Equal(, ) { .Errorf("block cipher affected by data outside of src slice bounds; got %x, want %x", , ) }// Check that src isn't read from beyond BlockSize even if the slice is // longer and contains data in the suffix (, [:]) // Input long srcif !bytes.Equal(, ) { .Errorf("block cipher affected by src data beyond BlockSize bytes; got %x, want %x", [:], ) } }) .Run("NonZeroDst", func( *testing.T) { := newRandReader()// Record what the cipher writes into a destination of zeroes := make([]byte, ) .Read() := make([]byte, ) (, )// Make nonzero dst := make([]byte, *2) .Read()// Remember the random suffix which shouldn't be written to = append(, [:]...) (, )if !bytes.Equal(, ) { .Errorf("block cipher behavior differs when given non-zero dst; got %x, want %x", , ) } }) .Run("BufferOverlap", func( *testing.T) { := newRandReader() := make([]byte, *2) .Read(())// Make src and dst slices point to same array with inexact overlap := [:] := [1 : +1]mustPanic(, "invalid buffer overlap", func() { (, ) })// Only overlap on one byte = [:] = [-1 : 2*-1]mustPanic(, "invalid buffer overlap", func() { (, ) })// src comes after dst with one byte overlap = [-1 : 2*-1] = [:]mustPanic(, "invalid buffer overlap", func() { (, ) }) })// Test short input/output. // Assembly used to not notice. // See issue 7928. .Run("ShortBlock", func( *testing.T) {// Returns slice of n bytes of an n+1 length array. Lets us test that a // slice is still considered too short even if the underlying array it // points to is large enough := func( int) []byte { returnmake([]byte, +1)[0:] }// Off by one bytemustPanic(, "input not full block", func() { ((), (-1)) })mustPanic(, "output not full block", func() { ((-1), ()) })// Small slicesmustPanic(, "input not full block", func() { ((1), (1)) })mustPanic(, "input not full block", func() { ((100), (1)) })mustPanic(, "output not full block", func() { ((1), (100)) }) })}func mustPanic( *testing.T, string, func()) { .Helper()deferfunc() { .Helper() := recover()if == nil { .Errorf("function did not panic for %q", ) } }() ()}
The pages are generated with Goldsv0.7.3. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.