)
對稱加密和非對稱加密這兩個詞幾乎是搞開發(fā)的人都繞不開的坎。剛?cè)胄心菚何乙欢纫詾樗鼈冎皇莾煞N可以替換著用的加密套路直到真正做接口加密、文件加密、配合HTTP協(xié)議調(diào)優(yōu)時才意識到背后其實是兩套完全不同的安全模型。選錯方案或者混用算法輕則性能崩盤重則業(yè)務(wù)數(shù)據(jù)直接裸奔。這篇文章我會從底層邏輯、主流算法選型、混合加密實戰(zhàn)一直聊到高頻報錯和排查套路把這兩條技術(shù)路線一次講透。新手能照著做老手也能查漏補缺。1. 兩套加密體系的底層邏輯拆解1.1 對稱加密一把鑰匙走到底對稱加密的核心思想非常簡單加密和解密用的是同一個密鑰。你拿這個密鑰把明文變成密文接收方拿同一個密鑰把密文還原成明文全程沒有任何第二把鑰匙參與。舉個例子你把一份文件鎖進保險箱用一把鑰匙鎖上再把箱子寄給對方對方用同一把鑰匙打開。這個模型的關(guān)鍵假設(shè)是這把鑰匙必須在通信之前就安全地送到對方手里。如果鑰匙在傳輸過程中被截獲那加密就形同虛設(shè)。在工程實現(xiàn)上對稱加密算法普遍依賴兩類操作混淆和擴散?;煜屆芪暮兔荑€、明文之間的關(guān)系變得極其復(fù)雜攻擊者看不出規(guī)律擴散則讓明文中哪怕一個bit的變化也能擴散到密文的大部分位這就是所謂雪崩效應(yīng)。對稱加密最大的優(yōu)勢是快。硬件上普遍有AES指令集加速一塊支持AES-NI的處理器做AES加解密吞吐量能做到每秒幾個GB級別。所以凡是涉及大量數(shù)據(jù)加密的場景比如文件加密、數(shù)據(jù)庫加密、TLS數(shù)據(jù)傳輸?shù)讓訋缀醵际菍ΨQ加密在干活。它最大的痛點也寫在明面上密鑰怎么安全分發(fā)。兩個人從來沒碰過面沒有任何安全通道怎么把同一把密鑰同時送到雙方手上在互聯(lián)網(wǎng)場景里這是個致命問題。1.2 非對稱加密公鑰私鑰分工協(xié)作非對稱加密的模型和對稱加密完全不同。它生成的不是一把鑰匙而是一對數(shù)學(xué)上關(guān)聯(lián)的密鑰公鑰和私鑰。公鑰可以公開分發(fā)私鑰只有自己持有。這里有兩組經(jīng)典操作很多人容易記混。第一組是公鑰加密、私鑰解密。任何人拿到你的公鑰都能把消息加密后發(fā)給你但只有你的私鑰能解開。這解決的是機密性問題??梢灶惐瘸梢粋€帶投信口的郵箱任何人都能從投信口把信塞進去但只有拿鑰匙的郵遞員能打開箱門取信。第二組是私鑰簽名、公鑰驗簽。你用私鑰對一段數(shù)據(jù)做簽名別人用你的公鑰驗證簽名是否有效。這解決的是身份認(rèn)證和完整性防篡改問題。類比的話就像你在文件上蓋了一個只有你能蓋的私章別人拿著你的公開印模來核對真假。非對稱加密的數(shù)學(xué)基礎(chǔ)通常是某種單向函數(shù)難題。經(jīng)典RSA依賴的是大整數(shù)分解的困難性兩個大素數(shù)相乘很容易但把一個很大的合數(shù)分解回兩個素數(shù)極難。橢圓曲線密碼則依賴橢圓曲線離散對數(shù)問題在同樣安全強度下密鑰長度可以做到比RSA短得多計算開銷也更小。非對稱加密的優(yōu)點是密鑰分發(fā)壓力小公鑰隨便公開私鑰不出本地。缺點是慢而且慢得很明顯。RSA做一次私鑰解密可能比AES做一次分組加密慢兩到三個數(shù)量級。所以它只適合加密少量數(shù)據(jù)比如密鑰本身、哈希值不可能用于海量業(yè)務(wù)數(shù)據(jù)的直接加密。1.3 為什么現(xiàn)實方案幾乎都是混合加密很多人會問既然非對稱加密能解決密鑰分發(fā)問題那所有數(shù)據(jù)都用非對稱加密不就行了答案是不行非對稱加密太慢了。反過來如果只用對稱加密密鑰分發(fā)問題無解。于是工程界普遍采用混合加密方案用非對稱加密協(xié)商或傳輸一個隨機會話密鑰再用這個會話密鑰配合對稱加密去加密真正的業(yè)務(wù)數(shù)據(jù)。密鑰分發(fā)問題交給非對稱加密數(shù)據(jù)加密問題交給對稱加密兩者各干各擅長的事。你在瀏覽器里訪問任何HTTPS站點背后都是這么工作的。TLS握手階段用證書和密鑰交換算法完成身份驗證與會話密鑰協(xié)商后續(xù)所有HTTP請求體、響應(yīng)體全是用對稱加密來保護的。這個設(shè)計思路是理解整個加密體系的關(guān)鍵。當(dāng)你自己設(shè)計接口加密方案時也應(yīng)該沿用混合思路而不是天真地拿RSA去加密幾百KB的報文。2. 算法選型實戰(zhàn)哪些加密算法值得用2.1 對稱加密的主流選擇現(xiàn)在最值得關(guān)注的對稱加密算法我首推AES。它已經(jīng)標(biāo)準(zhǔn)化幾十年硬件加速覆蓋極其廣泛安全分析也足夠充分。AES支持128、192、256位三種密鑰長度一般業(yè)務(wù)場景用AES-128就夠涉及長期敏感數(shù)據(jù)建議直接AES-256。AES屬于分組密碼每16字節(jié)一塊處理。單獨使用分組密碼會暴露數(shù)據(jù)規(guī)律所以必須搭配工作模式。模式選不好算法再強也白搭。ECB模式最不該用。同一個明文塊永遠(yuǎn)產(chǎn)生同一個密文塊數(shù)據(jù)量大一點就會暴露結(jié)構(gòu)特征直接放棄。CBC模式需要IV加密每個分組前先和上一個密文塊異或安全性遠(yuǎn)好于ECB但它不提供完整性保護密文被篡改了檢測不到。GCM模式是目前我最推薦的它是AEAD模式一份輸出同時搞定機密性和完整性校驗內(nèi)部生成的認(rèn)證標(biāo)簽可以識別密文是否被改動過。CTR模式把分組密碼變成流式加密也能用但同樣要額外做認(rèn)證。ChaCha20也是一款很優(yōu)秀的流式對稱加密算法在手機等無AES硬件加速的環(huán)境下表現(xiàn)不錯TLS 1.3里也把它列為推薦套件。合規(guī)敏感、有國產(chǎn)化要求的項目還會考慮SM4。選型時可以按這個原則默認(rèn)AES-256-GCM嵌入式或弱硬件環(huán)境考慮ChaCha20有合規(guī)要求再看SM4。2.2 非對稱加密的主流選擇RSA是最常見的非對稱算法核心優(yōu)勢是普及度高幾乎任何語言、任何加密庫都支持。但它的密鑰長度要求越來越苛刻2048位是底線我建議新項目直接上3072位或4096位。密鑰變長帶來的直接代價是加解密速度進一步變慢RSA-4096的一次私鑰操作會比RSA-2048慢好幾倍做批量簽名時CPU壓力很明顯。ECC類算法是更現(xiàn)代的選擇。同樣安全強度下256位的橢圓曲線密鑰約等于3072位RSA的安全性密鑰和簽名都短一大截計算效率也更高。像ECDHE、ECDSA都是ECC的具體應(yīng)用形式SM2也屬于橢圓曲線體系。使用ECC時要避免自己定義曲線直接使用成熟的標(biāo)準(zhǔn)曲線比如常見的P-256。這里必須強調(diào)一個高頻誤區(qū)簽名和加密是兩個不同的操作不能混用。RSA加密應(yīng)該使用OAEP填充RSA簽名應(yīng)該使用PSS填充。不少初學(xué)者圖省事用PKCS1v15填充一把梭或者拿著加密的接口去驗簽結(jié)果不是報錯就是存在嚴(yán)重安全隱患。簽名驗簽的方向也別搞反私鑰簽名、公鑰驗簽這是證明消息確實來自私鑰持有者公鑰加密、私鑰解密才是保證只有私鑰持有者能讀內(nèi)容。2.3 不同類型業(yè)務(wù)的選型建議業(yè)務(wù)場景推薦方案關(guān)鍵理由Web/App服務(wù)端TLSECDHE AES-256-GCM前向保密性能與安全均衡接口報文加密接收方RSA-2048公鑰加密會話密鑰 AES-GCM加密業(yè)務(wù)體混合加密避免非對稱性能瓶頸數(shù)據(jù)簽名ECDSA P-256 或 RSA-3072 PSS驗簽效率高簽名長度短文件存儲加密AES-256-GCM 獨立密鑰管理大文件吞吐量要求高AEAD防篡改國內(nèi)合規(guī)項目SM2 SM4符合指定標(biāo)準(zhǔn)要求選型沒有唯一答案但有一條通用原則盡量選擇密碼學(xué)界廣泛接受、有持續(xù)安全分析的算法避免自研算法和過時協(xié)議。算法本身不是越復(fù)雜越好能被全世界安全專家反復(fù)審過的算法才更值得信任。3. 混合加密方案與HTTPS握手過程拆解3.1 TLS為什么選擇混合加密TLS協(xié)議從設(shè)計之初就決定了它必須采用混合加密。公開網(wǎng)絡(luò)上不可能預(yù)先給每個客戶端分發(fā)對稱密鑰直接使用非對稱加密又扛不住海量HTTP流量。于是TLS的做法是先通過證書體系驗證服務(wù)器身份再通過密鑰交換算法讓客戶端和服務(wù)器各自算出一個只有雙方知道的會話密鑰最后進入對稱加密階段。理解了這個邏輯你就可以解釋很多工程現(xiàn)象。比如為什么TLS握手階段比數(shù)據(jù)傳輸階段更慢因為握手里涉及非對稱運算。為什么抓包看到的是密文因為真正業(yè)務(wù)數(shù)據(jù)全部走了對稱加密。為什么推薦ECDHE這類臨時密鑰交換算法因為每次握手生成的臨時密鑰用完即棄即使服務(wù)器長期私鑰泄露歷史流量也解不開這就是前向保密的價值。3.2 一次完整握手的核心流程以TLS 1.3為例我把它簡化成三個關(guān)鍵階段來看。第一階段是ClientHello??蛻舳松梢粋€臨時的橢圓曲線密鑰對把公鑰放進Key Share字段發(fā)給服務(wù)器同時附上支持的密碼套件列表。第二階段是ServerHello。服務(wù)器選一個雙方都支持的套件返回自己的臨時公鑰、證書鏈并對當(dāng)前握手消息做簽名。客戶端拿到證書后要驗證證書鏈?zhǔn)欠窨尚?、域名是否匹配、證書是否過期然后用服務(wù)器臨時公鑰和自己的臨時私鑰算出同樣的會話密鑰。第三階段從此刻起雙方已經(jīng)完成密鑰協(xié)商。后面發(fā)送的所有數(shù)據(jù)都用會話密鑰配合對稱加密保護TLS 1.3還引入了單獨的Finished消息用來校驗握手過程的真實性防止中間人篡改握手消息。簡化成一句口訣證書確立身份臨時密鑰交換建立會話密鑰對稱加密保護數(shù)據(jù)。3.3 握手過程中最容易忽略的安全點證書校驗是第一道坎。很多開發(fā)者在聯(lián)調(diào)時為了省事直接把證書校驗關(guān)閉這在生產(chǎn)環(huán)境是巨大的災(zāi)難。一旦跳過證書驗證客戶端就無法確認(rèn)正在通信的是不是真正的服務(wù)器中間人可以拿著任意證書截獲并轉(zhuǎn)發(fā)流量。密碼套件配置也很關(guān)鍵。老舊的TLS 1.0、TLS 1.1協(xié)議以及RC4、CBC類弱套件應(yīng)該直接禁用。TLS 1.3已經(jīng)只保留少數(shù)幾個AEAD套件這是趨勢。如果你的業(yè)務(wù)還在維護老協(xié)議至少要保證默認(rèn)走TLS 1.2以上并優(yōu)先選擇ECDHEAES-GCM。會話密鑰的熵也要關(guān)注??蛻舳撕头?wù)器的隨機數(shù)質(zhì)量直接決定會話密鑰強度任何一方使用了弱隨機數(shù)生成器整個加密鏈路都不可信。這也是為什么服務(wù)端一定要配置足夠的熵源不能依賴系統(tǒng)默認(rèn)的劣質(zhì)隨機算法。4. 實操一條龍密鑰生成、文件加密、混合傳輸4.1 生成并檢查RSA與ECC密鑰實際操作中離不開命令行工具。生成RSA私鑰并導(dǎo)出公鑰兩條命令就能做完openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out rsa_private.pem openssl pkey -in rsa_private.pem -pubout -out rsa_public.pem生成的私鑰文件默認(rèn)是PKCS#8格式已經(jīng)帶上了Base64外殼。查看密鑰細(xì)節(jié)可以用openssl pkey -in rsa_private.pem -text -nooutECC密鑰類似只是指定曲線參數(shù)openssl ecparam -genkey -name prime256v1 -out ecc_private.pem openssl ec -in ecc_private.pem -pubout -out ecc_public.pem生成之后建議立刻做兩件事一是給私鑰設(shè)置強口令保護二是把公鑰單獨導(dǎo)出交給對接方私鑰永遠(yuǎn)不要出現(xiàn)在任何日志或代碼倉庫里。我見過太多次私鑰被當(dāng)普通文本提交到倉庫的翻車事件這一類安全事故的后果基本都是災(zāi)難性的。4.2 用對稱加密加密文件加密單個文件可以先用OpenSSL命令行快速驗證鏈路openssl enc -aes-256-cbc -pbkdf2 -salt -in plain.txt -out encrypted.bin執(zhí)行時會要求輸入口令這個口令通過PBKDF2派生為真正的AES密鑰。加上鹽可以避免相同口令產(chǎn)生相同密鑰從而提高安全性。不過生產(chǎn)環(huán)境我更推薦直接用代碼庫來處理尤其是GCM這類AEAD模式。在Python里使用cryptography庫from cryptography.hazmat.primitives.ciphers.aead import AESGCM import os key AESGCM.generate_key(bit_length256) nonce os.urandom(12) aesgcm AESGCM(key) plaintext bconfidential file content ciphertext aesgcm.encrypt(nonce, plaintext, None) decrypted aesgcm.decrypt(nonce, ciphertext, None) print(decrypted)這段代碼里nonce必須隨機生成并且絕對不能重復(fù)使用。重復(fù)使用同一個nonce加密兩個不同消息會直接破壞GCM的安全性。encrypt返回的密文其實已經(jīng)自動拼接了16字節(jié)的認(rèn)證標(biāo)簽解密時原樣傳入即可。4.3 一個可直接套用的混合加密demo真實業(yè)務(wù)中更常見的需求是把消息加密后傳輸給對方。我用一段Python代碼演示完整混合加密流程。from cryptography.hazmat.primitives.asymmetric import rsa, padding from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.ciphers.aead import AESGCM import os # 接收方生成密鑰對實際項目中從密鑰文件加載 private_key rsa.generate_private_key(public_exponent65537, key_size2048) public_key private_key.public_key() # 1. 生成隨機會話密鑰 session_key os.urandom(32) # 2. 用接收方公鑰加密會話密鑰OAEP填充 encrypted_session_key public_key.encrypt( session_key, padding.OAEP( mgfpadding.MGF1(algorithmhashes.SHA256()), algorithmhashes.SHA256(), labelNone ) ) # 3. 用會話密鑰和AES-GCM加密業(yè)務(wù)數(shù)據(jù) aesgcm AESGCM(session_key) nonce os.urandom(12) ciphertext aesgcm.encrypt(nonce, bbusiness data, None) # 4. 組裝包加密會話密鑰 nonce 密文 packet encrypted_session_key nonce ciphertext # 接收方反解 decrypted_session_key private_key.decrypt( encrypted_session_key, padding.OAEP( mgfpadding.MGF1(algorithmhashes.SHA256()), algorithmhashes.SHA256(), labelNone ) ) aesgcm_receiver AESGCM(decrypted_session_key) plaintext aesgcm_receiver.decrypt(nonce, ciphertext, None) print(plaintext)這個demo的思路和HTTPS的混合加密本質(zhì)上是完全一致的。會話密鑰隨機生成長度32字節(jié)AES-GCM完成高效加密RSA-OAEP負(fù)責(zé)會話密鑰的安全傳輸。實際落地時建議把公鑰存成PEM文件從外部加載不要每次都現(xiàn)場生成密鑰對非對稱密鑰應(yīng)該是穩(wěn)定的不是每次請求都換一把。4.4 參數(shù)選擇的幾個硬性建議密鑰長度不能將就。RSA低于2048位我建議直接放棄AES-128可以接受但敏感數(shù)據(jù)優(yōu)先AES-256SM4密鑰長度固定128位合規(guī)場景下按標(biāo)準(zhǔn)執(zhí)行就好。nonce和IV必須隨機且唯一。AES-GCM的nonce標(biāo)準(zhǔn)長度是12字節(jié)也就是96位推薦由密碼學(xué)安全隨機數(shù)生成器產(chǎn)生。不要用時間戳、自增ID這類可預(yù)測值當(dāng)nonce這會打開災(zāi)難性的口子。填充模式必須和算法匹配。AES-CBC需要PKCS7填充RSA加密用OAEPRSA簽名用PSS。把各種模式混著配程序大概率直接拋異常就算不報錯也埋下了安全隱患。編碼也是一個容易翻車的環(huán)節(jié)。密文是二進制網(wǎng)絡(luò)傳輸、JSON序列化時要用Base64或Hex編碼不能直接把二進制塞進字符串。解碼時也要注意Base64是否包含換行、URL安全字符替換這類細(xì)節(jié)。5. 高頻報錯與排查技巧實錄5.1 五類高頻報錯及處理報錯信息典型原因處理方式pem routines:get_name:no start line密鑰文件不是合法PEM或內(nèi)容被截斷/錯誤解碼檢查文件首尾是否有完整BEGIN/END行確認(rèn)沒有混入換行或字符unsupported paddingRSA填充模式不匹配統(tǒng)一使用OAEP加密、PSS簽名并確認(rèn)兩端算法一致Wrong final block lengthCBC模式密文長度不是分組的整數(shù)倍或被截斷檢查密文是否完整Base64解碼后長度是否對得上Tag verification failedGCM認(rèn)證標(biāo)簽校驗失敗密文被篡改或nonce錯誤確認(rèn)密文、nonce、關(guān)聯(lián)數(shù)據(jù)是否被改動優(yōu)先檢查解密輸入key size must be 128 or 256 bitsAES密鑰長度不符合要求檢查密鑰是不是被錯誤編碼Base64串是否忘了解碼成原始字節(jié)這些報錯里GCM的Tag驗證失敗最值得警惕。它不一定是代碼寫錯了也可能是密文在傳輸過程中被別人動過手腳。遇到這個錯誤先把日志拉出來檢查密文包是否完整再從鏈路中間件排查有沒有被篡改不要急著改代碼。5.2 問題定位的常用套路加密問題排查和普通業(yè)務(wù)Bug不太一樣它不是看一眼堆棧就能解決的核心難點在于你處理的大多是二進制數(shù)據(jù)日志打不出來中間過程也很難直觀檢查。我的經(jīng)驗是先分層驗證。第一步用命令行工具獨立驗證硬件和算法鏈路比如用openssl先生成密鑰、加密、解密確認(rèn)這條鏈路是通的。第二步寫最小化代碼腳本只做內(nèi)存中加解密排除網(wǎng)絡(luò)、序列化、存儲干擾。第三步再接入完整業(yè)務(wù)流程這個時候如果還有問題基本就能鎖定是某一段數(shù)據(jù)裝配或編碼環(huán)節(jié)出了問題。調(diào)試時還要善于用十六進制視圖。二進制數(shù)據(jù)用print打出來是一堆亂碼完全沒法判斷。正確做法是把每一段關(guān)鍵中間結(jié)果轉(zhuǎn)成Hex輸出一次就能看出長度對不對、數(shù)據(jù)有沒有被截斷。加日志也有講究。密鑰、IV、nonce這些敏感信息絕對不能直接打到日志里但可以記錄它們各自的長度、來源、生成時間以及長度校驗結(jié)果。長度對不上往往比內(nèi)容對不上更容易定位問題。5.3 幾個我自己踩過的坑有一次做接口聯(lián)調(diào)對方反饋解密一直失敗報的是padding錯誤。我檢查了代碼RSA填充模式確實是OAEP密鑰也完全一致。折騰了半天最后發(fā)現(xiàn)是對方在把密鑰從JSON解析出來時Base64字符串里的換行符被JSON解析吃掉了導(dǎo)致整個公鑰內(nèi)容不完整解析出來的密鑰根本是殘缺的。還有一次AES-GCM在測試環(huán)境一直正常一上生產(chǎn)就偶發(fā)解密失敗。后來定位到是生產(chǎn)環(huán)境緩存層對key做了序列化處理把密文的尾字節(jié)截斷了。GCM的認(rèn)證標(biāo)簽在密文末尾少一個字節(jié)都會導(dǎo)致Tag驗證失敗。從那以后我養(yǎng)成了一個習(xí)慣凡是經(jīng)過緩存、消息隊列、數(shù)據(jù)庫的二進制字段必須檢查底層存儲類型是否支持完整二進制內(nèi)容不能默認(rèn)所有中間件都能原樣搬運byte數(shù)組。另外要提醒大家注意一個數(shù)學(xué)層面的坑用RSA加密時能加密的明文長度上限是密鑰字節(jié)數(shù)減掉填充開銷2048位密鑰只能加密約190字節(jié)。很多人沒意識到這一點直接拿RSA去加密幾百字節(jié)的業(yè)務(wù)數(shù)據(jù)結(jié)果程序報錯或者發(fā)明各種奇怪的拆分方案。正確的做法永遠(yuǎn)是用RSA保護會話密鑰用會話密鑰保護業(yè)務(wù)數(shù)據(jù)。6. 做加密方案設(shè)計時容易忽略的邊界6.1 密鑰生命周期管理很多開發(fā)者把精力都花在算法和模式選擇上卻忽略了密鑰本身是需要管理的。密鑰從生成、存儲、使用、輪換到銷毀每一個環(huán)節(jié)都可能成為安全短板。密鑰不應(yīng)該出現(xiàn)在源碼里更不應(yīng)該出現(xiàn)在配置文件里并跟隨倉庫一起分發(fā)。正確的做法是放在獨立的密鑰管理系統(tǒng)、硬件安全模塊或云上的密鑰管理服務(wù)里應(yīng)用運行時通過權(quán)限受控的接口獲取。密鑰還要定期輪換一旦懷疑泄露就要立即吊銷并簽發(fā)新密鑰。證書有效期到期的場景大家都熟悉但業(yè)務(wù)自定義的非對稱密鑰對往往沒人管過期一用就是好幾年這其實非常危險。6.2 認(rèn)證、機密性、完整性三者缺一不可加密并不等于安全。單純的加密算法只解決機密性問題它不能防止數(shù)據(jù)被篡改也不能證明數(shù)據(jù)來自合法發(fā)送方。很多方案里開發(fā)者費了半天勁加密了數(shù)據(jù)卻沒有做完整性校驗結(jié)果攻擊者隨便翻轉(zhuǎn)幾個bit接收方解出來的內(nèi)容已經(jīng)面目全非程序卻完全感知不到。這就是我對AEAD模式情有獨鐘的原因。AES-GCM一份代碼同時解決機密性和完整性附帶的認(rèn)證標(biāo)簽直接暴露數(shù)據(jù)是否被改動。而在混合加密方案里如果還需要確認(rèn)發(fā)送方身份就應(yīng)該再用發(fā)送方私鑰對數(shù)據(jù)做一次簽名形成簽名加密的組合。簽名確認(rèn)來源加密保護內(nèi)容認(rèn)證標(biāo)簽防篡改三者各司其職缺一不可。6.3 最后聊幾點體會做了幾年加密相關(guān)工作最大的感受是永遠(yuǎn)不要自己發(fā)明加密協(xié)議。密碼學(xué)發(fā)展到現(xiàn)在經(jīng)過全世界頂尖研究者反復(fù)分析過的算法和標(biāo)準(zhǔn)協(xié)議已經(jīng)足夠好用了普通業(yè)務(wù)真正要做的不是設(shè)計算法而是正確組裝組合方案并保證密鑰管理安全。那些宣稱不可破解的自研算法最后幾乎都成了安全界的笑話。隨機數(shù)質(zhì)量也是經(jīng)常被低估的一環(huán)。很多語言默認(rèn)的隨機數(shù)生成器不適合用于加密一定要使用專門的密碼學(xué)安全隨機數(shù)生成接口比如Python里的os.urandom和加密庫提供的生成函數(shù)。隨機性不是看起來隨機而是不可預(yù)測這兩者有著本質(zhì)區(qū)別。最后一個小建議把常用的加解密流程封裝成統(tǒng)一的標(biāo)準(zhǔn)模塊對外只暴露加密、解密、簽名、驗簽四個接口。這樣業(yè)務(wù)方不需要關(guān)心底層RSA還是ECC、GCM還是CBC安全團隊也可以集中精力在一個受控的模塊里做審計和加固。加密是手段不是目的能讓人用對、用好才是有價值的工程實踐。