Фон
Для удовольствия я пытаюсь написать свойство для быстрой проверки, которое может протестировать основную идею криптографии с RSA.
- Выберите два разных простых числа,
p
иq
. - Пусть
N = p*q
-
e
- это некоторое число относительно простое до(p-1)(q-1)
(на практике e обычно 3 для быстрого кодирования) -
d
является модульным обратнымe
по модулю(p-1)(q-1)
Для всех x
таких, что 1 < x < N
, всегда верно, что (x^e)^d = x modulo N
Другими словами, x
является "сообщением", поднимая его на e
th power mod N
, является действием "кодирования" сообщения и повышения кодированного сообщения до d
th power mod N
- это акт его "декодирования".
(Свойство также тривиально верно для x = 1
, случай, который является его собственным шифрованием)
код
Вот методы, которые я кодировал до сих пор:
import Test.QuickCheck
-- modular exponentiation
modExp :: Integral a => a -> a -> a -> a
modExp y z n = modExp' (y `mod` n) z `mod` n
where modExp' y z | z == 0 = 1
| even z = modExp (y*y) (z `div` 2) n
| odd z = (modExp (y*y) (z `div` 2) n) * y
-- relatively prime
rPrime :: Integral a => a -> a -> Bool
rPrime a b = gcd a b == 1
-- multiplicative inverse (modular)
mInverse :: Integral a => a -> a -> a
mInverse 1 _ = 1
mInverse x y = (n * y + 1) `div` x
where n = x - mInverse (y `mod` x) x
-- just a quick way to test for primality
n `divides` x = x `mod` n == 0
primes = 2:filter isPrime [3..]
isPrime x = null . filter (`divides` x) $ takeWhile (\y -> y*y <= x) primes
-- the property
prop_rsa (p,q,x) = isPrime p &&
isPrime q &&
p /= q &&
x > 1 &&
x < n &&
rPrime e t ==>
x == (x `powModN` e) `powModN` d
where e = 3
n = p*q
t = (p-1)*(q-1)
d = mInverse e t
a `powModN` b = modExp a b n
(Спасибо, google и случайный блог, для реализация модульного мультипликативного обратного)
Вопрос
Проблема должна быть очевидной: существует слишком много условий для свойства, чтобы сделать его применимым. При попытке вызвать quickCheck prop_rsa
в ghci мой терминал зависает.
Итак, я немного покрутил руководство QuickCheck, и он говорит:
Свойства могут иметь вид
forAll <generator> $ \<pattern> -> <property>
Как сделать <generator>
для простых чисел? Или с другими ограничениями, так что quickCheck
не нужно просеивать кучу неудачных условий?
Приветствуем любые другие общие рекомендации (особенно в отношении QuickCheck).