// GenerateSafePrime tries to find a safe prime concurrently.
// The returned result is a safe prime `p` and prime `q` such that `p=2q+1`.
// Concurrency level can be controlled with the `concurrencyLevel` parameter.
// If a safe prime could not be found in the specified `timeout`, the error
// is returned. Also, if at least one search process failed, error is returned
// as well.
//
// How fast we generate a prime number is mostly a matter of luck and it depends
// on how lucky we are with drawing the first bytes.
// With today's multicore processors, we can execute the process on multiple
// cores concurrently, accept the first valid result and cancel the rest of
// work. This way, with the same finding algorithm, we can get the result
// faster.
//
// Concurrency level should be set depending on what `bitLen` of prime is
// expected. For example, as of today, on a typical workstation, for 512-bit
// safe prime, `concurrencyLevel` should be set to `1` as generating the prime
// of this length is a matter of milliseconds for a single core.
// For 1024-bit safe prime, `concurrencyLevel` should be usually set to at least
// `2` and for 2048-bit safe prime, `concurrencyLevel` must be set to at least
// `4` to get the result in a reasonable time.
//
// This function generates safe primes of at least 6 `bitLen`. For every
// generated safe prime, the two most significant bits are always set to `1`
// - we don't want the generated number to be too small.
GenerateSafePrime tries to find a safe prime concurrently.
The returned result is a safe prime `p` and prime `q` such that `p=2q+1`.
Concurrency level can be controlled with the `concurrencyLevel` parameter.
If a safe prime could not be found in the specified `timeout`, the error
is returned. Also, if at least one search process failed, error is returned
as well.



Concurrency level should be set depending on what `bitLen` of prime is
expected. For example, as of today, on a typical workstation, for 512-bit
safe prime, `concurrencyLevel` should be set to `1` as generating the prime
of this length is a matter of milliseconds for a single core.
For 1024-bit safe prime, `concurrencyLevel` should be usually set to at least
`2` and for 2048-bit safe prime, `concurrencyLevel` must be set to at least
`4` to get the result in a reasonable time.

This function generates safe primes of at least 6 `bitLen`. For every
generated safe prime, the two most significant bits are always set to `1`
- we don't want the generated number to be too small.
// GenerateSafePrime tries to find a safe prime concurrently . // The returned result is a safe prime ` p ` and prime ` q ` such that ` p = 2q + 1 ` . // Concurrency level can be controlled with the ` concurrencyLevel ` parameter . // If a safe prime could not be found in the specified ` timeout ` the error // is returned . Also if at least one search process failed error is returned // as well . // // How fast we generate a prime number is mostly a matter of luck and it depends // on how lucky we are with drawing the first bytes . // With today ' s multicore processors we can execute the process on multiple // cores concurrently accept the first valid result and cancel the rest of // work . This way with the same finding algorithm we can get the result // faster . // // Concurrency level should be set depending on what ` bitLen ` of prime is // expected . For example as of today on a typical workstation for 512 - bit // safe prime ` concurrencyLevel ` should be set to ` 1 ` as generating the prime // of this length is a matter of milliseconds for a single core . // For 1024 - bit safe prime ` concurrencyLevel ` should be usually set to at least // ` 2 ` and for 2048 - bit safe prime ` concurrencyLevel ` must be set to at least // ` 4 ` to get the result in a reasonable time . // // This function generates safe primes of at least 6 ` bitLen ` . For every // generated safe prime the two most significant bits are always set to ` 1 ` // - we don ' t want the generated number to be too small .
func GenerateSafePrime(
	bitLen int,
	concurrencyLevel int,
	timeout time.Duration,
	random io.Reader,
) (*big.Int, *big.Int, error) {
	if bitLen < 6 {
		return nil, nil, errors.New("safe prime size must be at least 6 bits")
	}
	primeChan := make(chan safePrime, concurrencyLevel)
	errChan := make(chan error, concurrencyLevel)
	waitGroup := &sync.WaitGroup{}
	defer close(primeChan)
	defer close(errChan)
	defer waitGroup.Wait()
	ctx, cancel := context.WithCancel(context.Background())
	for i := 0; i < concurrencyLevel; i++ {
		waitGroup.Add(1)
		runGenPrimeRoutine(
			ctx, primeChan, errChan, waitGroup, random, bitLen,
		)
	}
	go func() {
		time.Sleep(timeout)
		cancel()
	}()
	select {
	case result := <-primeChan:
		cancel()
		return result.p, result.q, nil
	case err := <-errChan:
		cancel()
		return nil, nil, err
	case <-ctx.Done():
		return nil, nil, fmt.Errorf("generator timed out after %v", timeout)
	}
}
func GenerateSafePrime ( bitLen int , concurrencyLevel int , timeout time . Duration , random io . Reader , ) ( * big . Int , * big . Int , error ) { if bitLen < 6 { return nil , nil , errors . New ( " " ) } primeChan := make ( chan safePrime , concurrencyLevel ) errChan := make ( chan error , concurrencyLevel ) waitGroup := & sync . WaitGroup { } defer close ( primeChan ) defer close ( errChan ) defer waitGroup . Wait ( ) ctx , cancel := context . WithCancel ( context . Background ( ) ) for i := 0 ; i < concurrencyLevel ; i ++ { waitGroup . Add ( 1 ) runGenPrimeRoutine ( ctx , primeChan , errChan , waitGroup , random , bitLen , ) } go func ( ) { time . Sleep ( timeout ) cancel ( ) } ( ) select { case result := <- primeChan : cancel ( ) return result . p , result . q , nil case err := <- errChan : cancel ( ) return nil , nil , err case <- ctx . Done ( ) : return nil , nil , fmt . Errorf ( " " , timeout ) } }
GenerateSafePrime tries to find a safe prime concurrently.
GenerateSafePrime tries to find a safe prime concurrently .
// Cancel after the specified timeout.