1# Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu> 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# https://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15"""Functions for parallel computation on multiple cores. 16 17Introduced in Python-RSA 3.1. 18 19.. note:: 20 21 Requires Python 2.6 or newer. 22 23""" 24 25import multiprocessing as mp 26from multiprocessing.connection import Connection 27 28import rsa.prime 29import rsa.randnum 30 31 32def _find_prime(nbits: int, pipe: Connection) -> None: 33 while True: 34 integer = rsa.randnum.read_random_odd_int(nbits) 35 36 # Test for primeness 37 if rsa.prime.is_prime(integer): 38 pipe.send(integer) 39 return 40 41 42def getprime(nbits: int, poolsize: int) -> int: 43 """Returns a prime number that can be stored in 'nbits' bits. 44 45 Works in multiple threads at the same time. 46 47 >>> p = getprime(128, 3) 48 >>> rsa.prime.is_prime(p-1) 49 False 50 >>> rsa.prime.is_prime(p) 51 True 52 >>> rsa.prime.is_prime(p+1) 53 False 54 55 >>> from rsa import common 56 >>> common.bit_size(p) == 128 57 True 58 59 """ 60 61 (pipe_recv, pipe_send) = mp.Pipe(duplex=False) 62 63 # Create processes 64 try: 65 procs = [mp.Process(target=_find_prime, args=(nbits, pipe_send)) 66 for _ in range(poolsize)] 67 # Start processes 68 for p in procs: 69 p.start() 70 71 result = pipe_recv.recv() 72 finally: 73 pipe_recv.close() 74 pipe_send.close() 75 76 # Terminate processes 77 for p in procs: 78 p.terminate() 79 80 return result 81 82 83__all__ = ['getprime'] 84 85if __name__ == '__main__': 86 print('Running doctests 1000x or until failure') 87 import doctest 88 89 for count in range(100): 90 (failures, tests) = doctest.testmod() 91 if failures: 92 break 93 94 if count % 10 == 0 and count: 95 print('%i times' % count) 96 97 print('Doctests done') 98