數(shù)據(jù)庫加密字段進(jìn)行模糊查詢詳解
需求
對于一些敏感字段,比如手機(jī)號碼、身份證、地址、銀行卡號等,我們在存放進(jìn)數(shù)據(jù)庫前,可能需要對其進(jìn)行加密。
大部分情況下,我們只需要支持等值查詢。但是如果需要支持模糊查詢,那么整段內(nèi)容整體加密就不具備這個能力。
下面是幾種解決辦法,場景是我們需要根據(jù)手機(jī)號碼的前綴進(jìn)行匹配。
服務(wù)器端解密
因?yàn)榉?wù)器肯定是具備解密密文的能力的,因此最簡單的方式就是把整個表的密文字段數(shù)據(jù)拉下來,在服務(wù)器端進(jìn)行解密,然后再在服務(wù)器端進(jìn)行匹配。
findRecords(prefix) { records = getAllRecords() finds = [] for (record : records) { phone = decrypt(record.phone) if (phone.hasPrefix(prefix)) { finds.push(record) } } return finds }
如果數(shù)據(jù)量很小,那么這種做法也許還能夠接受。但是只要數(shù)據(jù)量上去,那么效率就會很低,而且還需要通過網(wǎng)絡(luò)IO把整個表的數(shù)據(jù)傳輸?shù)椒?wù)器端。
數(shù)據(jù)庫端解密
上面的做法需要把整個表的數(shù)據(jù)傳輸?shù)椒?wù)器端,那么我們只需要能夠在數(shù)據(jù)庫進(jìn)行匹配,就不需要傳輸整個表了。因此我們也可以在數(shù)據(jù)庫實(shí)現(xiàn)解密算法,在匹配的時候用解密算法解密密文,就能夠進(jìn)行模糊匹配了。
findRecords(prefix) { return query("select * from table where decrypt(phone) like '?%'", prefix) }
這個做法也是需要遍歷整個數(shù)據(jù)庫,因此只適合數(shù)據(jù)量比較小的情況下;而且需要把密鑰傳給數(shù)據(jù)庫,增加了密鑰泄露的風(fēng)險。
字符串分片
上面的做法我們都沒有用到數(shù)據(jù)庫的索引能力,正常情況下,前綴匹配我們是可以使用到索引的,比如where phone like 'prefix%'。如果加密后的密文,也能夠走索引,那么我們就不需要遍歷整個數(shù)據(jù)表了。
比如我們可以根據(jù)4位作為一個檢索條件,將手機(jī)號碼拆分位多個分片:比如手機(jī)號012345678901,我們可以拆分并對分片進(jìn)行加密:
分片 | 密文 |
---|---|
0123 | /egpaR5G9sMQUUWWz+3CLg |
1234 | eHCMZqxNSLx/B37koArx/w |
2345 | 9w1Pv8ik2H41s1KORLfPHA |
3456 | vcFFFvi0mwAgIjdSQjcmSw |
4567 | Tr/WaYfVySyMJhcZ78RFlA |
5678 | 2wFeC6sgdXX7wmo0YcYY/Q |
6789 | FfO9qD9XPx/lnJJuTfTfaA |
7890 | Wufth7zOBLEy2LmepG5Taw |
8901 | 1xR5MHRmlqOac5X6Cmn3kA |
這些密文拼接起來的串為:
/egpaR5G9sMQUUWWz+3CLgeHCMZqxNSLx/B37koArx/w9w1Pv8ik2H41s1KORLfPHAvcFFFvi0mwAgIjdSQjcmSwTr/WaYfVySyMJhcZ78RFlA2wFeC6sgdXX7wmo0YcYY/QFfO9qD9XPx/lnJJuTfTfaAWufth7zOBLEy2LmepG5Taw1xR5MHRmlqOac5X6Cmn3kA
然后就可以支持前綴查詢了(最少4位),比如前綴01234,我們可以按照上面的分片方式先分片,再拼接為查詢串:
分片 | 密文 |
---|---|
0123 | /egpaR5G9sMQUUWWz+3CLg |
1234 | eHCMZqxNSLx/B37koArx/w |
查詢串:
/egpaR5G9sMQUUWWz+3CLgeHCMZqxNSLx/B37koArx/w
可以看到查詢串為上面的前綴,因此可以進(jìn)行前綴查詢!
代價
這種方式也是會有一定的代價的:
密文長度較長
比如手機(jī)號碼是明文長度是11,但是按照4位分片的密文長度是198
分片長度不能太短
分片太短有安全問題,因此沒辦法支持過短的查詢。
主要是因?yàn)榍衅^短,會很容易被猜出來每一位對應(yīng)的密文。比如0-9的密文切片長度1切分:
分片 | 密文 |
---|---|
0 | hHjJXA0e+haw/+WZ1mFITA |
1 | y7qHn2nn3Ne/6wNRiwl/Lg |
2 | h0dmfkO5SUolFFLp8J2Y5A |
3 | ma/XrJjPv2MXSXE7Y4xs8w |
4 | Q9V4PXXPjJgdR7UChUMY1g |
5 | Wo57z24UXLoBdQ7QzxlOqA |
6 | fC+zrF4ga5TCb5Zu36KVrQ |
7 | z+XqHaWmlAsCnIP6NnD3lg |
8 | olm8cPYmLHCeD1jegauiWw |
9 | hJS77tLMd2Ol5SU4dIbbpw |
只有10種分片類型,如果對應(yīng)的是手機(jī)號碼字段,很容易根據(jù)統(tǒng)計(jì)每個數(shù)字的概率分布猜出每個數(shù)字對應(yīng)的密文。
可能有多余結(jié)果
可能有兩個不同分片對應(yīng)相同密文,這時候就需要在服務(wù)器再過濾一遍。
參考
實(shí)現(xiàn)
Golang實(shí)現(xiàn)基于AES+CBC+PKCS5Padding的可模糊查詢加密
以上就是數(shù)據(jù)庫加密字段進(jìn)行模糊查詢詳解的詳細(xì)內(nèi)容,更多關(guān)于數(shù)據(jù)庫加密字段模糊查詢的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
ACCESS轉(zhuǎn)SQLSERVER數(shù)據(jù)庫的注意事項(xiàng)
Access承重量太低,當(dāng)你考慮升級到SQL Server時,并不只是個連接字符串需要改變,需要改變的還有很多2007-01-01海量數(shù)據(jù)庫的查詢優(yōu)化及分頁算法方案 2 之 改良SQL語句
海量數(shù)據(jù)庫的查詢優(yōu)化及分頁算法方案 2 之 改良SQL語句...2007-03-03由拖庫攻擊談口令字段的加密策略(數(shù)據(jù)庫加密)
我不得不慘痛地寫在前面的是,這是一個安全崩盤的時代。過去一年,已經(jīng)證實(shí)的遭遇入侵、并導(dǎo)致關(guān)鍵數(shù)據(jù)被竊或者被泄露的公司,包括索尼、世嘉這樣的大型游戲設(shè)備廠商;包括花旗銀行這樣的金融機(jī)構(gòu),也包括了RSA這樣的安全廠商2012-01-01