TheAlgorithms/Go · critical
panic(err)
Error message
panic(err)
What it means
In dsaParameterGeneration (cipher/dsa), choosing the N-bit prime q uses crypto/rand.Prime. If the cryptographic RNG fails, the code panics with panic(err) instead of returning an error. This is a hard crash: the library treats RNG failure as unrecoverable rather than propagating it to the caller.
Source
Thrown at cipher/dsa/dsa.go:63
// 2. Choose a N-bit prime q
// 3. Choose a L-bit prime p such that p-1 is a multiple of q
// 4. Choose an integer h randomly from the range [2, p-2]
// 5. Compute g = h^((p-1)/q) mod p
// 6. Return (p, q, g)
func (dsa *dsa) dsaParameterGeneration() {
var err error
p, q, bigInt := new(big.Int), new(big.Int), new(big.Int)
one, g, h := big.NewInt(1), big.NewInt(1), big.NewInt(2)
pBytes := make([]byte, L/8)
// GPLoop is a label for the loop
// We use this loop to change the prime q if we don't find a prime p
GPLoop:
for {
// 2. Choose a N-bit prime q
q, err = rand.Prime(rand.Reader, N)
if err != nil {
panic(err)
}
for i := 0; i < 4*L; i++ {
// 3. Choose a L-bit prime p such that p-1 is a multiple of q
// In this case we generate a random number of L bits
if _, err := io.ReadFull(rand.Reader, pBytes); err != nil {
panic(err)
}
// This are the minimum conditions for p being a possible prime
pBytes[len(pBytes)-1] |= 1 // p is odd
pBytes[0] |= 0x80 // p has the highest bit set
p.SetBytes(pBytes)
// Instead of using (p-1)%q == 0
// We ensure that p-1 is a multiple of q and validates if p is prime
bigInt.Mod(p, q)
bigInt.Sub(bigInt, one)View on GitHub (pinned to 5ba447ec5f)
Solutions
- Fix the underlying entropy source so crypto/rand works (restore /dev/urandom access, fix container/VM configuration).
- Recover from the panic at the call boundary and translate it into a returned error.
- Replace the library's panic with error propagation (fork or upstream patch): return err from dsaParameterGeneration.
Example fix
// before
q, err = rand.Prime(rand.Reader, N)
if err != nil {
panic(err)
}
// after
q, err = rand.Prime(rand.Reader, N)
if err != nil {
return nil, fmt.Errorf("dsa: failed to generate prime q: %w", err)
} Defensive patterns
Strategy: try-catch
Validate before calling
// Go's crypto/rand cannot be pre-validated directly; verify entropy source availability
if _, err := os.Stat("/dev/urandom"); err != nil {
return fmt.Errorf("entropy source unavailable: %w", err)
} Type guard
func recoverDSAError() (err error) {
if r := recover(); r != nil {
if e, ok := r.(error); ok {
err = fmt.Errorf("dsa parameter generation panicked: %w", e)
} else {
err = fmt.Errorf("dsa parameter generation panicked: %v", r)
}
}
return
} Try / catch
func generateParamsSafe(N, L int) (p *dsa.Params, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("dsa: rng failure during parameter generation: %v", r)
}
}()
return dsa.GenerateParameters(N, L)
} Prevention
- Ensure the runtime environment exposes a working entropy source (e.g. /dev/urandom) before crypto operations.
- Wrap DSA key/parameter generation in a recover() boundary to convert panics into errors.
- In tests, only substitute rand.Reader with readers that never fail, or skip crypto tests in restricted sandboxes.
When it happens
Trigger: Calling any DSA key-generation entry point when crypto/rand.Reader cannot deliver bytes — e.g. a depleted or misconfigured entropy source, a sandboxed/containerized environment without proper /dev/urandom access, or a custom rand.Reader injected into the package that returns errors.
Common situations: Containers with restricted device access, stripped-down VMs or embedded systems low on entropy, tests that stub rand.Reader with a failing reader, or a broken/failed hardware RNG.
Related errors
AI-assisted analysis of TheAlgorithms/Go@5ba447ec5f (2026-09-02).
Data as JSON: /api/errors/0ed5d9bdcbf5b764.
Report an issue: GitHub.