非对称加解密基础 - RSA算法

来源:互联网 发布:社交网络的发展趋势 编辑:程序博客网 时间:2024/04/28 13:45

公钥和私钥的产生

N = 17 * 53 = 901m = (17-1)*(53-1)=832let e=17 // by random d = 49 // because ( d * e ) % m = 1 , that is ( d * 17 ) % 832 = 1

公钥(901,17) 私钥(901,49)


加密过程

int text = 123 (注意,消息必须比N小);

由于 text^e % N = code, 即123^17 % 901 = code

得到 code = 378


解密过程

int code = 378;

由于 code^d % N = text, 即378^49 % 901 = text

得到 text = 123


继续测试 text=456,text=789


pow=337587917446653715596592958817679803remain is encrypted msg, 378pow=1981975090781375567648692626283639181924626345824851461901652399140883944715714801363950285365649593405611421793924739086942208remain is decrypted msg, 123pow=1593684413895892775431288016392119629314523136remain is encrypted msg, 31pow=11932267966476130911517907186867185074148138371734008968629799047943267871remain is decrypted msg, 456pow=17795453274736834362412998969384875211516379055829remain is encrypted msg, 24pow=42692426938810341355395254247148178158685421582623594902764046516224remain is decrypted msg, 789


如果取随机私钥为23,由(d*e)%832=1得到, d=1447

密钥对(901,23) (901,1447)

加密过程2

int text = 123 (注意,消息必须比N小);

由于 text^e % N = code, 即123^23 % 901 = code

得到 code = 149

./rsa 123 23 901
pow=1169008215014432917465348578887506800769541157267remain=149


解密过程2

int code = 149;

由于 code^d % N = text, 即149^1447 % 901 = text

得到 text = 123

./rsa 149 1447 901pow=3985936655027786133408829502155172486035904622712472852621608241746913310297391658184716646894437322554704092666282273452855275384085318288046586224429347497827880247547339473036917816909223107117175531587260639648846353409844711958706092093596730245565996912003513233565007065727967455584025260911486810746630678094905762197449698418393359848248040053204101912486274919097714199485366154899138632699959288422245852748033196204793416492537560971606021510788711927751466478702987029084746015114294265995598688131965702319407549561404014161346291768678253671588393974329706005805322594725598901652699451931023169921356303019131994689149252324743527490479491940886193543681983109194838286138082417166699477848202718347964687820796592019328071391913496121999081649165198851436538061394347514783202440077109779016851948752385464899137550781743050874740569187871261877899262047556241037569513727241777013958245104990221096084832705392187584307190592892229359969096765098092852369655657703699448285550244408917771734036376812464079731831055765945558390839789584335008109083209997253493029025530744552730080488782762304788784814726079959495953838029404233253982382231821825059796386932843561833899624385090559266388309444170895176942274476213381834239263776359183712755409616899578532221617869355630180167696863598518217920559059880617368830175766115161601439972079153451714153741788486717251510899260246046823014371599692024285779413561563126708199148100439542764252953767607725285544447473028149388111275729639654549626974834654173824045613468737321214142959704129737498708807684383933171830693895907145483744154610946805717856953750819840697171152907340638764324070540105234490652588160359246349466614681404427878668385500329188714136429101735281721801482418741695141767516243529016466547669220693256890471638180522587977329481861127690785609948263132745032373176370846812221619669962814451607786769451764283956667048224778080078119822225893910169294528225164973914039173067841802331919352006767688214788854741209476129408348246067157963999292702077540465878741199438072301716437512437206906827652022918225801876338146245435414504850134452701815858979786932044372642085983768077238865428181442964225497161921056275373467702146501770271202169524135998423744124666111748049368433360408756284224496271587223056244362621755475005116811157719670973646470109741830322978187377451183707774175105440143172725174869125803081026121461473916991813456601031329814195352576206287933278596520860904193983118052847549233481720087449879783102557667902374897959615060335464554488838194211827049636607371477869631641345731986506361643642064555937668953135519546086134667128658277195852003986966590034063953363008297418066438616213070509869485074973762746760573414761610051773364844423773838759134377078566230721304823672091660155346094353132676209154505265788271907294843328075680525047092758196227733579042369746326640103471517003588082621099265771434203691296983507676617026988511984284930947929603040015756972741093414371038843713030209328408570065664368532865353731976350820941739288708181549678167180213092260955630329359228466794631319443883593072931779043019549remain=123


解密的优化(中国余数定理)

dp = d mod (p − 1) = 1447 mod (17− 1) = 7dq = d mod (q − 1) = 1447 mod (53− 1) = 43qInv*q mod p = 1 即 qInv * 53 mod 17 = 1 得到 qInv=9


m1=code^dp mod p = 149^7   mod17  = 4m2=code^dq mod q = 149^43 mod 53 = 17h= (qInv * (m1-m2))mod p = (9 * (-13)) mod 17 = 2r= m2 + h*q = 17 + 2*53= 17 + 106 = 123 

和上面没有优化的解法得到的结果一样。


演示程序

用c语言编写,大数计算库使用的是开源的GMP库,下载地址如下:

http://gmplib.org/


最常用的算法:x的n次方取m的模代码

#include <stdio.h>#include <stdlib.h>#include <gmp.h>int main(int argc, char * argv[]){mpz_t pow, mod;mpz_init(pow);mpz_init(mod);mpz_ui_pow_ui(pow, atoi(argv[1]), atoi(argv[2]));printf("pow=");mpz_out_str(stdout, 10, pow);printf("\n");mpz_mod_ui(mod, pow, atoi(argv[3]));printf("remain=");mpz_out_str(stdout, 10, mod);printf("\n");return 0;}


项目文件

http://hi.csdn.net/attachment/201201/20/0_1327043412h7wW.gif


ASN.1 规范定义的rsa公钥私钥保存结构

RSAPrivateKey ::= SEQUENCE {    version           Version,    modulus           INTEGER,  -- n    publicExponent    INTEGER,  -- e    privateExponent   INTEGER,  -- d    prime1            INTEGER,  -- p    prime2            INTEGER,  -- q    exponent1         INTEGER,  -- d mod (p-1)    exponent2         INTEGER,  -- d mod (q-1)    coefficient       INTEGER,  -- (inverse of q) mod p    otherPrimeInfos   OtherPrimeInfos OPTIONAL}


为什么要存储exponent1, exponent2?

答案:为了使用“中国剩余定理”优化计算过程

It has to do with optimizing RSA.It turns out that using the Chinese Remainder Theorem with p, q, d(mod p−1), and d(mod q−1) (i.e., prime1, prime2, exponent1, exponent2 from the data structure in the question) to run the decryption operation faster than if you only had d,n.

openssl输出一个RSAkey信息 openssl rsa -in cakey.pem -text -noout

Private-Key: (2048 bit)modulus:    00:d0:d8:21:b2:85:7b:23:b2:5f:48:2b:36:ac:46:    95:9e:5e:5b:77:1a:8a:95:6a:e1:ac:ef:dd:78:2a:    78:41:bc:4f:b6:0c:79:c7:59:5d:15:18:11:68:ab:    83:a1:2e:54:1a:cc:d6:89:59:3e:48:ea:13:7d:ad:    be:06:10:cb:3c:77:17:b8:1f:df:c6:44:39:22:1d:    3d:b6:09:b6:3e:8b:ac:04:b9:01:8c:ea:94:08:bb:    d9:66:ca:81:f3:f3:aa:6a:de:ab:ca:c9:50:12:55:    00:83:1c:59:51:b5:8b:b8:a9:0e:d6:fa:33:65:db:    0a:e6:db:27:ca:c2:7f:a8:dd:47:27:fe:a3:5a:84:    8c:9e:c3:20:c7:3d:74:ad:42:6f:8d:24:ab:e7:b8:    6e:be:b8:a8:af:c4:26:f1:93:48:7a:55:0a:8b:e0:    89:07:2d:3f:90:7c:40:39:05:60:a3:54:6f:24:7a:    db:7a:53:3b:95:cc:10:62:cf:05:4a:d3:8b:16:36:    4f:38:58:95:49:37:39:22:7e:50:4f:89:6b:1d:67:    62:d6:05:ec:85:33:07:8b:7c:aa:47:85:4f:a5:ba:    27:f1:ac:5f:82:25:3f:e1:1e:f1:46:e9:28:ae:e1:    3b:96:e3:eb:da:70:a2:db:a9:58:97:30:3b:27:64:    78:e9publicExponent: 65537 (0x10001)privateExponent:    79:4c:0e:c6:51:20:a4:2b:05:8c:35:0d:1c:22:22:    e4:48:89:77:33:c3:29:e5:5a:0d:c7:83:2a:38:00:    80:ad:8e:de:7d:80:7d:78:39:c7:f6:a2:a5:d8:78:    2b:35:6d:43:e3:94:f7:51:0e:0b:eb:68:46:a6:92:    a7:93:39:77:74:f4:21:cc:e1:7b:96:44:58:bc:03:    0b:a7:b8:61:bb:5d:bd:a0:76:76:12:08:c8:c9:d2:    0b:11:b3:48:ad:4d:5d:a4:d6:c2:81:0a:30:9b:8e:    20:98:66:88:3e:99:58:37:58:97:23:da:96:5e:12:    86:e2:e2:c9:b1:0d:d4:55:23:59:1c:44:1e:0c:01:    4d:0a:1d:1b:0e:4c:45:ed:d9:e6:43:9b:af:f4:fc:    3c:78:3c:7b:22:c2:b4:70:61:8b:d1:e8:33:f9:f5:    a6:15:80:a5:06:d9:8b:97:d9:45:25:60:58:65:a8:    8a:e5:77:a4:9a:c6:ad:03:46:12:61:e0:f4:98:1b:    4a:ca:62:b1:c4:8c:c8:63:6e:10:6f:cc:af:de:b8:    1f:b2:06:f6:d2:3f:8f:85:ea:cc:63:37:e0:b3:fd:    17:d2:68:ca:12:68:35:32:c7:40:c7:7e:56:27:ae:    df:df:b0:d5:47:23:10:e9:ac:e9:c0:5a:be:36:f8:    01prime1:    00:fb:f6:59:4a:66:53:9d:4a:cd:e0:5d:77:5a:d0:    d1:88:f8:f8:f3:b6:e2:1f:12:56:e8:6a:3d:5e:24:    bd:21:02:45:b3:d6:88:1a:f5:21:67:17:40:1e:d9:    4e:63:54:b5:88:9e:a8:6f:a6:20:d6:ef:11:14:7b:    a3:c7:04:c7:5c:55:21:8b:eb:40:ba:1d:a7:d2:4b:    f5:33:22:d6:77:7d:9c:4a:3e:5a:1c:e3:34:e7:e4:    6b:a1:15:e6:6a:3c:68:ab:65:65:95:92:12:91:dd:    7d:8f:0f:49:a6:41:c7:07:a9:75:a4:32:7f:01:e8:    e0:2b:a3:1b:15:e3:0a:75:b9prime2:    00:d4:30:e5:2d:84:b5:4c:22:0f:02:65:64:8f:04:    9e:50:01:d7:20:54:e1:a2:bc:b5:4d:6e:50:ac:05:    33:d7:38:02:81:9a:c0:6c:22:1c:cd:6d:3d:6e:67:    ab:1e:af:95:b7:83:4e:7c:b8:3b:6a:49:6a:f4:88:    83:ad:2d:ff:5a:d4:7f:4b:ba:99:a6:09:9d:66:89:    29:f1:e3:dc:d4:a2:9f:3e:e9:62:97:b9:7f:35:ea:    64:78:71:fb:d7:49:d1:1f:ec:e9:7d:05:84:f1:c1:    97:b9:08:7f:c5:5f:d3:78:6c:4f:7f:cb:4b:1a:46:    bd:ff:bc:25:0a:96:fb:b4:b1exponent1:    00:df:e1:a8:bb:84:2a:fd:d3:af:15:92:d7:70:19:    a6:65:d8:1c:95:a9:c6:48:a7:aa:13:7f:fb:21:80:    f1:90:b8:0d:29:5c:11:ba:2a:60:50:d3:07:05:a2:    3f:95:e1:7a:20:78:21:e0:7b:34:28:e7:6a:3c:d2:    13:d7:ce:76:3a:a3:e6:58:06:64:90:3b:b3:98:18:    28:3b:14:d4:8e:7e:4d:76:66:ea:f9:4a:26:03:7b:    22:eb:92:a3:17:78:af:e4:c4:07:3c:9c:fb:e5:22:    72:e3:c0:48:c7:f3:20:9f:bd:42:ab:f0:b6:8c:02:    d9:d5:cc:6b:4f:ca:5a:cb:f9exponent2:    67:ac:0c:0d:15:4d:cf:08:c4:f4:92:bd:72:f2:fa:    b6:74:6f:bb:28:3d:a5:d9:35:6b:c3:7e:3e:cd:bb:    ea:67:3f:32:3b:7d:d0:57:4a:63:44:00:43:b4:fa:    f2:5f:2f:73:1e:00:77:07:3c:60:4d:c6:a7:fb:1a:    fa:be:02:89:4a:51:77:9a:8f:ff:83:ab:17:b1:e4:    80:7e:a8:22:6b:e2:0a:46:d5:18:f4:54:a6:ef:02:    6f:a6:a1:39:2a:a3:b6:49:76:3a:d3:3b:85:32:e5:    02:4e:98:be:c2:76:fb:db:4f:6c:4c:d3:40:df:57:    6d:5f:6b:69:a5:23:0d:c1coefficient:    3b:2d:72:9f:e6:cf:f3:95:a8:94:ee:e7:e1:b2:6e:    0e:36:87:39:a6:b7:4f:68:6f:f4:7b:b1:37:73:77:    66:1d:4d:8c:ca:86:86:b9:02:0c:78:a5:d8:65:62:    77:ce:1f:8c:2a:01:01:33:1f:5f:6e:db:4a:ac:97:    8a:87:34:1c:50:d1:a9:17:33:69:b1:72:99:45:c3:    85:1e:7c:73:7c:17:a7:a5:2f:99:da:a8:c9:65:86:    96:26:4f:0f:1c:b6:cf:6e:8f:78:82:2a:9d:ff:84:    d9:d8:c8:0d:d0:2e:09:23:43:7a:ee:b0:f3:36:75:    1b:28:1a:ba:06:0a:a3:8a


RSA的安全性


RSA的公钥就是一个模数 N以及一个随机数(甚至就是著名的0x10001, 65537),所以如果N冲突怎么办(甚至2个N共享同一个分解因子)怎么办?

First, what matters is not having two identical private keys, if either of the prime numbers is the same in the modulus (which is part of the public key), it is easy to quickly recover the full private key.(Aside -- Brief RSA primer: In RSA for an n-bit private key, the public key is composed of an exponent, typically e=65537 and a modulus, N, which is the product of two n/2-bit prime numbers. The private key consists of the private exponent d (calculated by d = e-1 mod (p-1)(q-1) which is efficiently found using the extended Euclidean algorithm) and the modulus, N. The public pair allows encryption of a message, m, into a ciphertext, c, via modular exponentiation: c = m^e mod N, and the private key allows decryption via m = c^d mod N. This all works due to a fundamental part of number theory -- Euler's theorem and how to calculate totients).If two moduli share a factor, then you can take the greatest common divisor of the two moduli efficiently (using Euclid's algorithm) and find the shared factor. Let, the two moduli share a prime factor q, so N1 = p1 q and N2 = p2 q, then gcd(N1, N2) = q. With the found prime factor, it is trivial to find the other prime factor (p1 = N1/q) and to recreate the private exponent. A 2012 study looked at 4.7 million distinct RSA moduli and found shared factors in 12720 of them (that is 0.3% of the 4.7 million RSA keys trawled from the web are broken from their analysis). (The paper also found several other problems with RSA in practice, like shared keys used on seemingly different entities.)Now, choosing identical prime numbers is extremely low probability if your machine has a high amount of initial entropy and there is no flaw in the random number generation. Both of these assumptions aren't always true; see the Debian OpenSSL problem keys from 2006-2008 and note that many people create keys for systems on brand new (virtual) machines that haven't had enough time to establish a lot of entropy.Roughly, the strength of a 1024-bit key relies on the choice of the two 512-bit prime numbers that comprise the modulus. By the prime number theorem there are roughly (2512/ln 2512 - 2511/ln 2511) ~ 10151 distinct 512 bit prime numbers. From the birthday paradox, you should expect to have a collision of a prime number showing up more than once with about 50% probability, after generating sqrt(10151) ~ 1075 distinct prime numbers. That is if some government generated a billion 512-bit prime numbers per second per computer and used a billion computers and had this run for a billion years they would only have generated about 1034 prime numbers, and the probability of a collision with some external key would be essentially zero, the same chance as playing powerball exactly 10 times on consecutive weeks and buying exactly one ticket and winning the jackpot every single time without cheating. (It doesn't get significant chance of a single prime collision until nearly 1040 = 10000000000000000000000000000000000000000 times more prime numbers are generated).However, as the 2012 paper shows, this is not true in the real world as RSA keys are generated by flawed methods in practice at a rate of at least 0.3%.

http://windowsontheory.org/2012/05/17/factoring-rsa-moduli-part-ii/


问题1:为什么openssl rsautl -sign 的结果和openssl pkeyutil -sign ( or, openssl dgst -sign)的结果不一样?

http://stackoverflow.com/questions/13419201/why-are-the-rsa-sha256-signatures-i-generate-with-openssl-and-java-different

edit - a little more explanations:let's create a digest and show it$ openssl dgst -sha256 -binary < data.txt > digest$ hd digest00000000  26 3b 0a a1 2e b9 32 db  b8 dc d3 6f 37 94 0b 05  |&;....2....o7...|00000010  71 9c ba 79 46 34 28 9f  5c 5b 98 9a 64 61 c9 ec  |q..yF4(.\[..da..|now we take this digest and sign int using rsautl:$ openssl rsautl -sign -inkey private.pem < digest > sign1$ hd sign100000000  1b 7a cf a4 8d 41 8e 04  ed 3a bb ba 86 f1 f8 e0  |.z...A...:......|00000010  df f7 47 3e d7 a7 f4 90  7a 05 f8 7f 45 e5 29 e7  |..G>....z...E.).|00000020  9f f4 2c 91 97 2f e7 26  69 9f 6a 07 a3 48 1b 85  |..,../.&i.j..H..|00000030  2e f8 ee 44 4d 25 9f ae  05 95 81 c9 e3 07 68 ad  |...DM%........h.|now let's sign the same file using dgst directly:$ openssl dgst -sha256 -sign private.pem < data.txt > sign2$ hd sign200000000  15 c2 94 87 eb e6 cb 45  c8 63 0c 97 60 d3 07 f3  |.......E.c..`...|00000010  dc 65 32 ad 44 1c c2 2a  7f a3 e1 fc dd 84 27 8c  |.e2.D..*......'.|00000020  77 a6 97 2b 33 6b c6 d7  7d e1 1d 39 5c 48 b6 48  |w..+3k..}..9\H.H|00000030  cb 18 be bf 6a 66 90 d3  88 89 52 6c dd d1 b9 99  |....jf....Rl....|So what's different here? To see that, we can verify the signature and show the raw output. Both files do contain the digest, but the metadata and padding is different:$ openssl rsautl -raw -verify -inkey private.pem < sign1 | hd00000000  00 01 ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|00000010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff 00  |................|00000020  26 3b 0a a1 2e b9 32 db  b8 dc d3 6f 37 94 0b 05  |&;....2....o7...|00000030  71 9c ba 79 46 34 28 9f  5c 5b 98 9a 64 61 c9 ec  |q..yF4(.\[..da..|$ openssl rsautl -raw -verify -inkey private.pem < sign2 | hd00000000  00 01 ff ff ff ff ff ff  ff ff ff ff 00 30 31 30  |.............010|00000010  0d 06 09 60 86 48 01 65  03 04 02 01 05 00 04 20  |...`.H.e....... |00000020  26 3b 0a a1 2e b9 32 db  b8 dc d3 6f 37 94 0b 05  |&;....2....o7...|00000030  71 9c ba 79 46 34 28 9f  5c 5b 98 9a 64 61 c9 ec  |q..yF4(.\[..da..|To see this more clearly, we can try to use the -asn1parse flag, which won't work for the first signature, but for the second it shows the correct structure of the signature:$ openssl rsautl -verify -inkey private.pem -asn1parse < sign1Error in encoding139931349546656:error:0D07209B:asn1 encoding routines:ASN1_get_object:too long:asn1_lib.c:142:$ openssl rsautl -verify -inkey private.pem -asn1parse < sign2    0:d=0  hl=2 l=  49 cons: SEQUENCE              2:d=1  hl=2 l=  13 cons:  SEQUENCE              4:d=2  hl=2 l=   9 prim:   OBJECT            :sha256   15:d=2  hl=2 l=   0 prim:   NULL                 17:d=1  hl=2 l=  32 prim:  OCTET STRING            0000 - 26 3b 0a a1 2e b9 32 db-b8 dc d3 6f 37 94 0b 05   &;....2....o7...      0010 - 71 9c ba 79 46 34 28 9f-5c 5b 98 9a 64 61 c9 ec   q..yF4(.\[..da..


http://stackoverflow.com/questions/9951559/difference-between-openssl-rsautl-and-dgst

The simple answer is that dgst -sign creates a hash, ASN1 encodes it, and then signs the ASN1 encoded hash, whereas rsautl -sign just signs the input without hashing or ASN1 encoding. Both methods include the input data in the output, together with the signature, rather than producing only a signature as output. Here is a Bash script that shows the difference between openssl dgst -sign and openssl rsautl -sign.

#!/bin/bash# @(#) Bash script demos difference between openssl rsautl and dgst signing# Usage: $0 <name of file to sign> <private key file, without passphrase># 1. Make an ASN1 config filecat >asn1.conf <<EOFasn1 = SEQUENCE:digest_info_and_digest[digest_info_and_digest]dinfo = SEQUENCE:digest_infodigest = FORMAT:HEX,OCT:`openssl dgst -sha256 $1 |cut -f 2 -d ' '`[digest_info]algid = OID:2.16.840.1.101.3.4.2.1params = NULLEOF# If you are wondering what the "algid = OID:2.16.840.1.101.3.4.2.1" is, it's# the SHA256 OID, see http://oid-info.com/get/2.16.840.1.101.3.4.2.1# 2. Make a DER encoded ASN1 structure that contains the hash and# the hash typeopenssl asn1parse -i -genconf asn1.conf -out $1.dgst.asn1# 3. Make a signature file that contains both the ASN1 structure and# its signatureopenssl rsautl -sign -in $1.dgst.asn1 -inkey $2 -out $1.sig.rsa# 4. Verify the signature that we just made and ouput the ASN structureopenssl rsautl -verify -in $1.sig.rsa -inkey $2 -out $1.dgst.asn1_v# 5. Verify that the output from the signature matches the original# ASN1 structurediff $1.dgst.asn1 $1.dgst.asn1_v# 6. Do the equivalent of steps 1-5 above in one "dgst" commandopenssl dgst -sha256 -sign $2 -out $1.sig.rsa_dgst $1# 7. Verify that the signature file produced from the rsautl and the dgst# are identicaldiff $1.sig.rsa $1.sig.rsa_dgst


You can use rsautl that way : (with private key: my.key and public key my-pub.pem)$ openssl rsautl -sign -inkey my.key -out in.txt.rsa -in in.txtEnter pass phrase for my.key:$ openssl rsautl -verify -inkey my-pub.pem -in in.txt.rsa -pubinBonjourWith this method, all the document is included within the signature file and is outputed by the final command.But in my case, my certificate says : Signature Algorithm: sha1WithRSAEncryption. So I would recommend you to use the standard way of signing document in 4 steps: (This method is used for all asymmetric electronic signatures in order not to overcharge the signature file and/or CPU usage)Create digest of document to sign (sender)Sign digest with private key (sender)Create digest of document to verify (recipient)Verify signature with public key (recipient)OpenSSL do this in two steps:$ openssl dgst -sha256 -sign my.key -out in.txt.sha256 in.txt Enter pass phrase for my.key:$ openssl dgst -sha256 -verify my-pub.pem -signature in.txt.sha256 in.txt  Verified OKWith this method, you sent the recipient two documents : the original file plain text, the signature file signed digest. Attention: the signature file does not include the whole document! Only the digest.