談?wù)勎⑿殴娞栭_發(fā)中的信息加密(下)

上一篇說了微信消息的加密卓研。但是微信公眾號開發(fā)中需要密碼學(xué)的地方并不止這些盏檐。

試想這樣一個場景:用戶通過 URL 查詢所在位置附近的業(yè)余無線電中繼臺(或者飯店、旅館芯咧、加油站)牙捉,需要在 GET 報文中把自己的精確地理坐標(biāo)(精確到10米吧)以 query string 的形式發(fā)送給服務(wù)器,例如這樣:

http://repeater.applinzi.com/search/?lat=33.1234&lng=120.4321

精確的地理坐標(biāo)屬于較為敏感的用戶信息敬飒,如果這樣直接展示在 URL 里邪铲,那之前給消息加密不就成了掩耳盜鈴?所以无拗,需要加密(encryption)带到。

我需要確保地理坐標(biāo)在傳輸過程中沒有被篡改,即完整性(integrity)英染。

同時揽惹,我不希望用戶把上面的 URL 地址改吧改吧自己編制一條 GET 報文來套取數(shù)據(jù),所有合法的查詢 URL 只能由我自己生成四康,這就需要認(rèn)證(authentication)搪搏。

某些場合,比如訂單系統(tǒng)闪金,還需要加密系統(tǒng)能抵御重放攻擊(reply attack)疯溺,然而我并不在乎用戶點擊同一條 URL 多次,所以這不在我的設(shè)計需求之內(nèi)哎垦。

雖然 PyCrypto 分別提供了 Encryption 和 Authentication 算法囱嫩,但是卻并沒有提供 Authenticated Encryption 的完整實現(xiàn),需要用戶自己把二者結(jié)合起來漏设。結(jié)合方法有三種:

  • Encrypt-and-MAC墨闲,把明文分別加密和認(rèn)證,然而認(rèn)證算法是不一定能保證信息的私密性的愿题,所以可能會導(dǎo)致明文信息泄露损俭,不應(yīng)該使用。
  • Encrypt-then-MAC潘酗,先把明文加密杆兵,然后對密文進(jìn)行認(rèn)證。推薦使用仔夺。
  • MAC-then-Encrypt琐脏,先對明文進(jìn)行認(rèn)證,然后把密文和簽名一起進(jìn)行加密。在某些情況下能保證安全日裙,某些情況下不能吹艇。謹(jǐn)慎使用(其實就是別用)。

我還是使用了較為穩(wěn)妥的 Encrypt-then-MAC昂拂。代碼如下:

# utils/authencrypt.py

import base64
from Crypto.Cipher import AES
from Crypto import Random
from Crypto.Hash import HMAC


# 加密/認(rèn)證算法只接受字符串受神,如果是unicode需要先轉(zhuǎn)換
def to_str(text):
    if isinstance(text, unicode):
        text = text.encode('utf-8')
    return text


class AuthenticationError(Exception): pass


class AESCipher(object):
    def __init__(self, key):
        self.key = key

    def encrypt(self, plaintext):
        plaintext = to_str(plaintext)
        iv = Random.new().read(AES.block_size)
        cipher = AES.new(self.key, AES.MODE_CFB, iv)
        return base64.b64encode(iv+cipher.encrypt(plaintext))

    def decrypt(self, ciphertext):
        ciphertext = base64.b64decode(ciphertext)
        iv = ciphertext[:16]
        cipher = AES.new(self.key, AES.MODE_CFB, iv)
        return cipher.decrypt(ciphertext[16:]).decode('utf-8')


class Authen(object):
    def __init__(self, key):
        self.key = to_str(key)

    def get_signature(self, text):
        text = to_str(text)
        hmac = HMAC.new(self.key)
        hmac.update(text)
        return base64.b64encode(hmac.digest())

    def authenticated(self, text, signature):
        return self.get_signature(text) == signature


class AE(object):
    def __init__(self, key):
        self.aes = AESCipher(key)
        self.authen = Authen(key)

    def encrypt(self, plaintext):
        ciphertext = self.aes.encrypt(plaintext)
        signature = self.authen.get_signature(ciphertext)
        return ciphertext, signature

    def decrypt(self, ciphertext, signature):
        if not self.authen.authenticated(ciphertext, signature):
            raise AuthenticationError
        return self.aes.decrypt(ciphertext)

下面是使用范例:

>>> from utils.authencrypt import AE
>>> key='1234567890zxcvbn'
>>> ae=AE(key)
>>> plain='attack at dawn'
>>> cipher, signature=ae.encrypt(plain)
>>> cipher
'C8qh7rZ0lKXvenjG4JOOHRnuO0MiWtQyNXfsZV2G'
>>> signature
'Hpx0c5zpe7GUQPczePjF7g=='
>>> decrypted=ae.decrypt(cipher, signature)
>>> decrypted
u'attack at dawn'

這樣,文章開頭的 URL 被轉(zhuǎn)化為如下的形式:

http://repeater.applinzi.com/search/?cipher=C8qh7rZ0lKXvenjG4JOOHRnuO0MiWtQyNXfsZV2G&signature=Hpx0c5zpe7GUQPczePjF7g==

服務(wù)器接收到 GET 請求后格侯,先驗證簽名鼻听,簽名正確再解密,并利用解析出的地理坐標(biāo)返回相應(yīng)的結(jié)果联四。注意撑碴,不管其間出現(xiàn)了怎樣的異常,如簽名錯誤朝墩、解析不出坐標(biāo)還是解析出的坐標(biāo)沒有對應(yīng)的結(jié)果醉拓,都應(yīng)該返回統(tǒng)一的錯誤提示,以防止攻擊收苏。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末亿卤,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子倒戏,更是在濱河造成了極大的恐慌怠噪,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件杜跷,死亡現(xiàn)場離奇詭異傍念,居然都是意外死亡,警方通過查閱死者的電腦和手機葛闷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門憋槐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人淑趾,你說我怎么就攤上這事阳仔。” “怎么了扣泊?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵近范,是天一觀的道長。 經(jīng)常有香客問我延蟹,道長评矩,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任阱飘,我火速辦了婚禮斥杜,結(jié)果婚禮上虱颗,老公的妹妹穿的比我還像新娘。我一直安慰自己蔗喂,他們只是感情好忘渔,可當(dāng)我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著缰儿,像睡著了一般畦粮。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上返弹,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天锈玉,我揣著相機與錄音,去河邊找鬼义起。 笑死,一個胖子當(dāng)著我的面吹牛师崎,可吹牛的內(nèi)容都是我干的默终。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼犁罩,長吁一口氣:“原來是場噩夢啊……” “哼齐蔽!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起床估,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤含滴,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后丐巫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體谈况,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年递胧,在試婚紗的時候發(fā)現(xiàn)自己被綠了碑韵。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡缎脾,死狀恐怖祝闻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情遗菠,我是刑警寧澤联喘,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站辙纬,受9級特大地震影響豁遭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜牲平,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一堤框、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦蜈抓、人聲如沸启绰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽委可。三九已至,卻和暖如春腊嗡,著一層夾襖步出監(jiān)牢的瞬間着倾,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工燕少, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留卡者,地道東北人。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓客们,卻偏偏與公主長得像崇决,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子底挫,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容