python利用pycrypto實現RSA(轉)


原文:http://www.cnblogs.com/huxianglin/p/6387045.html

python利用pycrypto實現RSA

本節內容

  1. pycrypto模塊簡介
  2. RSA的公私鑰生成
  3. RSA使用公鑰加密數據
  4. RSA使用私鑰解密密文
  5. 破解博客園登陸

pycrypto模塊簡介

pycrypto模塊是python中用來處理加密解密等信息安全相關的一個很重要模塊。

該模塊支持的加密方式:

  1. 對稱加密方式:

    1. AES
    2. DES
    3. ARC4
  2. 散列值計算:

    1. MD5
    2. SHA
    3. HMAC
  3. 公鑰加密和簽名:

    1. RSA
    2. DSA

基本上常見的關於信息安全類的算法都可以支持,所以,這是一個很強大的模塊。

安裝方式:pip install pycrypto
如果在windows上的python3.5中安裝完成之后導入from Crypto import Random模塊失敗,需要找到python35安裝目錄下的Lib\site-packages\Crypto\Random\OSRNG\nt.py文件,將import winrandom修改成from . import winrandom

關於加密方式的了解可以看我這邊博客:加密方式介紹
關於非對稱加密算法(RSA)的使用可以看我這篇博客:數字簽名和數字證書

RSA的公私鑰生成

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
from  Crypto  import  Random
from  Crypto.PublicKey  import  RSA
 
 
# 偽隨機數生成器
random_generator  =  Random.new().read
# rsa算法生成實例
rsa  =  RSA.generate( 1024 , random_generator)
 
# master的秘鑰對的生成
private_pem  =  rsa.exportKey()
 
#--------------------------------------------生成公私鑰對文件-----------------------------------------------------------
with  open ( 'master-private.pem' 'wb' ) as f:
     f.write(private_pem)
 
public_pem  =  rsa.publickey().exportKey()
with  open ( 'master-public.pem' 'wb' ) as f:
     f.write(public_pem)
 
#---------------------------------------------------
# ghost的秘鑰對的生成
private_pem  =  rsa.exportKey()
with  open ( 'ghost-private.pem' 'wb' ) as f:
     f.write(private_pem)
 
public_pem  =  rsa.publickey().exportKey()
with  open ( 'ghost-public.pem' 'wb' ) as f:
     f.write(public_pem)
 
#-----------------------------------生成的公私鑰文件類似於如下形式-------------------------------------------------------
# 私鑰
- - - - - BEGIN RSA PRIVATE KEY - - - - -
MIICXAIBAAKBgQC6mwuOxuqYi6mugLGr3OuiHwm / hF4kQX1zd5VhGwxYf4H5 + pkO
CES2UjOyLP9Xh6w + DJtRwTGE2xwDd3wMfW2wkHijM / uHkM9Jt + oRGIjy4IiXo + 7t
ue / NWBkDiQm1qte0YDKlmkFREwvZ5X2KaCsSx + dyKH4QsovxQ3 / RxftdmQIDAQAB
AoGAPA5SNe1G6zlnrsW0aL99Bnw + wuhy8 / Av082Uwd / WpVTEHBPO1nlKw / LIuHtK
4nzDrmSYSEOJEF0EMwltXwevGSm1wq2FBhX4T + kz3XUpWfv9O0dlHeNtgxeD1QXL
kOxqU4F2WpdALgvi / rlPDd0aIagoXLi8MXkUH7hQlrJpQUECQQC6rygx3jDQA9Iw
kPUXlokEuLod + Kgoa700S5qpJi7vft675 + tMG5SZtr + HQeqGHty0fqc8MIcy1fJm
ZYUrogN9AkEA / + RrrOoTYQbR3ENslTsNsiqQa2aZW5XAv9pEyGJBWu / 4HUEEa6G3
FY0Y3ACZR0Xaraya8XAgOo61pWm83GBlTQJBAKH2812Ikzr2BbdDHJExdoEVL8xu
/ p3LE6U6bt2QFiqNHPtT9C3cw + k0xyi3RJzGS9 + A / uDWjYXKXvr92zMG5hUCQFXR
alccTZF9swX2ysSlgGtfIP4T85ymdXUiI208noR79C8DbhMWsgsVPeASh1VC1Rrn
xzLvkq9wyvSFqKQT5AUCQAxMO7KI1rwIm + ISuDEcwxRJXkdFypD74kOSYRxTqMun
Zdu4ku4t6mVeq5kBv1 / S2dtF3TiqMRlxmLmV / fx7KHM =
- - - - - END RSA PRIVATE KEY - - - - -
 
#公鑰
- - - - - BEGIN PUBLIC KEY - - - - -
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6mwuOxuqYi6mugLGr3OuiHwm /
hF4kQX1zd5VhGwxYf4H5 + pkOCES2UjOyLP9Xh6w + DJtRwTGE2xwDd3wMfW2wkHij
M / uHkM9Jt + oRGIjy4IiXo + 7tue / NWBkDiQm1qte0YDKlmkFREwvZ5X2KaCsSx + dy
KH4QsovxQ3 / RxftdmQIDAQAB
- - - - - END PUBLIC KEY - - - - -

RSA使用公私鑰加解密數據

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from  Crypto.PublicKey  import  RSA
from  Crypto.Cipher  import  PKCS1_v1_5 as Cipher_pkcs1_v1_5
import  base64
 
message  =  'hello ghost, this is a plian text'
with  open ( 'ghost-public.pem' , "r" ) as f:
      key  =  f.read()
      rsakey  =  RSA.importKey(key)   # 導入讀取到的公鑰
      cipher  =  Cipher_pkcs1_v1_5.new(rsakey)   # 生成對象
      cipher_text  =  base64.b64encode(cipher.encrypt(message.encode(encoding = "utf-8" )))   # 通過生成的對象加密message明文,注意,在python3中加密的數據必須是bytes類型的數據,不能是str類型的數據
      print (cipher_text)
 
with  open ( 'ghost-private.pem' ) as f:
     key  =  f.read()
     rsakey  =  RSA.importKey(key)   # 導入讀取到的私鑰
     cipher  =  Cipher_pkcs1_v1_5.new(rsakey)   # 生成對象
     text  =  cipher.decrypt(base64.b64decode(cipher_text),  "ERROR" )   # 將密文解密成明文,返回的是一個bytes類型數據,需要自己轉換成str
     print (text)
# 結果:
b 'meBtYXP35VNjtWXsONDluweXdG98tMHjb5GxBLFJ0GJzo+96wSrHe8SDhNJweDJP6/OdeIQ8jP1HKCK+aC9HA12YMSUUqcixsY5s8QUyTs+fkMjGrlC6I7hPLO4DGQbFXEY0jiqP9ycgmAi5FCsDMcm0oEm8/fVzv7vl9QarSN4='   # 加密后的密文
b 'hello ghost, this is a plian text'   # 解密后的明文

破解博客園登陸

經過分析博客園登陸方式為在用戶填入用戶名和密碼之后,點擊登錄時js將會使用JSEncrypt這個開源組件對用戶輸入的用戶名和密碼進行加密,加密的公鑰在js源碼中查找到了,為”MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCp0wHYbg/NOPO3nzMD3dndwS0MccuMeXCHgVlGOoYyFwLdS24Im2e7YyhB0wrUsyYf0/nhzCzBK8ZC9eCWqd0aHbdgOQT6CuFQBMjbyGYvlVYU2ZP7kG9Ft6YV6oc9ambuO7nPZh+bvXH0zDKfi02prknrScAKC0XhadTHT3Al0QIDAQAB”

后經查詢資料得知該js組件使用的加密方式為RSA加密,又獲取到了加密的公鑰,所以,我們可以自己模擬JS加密方式將我們自己的用戶名密碼使用RSA加密之后提交到博客園服務器來實現登錄。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import  re
import  json
from  Crypto.Cipher  import  PKCS1_v1_5 as Cipher_pkcs1_v1_5
from  Crypto.PublicKey  import  RSA
import  base64
import  requests
 
def  js_encrypt(text):
     # 通過拿到js中的RSA公鑰,構造完整的公鑰部分
     key  =  """-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCp0wHYbg/NOPO3nzMD3dndwS0MccuMeXCHgVlGOoYyFwLdS24Im2e7YyhB0wrUsyYf0/nhzCzBK8ZC9eCWqd0aHbdgOQT6CuFQBMjbyGYvlVYU2ZP7kG9Ft6YV6oc9ambuO7nPZh+bvXH0zDKfi02prknrScAKC0XhadTHT3Al0QIDAQAB
-----END PUBLIC KEY-----"""
 
     rsakey  =  RSA.importKey(key)
     cipher  =  Cipher_pkcs1_v1_5.new(rsakey)   # 生成對象
     cipher_text  =  base64.b64encode(cipher.encrypt(text.encode(encoding = "utf-8" )))   # 對傳遞進來的用戶名或密碼字符串加密
     print (cipher_text)
     value  =  cipher_text.decode( 'utf8' )   # 將加密獲取到的bytes類型密文解碼成str類型
 
     return  value
 
session  =  requests.Session()
 
i1  =  session.get( 'https://passport.cnblogs.com/user/signin' )   # 訪問博客園登陸頁面
rep  =  re. compile ( "'VerificationToken': '(.*)'" )   # 構造正則獲取博客園的CSRF鍵值對
=  re.search(rep, i1.text)
verification_token  =  v.group( 1 )   # 拿到CSRF值
 
form_data  =  {   # 構造post的請求體
     'input1' : js_encrypt( '你博客園賬號' ),   # 將用戶名填在提示位置,將返回加密后的用戶名
     'input2' : js_encrypt( '你博客園密碼' ),   # 將密碼填在提示位置,將返回加密后的密碼
     'remember' False
}
 
i2  =  session.post(url = 'https://passport.cnblogs.com/user/signin' ,   # post訪問登陸頁面,發送登陸請求
                   data = json.dumps(form_data),
                   headers = {
                       'Content-Type' 'application/json; charset=UTF-8' ,   # 設置Content-Type類型為JSON類型
                       'X-Requested-With' 'XMLHttpRequest' ,   # 設置頭部的X-Requested-With字段,標示該請求為AJAX請求
                       'VerificationToken' : verification_token}   # 將之前獲取到的CSRF鍵值對設置在頭部信息中
                   )
 
i3  =  session.get(url = 'https://i.cnblogs.com' )   # 訪問登陸后的頁面
 
print (i3.text)   # 如果打印出登陸后的頁面,說明登陸操作成功


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM