Annotation of OpenXM/src/ox_ntl/crypt/rsa/gmprsa.c, Revision 1.2
1.2 ! iwane 1: /* $OpenXM: OpenXM/src/ox_ntl/crypt/rsa/gmprsa.c,v 1.1 2004/08/16 03:59:58 iwane Exp $ */
1.1 iwane 2:
3: #include <stdio.h>
4: #include <stdlib.h>
5: #include <string.h>
6: #include <gmp.h>
7:
8: #include "gmprsa.h"
9: #include "sha1.h"
10:
11:
12: #define STR_PRT(STR, N) do { int _xxx; printf(#STR "[%d]=", N); for (_xxx = 0; _xxx < (N); _xxx++) printf("%02x", STR[_xxx]); printf("\n"); fflush(stdout); } while (0)
13:
14:
15: #define RSA_KEY_PRINT 0
16:
17:
18: /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
19: * CONV
20: *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
21: static void
22: rsa_uchar2mpz(mpz_ptr z, const unsigned char *buf, int len)
23: {
24: char *str;
25: int i;
26: size_t size = len * 2 * sizeof(char) + 1;
27:
28: str = __gmp_allocate_func(size);
29: for (i = 0; i < len; i++)
30: sprintf(str + 2 * i, "%02x", buf[i]);
31:
32: mpz_set_str(z, str, 16);
33:
34: __gmp_free_func(str, size);
35: }
36:
37:
38: static int
39: rsa_char2ui(int ch)
40: {
41: if (ch >= '0' && ch <= '9')
42: return (ch - '0');
43: else if (ch >= 'a' && ch <= 'z')
44: return (ch - 'a' + 10);
45: else
46: return (ch - 'A' + 10);
47: }
48:
49: static void
50: rsa_mpz2uchar(unsigned char *str, int len, const mpz_ptr z)
51: {
52: char *ptr = mpz_get_str(NULL, 16, z);
53: int length = strlen(ptr);
54: int i = 0, j = 0;
55:
56: for (j = (length + 1) / 2; j < len; j++)
57: str[i++] = '\0';
58:
59: j = 0;
60:
61: if (length % 2 != 0) {
62: str[i++] = rsa_char2ui(ptr[j++]);
63: }
64:
65: for (; i < len && j < length; i++, j += 2) {
66: str[i] = rsa_char2ui(ptr[j]) * 16 + rsa_char2ui(ptr[j + 1]);
67: }
68: str[i] = '\0';
69:
70: __gmp_free_func(ptr, length);
71: }
72:
73:
74: /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
75: * INITIALIZE
76: *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
77: void
78: rsa_init(rsa_key *r)
79: {
80: mpz_init(r->p);
81: mpz_init(r->q);
82: mpz_init(r->mod);
83: mpz_init(r->private_key);
84: mpz_init_set_si(r->public_key, 11);
85: }
86:
87: void
88: rsa_clear(rsa_key *r)
89: {
90: mpz_clear(r->p);
91: mpz_clear(r->q);
92: mpz_clear(r->mod);
93: mpz_clear(r->public_key);
94: mpz_clear(r->private_key);
95:
96: }
97: /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
98: * PRIME
99: *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
100: void
101: rsa_genprime(mpz_ptr prime, int len, const mpz_ptr seed, int rep)
102: {
103: const int LOOP = 4096;
104: const int BLOCK = 160;
105: int n, b;
106: int offset = 2;
107: int k, c, i;
108: int shalen;
109: mpz_t s, s1, sp;
110: unsigned char sha[32];
111: char *str;
112:
1.2 ! iwane 113: if (len < 2) {
! 114: mpz_set_ui(prime, 3);
! 115: return ;
! 116: }
! 117:
1.1 iwane 118: n = (len - 1) / BLOCK;
119: b = (len - 1) % BLOCK;
120:
121: mpz_init(s);
122: mpz_init(s1);
123: mpz_init(sp);
124:
125:
126: __RETRY:
127: for (c = 0; c < LOOP; c++) {
128: mpz_set_ui(prime, 0);
129: mpz_setbit(prime, len - 1);
130:
131: for (k = 0; k <= n; k++) {
132: mpz_add_ui(s1, seed, offset + c + k);
133:
134: str = mpz_get_str(NULL, 16, s1);
135: shalen = strlen(str);
136: sha1(sha, str, shalen);
137: __gmp_free_func(str, shalen);
138:
139: rsa_uchar2mpz(s, sha, 20);
140:
141: mpz_mul_2exp(sp, s, 160 * k);
142:
143: mpz_add(prime, prime, sp);
144:
145: offset += n + 1;
146: }
147:
148:
149: mpz_setbit(prime, 0);
150: mpz_setbit(prime, len - 1);
151: for (i = (n + 1) * BLOCK; i >= len; i--)
152: mpz_clrbit(prime, i);
153:
154:
155: #if RSA_KEY_PRINT
156: fprintf(stderr, "*"); fflush(stderr);
157: #endif
158: /* prime test */
159: if (mpz_probab_prime_p(prime, rep))
160: break;
161: }
162:
163: #if RSA_KEY_PRINT
164: fprintf(stderr, "+"); fflush(stderr);
165: #endif
166:
167: if (c == LOOP) {
168: offset += c + 13;
169: goto __RETRY;
170: }
171:
172: mpz_clear(s);
173: mpz_clear(s1);
174: mpz_clear(sp);
175:
176: }
177:
178:
179: static int
180: rsa_get_block_size(const mpz_ptr n)
181: {
182: return ((mpz_sizeinbase(n, 16) + 1) / 2);
183: }
184:
185:
186: /*
187: *
188: * bit >= 96 must
189: * rep >= 80 should
190: *
191: */
192: int
193: rsa_keygen(
194: rsa_key *rsa,
195: const mpz_ptr _seed1, const mpz_ptr _seed2,
196: unsigned int bit,
197: int rep)
198: {
199: int bitp, bitq;
200: mpz_t gcd;
201: mpz_t phi;
202: mpz_t seed1, seed2;
203:
204: /* 12 = PS_MIN + 3 + 1 */
205: if (bit < 12 * 8)
206: return (-1); /* too short */
207:
208:
209: bitp = bit / 2;
210: bitq = bit - bitp;
211:
212: mpz_init_set_ui(gcd, 1);
213: mpz_init(phi);
214:
215: mpz_init_set(seed1, _seed1);
216: mpz_init_set(seed2, _seed2);
217:
218: for (;;) {
219: if (mpz_cmp(seed1, seed2) == 0)
220: goto _NEXT;
221:
222: rsa_genprime(rsa->p, bitp, seed1, rep);
223: rsa_genprime(rsa->q, bitq, seed2, rep);
224:
225: mpz_clrbit(rsa->p, 0);
226: mpz_clrbit(rsa->q, 0);
227:
228: mpz_mul(phi, rsa->p, rsa->q);
229:
230: mpz_gcd(gcd, rsa->public_key, phi);
231: #if RSA_KEY_PRINT
232: fprintf(stderr, "@"); fflush(stderr);
233: #endif
234: if (mpz_cmp_ui(gcd, 1) != 0)
235: goto _NEXT;
236:
237: if (mpz_cmp(rsa->p, rsa->q) == 0)
238: goto _NEXT;
239:
240: break;
241:
242: _NEXT:
243: mpz_add(seed1, seed1, gcd);
244: mpz_sub(seed2, seed2, gcd);
245: }
246:
247: mpz_setbit(rsa->p, 0);
248: mpz_setbit(rsa->q, 0);
249:
250: mpz_invert(rsa->private_key, rsa->public_key, phi);
251:
252: mpz_mul(rsa->mod, rsa->p, rsa->q);
253:
254: rsa->k = rsa_get_block_size(rsa->mod);
255:
256: mpz_clear(gcd);
257: mpz_clear(phi);
258:
259: mpz_clear(seed1);
260: mpz_clear(seed2);
261:
262: return (0);
263: }
264:
265:
266: void
267: rsa_set_publickey(
268: rsa_key *rsa,
269: mpz_ptr public_key,
270: mpz_ptr mod)
271: {
272: mpz_set(rsa->mod, mod);
273: mpz_set(rsa->public_key, public_key);
274: rsa->k = rsa_get_block_size(rsa->mod);
275: }
276:
277: void
278: rsa_set_key(
279: rsa_key *rsa,
280: mpz_ptr public_key,
281: mpz_ptr private_key,
282: mpz_ptr mod)
283: {
284: mpz_set(rsa->private_key, private_key);
285: rsa_set_publickey(rsa, public_key, mod);
286: }
287:
288: /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
289: * ENCRYPT
290: *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
291: static int
292: rsa_encrypt(
293: unsigned char *eb,
294: const unsigned char *msg,
295: int size,
296: int k,
297: const mpz_ptr c,
298: const mpz_ptr mod,
299: int padding)
300: {
301: const int PS_MIN = 8;
302: const int OCTET_SIZE = 256;
303:
304: int i;
305: int s; /* length of data */
306: int ps; /* length of padding string */
307: const int DATA_MAX = k - PS_MIN - 3;
308: mpz_t x, y, ebz;
309:
310: if (k <= 0)
311: return (-2);
312:
313: mpz_init(x);
314: mpz_init(y);
315: mpz_init(ebz);
316:
317:
318: /* k == ps + s + 3 */
319: if (size > DATA_MAX) {
320: s = DATA_MAX;
321: ps = PS_MIN;
322: } else {
323: s = size;
324: ps = DATA_MAX - size + PS_MIN;
325: }
326:
327: /*-------------------------------------------------------------------*
328: * Encryption-block formatting
329: *-------------------------------------------------------------------*/
330: eb[0] = 0x00;
331: eb[1] = padding;
332:
333:
334: switch (padding) {
335: case RSA_PKCS_1_PADDING_PUBLIC:
336: for (i = 0; i < ps; i++) {
337: /* 0 < random number < 255 */
338: eb[i + 2] = (unsigned char)(random() % (OCTET_SIZE - 1) + 1);
339: }
340: break;
341: case RSA_PKCS_1_PADDING_PRIVATE:
342: for (i = 0; i < ps; i++) {
343: eb[i + 2] = 0xff;
344: }
345: break;
346: case RSA_PKCS_1_PADDING_PRIVATE0:
347: for (i = 0; i < ps; i++) {
348: eb[i + 2] = 0x00;
349: }
350: break;
351: default:
352: mpz_clear(x);
353: mpz_clear(y);
354: mpz_clear(ebz);
355: return (-1);
356: }
357:
358: eb[ps + 2] = 0x00;
359: for (i = 0; i < s; i++) {
360: eb[ps + 3 + i] = *msg++;
361: }
362:
363:
364: /*-------------------------------------------------------------------*
365: * Octet-string-to-integer conversion
366: *-------------------------------------------------------------------*/
367: rsa_uchar2mpz(x, eb, k);
368:
369: /*-------------------------------------------------------------------*
370: * RSA computation
371: *-------------------------------------------------------------------*/
372: mpz_powm(y, x, c, mod);
373:
374: /*-------------------------------------------------------------------*
375: * Integer-to-octet-string conversion
376: *-------------------------------------------------------------------*/
377: rsa_mpz2uchar(eb, k, y);
378:
379:
380: mpz_clear(x);
381: mpz_clear(y);
382: mpz_clear(ebz);
383:
384: return (s);
385: }
386:
387:
388: /****************************************************************************
389: * RSA decryption.
390: *
391: * MEMO: 平文が 0x00 で始まるよう瘢雹なメッセ・踉札犬陸苳詞合,
392: * 正しく復号化することができない.
393: *
394: ****************************************************************************/
395: static int
396: rsa_decrypt(
397: unsigned char *d,
398: const unsigned char *eb,
399: int k,
400: const mpz_ptr exp,
401: const mpz_ptr mod,
402: int padding)
403: {
404: const int PS_MIN = 8;
405:
406: mpz_t x, y;
407: int i, n, bt;
408: int ret = 0;
409:
410: mpz_init(x);
411: mpz_init(y);
412:
413: /*--------------------------------------------------------------------*
414: * Octet-string-to-integer
415: *--------------------------------------------------------------------*/
416: rsa_uchar2mpz(y, eb, k);
417:
418: /* error check */
419: if (mpz_cmp(y, mod) >= 0 || mpz_sgn(y) < 0) {
420: ret = -1;
421: goto _ERR;
422: }
423:
424: /*--------------------------------------------------------------------*
425: * RSA computation
426: *--------------------------------------------------------------------*/
427: mpz_powm(x, y, exp, mod);
428:
429: /*--------------------------------------------------------------------*
430: * Integer-to-octet-string
431: *--------------------------------------------------------------------*/
432: rsa_mpz2uchar(d, k, x);
433:
434:
435: /*--------------------------------------------------------------------*
436: * Encryption-block parsing
437: * EB = 00 || BT || PS || 00 || D
438: *--------------------------------------------------------------------*/
439: if (d[0] != 0x00) {
440: ret = -2;
441: goto _ERR;
442: }
443:
444:
445: if (padding == RSA_PKCS_1_PADDING_PUBLIC) { /* public key */
446: bt = d[1];
447:
448: if (bt != RSA_PKCS_1_PADDING_PRIVATE0 && bt != RSA_PKCS_1_PADDING_PRIVATE) {
449: ret = -3;
450: goto _ERR;
451: }
452:
453: if (bt == RSA_PKCS_1_PADDING_PRIVATE0) {
454: for (i = 0; i < k - 3; i++) {
455: if (d[i + 2] != 0x00) {
456: i--;
457: break;
458: }
459: }
460: } else {
461: for (i = 0; i < k - 3; i++) {
462: if (d[i + 2] != 0xff) {
463: break;
464: }
465: }
466: }
467: } else { /* private key */
468:
469: if (d[1] != RSA_PKCS_1_PADDING_PUBLIC) {
470: ret = -4;
471: goto _ERR;
472: }
473:
474: for (i = 0; i < k - 3; i++) {
475: if (d[i + 2] == 0x00) {
476: break;
477: }
478: }
479: }
480:
481: if (d[i + 2] != 0x00) {
482: ret = -5;
483: goto _ERR;
484: }
485:
486: if (i < PS_MIN) { /* too short */
487: ret = -6;
488: goto _ERR;
489: }
490:
491: if (i == k - 3) { /* parse error */
492: ret = -7;
493: goto _ERR;
494: }
495:
496: n = k - 3 - i;
497: memmove(d, d + i + 3, n); /* ........ */
498:
499: mpz_clear(x);
500: mpz_clear(y);
501:
502: return (n);
503: _ERR:
504:
505: mpz_clear(x);
506: mpz_clear(y);
507: return (ret);
508: }
509:
510: int
511: rsa_encrypt_by_public_key(rsa_key *rsa, unsigned char *eb, const unsigned char *msg, int len, int padding)
512: {
513: return (rsa_encrypt(eb, msg, len, rsa->k, rsa->public_key, rsa->mod, RSA_PKCS_1_PADDING_PUBLIC));
514: }
515:
516: int
517: rsa_encrypt_by_private_key(rsa_key *rsa, unsigned char *eb, const unsigned char *msg, int len, int padding)
518: {
519: return (rsa_encrypt(eb, msg, len, rsa->k, rsa->private_key, rsa->mod, RSA_PKCS_1_PADDING_PRIVATE));
520: }
521:
522: int
523: rsa_decrypt_by_public_key(rsa_key *rsa, unsigned char *buf, const unsigned char *eb, int padding)
524: {
525: return (rsa_decrypt(buf, eb, rsa->k, rsa->public_key, rsa->mod, RSA_PKCS_1_PADDING_PUBLIC));
526: }
527:
528: int
529: rsa_decrypt_by_private_key(rsa_key *rsa, unsigned char *buf, const unsigned char *eb, int padding)
530: {
531: return (rsa_decrypt(buf, eb, rsa->k, rsa->private_key, rsa->mod, RSA_PKCS_1_PADDING_PRIVATE));
532: }
533:
534:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>