程式碼中的敏感資訊加密方案

運維咖啡吧發表於2018-10-29

曾有個同事不小心把專案程式碼給傳到了Github上,導致程式碼裡邊的一個明文郵箱賬號密碼被利用,為此公司及個人都付出了沉重的代價。那麼程式碼中的敏感資訊該如何處理呢?本文將簡單介紹一下我們的實踐方法。

實現目標

  1. 程式碼中的敏感資訊加密,例如郵箱賬號密碼、連線資料庫的賬號密碼、第三方校驗的key
  2. 對於生產使用的原始密碼等資訊應儘量少的人接觸,例如資料庫的密碼應只有DBA知道

資訊加密

資訊加密常見的有兩類:

第一類無需解密:例如系統登入密碼加密,通過加密演算法對使用者輸入密碼進行加密後存放在資料庫中,使用者再次登入時依然拿相同的加密演算法對使用者輸入密碼進行加密,拿加密後的結果和資料庫中存放的結果做對比,整個過程中都不需要知道使用者輸入的原始密碼是什麼,MD5是處理此類加密最常用的加密演算法

第二類需要解密:例如我們寫在專案程式碼中連線資料庫的賬號密碼,專案程式碼中以密文方式儲存,當需要連線資料庫的時候,要對密文進行解密,拿到原始未加密的賬號密碼去連線資料庫,與MD5單向加密不同,這類加密需要能對加密後的密文進行解密,此類加密方法目前最常用的加密演算法為RSA

我們這裡考慮的是給配置檔案裡的敏感資訊加密,也就是上邊說的第二類情況,採用的也是RSA加密演算法,關於RSA加密演算法的詳細內容自行Google下吧,這裡不贅述,需要知道以下兩點就可以了:

  1. 加密演算法需要生成一對RSA祕鑰,分別為公鑰和私鑰
  2. 拿公鑰對密碼進行加密得到加密後的字串配置在專案程式碼中,需要使用原始密碼的時候拿私鑰對加密後的字串進行解密得到原始密碼

這裡注意一個問題,拿到私鑰就可以對加密字串進行解密,那麼這個祕鑰肯定就不能放在專案程式碼中了,不然再遇到程式碼給傳Github的情況就可以拿祕鑰進行解密,失去了加密的意義了。這裡我們的策略是祕鑰統一由運維管理,直接放在生產伺服器中,專案代理裡配置路徑可讀取祕鑰即可,避免祕鑰因程式碼洩露而洩露。

RSA加解密python指令碼,可以直接使用此指令碼生成RSA祕鑰對,加密密碼或者解密,當然也可以使用OpenSSL工具完成此操作

import binascii
from Cryptodome.PublicKey import RSA
from Cryptodome.Cipher import PKCS1_v1_5


class RsaCrypto():
    '''RSA 加解密'''

    def create_rsa_key(self):
        '''生成RSA祕鑰對'''
        try:
            key = RSA.generate(2048)
            encrypted_key = key.exportKey(pkcs=8)

            public_key = key.publickey().exportKey().decode('utf-8')
            private_key = encrypted_key.decode('utf-8')

            return {'state': 1, 'message': {'public_key': public_key, 'private_key': private_key}}
        except Exception as err:
            return {'state': 0, 'message': str(err)}

    def encrypt(self, public_key, plaintext):
        '''加密方法'''
        try:
            recipient_key = RSA.import_key(public_key)
            cipher_rsa = PKCS1_v1_5.new(recipient_key)

            en_data = cipher_rsa.encrypt(plaintext.encode('utf-8'))
            hex_data = binascii.hexlify(en_data).decode('utf-8')

            return {'state': 1, 'message': hex_data}
        except Exception as err:
            return {'state': 0, 'message': str(err)}

    def decrypt(self, private_key, hex_data):
        '''解密方法'''
        try:
            private_key = RSA.import_key(private_key)
            cipher_rsa = PKCS1_v1_5.new(private_key)

            en_data = binascii.unhexlify(hex_data.encode('utf-8'))
            data = cipher_rsa.decrypt(en_data, None).decode('utf-8')

            return {'state': 1, 'message': data}
        except Exception as err:
            return {'state': 0, 'message': str(err)}


if __name__ == '__main__':
    print(RsaCrypto().create_rsa_key())
複製程式碼

流程管控

以資料庫的密碼管理為樣例來介紹下我們的流程

程式碼中的敏感資訊加密方案

  1. 運維通過加密系統生成RSA祕鑰對,並將祕鑰對放在生產伺服器上,通知開發祕鑰在伺服器上的存放路徑,由開發寫在專案程式碼配置檔案中
  2. DBA建立資料庫賬號密碼,通過上一步運維生成的祕鑰對密碼進行加密,並將加密後的字串給到開發寫在專案程式碼配置檔案中

祕鑰跟程式碼分離,這樣在整個過程中,開發、運維都無法接觸到資料庫密碼,每個角色得到的資訊都夠用且最少,減少中間出錯或洩露的可能

以上流程中,生成祕鑰對和通過祕鑰對密碼進行加密我們已經在web端實現了這個功能,可以方便運維及DBA進行操作,介面如下:

程式碼中的敏感資訊加密方案

以上介面為運維操作介面,可以生成祕鑰、檢視祕鑰、下載祕鑰

程式碼中的敏感資訊加密方案

以上介面為DBA操作介面,可以選擇祕鑰並對密碼進行加密生成加密後密文

兩個介面按許可權劃分,運維只能看到第一個介面,DBA只能看到第二個

寫在最後

  1. 公司程式碼上傳Github這種事千萬千萬千萬不能幹
  2. 每個人都可能犯錯,信任夥伴但也應優化流程,減少人為出錯,把風險降到最低
  3. 這些流程依然無法完全杜絕問題,每個人都應對自己的職業有敬畏,保持良好的職業道德,不做出格的事

長按關注公眾號檢視更多原創文章

如果你覺得文章對你有幫助,請轉發分享給更多的人。如果你覺得讀的不盡興,推薦閱讀以下文章:

相關文章