LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 791|回复: 0

学习了一下RSA的实现

[复制链接]
发表于 2006-12-28 14:31:02 | 显示全部楼层 |阅读模式
主要参考PKCS#1文档
利用了gmp和mhash库.
使用示例:

./rsa -k rsakey --pin password -f testin -o eout
./rsa -k rsakey --pin password -d -f eout -o dout

Key-Pair示例

  1. # rsakey file
  2. # every line should like below verbosly without #
  3. #p=1234345234521
  4. #p=0xabcd78681
  5. #p=071234

  6. # has these sections
  7. # p,q private prime
  8. # n   modulus, n's length should be at least hash_len+4 bytes, the longer the better,
  9. #     and more efficent for size.
  10. #     the hash_len for sha1 is 20, and sha256 is 32. cur use sha1.
  11. # d   decrypt priavte key
  12. # e   encrypt public key
  13. #  e=3213531385645551797655269345573485190241206387309544045384388753404578116867113921876014611339100923015091369066697829034443462519195336194839504846753773774626577528969985966217658232582247938901026223885442288817533990973400082467391172354029840157896081712524931431293739237905110365860173846145516826473720173566603102479940816595204190897685793188168701573643367447673000281308639244587618508591206234889570336933007277222902143744080839473018561732769400144090027728147701711440722839602873469978897861479886422925304985168762104108292149429656210650105528213534039327391044048786478565209414879849225257747337
  14. d=169258535211602407454289366564760320314234449009819175987247464020576502124431674676109820966938765248459868936451649729834408405473756699992778158122135155340959763340236569311539730618855953
  15. n=3356290175696944624889977359872915979764431525108550170386939121287775220471939091212620798724268489404968079532769980701058719660984642444522841248246878762394831180392646437417022723983414069327776338557319351828352982962288653043591388990548600488975194801824576739762555445519545665671552544553787647853875680072274077042431073586458592666493927202419993693748745226844065298333730440143538863306890276021012673272660746971921282501693884488811972505697716590409600692791313052443703252691607181569688328691460606100738042959614921557621790163293233102615102397781075505774943293514173712562558459824017024904519
复制代码


  1. /*
  2. /*
  3. * try to implments RSA and learn gmp
  4. *
  5. * gcc -lmhash -lgmp rsa.c -o rsa
  6. *
  7. */
  8. #include<stdio.h>
  9. #include<gmp.h>
  10. #include<mhash.h>
  11. #include<getopt.h>
  12. #include<assert.h>

  13. typedef struct
  14. {
  15. mpz_t n; // the RSA modulus, a positive integer
  16. mpz_t e; // the RSA public exponent, a positive integer
  17. mpz_t d; // the RSA private exponent, a positive integer
  18. int   k; // the length in ocets of the modulus n.
  19. mpz_t p; // the first factor, a positive integer
  20. mpz_t q; // the second factor, a positive integer
  21. }rsa_key_t;

  22. typedef struct
  23. {
  24. int hLen;
  25. int limit;
  26. unsigned char *(*func)(unsigned char *t, int l);
  27. }hash_t;


  28. /*
  29. * formula
  30. * e*d \equiv 1 \mod \lambda(n) ==> e*d=1 mod (phi(n))
  31. * e*dP = 1 mod (p-1)
  32. * e*dQ = 1 mod (q-1)
  33. * q*qInv = 1 mod p
  34. */


  35. /*
  36. * I2OSP (x, xLen)
  37. *
  38. * input x nonegative  integer to be converted.
  39. *       xLen intended length of the resulting octet string.
  40. * output X corresponding octet string of length xLen.
  41. * Error: "integer too large"
  42. */

  43. // assume pool has least xLen's length!
  44. int i2osp(mpz_t x, unsigned char* pool, int xLen)
  45. {
  46. int s, bs;
  47. s=mpz_sizeinbase(x, 2);
  48. bs=((s+7)>>3);
  49. if(bs>xLen) return -2;
  50. memset(pool, 0, xLen-bs);
  51. mpz_export(pool+xLen-bs, NULL, 1, 1, 1, 0, x);
  52. return 1;
  53. }

  54. /*
  55. * OS2IP
  56. * Input:         X        octet string to be converted
  57. *  Output:        x        corresponding nonnegative integer
  58. */
  59. int os2ip(mpz_t x, unsigned char *pool, int len)
  60. {
  61. mpz_import(x, len, 1, sizeof(pool[0]), 1, 0, pool);
  62. return 1;
  63. }


  64. inline int hrsapowm(mpz_t c, mpz_t n, mpz_t e, mpz_t m)
  65. {
  66. /* non check, just work for right case?
  67. if(mpz_cmp(n,m)<1 || mpz_sgn(m)==-1)
  68.   {
  69.    exit(17);
  70.    return -1;
  71.   }
  72. */
  73. mpz_powm(c, m, e, n);
  74. return 1;
  75. }

  76. /*
  77. * RSAEP ((n, e), m)
  78. * Input:
  79. * (n, e) RSA public key
  80. * m message representative, an integer between 0 and n ­ 1
  81. * Output:
  82. * c      ciphertext representative, an integer between 0 and n ­ 1
  83. * Error:        "message representative out of range"
  84. * Assumption: RSA public key (n, e) is valid
  85. */

  86. int rsaep(mpz_t x, rsa_key_t *K, mpz_t m)
  87. {
  88. return hrsapowm(x, K->n, K->e, m);
  89. }


  90. /*
  91. * RSADP (K, c)
  92. * Input:
  93. * K RSA private key, where K has one of the following forms:
  94. * a pair (n, d)
  95. * a quintuple (p, q, dP, dQ, qInv) and
  96. * a possibly empty sequence of triplets (ri, di, ti), i = 3, ..., u
  97. * c      ciphertext representative, an integer between 0 and n ­ 1
  98. * Output:
  99. * m      message representative, an integer between 0 and n ­ 1
  100. * Error:  "ciphertext representative out of range"
  101. * Assumption: RSA private key K is valid
  102. */

  103. int  rsadp(mpz_t m, rsa_key_t *K, mpz_t c)
  104. {
  105. return hrsapowm(m, K->n, K->d, c);
  106. }

  107. int rsasp1(mpz_t c, rsa_key_t *K, mpz_t m)
  108. {
  109. return rsadp(c, K, m);
  110. }

  111. int resvp1(mpz_t c, rsa_key_t *K, mpz_t m)
  112. {
  113. return rsaep(c, K, m);
  114. }

  115. void osxor(unsigned char*dst, int len,
  116.            unsigned char*s1, unsigned char*s2)
  117. {
  118. int i;
  119. for(i=0;i<len;++i)
  120.   {
  121.    dst[i]=s1[i] ^ s2[i];
  122.   }
  123. }


  124. // mask should be at least mask_len+hash_len-1 size;
  125. // tmpppool should be at least seed_len+4 size
  126. void mgf1(unsigned char *seed, int seedlen, hash_t *hash,
  127.           unsigned char *mask, int masklen, unsigned char * tmppool)
  128. {
  129. int i;
  130. int c=(masklen+hash->hLen-1)/hash->hLen;

  131. memcpy(tmppool, seed, seedlen);
  132. unsigned char* Hash;
  133. for(i=0;i<c;++i)
  134.   {
  135.    tmppool[seedlen]=(i>>24);
  136.    tmppool[seedlen+1]=(i>>16);
  137.    tmppool[seedlen+2]=(i>>8);
  138.    tmppool[seedlen+3]=i;
  139.    Hash=hash->func(tmppool, seedlen+4);
  140.    memcpy(mask+i*hash->hLen,Hash, hash->hLen);
  141.   }
  142. }

  143. typedef struct {
  144. unsigned char *DB, *dbmask;
  145. unsigned char *tmppool;
  146. unsigned char *seed, *seedmask;
  147. unsigned char *EM;
  148. unsigned char *pin;
  149. mpz_t ic, im;
  150. }oaep_pool_t;

  151. void init_oaep_pool(oaep_pool_t *pool, rsa_key_t *K, hash_t *hash, char *pin)
  152. {
  153. pool->DB=(unsigned char*)malloc(K->k-hash->hLen-1);
  154. pool->dbmask=(unsigned char*)malloc(K->k-2);
  155. pool->seed=(unsigned char*)malloc(hash->hLen);
  156. pool->seedmask=(unsigned char*)malloc(hash->hLen+hash->hLen-1);
  157. pool->EM=(unsigned char*)malloc(K->k);
  158. pool->tmppool=hash->func((unsigned char*)pin, strlen(pin));
  159. pool->pin=(unsigned char*)malloc(hash->hLen);
  160. memcpy(pool->pin, pool->tmppool, hash->hLen);
  161. pool->tmppool=(unsigned char*)malloc(K->k+4);
  162. mpz_init2(pool->ic, K->k*8);
  163. mpz_init2(pool->im, K->k*8);
  164. }

  165. void deinit_oaep_pool(oaep_pool_t *pool)
  166. {
  167. mpz_clear(pool->ic);
  168. mpz_clear(pool->im);
  169. free(pool->DB);
  170. free(pool->dbmask);
  171. free(pool->seedmask);
  172. free(pool->seed);
  173. free(pool->tmppool);
  174. free(pool->EM);
  175. free(pool->pin);
  176. }


  177. unsigned char *rsaes_oaep_encrypt(rsa_key_t *K,
  178.                                   unsigned char *M, int mLen,
  179.                                   unsigned char *L, int lLen,
  180.                                   hash_t *hash,
  181.                                   oaep_pool_t *pool)

  182. {
  183. //len checking ...
  184. if(lLen>hash->limit
  185.     || mLen> K->k-2*hash->hLen-2 )
  186.    return NULL;

  187. // EME-OAEP encoding
  188. unsigned char * Hash;
  189. int i, lPs=K->k-mLen-2*hash->hLen-2;
  190. Hash=hash->func(L, lLen);
  191. // set DB
  192. int dbLen=K->k-hash->hLen-1;
  193. memcpy(pool->DB, Hash, hash->hLen);
  194. memset(pool->DB+hash->hLen, 0, lPs);
  195. pool->DB[lPs+hash->hLen]=1;
  196. memcpy(pool->DB+lPs+hash->hLen+1, M, mLen);
  197. for(i=0;i<hash->hLen;++i)  pool->seed[i]=random();

  198. mgf1(pool->seed, hash->hLen, hash,
  199.       pool->dbmask, dbLen, pool->tmppool);
  200. osxor(pool->DB, dbLen, pool->DB, pool->dbmask);

  201. mgf1(pool->DB, dbLen, hash,
  202.       pool->seedmask, hash->hLen, pool->tmppool);
  203. osxor(pool->seed, hash->hLen, pool->seed, pool->seedmask);
  204. // added by pointer, not standard!!
  205. osxor(pool->seed, hash->hLen, pool->pin, pool->seed);

  206. pool->EM[0]=0;
  207. memcpy(pool->EM+1, pool->seed, hash->hLen);
  208. memcpy(pool->EM+hash->hLen+1, pool->DB, dbLen);

  209. os2ip(pool->im, pool->EM, K->k);
  210. rsaep(pool->ic, K, pool->im);
  211. i2osp(pool->ic, pool->EM, K->k);

  212. return pool->EM;
  213. }


  214. unsigned char * rsaes_oaep_decrypt(rsa_key_t *K,
  215.                                    unsigned char *C, int k,
  216.                                    unsigned char *L, int lLen,
  217.                                    hash_t *hash,
  218.                                    oaep_pool_t *pool)
  219. {
  220. if(lLen>hash->limit
  221.     || k!= K->k
  222.     || k< 2*hash->hLen+2)
  223.   return NULL;
  224. int i;
  225. os2ip(pool->ic, C, K->k);
  226. if(rsadp(pool->im, K, pool->ic)<0)
  227.   return NULL;
  228. i=i2osp(pool->im, pool->EM, K->k);
  229. if(i==-1 || pool->EM[0]!=0) {
  230.   fprintf(stderr, "not like a encrypted block?\n");
  231.   return NULL;
  232. }

  233. int dbLen=K->k-hash->hLen-1;
  234. mgf1(pool->EM+1+hash->hLen, dbLen, hash,
  235.       pool->seedmask, hash->hLen, pool->tmppool);
  236. osxor(pool->seed, hash->hLen, pool->EM+1, pool->seedmask);
  237. // added by pointer, not standard!!
  238. osxor(pool->seed, hash->hLen, pool->seed, pool->pin);

  239. mgf1(pool->seed, hash->hLen, hash,
  240.       pool->dbmask, dbLen, pool->tmppool);
  241. osxor(pool->DB, dbLen, pool->EM+1+hash->hLen, pool->dbmask);

  242. unsigned char *Hash=hash->func(L, lLen);
  243. if(memcmp(Hash, pool->DB, hash->hLen)!=0)
  244.   {
  245.    fprintf(stderr, "[decrypt][warning] check hash fail, maybe incorrect ...\n");
  246.   }
  247. i=hash->hLen;
  248. while(i<K->k && pool->DB[i]==0) ++i;
  249. if(i==K->k || pool->DB[i]!= 1)
  250.   {
  251.    fprintf(stderr, "[decrypt] fail with K.k=%d i=%d %.2x!=01\n", K->k, i, pool->DB[i]);
  252.    return NULL;
  253.   }
  254. return pool->DB+i+1;
  255. }
  256.                   

  257. unsigned char *hash_sha1(unsigned char *t, int len)
  258. {
  259. static unsigned char hash[20];
  260. MHASH td=mhash_init(MHASH_SHA1);
  261. if(td == MHASH_FAILED) exit(13);
  262. mhash(td, t, len);
  263. mhash_deinit(td, hash);
  264. return hash;
  265. }

  266. void init_hash(hash_t *hash)
  267. {
  268. hash->hLen=20;
  269. hash->limit=INT_MAX;
  270. hash->func = hash_sha1;
  271. }

  272. int main(int argc, char *argv[])
  273. {
  274. char *usage="%s -k keyfile [-e] [-d] [--pin password] [-f inputfile] [-o outputfile]\n";
  275. int is_encrypt=1;
  276. int is_decrypt=0;
  277. unsigned char *label=(unsigned char*)"seceret";
  278. int lLen;
  279. char *infile=NULL;
  280. char *outfile=NULL;
  281. char *keyfile=NULL;
  282. char *pin=argv[0];

  283. FILE *ifp=NULL, *ofp=NULL, *kfp=NULL;

  284.   rsa_key_t K;
  285.   mpz_init(K.p);
  286.   mpz_init(K.q);
  287.   mpz_init(K.e);
  288.   mpz_init(K.d);
  289.   mpz_init(K.n);

  290. struct option lopt[]=
  291.   {
  292.    {"key-file", 1, 0, 'k'},
  293.    {"encrypt", 0, 0, 'e'},
  294.    {"decrypt", 0, 0, 'd'},
  295.    {"input", 1, 0, 'f'},
  296.    {"output", 1, 0, 'o'},
  297.    {"label",1,0,'l'},
  298.    {"help",0,0,'h'},
  299.    {"pin",1,0,'p'},
  300.    {"Kn",1, 0, 257},
  301.    {"Ke",1, 0, 258},
  302.    {"Kd",1, 0, 259},
  303.    {"Kp",1, 0, 260},
  304.    {"Kq",1, 0, 261},
  305.    {0,0,0,0}
  306.   };
  307. int c, opt_idx;

  308. while(1)
  309.   {
  310.    c=getopt_long(argc, argv, "k:f:o:l:p:edh", lopt, &opt_idx);
  311.    if(c==-1) break;
  312.    switch(c)
  313.     {
  314.     case 0:
  315.      break;
  316.     case 'f':
  317.      infile=optarg;
  318.      if(ifp!=NULL) fclose(ifp);
  319.      ifp=fopen(infile, "rb");
  320.      break;
  321.     case 'o':
  322.      outfile=optarg;
  323.      if(ofp!=NULL) fclose(ofp);
  324.      ofp=fopen(outfile, "wb");
  325.      break;
  326.     case 'k':
  327.      keyfile=optarg;
  328.      if(kfp!=NULL) fclose(kfp);
  329.      kfp=fopen(keyfile, "r");
  330.      break;
  331.     case 'e':
  332.      is_encrypt=1;
  333.      is_decrypt=0;
  334.      break;
  335.     case 'd':
  336.      is_decrypt=1;
  337.      is_encrypt=0;
  338.      break;
  339.     case 'l':
  340.      label=(unsigned char*)optarg;
  341.      break;
  342.     case 'p':
  343.      pin=optarg;
  344.      break;
  345.     case 257://Kn
  346.      mpz_set_str(K.n, optarg, 0);
  347.      break;
  348.     case 258://Ke
  349.      mpz_set_str(K.e, optarg, 0);
  350.      break;
  351.     case 259://Kd
  352.      mpz_set_str(K.d, optarg, 0);
  353.      break;
  354.     case 260://Kp
  355.      mpz_set_str(K.p, optarg, 0);
  356.      break;
  357.     case 261://Kq
  358.      mpz_set_str(K.q, optarg, 0);
  359.      break;
  360.     default:
  361.      fprintf(stderr, usage, argv[0]);
  362.      return 1;
  363.     }
  364.   }
  365. if(ifp==NULL) ifp=stdin;
  366. if(ofp==NULL) ofp=stdout;
  367. lLen=strlen((char*)label);


  368. unsigned char buf[1<<16], *p;
  369. while(kfp!=NULL && !feof(kfp))
  370.   {
  371.    fgets((char*)buf, 1<<16, kfp);
  372.    switch(buf[0])
  373.     {
  374.     case ' ':
  375.     case '\t':
  376.     case   0:
  377.     case '#':
  378.     case '\r':
  379.     case '\n':
  380.      break;
  381.     case 'p':
  382.      if(buf[1]=='=' && mpz_sgn(K.p)==0 ) mpz_set_str(K.p,(char*)buf+2, 0);
  383.      break;
  384.     case 'q':
  385.      if(buf[1]=='=' && mpz_sgn(K.q)==0 ) mpz_set_str(K.q,(char*)buf+2, 0);
  386.      break;
  387.     case 'd':
  388.      if(buf[1]=='=' && mpz_sgn(K.d)==0 ) mpz_set_str(K.d,(char*)buf+2, 0);
  389.      break;
  390.     case 'e':
  391.      if(buf[1]=='=' && mpz_sgn(K.e)==0 ) mpz_set_str(K.e,(char*)buf+2, 0);
  392.      break;
  393.     case 'n':
  394.      if(buf[1]=='=' && mpz_sgn(K.n)==0 ) mpz_set_str(K.n,(char*)buf+2, 0);
  395.      break;
  396.     default:
  397.      fprintf(stderr, "rsakey error: %s\n", buf);
  398.      break;
  399.     }
  400.   }
  401. if(kfp!=NULL) fclose(kfp);

  402. if(mpz_sgn(K.n)!=1)
  403.   {
  404.    if(mpz_sgn(K.p)==1 && mpz_sgn(K.q)==1)
  405.     {
  406.      mpz_mul(K.n, K.p, K.q);
  407.     }
  408.    else
  409.     {
  410.      fprintf(stderr, "[K] modulus not set, and not p or q, ...\n");
  411.      return 21;
  412.     }
  413.   }

  414. K.k=(mpz_sizeinbase(K.n, 2)+7)/8;

  415. hash_t hash;
  416. init_hash(&hash);
  417. oaep_pool_t pool;
  418. init_oaep_pool(&pool, &K, &hash, pin);
  419. int len, t;

  420. if(is_decrypt)
  421.   {
  422.    if(mpz_sgn(K.n)!=1 || mpz_sgn(K.d)!=1)
  423.     {
  424.      fprintf(stderr, "[main] no private set to decrypt ...\n");
  425.      return 23;
  426.     }
  427.    while(!feof(ifp))
  428.     {
  429.      len=fread(buf, 1, K.k, ifp);
  430.      if(len==K.k)
  431.       {
  432.        p=rsaes_oaep_decrypt(&K, buf, K.k, label, lLen, &hash, &pool);
  433.        if(p==NULL) exit(1);
  434.        t=K.k-hash.hLen-1-(p-pool.DB);
  435.        fwrite(p, 1, t, ofp);
  436.       }
  437.      else
  438.       {
  439.        if(len>0)
  440.         fprintf(stderr, "fread wrong, len=%d K.k=%d\n", len, K.k);
  441.        break;
  442.       }
  443.     }
  444.   }
  445. else
  446.   {
  447.    if(mpz_sgn(K.n)!=1 || mpz_sgn(K.e)!=1)
  448.     {
  449.      fprintf(stderr, "[main] no public set to encrypt ...\n");
  450.      return 24;
  451.     }
  452.    int mLen=K.k-2*hash.hLen-2;
  453.    while(!feof(ifp))
  454.     {
  455.      len=fread(buf, 1, mLen, ifp);
  456.      if(len)
  457.       {
  458.        p=rsaes_oaep_encrypt(&K, buf, len, label, lLen, &hash, &pool);
  459.        if(p==NULL) exit(1);
  460.        fwrite(p, 1, K.k, ofp);
  461.       }
  462.     }
  463.   }
  464. fclose(ifp);
  465. fclose(ofp);
  466. deinit_oaep_pool(&pool);
  467. return 0;
  468. }
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表