From cb3844c27b563902e1ba6747e1010c7148c0d21b Mon Sep 17 00:00:00 2001 From: Gerald Teschl Date: Wed, 6 Nov 2024 22:22:51 +0100 Subject: [PATCH] previous/next safe prime --- kryptools/__init__.py | 2 +- kryptools/primes.py | 30 +++++++++++++++++++++++++++++- tests/test_primes.py | 14 +++++++++++--- 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/kryptools/__init__.py b/kryptools/__init__.py index 3360c1b..bad8c06 100644 --- a/kryptools/__init__.py +++ b/kryptools/__init__.py @@ -9,7 +9,7 @@ __email__ = "Gerald.Teschl@univie.ac.at" from .nt import egcd, cf, convergents, legendre_symbol, jacobi_symbol, sqrt_mod, euler_phi, carmichael_lambda, moebius_mu, is_carmichael_number, order, crt -from .primes import sieve_eratosthenes, prime_pi, is_prime, next_prime, previous_prime, random_prime, random_strongprime, is_safeprime, random_safeprime, is_blumprime, random_blumprime, miller_rabin_test, lucas_test +from .primes import sieve_eratosthenes, prime_pi, is_prime, next_prime, previous_prime, next_safeprime, previous_safeprime, random_prime, random_strongprime, is_safeprime, random_safeprime, is_blumprime, random_blumprime, miller_rabin_test, lucas_test from .intfuncs import iroot, ilog, perfect_square, perfect_power, prime_power from .factor import factorint, divisors from .dlp import dlog diff --git a/kryptools/primes.py b/kryptools/primes.py index aef42d7..4ade84f 100644 --- a/kryptools/primes.py +++ b/kryptools/primes.py @@ -5,6 +5,8 @@ is_prime(n) test if n is probably prime next_prime(n) find the next prime larger or equal n previous_prime(n) find the previous prime smaller or equal n + next_safeprime(n) find the next safe prime larger or equal n + previous_safeprime(n) find the previous safe prime smaller or equal n random_bitlength(l) return a random number with bit lenght l random_prime(l) return a random prime with bit length l random_strongprime(l) return a random strong prime with factors of bit length l @@ -188,7 +190,9 @@ def is_prime(n: int, trialdivision: bool = True) -> bool: def is_safeprime(p: int) -> bool: """Tests if a number is a safe prime.""" - return is_prime(p) and is_prime((p - 1) // 2) + if p < 107: + return p in (5, 7, 11, 23, 47, 59, 83) + return p % 12 == 11 and is_prime(p) and is_prime((p - 1) // 2) def is_blumprime(p: int) -> bool: """Tests if a number is a Blum prime.""" @@ -218,6 +222,30 @@ def previous_prime(n: int) -> int: n -= 2 return n +def next_safeprime(n: int) -> int: + """Find the next safe prime larger or equal `n`.""" + if n < 6: + return 5 + if n < 8: + return 7 + n = n - (n % 12) + 11 # make sure p % 12 = 11 + while not is_safeprime(n): + n += 12 + return n + +def previous_safeprime(n: int) -> int: + """Find the previous safe prime smaller or equal `n`.""" + if n < 7: + return 5 + if n < 11: + return 7 + tmp = (n % 12) + 1 + if tmp != 12: + n = n - tmp # make sure p % 12 = 11 + while not is_safeprime(n): + n -= 12 + return n + def random_bitlength(l: int) -> int: "Return a random number with bit lenght `l`." l = max(2, l) diff --git a/tests/test_primes.py b/tests/test_primes.py index ca556bd..c4a7c41 100644 --- a/tests/test_primes.py +++ b/tests/test_primes.py @@ -1,7 +1,7 @@ import pytest from math import isqrt from random import randint, seed -from kryptools import sieve_eratosthenes, prime_pi, next_prime, previous_prime, is_prime, is_safeprime, is_blumprime +from kryptools import sieve_eratosthenes, prime_pi, next_prime, previous_prime, next_safeprime, previous_safeprime, is_prime, is_safeprime, is_blumprime from kryptools import miller_rabin_test, lucas_test, random_prime, random_safeprime, random_blumprime, random_strongprime seed(0) @@ -46,6 +46,8 @@ def sieve(max: int) -> list: def test_sieve_eratosthenes(): for i, p in enumerate(sieve_eratosthenes(OEIS_A000010[-1])): assert p == OEIS_A000010[i] + assert previous_prime(p) == p + assert next_prime(p) == p if i > 0: assert previous_prime(p-1) == OEIS_A000010[i-1] if i < len(OEIS_A000010) - 1: @@ -74,8 +76,14 @@ def test_is_prime(): def test_is_safeprime(): for n in range(OEIS_A005385[-1]+1): assert is_safeprime(n) == (n in OEIS_A005385) - for n in OEIS_A005385: - assert is_safeprime(n) == True + for i, p in enumerate(OEIS_A005385): + assert is_safeprime(p) == True + assert previous_safeprime(p) == p + assert next_safeprime(p) == p + if i > 0: + assert previous_safeprime(p-1) == OEIS_A005385[i-1] + if i < len(OEIS_A005385) - 1: + assert next_safeprime(p+1) == OEIS_A005385[i+1] #https://oeis.org/A014233 OEIS_A014233 = [ 2047, 1373653, 25326001, 3215031751, 2152302898747, 3474749660383,