home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1993 #3 / NN_1993_3.iso / spool / alt / sources / 3096 < prev    next >
Encoding:
Text File  |  1993-01-25  |  9.3 KB  |  422 lines

  1. Newsgroups: alt.sources
  2. Path: sparky!uunet!mcsun!news.funet.fi!network.jyu.fi!paasivir
  3. From: paasivir@jyu.fi (Risto Paasivirta)
  4. Subject: Multiprecision math library
  5. Message-ID: <1993Jan25.142037.24768@jyu.fi>
  6. Followup-To: alt.sources.d
  7. Summary: Math library and RSA encryption in C.
  8. Keywords: C obfuscated crypt math RSA portable fnord
  9. Organization: University of Jyvaskyla, Finland
  10. Date: Mon, 25 Jan 1993 14:20:37 GMT
  11. Lines: 409
  12.  
  13.  
  14. Hope someone finds this useful.
  15.  
  16. #!/bin/sh
  17. # This is a shell archive (produced by shar 3.49)
  18. # To extract the files from this archive, save it to a file, remove
  19. # everything above the "!/bin/sh" line above, and type "sh file_name".
  20. #
  21. # made 01/25/1993 14:09 UTC by paasivir@tukki
  22. # Source directory /home/tukki/opis/paasivir/cwr
  23. #
  24. # existing files will NOT be overwritten unless -c is specified
  25. #
  26. # This shar contains:
  27. # length  mode       name
  28. # ------ ---------- ------------------------------------------
  29. #   1006 -rw-r--r-- README
  30. #   6351 -rw-r--r-- mtest.c
  31. #
  32. # ============= README ==============
  33. if test -f 'README' -a X"$1" != X"-c"; then
  34.     echo 'x - skipping README (File already exists)'
  35. else
  36. echo 'x - extracting README (Text)'
  37. sed 's/^X//' << 'SHAR_EOF' > 'README' &&
  38. X
  39. This is a not-anything-better-to-do hack which took two
  40. days to write. Math library and toy RSA implementation. 
  41. Have fun. This should be portable to almost any machine 
  42. with 8-bit chars, >8-bit shorts and ANSI-C compiler.
  43. X
  44. X    Risto, Paasivir@jyu.fi
  45. X
  46. Example output:
  47. X
  48. 6.Risto:crypt/src> mtest 123456789abcdef fedba987654321
  49. Generating key...
  50. o
  51. Done, key components: pq,e,d,p,q,dp,dq,qp
  52. 00000121f8c9fd0967040d8e2cd56061a7
  53. 0000000000000000000000000000000003
  54. 000000305421aa2c3bd5a73cd9f60d3807
  55. 0000000000000000000123456789abce1b
  56. 00000000000000000000fedba987654365
  57. 00000000000000000000c22e4506728967
  58. 00000000000000000000a9e7c65a438243
  59. 00000000000000000001131e77b8539abb
  60. testing, msg,cip,dec1,dec2
  61. 000000c0779cc8dd3286b517b445dac469
  62. 000000c5e1a492e91f8044ef6f8acfc1aa
  63. 000000c0779cc8dd3286b517b445dac469
  64. 000000c0779cc8dd3286b517b445dac469
  65. 6.Risto:crypt/src>
  66. X
  67. (Chinese remainder shortcut isn't here faster than
  68. brute force, because modexp doesn't optimize precision.
  69. That optimization is trivial to add however.)
  70. X
  71. SHAR_EOF
  72. chmod 0644 README ||
  73. echo 'restore of README failed'
  74. Wc_c="`wc -c < 'README'`"
  75. test 1006 -eq "$Wc_c" ||
  76.     echo 'README: original size 1006, current size' "$Wc_c"
  77. fi
  78. # ============= mtest.c ==============
  79. if test -f 'mtest.c' -a X"$1" != X"-c"; then
  80.     echo 'x - skipping mtest.c (File already exists)'
  81. else
  82. echo 'x - extracting mtest.c (Text)'
  83. sed 's/^X//' << 'SHAR_EOF' > 'mtest.c' &&
  84. X
  85. #include <stdio.h>
  86. #include <stdlib.h>
  87. X
  88. /*
  89. X * Small-is-beautiful portable multiprecision math library
  90. X * 24-Jan-93 Risto Paasivirta, paasivir@jyu.fi.
  91. X * PD, no warranty, use as you wish.
  92. X */
  93. X
  94. /*
  95. X * change S to change precision bytes 
  96. X * (17 (=128+8 bits) is too low for real)
  97. X */
  98. #define S 17
  99. #define W while
  100. #define R return
  101. typedef unsigned char *N, NN[S];
  102. typedef unsigned short I;
  103. typedef void V;
  104. X
  105. /*
  106. X * ts(a) -- test signed
  107. X */
  108. X
  109. int ts(N a){I i=S;if(a[S-1]&128)R -1;W(i--)if(*a++)R 1;R 0;}
  110. X
  111. /*
  112. X * ng(a) -- a = -a, negate
  113. X */
  114. X
  115. I ng(N a){I c=0,i=S;W(i--){c=0-*a-c;*a++=c;c=(c>>8)&1;}R c;}
  116. X
  117. /*
  118. X * cl(a) -- a = 0, clear
  119. X */
  120. X
  121. V cl(N a){I i=0;W(i++<S)*a++=0;}
  122. X
  123. /*
  124. X * cp(a,b) -- a = b, copy
  125. X */
  126. X
  127. V cp(N a, N b){I i=S;W(i--)*a++=*b++;}
  128. X
  129. /*
  130. X * cu(a,b) -- compare unsigned
  131. X */
  132. X
  133. int cu(N a,N b){I i=S;a+=S;b+=S;W(i--)if(*--a-*--b)R(int)*a-
  134. (int)*b;R 0;}
  135. X
  136. /*
  137. X * ad(a,b) -- a += b, add (return carry)
  138. X */
  139. X
  140. I ad(N a,N b){I c=0, i=S;W(i--){c=*b++ +*a+c;*a++=c;c>>=8;}R
  141. c;}
  142. X
  143. /*
  144. X * sb(a,b) -- a -= b, substract (return carry)
  145. X */
  146. X
  147. I sb(N a,N b){I c=0,i=S;W(i--){c=*a-*b++-c;*a++=c;c=(c>>8)&1
  148. ;}R c;}
  149. X
  150. /*
  151. X * sr(a) -- a /= 2, shift right (return lo bit)
  152. X */
  153. X
  154. I sr(N a){I c=0, i=S;a+=S;W(i--){c|=*--a;*a=c>>1;c=(c&1)<<8;
  155. }R c;}
  156. X
  157. /*
  158. X * sl(a) -- a *= 2, shift left (return hi bit)
  159. X */ 
  160. X
  161. I sl(N a){I c=0,i=S;W(i--){c|=(I)*a<<1;*a++=c;c=(c>>8)&1;}R 
  162. c;}
  163. X
  164. /*
  165. X * dm(a,b,c) --  a /= b, c = a % b, divide/mod
  166. X */
  167. X
  168. V dm(N a,N b,N c){I i=S*8;cl(c);W(i--){sl(c);*c|=sl(a);if(sb
  169. (c,b))ad(c,b);else *a|=1;}}
  170. X
  171. /*
  172. X * mu(a,b) -- a *= b, unsigned multiply
  173. X */
  174. X
  175. V mu(N a,N b){I i=S*8;NN c;cl(c);W(i--){sl(c);if(sl(a))ad(c,
  176. b);}cp(a,c);}
  177. X
  178. /*
  179. X * mm(a,b,m) -- a *= b mod m, modular multiply
  180. X */
  181. X
  182. V mm(N a,N b,N m){I i=S*8;NN c;cl(c);W(i--){sl(c);if(sb(c,m)
  183. )ad(c,m);if(sl(a))ad(c,b);if(sb(c,m))ad(c,m);}cp(a,c);}
  184. X
  185. /*
  186. X * em(a,e,m) -- a = a^b mod m, modular exponentation
  187. X * This function is the one to optimize first!
  188. X */
  189. X
  190. V em(N a,N e,N m){I i=S,j;NN c,t;cl(c);*c=1;e+=S;W(!*--e&&i)
  191. i--;W(i--){for(j=8;j--;){cp(t,c);mm(c,t,m);if(*e&(1<<j))mm(c
  192. ,a,m);}e--;}cp(a,c);}
  193. X
  194. /*
  195. X * gd(N a, N b) -- a = gcd(a,b), find greatest common divisor
  196. X */
  197. X
  198. V gd(N a,N bb){NN r,b;cp(b,bb);W(ts(b)){dm(a,b,r);cp(a,b);cp
  199. (b,r);}}
  200. X
  201. /* iv(N a, N b) -- a = a^{-1} mod b (inverse) */
  202. X
  203. V iv(N a,N b){NN c,d,e,f,g,y;cp(c,b);cl(e);cl(f);*f=1;W(ts(a
  204. )){cp(y,c);dm(y,a,d);if(f[S-1]&128){ng(f);mu(y,f);ng(f);ng(y
  205. );}else mu(y,f);cp(g,e);sb(g,y);cp(c,a);cp(a,d);cp(e,f);cp(f
  206. ,g);}if(e[S-1]&128)ad(e,b);cp(a,e);}
  207. X
  208. /* nh(N a, N b) -- number to hex */
  209. X
  210. V nh(N a,N b){N d="0123456789abcdef";I i=S;a+=S*2;*a=0;W(i--
  211. ){*--a=d[*b&15];*--a=d[*b++>>4];}}
  212. X
  213. /* hn(N a, N b) -- hex to number */
  214. X
  215. V hn(N a,N b){cl(a);W(*b){sl(a);sl(a);sl(a);sl(a);*a+=*b<'a'
  216. ?*b-'0':*b-('a'-10);b++;}}
  217. X
  218. /*
  219. X * ri() -- (not cryptologically strong) pseudorandom generator
  220. X */
  221. X
  222. I ri(V){static I s=27182;s=s*31421+6927;R s;}
  223. X
  224. /*
  225. X * rn(N a) -- randomize a
  226. X */
  227. X
  228. V rn(N a){I i=S;W(i--)*a++^=ri()>>8;}
  229. X
  230. #undef W
  231. #undef R
  232. /*-------------------  end library code  ------------------*/
  233. X
  234. /*
  235. X * Example: RSA public key cryptosystem
  236. X * 25-Jan-93 Risto Paasivirta, paasivir@jyu.fi.
  237. X * PD, no warranty, use as you wish.
  238. X */
  239. X
  240. typedef struct rsa_key {
  241. X    I    b;
  242. X    NN    pq, e;
  243. X    NN    d, p, q, dp, dq, qp;
  244. } rsa_key;
  245. X
  246. /*
  247. X * think() -- twiddle thumbs
  248. X */
  249. X
  250. I show_think = 1;
  251. X
  252. V think(void)
  253. {
  254. X    static I j=0;
  255. X    if(show_think) {
  256. X        putchar(".oOo"[j&3]); j++;
  257. X        putchar('\b'); fflush(stdout);
  258. X    }
  259. }
  260. X
  261. /*
  262. X * success = rsa_gen(rsa_key *key)
  263. X * Generate a RSA key. Give seed values of appropriate size in key->p
  264. X * and key->q. Returns number of bits in modulus if success, 0 if failure.
  265. X * (If gen fails, give new seed values and try again.)
  266. X */
  267. X
  268. #define N_PRIMES 54
  269. X
  270. static unsigned char small_prime[N_PRIMES] = {
  271. X  2,  3,  5,  7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53,
  272. X 59, 61, 67, 71, 73, 79, 83, 89, 97,101,103,107,109,113,127,131, 
  273. 137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223, 
  274. 227,229,233,239,241,251
  275. };
  276. X
  277. V next_prime(N a)
  278. {
  279. X    I i;
  280. X    NN b,c,d;
  281. X
  282. X    *a |= 1; /* make odd */
  283. X
  284. X    cl(b);
  285. X
  286. X    for(;;) {
  287. X        think();
  288. X        for(i=1;i<N_PRIMES;i++) {
  289. X            /* sieve with small primes */
  290. X            *b = small_prime[i];
  291. X            cp(c,a);
  292. X            dm(c,b,d);
  293. X            if(!ts(d)) break; /* found divisor */
  294. X        }
  295. X        if(i==N_PRIMES) {
  296. X            /* probable prime if 2^(a-1) mod a ==1 */
  297. X            *b = 1;
  298. X            cp(c,a);
  299. X            sb(c,b);
  300. X            cl(d);
  301. X            *d = 2;
  302. X            em(d,c,a);
  303. X            *b = 1;
  304. X            if(!cu(b,d)) return; /* is prob prime */
  305. X        }
  306. X        *b = 2; /* increment by 2 */
  307. X        ad(a,b);
  308. X        
  309. X    }
  310. }
  311. X
  312. I rsa_gen(rsa_key *k)
  313. {
  314. X    NN p1,q1,pq1,f,g,t;
  315. X    next_prime(k->p);
  316. X    next_prime(k->q);
  317. X
  318. X    if(cu(k->p,k->q)<0) {
  319. X        cp(t,k->p);
  320. X        cp(k->p,k->q);
  321. X        cp(k->q,t);
  322. X    }
  323. X    hn(t,"1"); cp(p1,k->p); sb(p1,t);
  324. X    cp(q1,k->q); sb(q1,t); cp(g,p1); gd(g,q1);
  325. X    hn(t,"ff");
  326. X    if(cu(t,g)<0) return 0; /* gcd(p-1,q-1) large */
  327. X    cp(k->pq,k->p); mu(k->pq,k->q);
  328. X    cp(pq1,p1); mu(pq1,q1); cp(f,pq1); dm(f,g,t);
  329. X    hn(k->e,"3"); hn(k->qp,"1"); /* try e */
  330. X    cp(t,pq1); gd(t, k->e);
  331. X    if(cu(t,k->qp)) {
  332. X        hn(k->e,"10001");
  333. X        cp(t,pq1); gd(t, k->e);
  334. X        if(cu(t,k->qp)) return 0;
  335. X    }
  336. X    cp(k->d,k->e); iv(k->d,f);
  337. X    cp(t,k->d); dm(t,p1,k->dp);
  338. X    cp(t,k->d); dm(t,q1,k->dq);
  339. X    cp(k->qp,k->q); iv(k->qp,k->p);
  340. X    cp(t,k->pq); for(k->b = 0; ts(t); sr(t),k->b++);
  341. X    return k->b;
  342. }
  343. X
  344. /*
  345. X * rsa_dec(m, rsa_key) -- rsa decrypt using chinese remainder shortcut
  346. X */
  347. X
  348. V rsa_dec(N m, rsa_key *k)
  349. {
  350. X    NN mp,mq,t;
  351. X    cp(t,m); dm(t,k->p,mp);
  352. X    cp(t,m); dm(t,k->q,mq);
  353. X    em(mp,k->dp,k->p);
  354. X    em(mq,k->dq,k->q);
  355. X    if(sb(mp,mq)) ad(mp,k->p);
  356. X    mm(mp,k->qp,k->p);
  357. X    mu(mp,k->q);
  358. X    ad(mp,mq);
  359. X    cp(m,mp);
  360. }
  361. X
  362. /*
  363. X * rsa_enc(N m, rsa_key k) -- rsa encrypt
  364. X */
  365. X
  366. V rsa_enc(N m, rsa_key *k)
  367. {
  368. X    em(m, k->e, k->pq);
  369. }
  370. X
  371. X
  372. V main(int i, N *v) {
  373. X    NN m,c,d;
  374. X    rsa_key key;
  375. X    char s[S*2+2];
  376. X    if(i!=3) {
  377. X        puts("Usage: mtest [hex_pseed] [hex_qseed]");
  378. X        exit(EXIT_FAILURE);
  379. X    }
  380. X
  381. X    hn(key.p,v[1]);
  382. X    hn(key.q,v[2]);
  383. X
  384. X    puts("Generating key...");
  385. X    if(!rsa_gen(&key)) {
  386. X        puts("Failed, try other seed values.");
  387. X        exit(EXIT_FAILURE);
  388. X    }
  389. X    puts("\nDone, key components: pq,e,d,p,q,dp,dq,qp");        
  390. X    nh(s,key.pq); puts(s);
  391. X    nh(s,key.e); puts(s);
  392. X    nh(s,key.d); puts(s); 
  393. X    nh(s,key.p); puts(s);
  394. X    nh(s,key.q); puts(s);
  395. X    nh(s,key.dp); puts(s);
  396. X    nh(s,key.dq); puts(s);
  397. X    nh(s,key.qp); puts(s);
  398. X    puts("testing, msg,cip,dec1,dec2");
  399. X    cl(c);rn(c);dm(c,key.pq,m);    
  400. X    nh(s,m); puts(s);
  401. X    cp(c,m); rsa_enc(c,&key);
  402. X    nh(s,c); puts(s);
  403. X    cp(d,c); em(d,key.d,key.pq); /* slow way */
  404. X    nh(s,d); puts(s);
  405. X    cp(d,c); rsa_dec(d,&key); /* faster way */
  406. X    nh(s,d); puts(s);
  407. X    exit(EXIT_SUCCESS);
  408. }
  409. X
  410. SHAR_EOF
  411. chmod 0644 mtest.c ||
  412. echo 'restore of mtest.c failed'
  413. Wc_c="`wc -c < 'mtest.c'`"
  414. test 6351 -eq "$Wc_c" ||
  415.     echo 'mtest.c: original size 6351, current size' "$Wc_c"
  416. fi
  417. exit 0
  418.  
  419. -- 
  420. /*paasivir@jyu.fi*/int a[3302],b=3301,*c=a,d,e,f;main(){for(e=b;--e;*c++=1);*c
  421. =2;for(d=2001;d--;printf("%05d",f))for(c=a,e=b;e;f/=e--){f+=*c*1e5;*c++=f%e;}}
  422.