原文:http://www.cnblogs.com/huxianglin/p/6387045.html
python利用pycrypto實現RSA
本節內容
- pycrypto模塊簡介
- RSA的公私鑰生成
- RSA使用公鑰加密數據
- RSA使用私鑰解密密文
- 破解博客園登陸
pycrypto模塊簡介
pycrypto模塊是python中用來處理加密解密等信息安全相關的一個很重要模塊。
該模塊支持的加密方式:
-
對稱加密方式:
- AES
- DES
- ARC4
-
散列值計算:
- MD5
- SHA
- HMAC
-
公鑰加密和簽名:
- RSA
- 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鍵值對
v
=
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)
# 如果打印出登陸后的頁面,說明登陸操作成功
|
