Python 常見加密方式和實現

Python 加密與解密小結

這篇文章主要介紹了Python 加密與解密,使用base64或pycrypto模塊

前言

據記載,公元前400年,古希臘人發明了置換密碼。1881年世界上的第一個電話保密專利出現。在第二次世界大戰期間,德國軍方啟用“恩尼格瑪”密碼機,密碼學在戰爭中起著非常重要的作用。隨著信息化和數字化社會的發展,人們對信息安全和保密的重要性認識不斷提高,于是在1997年,美國國家標準局公布實施了“美國數據加密標準(DES)”,民間力量開始全面介入密碼學的研究和應用中,采用的加密算法有DES、RSA、SHA等。隨著對加密強度需求的不斷提高,近期又出現了AES、ECC等。

使用密碼學可以達到以下目的:保密性:防止用戶的標識或數據被讀取。數據完整性:防止數據被更改。身份驗證:確保數據發自特定的一方。

我們所說的加密方式,都是對二進制編碼的格式進行加密的,對應到Python中,則是我們的Bytes。所以當我們在Python中進行加密操作的時候,要確保我們操作的是Bytes,否則就會報錯。注:兩位十六進制常常用來顯示一個二進制字節。

將字符串和Bytes互相轉換可以使用encode()decode()方法。

# 方法中不傳參數則是以默認的utf-8編碼進行轉換
In [1]: '南北'.encode()
Out[1]: b'\xe5\x8d\x97\xe5\x8c\x97'In [2]: b'\xe5\x8d\x97\xe5\x8c\x97'.decode()
Out[2]: '南北'

利用binascii模塊可以將十六進制顯示的字節轉換成我們在加解密中更常用的顯示方式:

In [1]: import binasciiIn [2]: '南北'.encode()
Out[2]: b'\xe5\x8d\x97\xe5\x8c\x97'In [3]: binascii.b2a_hex('南北'.encode())
Out[3]: b'e58d97e58c97'In [4]: binascii.a2b_hex(b'e58d97e58c97')
Out[4]: b'\xe5\x8d\x97\xe5\x8c\x97'In [5]: binascii.a2b_hex(b'e58d97e58c97').decode()
Out[5]: '南北'

加密算法分類

對稱加密算法:

對稱加密采用了對稱密碼編碼技術,它的特點是文件加密和解密使用相同的密鑰發送方和接收方需要持有同一把密鑰,發送消息和接收消息均使用該密鑰。相對于非對稱加密,對稱加密具有更高的加解密速度,但雙方都需要事先知道密鑰,密鑰在傳輸過程中可能會被竊取,因此安全性沒有非對稱加密高。常見的對稱加密算法:DES,AES,3DES等等

非對稱加密算法:

文件加密需要公開密鑰(publickey)和私有密鑰(privatekey)。接收方在發送消息前需要事先生成公鑰和私鑰,然后將公鑰發送給發送方。發送放收到公鑰后,將待發送數據用公鑰加密,發送給接收方。接收到收到數據后,用私鑰解密。在這個過程中,公鑰負責加密,私鑰負責解密,數據在傳輸過程中即使被截獲,攻擊者由于沒有私鑰,因此也無法破解。非對稱加密算法的加解密速度低于對稱加密算法,但是安全性更高。非對稱加密算法:RSA、DSA、ECC等算法

消息摘要算法:

消息摘要算法可以驗證信息是否被篡改。在數據發送前,首先使用消息摘要算法生成該數據的簽名,然后簽名和數據一同發送給接收者。接收者收到數據后,對收到的數據采用消息摘要算法獲得簽名,最后比較簽名是否一致,以此來判斷數據在傳輸過程中是否發生修改。

Python加密庫

PyCrypto是 Python 中密碼學方面最有名的第三方軟件包。可惜的是,它的開發工作于2012年就已停止。其他人還在繼續發布最新版本的 PyCrypto,如果你不介意使用第三方的二進制包,仍可以取得Python 3.5 的相應版本。比如,可以在 Github 上找到了對應Python3.5的PyCrypto 二進制包。幸運的是,有一個該項目的分支?PyCrytodome 取代了 PyCrypto 。

# Linux 上安裝它,你可以使用以下pip 命令:
pip3 install -i https://pypi.douban.com/simple pycryptodome
# 導入
import Crypto# 在Windows 系統上安裝則稍有不同:
pip3 install -i https://pypi.douban.com/simple pycryptodomex
# 導入
import Cryptodome

DES加密

全稱為Data EncryptionStandard,即數據加密標準,是一種使用密鑰加密的塊算法,又被稱為美國數據加密標準

DES算法的入口參數有三個:Key、Data、Mode。其中Key為7個字節共56位,是DES算法的工作密鑰;Data為8個字節64位,是要被加密或被解密的數據;Mode為DES的工作方式,有兩種:加密或解密。

密鑰長64位,密鑰事實上是56位參與DES運算(第8、16、24、32、40、48、56、64位是校驗位,使得每個密鑰都有奇數個1),分組后的明文組和56位的密鑰按位替代或交換的方法形成密文組。

from Crypto.Cipher import DES
key = b'abcdefgh' # 密鑰 8位或16位,必須為bytesdef pad(text):# 加密函數,如果text不是8的倍數【加密文本text必須為8的倍數!】,那就補足為8的倍數while len(text) % 8 != 0:text += ' 'return textdes = DES.new(key, DES.MODE_ECB)  # 創建一個DES實例
text = 'Python rocks!'
padded_text = pad(text)  # 需要加密的數據
encrypted_text = des.encrypt(padded_text.encode('utf-8'))  # 加密
print(encrypted_text)
# rstrip(' ')返回從字符串末尾刪除所有字符串的字符串(默認空白字符)的副本
plain_text = des.decrypt(encrypted_text).decode().rstrip(' ')  # 解密
print(plain_text)

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)))

AES加密

高級加密標準(英語:Advanced Encryption Standard,縮寫:AES),在密碼學中又稱Rijndael加密法,是美國聯邦政府采用的一種區塊加密標準。這個標準用來替代原先的DES,已經被多方分析且廣為全世界所使用。經過五年的甄選流程,高級加密標準由美國國家標準與技術研究院(NIST)于2001年11月26日發布于FIPS PUB 197,并在2002年5月26日成為有效的標準。2006年,高級加密標準已然成為對稱密鑰加密中最流行的算法之一。

AES在軟件及硬件上都能快速地加解密,相對來說較易于實作,且只需要很少的存儲器。作為一個新的加密標準,目前正被部署應用到更廣大的范圍。

AES只是個基本算法,實現AES有若干模式。其中的CBC模式因為其安全性而被TLS(就是https的加密標準)和IPSec(win采用的)作為技術標準。簡單地說,CBC使用密碼和salt(起擾亂作用)按固定算法(md5)產生key和iv。然后用key和iv(初始向量,加密第一塊明文)加密(明文)和解密(密文)。

特點

  1. 抵抗所有已知的攻擊。
  2. 在多個平臺上速度快,編碼緊湊。
  3. 設計簡單。

AES為分組密碼,分組密碼也就是把明文分成一組一組的,每組長度相等,每次加密一組數據,直到加密完整個明文。在AES標準規范中,分組長度只能是128位,也就是說,每個分組為16個字節(每個字節8位)。密鑰的長度可以使用128位、192位或256位(16、24和32字節)。密鑰的長度不同,推薦加密輪數也不同。

##################################### AES.MODE_ECB ####################################
from Cryptodome.Cipher import AES
from binascii import b2a_hex, a2b_hex
# 密鑰key 長度必須為16(AES-128)、24(AES-192)、或32(AES-256)Bytes 長度.
# 目前AES-128足夠用
key = 'abcdefghigklmnop'
# 加密內容需要長達16位字符,所以進行空格拼接
def pad(text):while len(text) % 16 != 0:text += ' 'return text# 進行加密算法,模式ECB模式,把疊加完16位的秘鑰傳進來
aes = AES.new(key.encode(), AES.MODE_ECB)
# 加密內容,此處需要將字符串轉為字節
text = 'hello'
# 進行內容拼接16位字符后傳入加密類中,結果為字節類型
encrypted_text = aes.encrypt(pad(text).encode())
encrypted_text_hex = b2a_hex(encrypted_text)
print(encrypted_text_hex)# 此處是為了驗證是否能將字節轉為字符串后,進行解密成功
# 實際上a 就是 encrypted_text ,也就是加密后的內容
# 用aes對象進行解密,將字節類型轉為str類型,錯誤編碼忽略不計
de = str(aes.decrypt(a2b_hex(encrypted_text_hex)), encoding='utf-8',errors="ignore")
# 獲取str從0開始到文本內容的字符串長度。
print(de[:len(text)])##################################### AES.MODE_CFB ####################################
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())

面向對象方式

#coding: utf8
import sys
from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hexclass prpcrypt():def __init__(self, key):self.key = keyself.mode = AES.MODE_CBC#加密函數,如果text不是16的倍數【加密文本text必須為16的倍數!】,那就補足為16的倍數def encrypt(self, text):cryptor = AES.new(self.key, self.mode, self.key)#這里密鑰key 長度必須為16(AES-128)、24(AES-192)、或32(AES-256)Bytes 長度.目前AES-128足夠用length = 16count = len(text)add = length - (count % length)text = text + ('\0' * add)self.ciphertext = cryptor.encrypt(text)#因為AES加密時候得到的字符串不一定是ascii字符集的,輸出到終端或者保存時候可能存在問題#所以這里統一把加密后的字符串轉化為16進制字符串return b2a_hex(self.ciphertext)#解密后,去掉補足的空格用strip() 去掉def decrypt(self, text):cryptor = AES.new(self.key, self.mode, self.key)plain_text = cryptor.decrypt(a2b_hex(text))return plain_text.rstrip('\0')if __name__ == '__main__':pc = prpcrypt('keyskeyskeyskeys')   #初始化密鑰e = pc.encrypt("00000")d = pc.decrypt(e)           print e, de = pc.encrypt("00000000000000000000000000")d = pc.decrypt(e)         print e, d

運行結果

a9755fd70d8d6db65a6fac12d4797dde 00000

2c1969f213c703ebedc36f9e7e5a2b88922ac938c983201c200da51073d00b2c 00000000000000000000000000

RSA加密

RSA加密算法是一種非對稱加密算法。在公開密鑰加密和電子商業中RSA被廣泛使用。

該算法基于一個十分簡單的數論事實:將兩個大素數相乘十分容易,但那時想要對其乘積進行因式分解卻極其困難,因此可以將乘積公開作為加密密鑰,即公鑰,而兩個大素數組合成私鑰。公鑰是可發布的供任何人使用,私鑰則為自己所有,供解密之用。

3個參數:rsa_n, rsa_e,message。rsa_n, rsa_e 用于生成公鑰,message: 需要加密的消息

因為RSA加密算法的特性,RSA的公鑰私鑰都是10進制的,但公鑰的值常常保存為16進制的格式,所以需要將其用int()方法轉換為10進制格式。

安裝 pip install rsa

使用

import rsa
from binascii import b2a_hex, a2b_hexclass rsacrypt():def __init__(self, pubkey, prikey):self.pubkey = pubkeyself.prikey = prikeydef encrypt(self, text):self.ciphertext = rsa.encrypt(text.encode(), self.pubkey)# 因為rsa加密時候得到的字符串不一定是ascii字符集的,輸出到終端或者保存時候可能存在問題# 所以這里統一把加密后的字符串轉化為16進制字符串return b2a_hex(self.ciphertext)def decrypt(self, text):decrypt_text = rsa.decrypt(a2b_hex(text), prikey)return decrypt_textif __name__ == '__main__':pubkey, prikey = rsa.newkeys(256)rs_obj = rsacrypt(pubkey,prikey)text='hello'ency_text = rs_obj.encrypt(text)print(ency_text)print(rs_obj.decrypt(ency_text))"""
b'7cb319c67853067abcd16aad25b3a8658e521f83b1e6a6cf0c4c2e9303ad3e14'
b'hello'
"""

base64

?

Base64編碼,64指A-Z、a-z、0-9、+和/這64個字符,還有“=”號不屬于編碼字符,而是填充字符。為什么發明這么個編碼呢,這個編碼的原理很簡單,“破解”也很容易,原因是電子郵件剛出來的時候,只傳遞英文字符,這沒有問題,但是后來,中國人,日本人都要發email,這樣問題就來了,因為這些字符有可能會被郵件服務器或者網關當成命令處理,故必須得有一種編碼來對郵件進行加密,但是加密的目的是為了能夠使得一些原始的服務器不出問題(現在服務器早已經能處理這些亂七八糟得情況了,不過因為已經形成了一套規范,所以郵件還是得經過Base64編碼才能傳遞)。

優點:方法簡單。缺點:不保險,別人拿到密文可以自己解密出明文

編碼原理:將3個字節轉換成4個字節((3 X 8)=24=(4X6)),先讀入3個字節,每讀一個字節,左移8位,再右移四次,每次6位,這樣就有4個字節了。解碼原理:將4個字節轉換成3個字節,先讀入4個6位(用或運算),每次左移6位,再右移3次,每次8位,這樣就還原了。

import base64
s1 = base64.encodestring('hello world')
s2 = base64.decodestring(s1)
print s1, s2

結果

aGVsbG8gd29ybGQ=
hello world

?

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/454665.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/454665.shtml
英文地址,請注明出處:http://en.pswp.cn/news/454665.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

jenkins日志亂碼linux,Jenkins控制臺中亂碼問題解決

由于服務器環境及應用層各版本的不同、編碼方式的不同因此會有很多種情況會出現亂碼問題。由于Jenkins中的job運行的是獨立的一個shell環境,許多的環境變量與服務器中是不一樣的,因此在job中執行的命令也就會有所差異。因此可以在job中執行env命令&#…

13,反轉鏈表《劍指offer》

題目: 輸入一個鏈表,反轉鏈表后,輸出鏈表的所有元素。 思路: 反轉鏈表,對于片段 1--->2--->3循環操作; 要反轉鏈表需要兩步: 一,將2->next指向1 (如果不保存3那…

什么是面試的關鍵?資深HR告訴你!

求職指南、面試寶典、應聘手冊……到任何一個書店去轉轉,總能發現一兩本這樣的書,有關面試應聘的包裝技巧實在太多,既讓應聘者眼花繚亂、無所適從,也讓人事經理頭疼,總擔心會被應聘者的包裝所蒙騙。東方控股集團有限公…

windows商店_Windows記事本應用現在可以從Microsoft Store中獲得

早在2019年8月,微軟就宣布將把人們最常用的Windows記事本應用搬到應用商店,讓這款深受用戶喜愛的應用更新速度更快、響應更靈敏。12月晚些時候,微軟卻放棄了這一計劃,也沒有給出太多理由。但現在,這一計劃已經完成&…

.net core linux 編譯,.NET Core 源碼編譯的問題解析

引言: .NET Core 源碼編譯https://github.com/dotnetgit clone https://github.com/dotnet/runtime.git一:Windows 編譯VS 2019 16.6(不要安裝預覽版)Win 10 專業版,最新版本 (1903/2004)長路徑支持:組策略(gpedit.msc) > 計算…

jmeter 壓測duobbo接口,施壓客戶端自己把自己壓死了

jmeter 壓測duobbo接口,jmeter代碼不合理,導致每執行一次請求,會調用一次消耗內存的實例化。導致越壓越慢,請求發不出去。這個時候需要考慮修改代碼了。 截圖中,tps越來越少。 原來初始化的代碼放在 runTest中執行。修…

oracle pl/sql 包

包用于在邏輯上組合過程和函數,它由包規范和包體兩部分組成。1)、我們可以使用create package命令來創建包,如:i、創建一個包sp_packageii、聲明該包有一個過程update_saliii、聲明該包有一個函數annual_income --聲明該包有一個存儲過程和一…

MySQL 之 explain

explain 介紹 explain顯示了MySQL如何使用索引來處理select語句以及連接表。可以幫助選擇更好的索引和寫出更優化的查詢語句。簡單講,它的作用就是分析查詢性能。explain 查詢SQL - 用于顯示SQL執行信息參數,根據參考信息可以進行SQL優化 示例&#x…

[置頂]微軟面試智力題

這個笑話反映了兩個公司不同的企業文化。很多人都知道微軟的企業文化是寬松和自由,給員工一個充分發揮創造力的空間,這也是微軟能吸引很多人才的原因之一。但是,要想進微軟工作可不容易,微軟在招聘工作上一點也不馬虎,…

背單詞軟件 單詞風暴 分享id_周一考研高效背單詞系列(一):利用單詞軟件如何背好單詞...

高效背單詞考研單詞作為考研路上的第一大難關,相信很多小伙伴都在這上面吃過不少苦,有同學更是看到密密麻麻的大綱詞匯就頭疼,但只要是學習就是有方法的,今天,我們開始推出高效背單詞系列——墨墨背單詞。另&#xff1…

linux c++ 編譯 庫,LINUX C/C++ 編譯庫關系

在LINUX 下安裝個啥,都要涉及到編譯,尤其是開源軟件. 那么編譯就涉及到C/C 和對應的庫. 我們理一理之間的關系有助于MYSQL8源碼編譯libc glibc libc libstdc eglibc GCC G CMakeGDB從libc說起。libc是Linux下原來的標準C庫,也就是當初寫hello world時包含的頭文件#…

Linux_學習_Day3_bash

Shell bash是外部程序:type/whichis bash。 shell, 子shell。可以利用bash打開另一個bash。即打開一個子shell。并且每個進程是獨立存在的。對于子shell而言,bash并不認知其他bash的存在。 執行了多次bash,要退出只需exit。用pst…

mysql 之 優化 (收集于網絡)

(以下內容均來自于網絡,如果有版權限制,請聯系我0.0) Mysql存儲千億級的數據,是一項非常大的挑戰。Mysql單表可以存儲10億級的數據,只是這個時候性能非常差,項目中大量的實驗證明,M…

hadoop-09-安裝資源上傳

hadoop-09-安裝資源上傳 在/software/www/html 下面上傳 ambari HDP HDP-UTILS-1.1.0.21 文件,之后解壓;

easyui 收費_收費班長喻玉華三尺崗亭獻青春

- 2020 第四期 人物訪談報道 -拼搏人生最美勵志先鋒人物專訪2013年,22歲的她來到巴南高速這個大家庭中,成為恩陽收費站一名普通的收費員。懷著對事業的執著追求與熱愛,經過兩年不懈的努力,獲得了領導和同事的認可和喜愛。2015年5月…

編程技術面試的五大要點

(寫在前面的話:本文最初發表于《程序員》雜志2011年10月刊,并收錄到《劍指Offer——名企面試官精講典型編程題》一書中。) 近年來找工作一直是一個很熱門的話題。我們要想找到心儀的工作,難免需要經過很多輪面試。編程…

訪問linux服務主機,如何把Linux配置為日志服務主機。

如網絡設備很多,可把同類的設備配置為相同的設備號例:more switch.log | grep X.X.X.X //查看某一設備的日志審核和記錄系統的事件是非常重要的。如果僅僅把系統事件作為日志記錄下來,而不去查看,還是無濟于事。可用webadmin管理和…

WSARecv() 函數使用解析

詳情參考:https://msdn.microsoft.com/en-us/library/windows/desktop/ms741688(vvs.85).aspx 簡述 The WSARecv function receives data from a connected socket or a bound connectionless socket. The WSARecv function provides some additional features comp…

獲取 docker 容器(container)的 ip 地址

獲取單個IP docker inspect --format {{ .NetworkSettings.IPAddress }} <container-ID> 獲取所有容器IP docker inspect -f {{.Name}} - {{.NetworkSettings.IPAddress }} $(docker ps -aq)轉載于:https://www.cnblogs.com/Tempted/p/7774789.html

山西臺達plc可編程控制器_可編程控制器2(PLC)控制原理

采用繼電器控制采用PC控制PC的控制原理(繼電器PC控制)a)當SB1按下&#xff0c;輸入繼電器00000的線圈通電&#xff0c;00000的常開觸點閉合&#xff0c;使得輸出繼電器01000的線圈得電&#xff0c;01000對應的硬輸出觸電閉合&#xff0c;KM1得電M1開始運轉&#xff0c;同時0100…