1. 程式人生 > >公鑰,私鑰和數字簽名這樣最好理解,以及加解密例項

公鑰,私鑰和數字簽名這樣最好理解,以及加解密例項

原文:http://blog.csdn.net/21aspnet/article/details/7249401

一、公鑰加密 
假設一下,我找了兩個數字,一個是1,一個是2。我喜歡2這個數字,就保留起來,不告訴你們(私鑰),然後我告訴大家,1是我的公鑰。

我有一個檔案,不能讓別人看,我就用1加密了。別人找到了這個檔案,但是他不知道2就是解密的私鑰啊,所以他解不開,只有我可以用
數字2,就是我的私鑰,來解密。這樣我就可以保護資料了。

我的好朋友x用我的公鑰1加密了字元a,加密後成了b,放在網上。別人偷到了這個檔案,但是別人解不開,因為別人不知道2就是我的私鑰,
只有我才能解密,解密後就得到a。這樣,我們就可以傳送加密的資料了。

二、私鑰簽名
如果我用私鑰加密一段資料(當然只有我可以用私鑰加密,因為只有我知道2是我的私鑰),結果所有的人都看到我的內容了,因為他們都知
道我的公鑰是1,那麼這種加密有什麼用處呢?

但是我的好朋友x說有人冒充我給他發信。怎麼辦呢?我把我要發的信,內容是c,用我的私鑰2,加密,加密後的內容是d,發給x,再告訴他
解密看是不是c。他用我的公鑰1解密,發現果然是c。
這個時候,他會想到,能夠用我的公鑰解密的資料,必然是用我的私鑰加的密。只有我知道我得私鑰,因此他就可以確認確實是我發的東西。
這樣我們就能確認傳送方身份了。這個過程叫做數字簽名。當然具體的過程要稍微複雜一些。用私鑰來加密資料,用途就是數字簽名

總結:公鑰和私鑰是成對的,它們互相解密。

公鑰加密,私鑰解密。

私鑰數字簽名,公鑰驗證。

舉例

比如有兩個使用者Alice和Bob,Alice想把一段明文通過雙鑰加密的技術傳送給Bob,Bob有一對公鑰和私鑰,那麼加密解密的過程如下:

  1. Bob將他的公開金鑰傳送給Alice。
  2. Alice用Bob的公開金鑰加密她的訊息,然後傳送給Bob。
  3. Bob用他的私人金鑰解密Alice的訊息。

  上面的過程可以用下圖表示,Alice使用Bob的公鑰進行加密,Bob用自己的私鑰進行解密。

例子和圖出自《網路安全基礎 應用與標準第二版》

RSA演算法

RSA公鑰加密演算法是1977年由Ron Rivest、Adi Shamirh和LenAdleman在(美國麻省理工學院)開發的。RSA取名來自開發他們三者的名字。RSA是目前最有影響力的公鑰加密演算法,它能夠抵抗到目前為止已知的所有密碼攻擊,已被ISO推薦為公鑰資料加密標準。RSA演算法基於一個十分簡單的數論事實:將兩個大素數相乘十分容易,但那時想要對其乘積進行因式分解卻極其困難,因此可以將乘積公開作為加密金鑰。

#################################################################################################################


openssl是一個功能強大的工具包,它集成了眾多密碼演算法及實用工具。我們即可以利用它提供的命令臺工具生成金鑰、證書來加密解密檔案,也可以在利用其提供的API介面在程式碼中對傳輸資訊進行加密。

RSA是一個非對稱加密演算法。簡單說來,非對稱加密演算法就是說加密解密一個檔案需要有兩個金鑰,一個用來加密,為公鑰,一個用來解密,為私鑰。證書可以用來授權公鑰的使用。

今天小研究了下openssl的rsa加密,其中主要涉及利用公鑰和金鑰加解密檔案,沒有涉及對證書的操作。想要集體瞭解的可以去:

---------------------------------------------------------------------------------------------------------------------

首先介紹下命令臺下openssl工具的簡單使用:

生成一個金鑰:

openssl genrsa -out test.key 1024

這裡-out指定生成檔案的。需要注意的是這個檔案包含了公鑰和金鑰兩部分,也就是說這個檔案即可用來加密也可以用來解密。後面的1024是生成金鑰的長度。

openssl可以將這個檔案中的公鑰提取出來:

openssl rsa -in test.key -pubout -out test_pub.key

-in指定輸入檔案,-out指定提取生成公鑰的檔名。至此,我們手上就有了一個公鑰,一個私鑰(包含公鑰)。現在可以將用公鑰來加密檔案了。

我在目錄中建立一個hello的文字檔案,然後利用此前生成的公鑰加密檔案

openssl rsautl -encrypt -in hello -inkey test_pub.key -pubin -out hello.en 

-in指定要加密的檔案,-inkey指定金鑰,-pubin表明是用純公鑰檔案加密,-out為加密後的檔案。

解密檔案:

openssl rsautl -decrypt -in hello.en -inkey test.key -out hello.de

-in指定被加密的檔案,-inkey指定私鑰檔案,-out為解密後的檔案。

至此,一次加密解密的過程告終。在實際使用中還可能包括證書,這個以後有機會再說~

-------------------------------------------------------------------------------------------------------------------
下來介紹下在程式如何利用之前生成的test.key和test_pub.key來進行資訊的加密與解密(當然也可以直接利用openssl的API來生成金鑰檔案)。

下面是一個例子,這個例子利用已有的金鑰來對source字串進行加密與解密:

複製程式碼
 1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<string.h>
4 #include<openssl/rsa.h>
5 #include<openssl/pem.h>
6 #include<openssl/err.h>
7 #define OPENSSLKEY "test.key"
8 #define PUBLICKEY "test_pub.key"
9 #define BUFFSIZE 1024
10 char* my_encrypt(char *str,char *path_key);//加密11 char* my_decrypt(char *str,char *path_key);//解密12 int main(void){
13 char *source="i like dancing !";
14 char *ptr_en,*ptr_de;
15 printf("source is :%s\n",source);
16 ptr_en=my_encrypt(source,PUBLICKEY);
17 printf("after encrypt:%s\n",ptr_en);
18 ptr_de=my_decrypt(ptr_en,OPENSSLKEY);
19 printf("after decrypt:%s\n",ptr_de);
20 if(ptr_en!=NULL){
21 free(ptr_en);
22 }
23 if(ptr_de!=NULL){
24 free(ptr_de);
25 }
26 return 0;
27 }
28 char *my_encrypt(char *str,char *path_key){
29 char *p_en;
30 RSA *p_rsa;
31 FILE *file;
32 int flen,rsa_len;
33 if((file=fopen(path_key,"r"))==NULL){
34 perror("open key file error");
35 return NULL;
36 }
37 if((p_rsa=PEM_read_RSA_PUBKEY(file,NULL,NULL,NULL))==NULL){
38 //if((p_rsa=PEM_read_RSAPublicKey(file,NULL,NULL,NULL))==NULL){ 換成這句死活通不過,無論是否將公鑰分離原始檔39 ERR_print_errors_fp(stdout);
40 return NULL;
41 }
42 flen=strlen(str);
43 rsa_len=RSA_size(p_rsa);
44 p_en=(unsigned char *)malloc(rsa_len+1);
45 memset(p_en,0,rsa_len+1);
46 if(RSA_public_encrypt(rsa_len,(unsigned char *)str,(unsigned char*)p_en,p_rsa,RSA_NO_PADDING)<0){
47 return NULL;
48 }
49 RSA_free(p_rsa);
50 fclose(file);
51 return p_en;
52 }
53 char *my_decrypt(char *str,char *path_key){
54 char *p_de;
55 RSA *p_rsa;
56 FILE *file;
57 int rsa_len;
58 if((file=fopen(path_key,"r"))==NULL){
59 perror("open key file error");
60 return NULL;
61 }
62 if((p_rsa=PEM_read_RSAPrivateKey(file,NULL,NULL,NULL))==NULL){
63 ERR_print_errors_fp(stdout);
64 return NULL;
65 }
66 rsa_len=RSA_size(p_rsa);
67 p_de=(unsigned char *)malloc(rsa_len+1);
68 memset(p_de,0,rsa_len+1);
69 if(RSA_private_decrypt(rsa_len,(unsigned char *)str,(unsigned char*)p_de,p_rsa,RSA_NO_PADDING)<0){
70 return NULL;
71 }
72 RSA_free(p_rsa);
73 fclose(file);
74 return p_de;
75 }
複製程式碼

一個比較奇怪的問題:

37、38行中為從檔案中獲取金鑰,發現如果使用openssl提供的PEM_read_RSAPublicKey方法會一直失敗。

估計是檔案格式的問題~