Mongodb數據庫加密存儲(python)

 需求: 前端

  不知道你們有沒有遇到過這樣的需求:本身的服務器出於對數據庫安全的保護,須要對存儲的數據進行加密保護。這樣萬一數據庫被人拿到,別人也不能拿到數據庫裏面的內容。這裏還有一個前提:前端的展現頁面是不對外公開的,須要驗證才能進入。爲何提這個,就是由於前端所展示的內容必定是明文的,否則管理人員如何閱讀查看呢(這也給爬蟲留下了機會,不過關鍵仍是在於你可以拿到管理人員的密碼)。python

 

背景介紹:git

  •   系統數據庫採用的是Mongodb;
  •   後臺使用的語言是Python;
  •   python與數據庫的交互主要藉助於Pymongo。

 

尋找突破口:github

  從這裏面咱們大概能夠發現有兩個地方能夠下手:算法

  1. 每次進行數據庫操做的時候對數據進行加解密操做。具體來講就是:增刪改查以前對數據進行加密(這樣才能在數據庫中找到),查找以後對數據進行解密(這樣才能獲得明文的內容進行展現);
  2. 修改與數據庫進行交互的庫Pymongo,讓其實現加密存儲,解密讀取。

  比較下兩種方法的優缺點:數據庫

  第一種方案:實現很簡單,但不適合大項目。項目一旦大了,對數據庫的操做不太可能徹底經過某個數據庫操做模塊來實現,這樣修改起來就很麻煩了;安全

  第二種方案:對業務邏輯是透明的。並不須要對網站代碼進行修改,但須要對pymongo的源碼進行分析,找出增刪改查相應的關鍵點,在這些關鍵點上進行加解密操做。服務器

  因爲本身的項目確實不小,存在不少模塊。因此選擇了第二種方案。ide

 

具體步驟:函數

  1. 實現加解密函數庫

    既然須要用到加解密操做,那麼顯然須要實現本身的加解密函數。具體實現中我使用了pycrypto加密庫,利用其中的AES加密算法對文檔進行加解密。加解密過程不難,利用裏遞歸實現,代碼實現以下:

 1 from Crypto.Cipher import AES  2 import bson  3 from bson.binary import Binary, UUIDLegacy  4 from pymongo import config  5 
 6 key = config.key  7 
 8 obj = AES.new(key)  9 
10 def encrypt_helper(s): 11     length = 16 - (len(s) % 16) 12     s += chr(length) * length 13     s = obj.encrypt(s) 14     s = Binary(s, 1) 15     return s 16 
17 def decrypt_helper(s): 18     s = obj.decrypt(s) 19     buf = bytearray(s) 20     length = buf[-1] 21     s = s[: -length] 22     return s 23 
24 def encrypt_doc(doc): 25     if isinstance(doc, str): 26         return encrypt_helper(doc) 27     if isinstance(doc, dict): 28         for key in doc: 29             if cmp(key, "channel") != 0: 30                 doc[key] = encrypt_doc(doc[key]) 31         return doc 32 
33     if isinstance(doc, list): 34         for i in range(len(doc)): 35             doc[i] = encrypt_doc(doc[i]) 36         return doc 37     return doc 38 
39 
40 def decrypt_doc(doc): 41     if isinstance(doc, Binary): 42         return decrypt_helper(doc) 43     if isinstance(doc, dict): 44         temp_doc = {} 45         for key in doc: 46             #version 1
47             #doc[key] = decrypt_doc(doc[key])
48 
49             #version 2
50             temp_doc[str(key)] = decrypt_doc(doc[key]) 51         doc = temp_doc 52         return doc 53 
54     if isinstance(doc, list): 55         for i in range(len(doc)): 56             doc[i] = decrypt_doc(doc[i]) 57         return doc 58     return doc
View Code

  2. 找到pymongo中進行增刪改查操做的代碼並插入加解密的操做

    通過研讀pymongo的代碼發現,增刪改查的操做主要是在兩個文件裏面進行的:collection.py,cursor.py。因此在實現過程當中,我只對這兩個文件的相關部分進行了修改(注意,我使用pymongo版本是2.7,若是使用其餘版本的可能會有差異)。

    我就簡單列舉一下我修改的函數吧,你們有興趣能夠上github具體查看下整個實現:

    •  collection.py:
      • insert
      • update
      • find_one
      • remove
      • aggregate
    •  cursor.py
      • __getitem__
      • __send_message

    有興趣的能夠看看代碼,github地址:https://github.com/ybAmazing/encrypt_pymongo

 

思考和總結

這個功能的必要性,我本身是持懷疑態度的。因爲對黑客技術也不是很瞭解,也說不出個因此然來。你們若是有什麼想法或建議的,能夠留言,相互交流學習一下。