哈希值+非对称加密+网络+数字签名,你真的知道怎么给游戏充钱吗
前文
使用socket實現局域網不同主機通信
SHA256算法的實現和消息的哈希散列值計算
python實現RSA算法,對數據進行加密認證
文章目錄
- 數字簽名與認證
- 攻擊類型
- 算法選擇
- 實現流程
- 總結
數字簽名與認證
什么是數字簽名?
??簽名我們大家都知道,A在紙上簽上自己的名字,其余人在紙上看到A的簽名,確認是A的字跡,那么就可以確定這個簽名是A留下的。
??但是如何確保這是A本人簽上去的而不是第三方偽造的呢?
??這要依賴于A的習慣和字跡是有鮮明特征,與他人不同的。可在經過反復訓練后,第三方仍然可以模仿A的字跡進行簽名。
??數字簽名同樣是代表A身份的一個簽名,但是由于數據量的龐大,第三方幾乎不可能(或者說短時間內不可能)偽造出A的簽名,這在一定程度上比我們一般知道的手寫簽名要安全、可靠。
加密和解密
??在密碼學中,我們有一套加密方法,與之對應有一套解密方法,發送方使用加密方法對信息(稱作明文)加密,加密后的信息形成密文,將密文暴露在公共環境下,任何人都可以有機會獲得這條密文。但是加密后的密文與明文幾乎沒有關聯,沒有經過授權的人無法解讀密文的內容,而授權用戶對密文進行解密,得到明文(原文),才能讀懂信息。
認證
??上述已經了解到什么是解密和解密,但是在這個過程中,發送方無法確定接收方能否接收到信息并解密。接收方也無法確定消息是否真的是發送方發送,而不是第三方偽造。
??也就是說,發送方可以抵賴發送這條消息的真實性,接收方無法確認這條消息是否被主動攻擊過(偽造、篡改)。
??或許你已經想到,有一個可靠的第三方來確認雙方的身份和消息的安全,但這也不是絕對安全,因為問題轉到了如何確認可靠的第三方是否可靠上面。
??現在介紹一種方法:先將要發送的消息M經過不可逆的運算變成H。確保在得到H后,無法反推出原文M;確保每一個原文M,都只對應唯一一個H,當原文發生任何改變后,得到的H都完全不一樣。隨后,發送方使用自己的簽名方法對H進行加密形成密文C。原文M和密文C一起發送給接收方。接收方接收到M和C,使用同樣的不可逆算法計算M得到H,再對C使用與發送方簽名方法相對應的解密方法進行解密,得到D,對比D和H,如果D和H一樣,則認證成功。
??在這個過程中,這條消息無法被修改,因為任何一點的改動都會導致產生很大差別的H。同時,發送方無法抵賴他發送過這條消息的存在性,因為H唯一而且只有發送方才能對H簽名成C,C也是不可修改的,接收方收到的C解密后與H一致。
??那么這和游戲充值有什么關系呢?不難發現,網絡支付都需要這種手段去認證支付記錄。假設A要想B發起一筆交易,B想要認證這筆交易的完整性和這筆交易確實是A發起的,就需要上述簽名認證技術。
攻擊類型
??如果第三方要偽造信息和簽名方法,需要找到一條和發送方發送的信息不一樣,但是經過不可逆算法計算出來的H一樣。或者根據已知的發送信息M和H簽名后的C,逆推出發送方使用的簽名方法。
算法選擇
??計算消息的唯一對應值,可以說是信息摘要,可以使用的是MD5、DES、SHA等算法,但是這些算法不是絕對可靠的,表現在他們會發生碰撞(兩個不同的消息得到相同的信息摘要)。對摘要進行加密,可以使用RSA和ECC。
??在本文實現中采用SHA256和RSA方法,前文鏈接SHA、RSA。同時,我們要模擬發送方和接收方在網絡上進行數據的傳輸,使用到網絡連接的方法。
實現流程
??首先需要模擬一個發送方和一個接收方,它們在網上進行在線支付,那就使用網絡連接協議,創建一個游戲官方服務器和一個終端玩家。
??當玩家在游戲內點擊充值時,游戲的服務器給玩家發送這樣的請求:你給我支付648人民幣,我給你時裝道具。游戲官方確認這筆交易并對它進行簽名,發送給玩家。玩家接收到后,確認這筆交易的完整,確認發起方是游戲官方,才進行交易的下一步。
??在服務器端,服務器對交易的內容實驗SHA256計算散列值,根據RSA算法使用自己的秘鑰對散列值簽名,將交易和簽名后的數據拼接在一起回送給玩家。
??玩家接收到回送數據后,檢驗該數據是否正確,如果服務器的身份合法,則進行后續操作。
服務器端:
def udpServer(address,port=8686):# dgram代表udp方式server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)server.bind((address, port))print('Server start')while True:data, ad = server.recvfrom(1024)# 處理接收到的數據print('receive from : ', ad, ' data: ', data)ret = serverProcess(data)print('send back: ',ret)server.sendto(ret,ad)c = [chr(data[i]) for i in range(5)]if ''.join(c) == 'close':breakserver.close()print('Server close')def serverProcess(msg):msg = msg.decode('gbk')ret = ''if msg == '充錢!648塊錢':deal = '你給我648塊我就給你道具'bt = deal.encode('gbk')bt = byte2str(bt)ret += 'charge'l = len(bt)if len(str(l)) < 8:l = '0'*(8-len(str(l))) + str(l)else:l = str(l)ret += l + bthash_index = int(mySHA256(bt),16)e = n = 0with open('e.txt', 'r') as f:e = int(f.read())with open('n.txt', 'r') as f:n = int(f.read())c = quickPowerMod(hash_index,e,n)ret += str(c)return ret.encode('utf-8')if __name__ == "__main__":address = "localhost"port = 8686udpServer(address,port)玩家端
def process(msg):msg = msg.decode('utf-8')if msg[:6] == 'charge':deal_len = int(msg[6:14])deal = msg[14:deal_len+14]print('deal detail: ', str2byte(deal).decode('gbk'))c = int(msg[deal_len+14:])cal_index = mySHA256(deal)with open('d.txt', 'r') as f:d = int(f.read())with open('n.txt', 'r') as f:n = int(f.read())de_index = quickPowerMod(c,d,n)de_index = hex(de_index)[2:]print('計算的哈希值: ',cal_index)print('解密的哈希值: ', de_index)if de_index == cal_index:print('是合法的官方')else:print('非法數據')if __name__ == '__main__':address = 'localhost'port = 8686message = '充錢!648塊錢'bt = message.encode('gbk')receive = udpSend(address, port, bt)process(receive)玩家端結果
總結
使用了SHA、RSA和SOCKET實現網絡支付的一般流程,不足之處是欠缺許多功能。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的哈希值+非对称加密+网络+数字签名,你真的知道怎么给游戏充钱吗的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql binlog过期策略_对存在
- 下一篇: android support libr