Python與常見加密方式
數據加密與解密通常是為了保證數據在傳輸過程中的安全性眠菇,自古以來就一直存在攀例,古代主要應用在戰(zhàn)爭領域脑蠕,戰(zhàn)爭中會有很多情報信息要傳遞,這些重要的信息都會經過加密蔬将,在發(fā)送到對應的人手上。
現代 央星,在網絡發(fā)展初期霞怀,網絡的數據安全性是沒有被足夠的重視的。事實上莉给,當時為了實現數據可以通過網絡進行傳輸已經耗費了科學家大部分腦細胞毙石,因此在TCP/IP協(xié)議設計的初期,他們也實在沒有太多精力去過多考慮數據在網絡傳輸過程中可能存在的安全性問題颓遏。隨著TCP/IP協(xié)議及相關技術的日漸成熟徐矩,網絡數據傳輸技術越來越穩(wěn)定,人們才慢慢開始重視這個問題 叁幢。
一滤灯、什么是加密解密
1、簡介
“加密”的過程,就是把“明文”變成“密文”的過程鳞骤;反之窒百,“解密”的過程,就是把“密文”變?yōu)椤懊魑摹痹ゾ T谶@兩個過程中贝咙,都需要一個關鍵的東西——叫做“密鑰”——來參與數學運算。
加密與解密函數的參數都要求是字節(jié)對象 拂募,在python中也就是我們的Bytes
對象
Python 3.x中的str是字符串 庭猩, 使用python3進行加密與解密操作的時候,要確保我們操作的數據是Bytes
字符串和Bytes
互相轉換可以使用encode()
和decode()
方法陈症。
注:兩位十六進制常常用來顯示一個二進制字節(jié)蔼水。
利用binascii
模塊可以將十六進制顯示的字節(jié)轉換成我們在加解密中更常用的顯示方式:
In [1]: import binascii
In [2]: '測試'.encode()
Out[2]: b'\xe6\xb5\x8b\xe8\xaf\x95'
In [3]: binascii.b2a_hex('測試'.encode())
Out[3]: b'e6b58be8af95'
In [4]: binascii.a2b_hex(b'e6b58be8af95')
Out[4]: b'\xe6\xb5\x8b\xe8\xaf\x95'
In [5]: binascii.a2b_hex(b'e6b58be8af95').decode()
Out[5]: '測試'
2、計算機使用的存儲單位
位(bit) 計算機使用的最小單位录肯, 用來存放二進制數
字節(jié)(Byte) 計算機最常用的基本單位趴腋,一個字節(jié)有八位 (1Byte = 8 bit)
- KB( K字節(jié)) 1K = 1024 Byte
- MB(兆字節(jié) ) 1M = 1024K
- GB(吉字節(jié) ) 1G = 1204M
- TB(太字節(jié)) 1T = 1024G
3、加密分類
網絡信息安全涉及到很多個方面论咏,其中主要有三個要解決的問題:
- 保密性(Confidentiality):信息在傳輸時不被泄露
- 完整性(Integrity):信息在傳輸時不被篡改
- 有效性(Availability):信息的使用者是合法的
針對以上幾個問題优炬,可以用以下幾種數據加密方式來解決(每種數據加密方式又有多種不同的算法實現):
數據加密方式 | 描述 | 主要解決的問題 | 常用算法 |
---|---|---|---|
對稱加密 | 指數據加密和解密使用相同的密鑰 | 數據的機密性 | DES, AES |
非對稱加密 | 也叫公鑰加密,指數據加密和解密使用不同的密鑰--密鑰對兒 | 身份驗證 | DSA厅贪,RSA |
單向加密 | 指只能加密數據蠢护,而不能解密數據 | 數據的完整性 | MD5,SHA系列算法 |
二养涮、單向加密
1葵硕、簡介
單向加密是指只能對明文數據進行加密,而不能解密數據贯吓。
舉個栗子:每個人都有不同的指紋懈凹,看到這個人,可以得出他的指紋等信息悄谐,并且唯一對應介评,但你只看一個指紋,是不可能看到或讀到這個人的長相或身份等信息爬舰。
主要功能:
通常用于保證數據的完整性们陆。
常用的算法實現:
- MD5: 128bits
- SHA: SHA1(160bits), SHA224, SHA256, SHA384
特點:
- 不可逆:無法根據數據指紋/特征碼還原原來的數據。
- 容易計算:從原數據計算出MD5值很容易洼专。
- 抗修改性:對原數據進行任何改動棒掠,哪怕只修改1個字節(jié)孵构,所得到的MD5值都有很大區(qū)別屁商。
- 定長輸出:任意長度的數據,算出的MD5值長度都是固定的。
2.蜡镶、MD5雾袱, SHA系列使用
由于MD5模塊在python3中被移除,在python3中使用hashlib
模塊進行md5操作
import hashlib
# 待加密信息
str = '這是一個測試'
# 創(chuàng)建md5對象官还, sha系列把md5換成sha系列的名字就可以了
hl = hashlib.md5()
hl.update(str.encode())
print('MD5加密前為 :' + str)
print('MD5加密后為 :' + hl.hexdigest())
運行結果
MD5加密前為 :這是一個測試
MD5加密后為 :cfca700b9e09cf664f3ae80733274d9f
MD5長度
md5的長度芹橡,默認為128bit,也就是128個0和1的二進制串望伦。這樣表達是很不友好的林说。所以將二進制轉成了16進制,每4個bit表示一個16進制屯伞,所以128/4 = 32 換成16進制表示后腿箩,為32位了。
三劣摇、 對稱加密
1珠移、簡介
對稱加密是指數據加密與解密使用相同的密鑰。
主要功能:
通常用于保證數據的機密性末融。
常用的算法實現:
- DES: Data Encryption Standard钧惧,秘鑰長度為56位,2003年左右被破解--秘鑰可以暴力破解勾习。
- 3DES: DES的改進版本浓瞪。
- AES: Advanced Encryption Standard,支持的秘鑰長度包括 128bits巧婶,192bits追逮,256bits,384bits粹舵,512bits钮孵。
需要說明的是,秘鑰長度越長眼滤,數據加密與解密的時間就越久巴席。
特點:
- 加密與解密使用的密鑰相同。
- 但是由于算法一般都是公開的诅需,因此機密性幾乎完全依賴于密鑰漾唉。
- 通常使用的是相對較小的密鑰,一般小于256bit堰塌。因為密鑰越大赵刑,加密越強,但加密與解密的過程越慢场刑。
2. python中的使用
PyCrypto是 Python 中密碼學方面最有名的第三方軟件包般此。可惜的是,它的開發(fā)工作于2012年就已停止铐懊。
幸運的是邀桑,有一個該項目的分支PyCrytodome 取代了 PyCrypto 。
PyCrypto文檔: https://pycryptodome.readthedocs.io/en/latest/src/introduction.html
安裝與導入
Windows安裝之前需要先安裝Microsoft Visual c++ 2015科乎。
在Linux上安裝壁畸,可以使用以下 pip 命令:
pip install pycryptodome
導入:
import Crypto
在Windows 系統(tǒng)上安裝則稍有不同:
pip install pycryptodomex
導入:
import Cryptodome
1)DES
簡介
DES算法為密碼體制中的對稱密碼體制,又被稱為美國數據加密標準茅茂。
DES是一個分組加密算法捏萍,典型的DES以64位為分組對數據加密,加密和解密用的是同一個算法空闲。
DES算法的入口參數有三個:Key照弥、Data、Mode进副。其中Key為8個字節(jié)共64位这揣,是DES算法的工作密鑰;Data為8個字節(jié)64位影斑,是要被加密或被解密的數據给赞;Mode為DES的工作方式,有兩種:加密或解密。
密鑰長64位矫户,密鑰事實上是56位參與DES運算(第8片迅、16、24皆辽、32柑蛇、40、48驱闷、56耻台、64位是校驗位,使得每個密鑰都有奇數個1)空另,對64位二進制數據塊進行加密盆耽,分組后的明文組和56位的密鑰按位替代或交換的方法形成密文組。每次加密對64位的輸入數據進行16輪編碼扼菠,經過一系列替換和移位后轉換成完全不同的64位輸出數據摄杂。
例子
# 導入DES模塊
from Cryptodome.Cipher import DES
import binascii
# 這是密鑰
key = b'abcdefgh'
# 需要去生成一個DES對象
des = DES.new(key, DES.MODE_ECB)
# 需要加密的數據
text = 'python spider!'
text = text + (8 - (len(text) % 8)) * '='
# 加密的過程
encrypto_text = des.encrypt(text.encode())
print(encrypto_text)
print(binascii.b2a_hex(encrypto_text))
#解密的過程
decrypt_text = des.decrypt(encrypto_text)
print(decrypt_text)
2)3DES
簡介
3DES(或稱為Triple DES)是三重數據加密算法(TDEA,Triple Data Encryption Algorithm)塊密碼的通稱循榆。它相當于是對每個數據塊應用三次DES加密算法析恢。
由于計算機運算能力的增強,原版DES密碼的密鑰長度變得容易被暴力破解秧饮。3DES即是設計用來提供一種相對簡單的方法映挂,即通過增加DES的密鑰長度來避免類似的攻擊泽篮,而不是設計一種全新的塊密碼算法。
3DES(即Triple DES)是DES向AES過渡的加密算法(1999年袖肥,NIST將3-DES指定為過渡的加密標準)咪辱,加密算法振劳,其具體實現如下:設Ek()和Dk()代表DES算法的加密和解密過程椎组,K代表DES算法使用的密鑰,M代表明文历恐,C代表密文寸癌,這樣:
3DES加密過程為:C=Ek3(Dk2(Ek1(M)))
3DES解密過程為:M=Dk1(EK2(Dk3(C)))
3)AES
簡介
高級加密標準(英語:Advanced Encryption Standard,縮寫:AES)弱贼,在密碼學中又稱Rijndael加密法蒸苇,是美國聯邦政府采用的一種區(qū)塊加密標準。這個標準用來替代原先的DES吮旅,已經被多方分析且廣為全世界所使用溪烤。經過五年的甄選流程,高級加密標準由美國國家標準與技術研究院(NIST)于2001年11月26日發(fā)布于FIPS PUB 197庇勃,并在2002年5月26日成為有效的標準檬嘀。2006年,高級加密標準已然成為對稱密鑰加密中最流行的算法之一责嚷。
AES在軟件及硬件上都能快速地加解密鸳兽,相對來說較易于實作,且只需要很少的存儲器罕拂。作為一個新的加密標準揍异,目前正被部署應用到更廣大的范圍。
特點與思想
- 抵抗所有已知的攻擊爆班。
- 在多個平臺上速度快衷掷,編碼緊湊。
- 設計簡單柿菩。
詳解
AES為分組密碼棍鳖,分組密碼也就是把明文分成一組一組的,每組長度相等碗旅,每次加密一組數據渡处,直到加密完整個明文。在AES標準規(guī)范中祟辟,分組長度只能是128位医瘫,也就是說,每個分組為16個字節(jié)(每個字節(jié)8位)旧困。密鑰的長度可以使用128位醇份、192位或256位稼锅。密鑰的長度不同,推薦加密輪數也不同僚纷。
一般常用的是128位
例子
from Cryptodome.Cipher import AES
from Cryptodome import Random
from binascii import b2a_hex
# 要加密的明文
data = '測試數據'
# 密鑰key 長度必須為16(AES-128)矩距、24(AES-192)、或32(AES-256)Bytes 長度.
# 目前AES-128足夠用
key = b'this is a 16 key'
# 生成長度等于AES塊大小的不可重復的密鑰向量
iv = Random.new().read(AES.block_size)
# 使用key和iv初始化AES對象, 使用MODE_CFB模式
mycipher = AES.new(key, AES.MODE_CFB, iv)
# 加密的明文長度必須為16的倍數怖竭,如果長度不為16的倍數锥债,則需要補足為16的倍數
# 將iv(密鑰向量)加到加密的密文開頭,一起傳輸
ciphertext = iv + mycipher.encrypt(data.encode())
# 解密的話要用key和iv生成新的AES對象
mydecrypt = AES.new(key, AES.MODE_CFB, ciphertext[:16])
# 使用新生成的AES對象痊臭,將加密的密文解密
decrypttext = mydecrypt.decrypt(ciphertext[16:])
print('密鑰k為:', key)
print('iv為:', b2a_hex(ciphertext)[:16])
print('加密后數據為:', b2a_hex(ciphertext)[16:])
print('解密后數據為:', decrypttext.decode())
運行結果:
密鑰k為: b'this is a 16 key'
iv為: b'3020aad2165cc917'
加密后數據為: b'25bd855fc0caca2a5f9f34dff175a36ade881337'
解密后數據為: 測試數據
三哮肚、非對稱加密(也叫公鑰加密)
1、簡介
指的是加密和解密使用不同的秘鑰广匙。
一把作為公開的公鑰允趟,另一把作為私鑰。這對密鑰中的公鑰進行加密鸦致,私鑰用于解密潮剪。反之亦然(被私鑰加密的數據也可以被公鑰解密) 。
在實際使用中私鑰一般保存在發(fā)布者手中分唾,是私有的不對外公開的抗碰,只將公鑰對外公布,就能實現只有私鑰的持有者才能將數據解密的方法鳍寂。 這種加密方式安全系數很高改含,因為它不用將解密的密鑰進行傳遞,從而沒有密鑰在傳遞過程中被截獲的風險迄汛,而破解密文幾乎又是不可能的捍壤。
但是算法的效率低,所以常用于很重要數據的加密鞍爱,常和對稱配合使用鹃觉,使用非對稱加密的密鑰去加密對稱加密的密鑰。
事實上睹逃,公鑰加密算法很少用于數據加密盗扇,它通常只是用來做身份認證,因為它的密鑰太長沉填,加密速度太慢--公鑰加密算法的速度甚至比對稱加密算法的速度慢上3個數量級(1000倍)疗隶。
主要作用:
通常用于保證身份驗證。
常用的公鑰加密算法有:
- RSA: 可以實現數字簽名 和 數據加密
- DSA: 只能實現數字簽名翼闹,不能實現數據加密
特點:
- 加密與解密使用的不同的密鑰斑鼻。
- 實際上它所使用的密鑰是一對兒,一個叫公鑰猎荠,一個叫私鑰坚弱。這對密鑰不是獨立的蜀备,公鑰是從私鑰中提煉出來,因此私鑰是很長的荒叶,968位碾阁、1024位、2048位些楣、4096位的都有脂凶。
- 通常公鑰是公開的,所有人都可以得到戈毒;私鑰是不能公開的艰猬,只有自己才有横堡。
- 用公鑰機密的內容只能用與之對應的私鑰才能解密埋市,反之亦然。
2命贴、python中的使用
1)RSA
RSA公鑰加密算法是1977年由羅納德·李維斯特(Ron Rivest)道宅、阿迪·薩莫爾(Adi Shamir)和倫納德·阿德曼(Leonard Adleman)一起提出的。RSA就是他們三人姓氏開頭字母拼在一起組成的胸蛛。 RSA是目前最有影響力的公鑰加密算法污茵,它能夠抵抗到目前為止已知的絕大多數密碼攻擊,RSA算法基于一個十分簡單的數論事實:將兩個大質數相乘十分容易葬项,但是想要對其乘積進行因式分解卻極其困難泞当,因此可以將乘積公開作為加密密鑰。
首先我們需要安裝一個rsa
模塊:
pip install rsa
而且民珍,因為RSA加密算法的特性襟士,RSA的公鑰私鑰都是10進制的,但公鑰的值常常保存為16進制的格式嚷量,所以需要將其用int()
方法轉換為10進制格式陋桂。
用網頁中的公鑰把數據加密
import rsa
import binascii
# 使用網頁中獲得的n和e值,將明文加密
def rsa_encrypt(rsa_n, rsa_e, message):
# 用n值和e值生成公鑰
key = rsa.PublicKey(rsa_n, rsa_e)
# 用公鑰把明文加密
message = rsa.encrypt(message.encode(), key)
# 轉化成常用的可讀性高的十六進制
message = binascii.b2a_hex(message)
# 將加密結果轉化回字符串并返回
return message.decode()
# RSA的公鑰有兩個值n和e蝶溶,我們在網站中獲得的公鑰一般就是這樣的兩個值嗜历。
# n常常為長度為256的十六進制字符串
# e常常為十六進制‘10001’
pubkey_n = '8d7e6949d411ce14d7d233d7160f5b2cc753930caba4d5ad24f923a505253b9c39b09a059732250e56c594d735077cfcb0c3508e9f544f101bdf7e97fe1b0d97f273468264b8b24caaa2a90cd9708a417c51cf8ba35444d37c514a0490441a773ccb121034f29748763c6c4f76eb0303559c57071fd89234d140c8bb965f9725'
pubkey_e = '10001'
# 需要將十六進制轉換成十進制
rsa_n = int(pubkey_n, 16)
rsa_e = int(pubkey_e, 16)
# 要加密的明文
message = '測試數據'
print("公鑰n值長度:", len(pubkey_n))
print(rsa_encrypt(rsa_n, rsa_e, message))
運行結果:
公鑰n值長度: 256
7b2ab6bffebc258c9ad577fed797868c5321a919b817e7f4fbf0f67ba450ace6cd4d9574345912226d1875dab7f0c973b3c442fc12fe5f1b71f8be3dccd071f8ca91c4dac7da046bba8461b7c88b5c8acfb4995650746aa3f5e241f5c97aafc46f5da222b41a7883aaa54457d9e47b62428fab94dc093bd840ba2454477143ad