有了非對稱密鑰、摘要、對稱密鑰等現代密碼學演算法與技術,是不是就能夠保證通信的安全無虞呢,並不是。 密碼學在互聯網應用的四個目標:機密性、完整性、身份驗證、防抵賴。到目前為止,我們討論的技術中,其中防抵賴的目標並沒有達到。 假設A、B、C三個人共用一個對稱加密演算法密鑰,現在A和B互相通信,A和B一直認 ...
有了非對稱密鑰、摘要、對稱密鑰等現代密碼學演算法與技術,是不是就能夠保證通信的安全無虞呢,並不是。
密碼學在互聯網應用的四個目標:機密性、完整性、身份驗證、防抵賴。到目前為止,我們討論的技術中,其中防抵賴的目標並沒有達到。
假設A、B、C三個人共用一個對稱加密演算法密鑰,現在A和B互相通信,A和B一直認為是雙方在發送消息。由於C也有同樣的密鑰,它可以攔截A發往B的消息,然後篡改消息並用同樣的密鑰加密後發送給B, B能夠正確解密,但是該消息其實已經被篡改。
同樣的場景,A、B、C三個人共用一個對稱加密演算法密鑰,A向B發送了一條消息,但是A可以抵賴說這條消息並不是他發送的,理由就是C也有同樣的密鑰,這條加密消息可能是C發送給B的,B無法向第三方證明是A給他發送了消息。
在公開密鑰演算法中,如果演算法用於加密解密,也同樣不能防止抵賴,以RSA加密演算法舉例,由於RSA的公鑰是完全公開的,RSA私鑰擁有者雖然能夠解密,但是並不能確認是哪個客戶端發送的消息,同理任何人都可以抵賴。
抵賴出現的根本原因就在於通信雙方無法確認對方的身份,也就是不能進行身份驗證,那麼在密碼學中有沒有對應的解決方案呢?可以使用數字簽名技術防抵賴。
在現實世界中,有哪些行為或者約定可以防止人抵賴呢?最明顯的就是合同,合同一般需要人簽字或者按指紋,考慮簽字可以模仿偽造,這裡重點用指紋簽署的合同來解釋。合同一旦由指紋簽署了,就可以被覆印多份。有了合同,合同簽署人就無法否認合同的合法性,原因就在於法律規定,指紋具備唯一性,每個人的指紋是不同的,或者說指紋就代表了一個人。
回到密碼學中,如果一個消息也含有特殊的指紋,是否就可以實現防抵賴呢。事實正是如此,在RSA密鑰對中,私鑰只有密鑰對的生成者持有,如果不考慮密鑰泄露的問題,私鑰擁有者使用密鑰(註意不是加密操作)簽署一條消息,然後發送給任意的接收方,接收方只要擁有私鑰對應的公鑰,就能成功反解簽署消息,由於只有私鑰持有者才能“簽署”消息,不能抵賴說這條簽署消息不是他發送的,這就是數字簽名技術的基本原理。
以下代碼顯示了簽名的過程:
import base64 from Crypto.PublicKey import RSA from Crypto.Hash import SHA from Crypto.Signature import PKCS1_v1_5 as PKCS1_signature from Crypto.Cipher import PKCS1_v1_5 as PKCS1_cipher def get_key(key_file): with open(key_file) as f: data = f.read() key = RSA.importKey(data) return key def rsa_private_sign(data,key): signer = PKCS1_signature.new(key) digest = SHA.new() digest.update(data.encode("utf8")) sign = signer.sign(digest) signature = base64.b64encode(sign) signature = signature.decode('utf-8') return signature private_key = get_key('demo_private_key.pem') with open("poetry.txt", "r", encoding='utf-8') as input_file: data = input_file.read() sign = rsa_private_sign(data,private_key) fo = open("sign.txt","w") fo.write(sign)
運行後,將對poetry.txt進行簽名,生成簽名文件sign.txt。隨後使用公共通道將兩個文件同時傳出,接收方使用這兩個文件來驗證是否發生了篡改。
相關代碼如下所示:
import base64 from Crypto.PublicKey import RSA from Crypto.Hash import SHA from Crypto.Signature import PKCS1_v1_5 as PKCS1_signature from Crypto.Cipher import PKCS1_v1_5 as PKCS1_cipher def get_key(key_file): with open(key_file) as f: data = f.read() key = RSA.importKey(data) return key def rsa_public_check_sign(text, sign): publick_key = get_key('demo_public_key.pem') verifier = PKCS1_signature.new(publick_key) digest = SHA.new() digest.update(text.encode("utf8")) return verifier.verify(digest, base64.b64decode(sign)) public_key = get_key('demo_public_key.pem') with open("poetry.txt", "r", encoding='utf-8') as input_file: data = input_file.read() signfile = open("sign.txt","r") sign = signfile.read() print(rsa_public_check_sign(data,sign)) with open("poetry-modify.txt", "r", encoding='utf-8') as input_file: data = input_file.read() signfile = open("sign.txt","r") sign = signfile.read() print(rsa_public_check_sign(data,sign))
poetry.txt將驗證結果為真。而對petry.txt修改後的poetry-modify.txt的驗證失敗,從而達到了防篡改的作用。