~seirdy/moac

6e0ad7abb812f7b1492538f330f658cb08c35483 — Rohan Kumar 2 years ago 2322109
Test: ensure GenPW panics properly w/o crypto/rand

Run a test that temporarily breaks crypto/rand and ensures that GenPW
panics without a CSPRNG. Also check that the logged message is correct.

This uses an approach borrowed from gopass:
github.com/gopasspw/gopass/blob/3894fb96b/pkg/pwgen/pwgen_test.go#L38
2 files changed, 39 insertions(+), 1 deletions(-)

M pwgen/indexing.go
A pwgen/nocrand_test.go
M pwgen/indexing.go => pwgen/indexing.go +1 -1
@@ 13,7 13,7 @@ import (
func randInt(max int) int {
	newInt, err := rand.Int(rand.Reader, big.NewInt(int64(max)))
	if err != nil {
		log.Panicf("specialIndexes: %v", err)
		log.Panicf("can't generate passwords: crypto/rand unavailable: %v", err)
	}

	return int(newInt.Int64())

A pwgen/nocrand_test.go => pwgen/nocrand_test.go +38 -0
@@ 0,0 1,38 @@
package pwgen_test

import (
	"crypto/rand"
	"strings"
	"testing"

	"git.sr.ht/~seirdy/moac/v2/charsets"
	"git.sr.ht/~seirdy/moac/v2/pwgen"
)

func TestGenPwPanics(t *testing.T) {
	shouldPanic(t)
}

func shouldPanic(t *testing.T) {
	t.Helper()

	pwr := pwgen.PwRequirements{
		CharsetsWanted: charsets.ParseCharsets([]string{"ascii", "latin", "🦖؆ص😈"}),
		MinLen:         32,
	}

	csprng := rand.Reader
	rand.Reader = strings.NewReader("")

	defer func() {
		rand.Reader = csprng

		if out := recover(); out != "can't generate passwords: crypto/rand unavailable: EOF" {
			t.Errorf("panic due to CSPRNG unavailability sent unexpected message: %v", out)
		}
	}()

	_, _ = pwgen.GenPW(pwr) //nolint:errcheck // we're checking for panics; errors are checked elsewhere

	t.Errorf("pwgen should have panicked without access to a CSPRNG")
}