size : 11739
uploaded_on : Mon May 17 00:00:00 1999
modified_on : Wed Dec 8 14:03:40 1999
title : BigPrime
org_filename : Bigprime.pas
author : Jes R. Klinke
authoremail : jesk@diku.dk
description : Routines for finding and manipulating arbitrarily large (at least 200 digits) primes. Requires BigNum.
keywords :
tested : not tested yet
submitted_by : The CKB Crew
submitted_by_email : ckb@netalive.org
uploaded_by : nobody
modified_by : nobody
owner : nobody
lang : pas
file-type : text/plain
category : pascal-alg-maths
__END_OF_HEADER__
unit BigPrime;
{ BigPrime v2.1, 32-bit for Delphi by Jes R. Klinke
This unit provides means for finding very large prime numbers and other
functions nessecary for serious cryptographic applications.
The sequential prime search algorithm is due to Philip Zimmermann
Features:
* Test and search for probable primes
Function are provided for finding really large primes. 100 digits in a
matter of seconds, 200 digits in about a minute (120 MHz Pentium).
* Calculation of inverse
A function which given E and M finds D such that (E * D) mod M = 1
is useful for RSA key generation.
Any comment or bug reports are welcome.
You can reach me at jesk@diku.dk or jesk@dk-online.dk.
My snail-mail address is Jes Rahbek Klinke
Haandvaerkerhaven 3, 2. mf
2400 Copenhagen NV }
interface
uses
BigNum;
function FermatTest(Candidate: TBigNum; MaxFermatBase: Integer): Boolean;
{ Test if a given number is a probable prime.
On a false return the number is definately not a prime.
On a true return the number is probably a prime, the higher the value
of MaxFermatBase, the less likely that the numer is really composite.
The minimum value, 2, will usually suffise. }
procedure ZimmermannSearch(Start: TBigNum; MaxFermatBase: Integer);
{ Seaches for the smallest probable prime greater than or equal to Start.
The result is also returned in the parameter Start. }
function RelativePrime(N, M: TBigNum): Boolean;
{ Tests if N is relatively prime to M, i.e. the smallest integer dividing
them both is 1. }
procedure Inverse(E, M: TBigNum);
{ Given E and M finds D such that (E * D) mod M = 1 }
implementation
const
PrimeTableSize = 1028;
PrimeTable: array [0..PrimeTableSize - 1] of Integer = (
2, 3, 5, 7, 11, 13, 17, 19,
23, 29, 31, 37, 41, 43, 47, 53,
59, 61, 67, 71, 73, 79, 83, 89,
97, 101, 103, 107, 109, 113, 127, 131,
137, 139, 149, 151, 157, 163, 167, 173,
179, 181, 191, 193, 197, 199, 211, 223,
227, 229, 233, 239, 241, 251, 257, 263,
269, 271, 277, 281, 283, 293, 307, 311,
313, 317, 331, 337, 347, 349, 353, 359,
367, 373, 379, 383, 389, 397, 401, 409,
419, 421, 431, 433, 439, 443, 449, 457,
461, 463, 467, 479, 487, 491, 499, 503,
509, 521, 523, 541, 547, 557, 563, 569,
571, 577, 587, 593, 599, 601, 607, 613,
617, 619, 631, 641, 643, 647, 653, 659,
661, 673, 677, 683, 691, 701, 709, 719,
727, 733, 739, 743, 751, 757, 761, 769,
773, 787, 797, 809, 811, 821, 823, 827,
829, 839, 853, 857, 859, 863, 877, 881,
883, 887, 907, 911, 919, 929, 937, 941,
947, 953, 967, 971, 977, 983, 991, 997,
1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049,
1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097,
1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163,
1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223,
1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283,
1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321,
1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423,
1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459,
1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511,
1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571,
1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619,
1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693,
1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747,
1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811,
1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877,
1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949,
1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003,
2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069,
2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129,
2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203,
2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267,
2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311,
2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377,
2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423,
2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503,
2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579,
2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657,
2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693,
2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741,
2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801,
2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861,
2879, 2887, 2897, 2903, 2909, 2917, 2927, 2939,
2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011,
3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079,
3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167,
3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221,
3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301,
3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347,
3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413,
3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491,
3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541,
3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607,
3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671,
3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727,
3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797,
3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863,
3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923,
3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003,
4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057,
4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129,
4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211,
4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259,
4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337,
4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409,
4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481,
4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547,
4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621,
4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673,
4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751,
4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813,
4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909,
4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967,
4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011,
5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087,
5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167,
5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233,
5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309,
5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399,
5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443,
5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507,
5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573,
5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653,
5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711,
5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791,
5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849,
5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897,
5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007,
6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073,
6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133,
6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211,
6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271,
6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329,
6337, 6343, 6353, 6359, 6361, 6367, 6373, 6379,
6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473,
6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563,
6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637,
6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701,
6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779,
6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833,
6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907,
6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971,
6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027,
7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121,
7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207,
7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253,
7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349,
7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457,
7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517,
7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561,
7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621,
7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691,
7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757,
7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853,
7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919,
7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009,
8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087,
8089, 8093, 8101, 8111, 8117, 8123, 8147, 8161,
8167, 8171, 8179, 8191);
function FermatTest(Candidate: TBigNum; MaxFermatBase: Integer): Boolean;
var
Base, BaseCopy, Exp: TBigNum;
begin
if Candidate.Negative then
raise EBigNumInvalidArg.Create('Negative prime candidate in FermatTest');
Base := TBigNum.Create;
BaseCopy := TBigNum.Create;
Exp := TBigNum.Create;
Result := True;
Base.AsLong := 2;
while Result and (Base.AsLong <= MaxFermatBase) do
begin
BaseCopy.Assign(Base);
Exp.Assign(Candidate);
Exp.AbsDecrement(1);
BaseCopy.PowerModulo(Exp, Candidate);
Exp.AsLong := 1;
Result := BaseCopy.Compare(Exp) = 0;
Base.AbsIncrement(1);
end;
Exp.Destroy;
BaseCopy.Destroy;
Base.Destroy;
end;
procedure ZimmermannSearch(Start: TBigNum; MaxFermatBase: Integer);
type
PRemainderTable = ^TRemainderTable;
TRemainderTable = array [0..PrimeTableSize - 1] of Integer;
var
RemainderTable: PRemainderTable;
Delta: Integer;
procedure InitRemainderTable(Start: TBigNum; RemainderTable: PRemainderTable);
var
I: Integer;
begin
for I := 0 to PrimeTableSize - 1 do
RemainderTable^[I] := Start.AbsModuloLong(PrimeTable[I]);
end;
function RemainderTest(Delta: Integer; RemainderTable: PRemainderTable): Boolean;
var
I: Integer;
begin
Result := True;
I := 0;
while Result and (I < PrimeTableSize) do
begin
Result := not ((RemainderTable^[I] + Delta) mod PrimeTable[I] = 0);
Inc(I);
end;
end;
begin
if Start.Negative then
Start.AsLong := PrimeTable[PrimeTableSize - 1];
if Start.AbsModuloLong(2) = 0 then
Start.AbsIncrement(1);
New(RemainderTable);
InitRemainderTable(Start, RemainderTable);
Delta := 0;
while not (RemainderTest(Delta, RemainderTable) and FermatTest(Start, MaxFermatBase)) do
begin
Inc(Delta, 2);
Start.AbsIncrement(2);
end;
Dispose(RemainderTable);
end;
function RelativePrime(N, M: TBigNum): Boolean;
var
TempN, TempM, I: TBigNum;
begin
if N.Negative or M.Negative then
raise EBigNumInvalidArg.Create('Negative argument in RelativePrime');
TempN := TBigNum.Create;
TempM := TBigNum.Create;
I := TBigNum.Create;
TempN.Assign(N);
TempM.Assign(M);
I.AsLong := 0;
while I.Compare(TempM) <> 0 do
begin
if TempM.Compare(TempN) = 1 then
TempM.Swap(TempN)
else
TempN.Modulo(TempM);
end;
I.AsLong := 1;
Result := I.Compare(TempN) = 0;
end;
procedure Inverse(E, M: TBigNum);
var
TempM: TBigNum;
procedure Euklid(A, B: TBigNum);
var
NA, NB, Test, Q: TBigNum;
begin
Test := TBigNum.Create;
try
Test.AsLong := 1;
if A.Compare(Test) <= 0 then
begin
if A.Compare(Test) < 0 then
raise EBigNumInvalidArg.Create('No inverse exists in Inverse');
end
else
begin
Test.AsLong := 0;
if B.Compare(Test) <= 0 then
raise EBigNumInvalidArg.Create('No inverse exists in Inverse');
NA := TBigNum.Create;
NB := TBigNum.Create;
Q := TBigNum.Create;
NA.Assign(B);
NB.Assign(A);
NB.Modulo(B);
Q.Assign(A);
Q.Divide(B);
Euklid(NA, NB);
A.Assign(NB);
B.Assign(NA);
NB.Multiply(Q);
B.Subtract(NB);
Q.Destroy;
NA.Destroy;
NB.Destroy;
end;
finally
Test.Destroy;
end;
end;
begin
TempM := TBigNum.Create;
TempM.Assign(M);
Euklid(TempM, E);
E.Modulo(M);
TempM.Destroy;
end;
end.