題:
關於加密和密碼學到的經驗教訓和誤解
goodguys_activate
2011-02-20 01:25:34 UTC
view on stackexchange narkive permalink

密碼學是一個廣泛的主題,即使經驗豐富的編碼人員也幾乎總是會在前幾次出現錯誤。但是加密是一個非常重要的主題,通常我們無法承擔這些錯誤。

該問題的目的是識別並列出與給定算法或API無關的 。這樣,我們可以從他人的經驗中學習並防止不良做法的傳播。

為使該問題具有建設性,請

  1. 包括一個“錯誤的”示例
  2. 說明該示例出了什麼問題
  3. 提供正確的實現(如果適用)。
  4. 盡您所能,提供有關上面#2和#3的參考。
  5. ol>
最常見的錯誤不是代碼中的錯誤,而是關於如何使用加密技術的誤解。換句話說,開發人員可能會以任何語言犯同樣的錯誤。因此,我建議擴大問題範圍,以免過於關注代碼。大多數錯誤是概念錯誤,而不是編碼缺陷。
即使答案被接受,也要繼續增加經驗教訓。至少它將具有教育意義。
另外,Colin Percival(tarsnap)的簡短演示:http://www.bsdcan.org/2010/schedule/attachments/135_crypto1hr.pdf
如果您需要閱讀“不做”列表,請不要做加密。請專門研究密碼學的安全工程師來幫助您。 :)
相關的元討論:[在“滾動自己的密碼”與“實施標準”之間進行澄清](http://meta.security.stackexchange.com/q/1119/396)
如果您認為不需要準備“不要做”列表,則在大多數情況下不要進行加密(https://en.wikipedia.org/wiki/Dunning%E2%80%93Kruger_effect)-Dave確信他的執行是安全的。
即使此問題涵蓋了一些非常重要的問題,但它的格式也不適合SE網站,因為它基本上是在輪詢“ X列表”,但效果不佳。
21 答案:
D.W.
2011-02-20 09:52:34 UTC
view on stackexchange narkive permalink

不要投放自己的加密貨幣。

不要發明自己的加密算法或協議;那是極容易出錯的。就像布魯斯·施耐爾(Bruce Schneier)喜歡說的那樣,

“任何人都可以發明一種他們自己無法破解的加密算法;要發明一種別人都無法破解的加密算法要困難得多”。

加密算法非常複雜,需要進行嚴格審查以確保其安全性;如果您發明了自己的產品,那麼您將一事無成,並且很容易在沒有意識到的情況下得到一些不安全的東西。

相反,請使用標準的加密算法和協議。可能是別人之前曾遇到您的問題,並為此目的設計了合適的算法。 );對於靜態數據,請使用GPG(或PGP)。如果您無法做到這一點,請使用高級加密庫,例如 cryptlib,GPGME, Keyczar NaCL,而不是低級的,例如OpenSSL,CryptoAPI,JCE等。感謝Nate Lawson的建議。

實際上,這應該是規則編號1-這會使我們所有其他規則無效。世界上可能只有數百個人應該設計或實現加密貨幣。我們其餘的人應該只使用他們(合理的)API。
.NET開發人員的最佳選擇是什麼?有教程或示例嗎?對於非加密專家而言,很難根據有效信息確定錯誤信息。
對於過去解決難題的創意工程師而言,將加密技術留給其他人尤其具有誘惑力。在加密貨幣之外,仍然存在許多難以解決的棘手問題。看一些在加密方面犯了嚴重錯誤並解決其他問題的人的例子。
+1 Crypto API提供了太多的靈活性,可能使外行開發人員陷入困境。互聯網上(和MSFT的支持站點)上有許多樣本至少違反了此頁面上所學到的一課。一些開發人員忘記考慮諸如如何交換,驗證和撤銷密鑰之類的事情。這就是棘手的地方。鑰匙在哪裡?密鑰如何發布?如何驗證密鑰?鑰匙輪換如何完成?即使開發人員很幸運地掌握了正確的數學方法或功能組合(CBC,塊,流等),該協議也可能被破壞。
對於.net的高級選項,我已經將[keyczar移植到C#](http://jbtule.github.com/keyczar-dotnet/)。
當我們看到[this](http://www.isg.rhul.ac.uk/tls/)時,沒有精美印刷品的“使用TLS”並不是一個好主意。
不發明密碼不是密碼學的原則,也不是濫用某些現有的API或算法。
D.W.
2011-02-20 09:36:29 UTC
view on stackexchange narkive permalink

未經消息身份驗證就不要使用加密

在不對數據進行身份驗證的情況下加密數據是一個非常常見的錯誤。

示例:開發人員想要對消息保密,因此請使用AES-CBC模式對消息進行加密。錯誤:在存在主動攻擊,重播攻擊,響應攻擊等情況下,這不足以確保安全。存在已知的未經消息身份驗證的加密攻擊,這些攻擊可能非常嚴重。解決方法是添加消息身份驗證。

此錯誤已導致在使用未經身份驗證的加密的已部署系統(包括 ASP.NET XML a)中存在嚴重漏洞。 > 加密 Amazon EC2 JavaServer Faces,Ruby on Rails,OWASP ESAPI IPSEC WEP ASP.NET SSH2。您不想成為此列表中的下一個。

為避免這些問題,每次應用加密時都需要使用消息身份驗證。您有兩種選擇方法:

  • 可能最簡單的解決方案是使用提供經過身份驗證的加密的加密方案,例如GCM, CWC,EAX,CCM,OCB。 (另請參閱: 1。)經過身份驗證的加密方案將為您處理此問題,因此您不必考慮它。

  • 或者,您可以按照以下方式應用自己的消息身份驗證。首先,使用適當的對稱密鑰加密方案(例如AES-CBC)對消息進行加密。然後,獲取整個密文(包括解密所需的任何IV,隨機數或其他值),應用消息身份驗證代碼(例如AES-CMAC,SHA1-HMAC,SHA256-HMAC),並將生成的MAC摘要附加到傳輸前的密文。在接收端,解密之前請檢查MAC摘要是否有效。這稱為加密然後認證結構。 (另請參見: 1 2。)這也可以正常工作,但需要您多加註意。

C#和Java用戶應查看[BouncyCastle](http://www.bouncycastle.org/csharp/)
@makerofthings7: GCM加密包含在Java 7的Oracle提供程序中。它也建議用於TLS(在RFC內)和XML加密v1.1。有彈性的實現與Sun提供程序中的實現兼容(除了有關經過身份驗證的數據和拋出的確切異常方面的差異)。
對於那些不了解密碼的人(因此請閱讀這篇文章),“身份驗證”與“登錄”或使用您的憑據無關。有點像校驗和。實際上,數學和處理過程的結合最終所要做的不僅僅是簡單地對數據進行校驗和。 (@D.W。您如何看待這個外行的解釋?)
@makerofthings7,很棒的解釋!如果本文提到的是“消息身份驗證”,而不僅僅是通用身份驗證,可能會更加清楚。我現在進行更改。
D.W.
2011-02-20 11:29:57 UTC
view on stackexchange narkive permalink

在散列之前連接多個字符串時要小心。

我有時會看到一個錯誤:人們想要對字符串S和T進行散列。他們將它們串聯以得到一個單個字符串S || T,然後對其進行哈希處理以獲得H(S || T)。這是有缺陷的。

問題:串聯使兩個字符串之間的邊界不明確。示例:內置 || 安全 = 內置 || 不安全。換句話說,哈希H(S || T)不能唯一地標識字符串S和T。因此,攻擊者可以在不更改哈希的情況下更改兩個字符串之間的邊界。例如,如果愛麗絲想安全地發送兩個字符串 builtin ,則攻擊者可以將它們更改為兩個字符串 builtin

不安全地而不使哈希無效。

將數字簽名或消息身份驗證代碼應用於字符串串聯時,也會出現類似的問題。

解決方法:而不是簡單的串聯,使用一些明確可解碼的編碼。例如,代替計算H(S || T),您可以計算H(length(S)||| S || T),其中length(S)是32位值,表示S的長度(以字節為單位)。或者,另一種可能性是使用H(H(S)|| H(T)),甚至使用H(H(S)|| T)。

有關此缺陷的真實示例,請參見 Amazon Web Services中的此缺陷 Flickr中的此缺陷 [pdf]。

我通常會向其扔HMAC。稍微貴一點,但是至少我不需要自己實現它。
@CodeInChaos,這些問題同樣適用於HMAC。如果在將多個字符串提供給HMAC之前將它們串聯起來,HMAC不會有任何幫助。
我的意思是我將一個用作密鑰,將另一個用作消息。
@CodeInChaos,很好,如果您對加密技能有足夠的信心來避免缺陷,請使用任何適合您的方法。就個人而言,我不會向其他人推薦這種方法。 (1)這不是HMAC設計的目的,因此,如果碰巧是安全的,您會“很幸運”。 (2)僅限於兩個字段。如果您有三個字段,則必須做一些更複雜的事情。因此最好一開始就使用適當的防禦措施,例如使用明確可解碼的編碼(例如,在要連接的每個字段之前加長)。
H(H(S)|| H(T))怎麼樣?由於H()的輸出是固定長度,因此您將無法移動邊界。另外,使用散列作為連接的輸入,實際上很難將其中一個輸入的一側的字符串操縱為所需的值。我看到的唯一缺點是,現在您正在執行3個哈希,而不是一個。但是,哈希值應該很慢,所以畢竟這不是一件壞事;)
@Marcin,是的,這是另一種合理的方法。我已將您的建議添加到我的答案中。謝謝你的建議! (在某些不太明顯的情況下,這不是一個好的解決方案,例如,S是秘密,H(S)是公共知識,T是挑戰,其目的是讓發送者證明S的知識通過傳回S和T的哈希值-但我不必擔心那些非常罕見的特殊情況。)
@Marcin“ _哈希應該很慢_”不,它們“不應該”很慢,並且它們“不應該”很慢
這裡的要求是清楚地知道邊界:hash-concatenate-hash方法要求您至少對一個元素以外的所有對象進行哈希處理-可以將已知位置中的一個元素保留為非哈希。因此,如果這是用於身份驗證的已知數量,則可以避免使用H(S)-代替使用S而是對所有其他分量進行哈希處理。無論如何,要小心,因為基礎數學可能會在串聯和重新哈希的變體中咬你。
我是crypto-n00b,所以這可能是一個愚蠢的問題,但是,如果您嘗試獲取兩個字符串“ builtin”和“ securely”的哈希,為什麼不使用哈希H(`builtin` ||| [somedelimiter ] ||`安全地`)?
@Matt,是的,可以工作!但是,您必須在這些字符串中轉義定界符的任何實例(否則,不可避免地,有人會鍵入包含定界符的字符串,然後這種方法會崩潰)。這增加了替代方案所沒有的複雜性。如果您向其他人推薦此方法,那麼不可避免地會有一個觀眾忘記轉義分隔符。如果他們忘記轉義分隔符,則該方案會悄悄地失敗:這是不安全的,但在正常操作中他們可能不會注意到這一點。所以,是的,它可以工作-但這可能不是我的首選。
H(json_encode(array(“ builtin”,“ securely”))))可以做到。和@penguat。 Realex Payments在處理信用卡時使用該形式的哈希:“ H(H(various)| secret)”。
哇???這個答案沒有道理。如果數據是模棱兩可的,則不必是攻擊者。愛麗絲不知道該如何“安全地構建”,因為鮑勃沒有在空格中放任何東西。這種歧義不是攻擊者引入的問題,而是選擇的數據表示中固有的。如果不能分類,我們怎麼消化?每條超過一比特長的消息都是一個鏈接。
-1
@D.W。我說過加密嗎?我的意思是寫“摘要”。在那裡,修復它。好東西讓我們在撰寫評論後數小時對其進行編輯。
好的,所以我們有兩個字符串“ builtin”和“ securely”。我們將它們放在一起,這樣就不會“安全地構建”邊界。無論如何,在消息中根本沒有表示分歧所在。沒有成幀的位或字節,沒有長度字段,什麼都沒有。然後我們對其進行哈希處理。因此,現在攻擊者“改變了邊界”。攻擊者如何“改變”不存在的*?
而且,如果我將兩個部分放在一起並對其進行哈希處理,那我不是在串接字符串嗎?因此,我們必須分別哈希每個位,以便對其進行標識。我們不希望攻擊者在位之間移動邊界,以使00 1突然變為0 11。
我已經看過幾次@Kaz,案例:發送者發送的消息分為兩部分,“內置”和“安全”。消息是明文,並且在消息中,劃分是明確的。為了保護其完整性,發送方在消息部分的串聯上附加MAC或哈希或簽名。缺陷:中間人可以將內置/安全的消息更改為內置/不安全的消息;兩者俱有相同的哈希/簽名/ MAC,因此收件人無法檢測到它。閱讀我鏈接到的兩個示例(AWS和Flickr)以更詳細地了解這種情況。是的,這確實是一個缺陷。
-1
Alex Holst
2011-02-20 02:11:32 UTC
view on stackexchange narkive permalink

請勿重用隨機數或IV

許多操作模式都需要IV(初始化向量)。您絕不能為IV重複使用相同的值。這樣做會取消所有安全保證,並造成災難性的安全破壞。

  • 對於流密碼操作模式(例如CTR模式或OFB模式),重新使用IV安全災難。

  • 對於其他操作模式,例如CBC模式,重新使用IV在某些情況下還可以促進明文恢復攻擊。 。

無論您使用哪種操作模式,都不應重複使用IV。如果您想知道如何正確執行操作,請參閱 NIST規範,其中提供了有關如何正確使用分組密碼操作模式的詳細文檔。這個陷阱。 Tarsnap通過將備份數據分成多個塊來加密,然後在CTR模式下使用AES加密每個塊。在1.0.22至1.0.27的Tarsnap版本中,無意中重複使用了相同的IV,從而實現了純文本恢復。

這是怎麼發生的?為了簡化Tarsnap代碼-並希望減少錯誤的可能性-Colin Percival藉此機會將AES-CTR代碼“重構”為一個新文件(Tarsnap源代碼中的lib / crypto / crypto_aesctr.c) ),並修改了使用AES-CTR來利用這些例程的現有位置。新代碼如下所示:

 / *加密數據。 * /-aes_ctr(&encr_aes-> key,encr_aes-> nonce ++,buf,len,-filebuf + CRYPTO_FILE_HLEN); + if(((stream = + crypto_aesctr_init(&encr_aes-> key,encr_aes-> nonce))== NULL)+ goto err0; + crypto_aesctr_stream(stream,buf,filebuf + CRYPTO_FILE_HLEN,len); + crypto_aesctr_free(stream); 

在重構過程中, encr_aes->nonce ++ 意外地變成了 encr_aes->nonce ,結果相同的隨機數被重複使用 >。特別是,在加密每個塊之後,CTR隨機數值不會增加。 (在處理完每16個字節的數據後,CTR計數器會正確遞增,但是對於每個新塊,此計數器都將重置為零。)Colin Percival在以下內容中描述了完整的詳細信息: http://www.daemonology.net /blog/2011-01-18-tarsnap-critical-security-bug.html

由於問題集中在隨機數上,因此請嘗試將該結果的標題設為(+1);問:隨機數通常是++,還是隨機的?
@makerofthings,取決於算法。某些算法和操作模式需要隨機隨機數(例如CBC模式);其他的僅要求隨機數是不同的,因此計數器就足夠了(例如CTR模式)。希望算法/操作模式的規範可以描述所需的內容。
我建議對答案進行編輯以包括IV。正確的IV /隨機數用法非常相似。
一次是N。是的,僅使用變量N一次。單數。不要重複。重複N會損害相關算法的強度。
這是一個錯誤的示例:WEP實現的RC4具有24位隨機數,每條消息後該數值都會增加。這帶來了兩個問題:(1)發送2 ^ 24個數據包後,重用了隨機數。 (2)RC4並非設計為具有“緊密相關”的隨機數,因為已知每個後續密碼都是前一個密碼的++。
這是一個正確的示例:假設加密設計人員不想將同一密鑰用於多個消息。一種解決方案是生成一個密鑰並使用PRG對其進行擴展。然後僅將x的每個倍數用作密鑰。其中細分1 ==鍵1,細分2 ==鍵2。
D.W.
2011-02-20 10:06:23 UTC
view on stackexchange narkive permalink

確保為隨機數生成器提供足夠的熵。

確保將加密強度的偽隨機數生成器用於生成密鑰,選擇IV /隨機數等操作。 。不要使用 rand() random() drand48()

請確保您用足夠的熵播種偽隨機數生成器。不要在一天中的任何時候播種。

示例: srand(time(NULL))非常糟糕。播種PRNG的一個好方法是從例如 / dev / urandom ,CryptGenRandom或類似的代碼中獲取128位或真隨機數。在Java中,請使用SecureRandom,而不要使用Random。在.NET中,請使用System.Security.Cryptography.RandomNumberGenerator,而不要使用System.Random。在Python中,請使用random.SystemRandom,而不是random。感謝Nate Lawson的一些示例。

真實示例:請參見 Netscape瀏覽器早期版本中的此缺陷,它允許攻擊者破壞SSL。

我記得在Apple上學習Basic [e。我正在編寫遊戲,需要一些隨機輸入,所以我使用了RND(1)。我必須不斷重新啟動才能調試遊戲,我注意到隨機元素在啟動後總是按照相同的順序進行。那時我了解了偽隨機數生成器。如果需要一些隨機種子,Random.org可提供基於大氣噪聲的免費隨機數生成。
Random.org最適合用於模擬和其他非安全目的。 Random.org並不是加密PRNG種子的良好基礎,因為您不能相信其他人不知道它。
goodguys_activate
2011-02-20 01:34:06 UTC
view on stackexchange narkive permalink

請勿將帶有ECB的分組密碼用於對稱加密

(適用於AES,3DES等)

此處是帖子和非常相似的 Microsoft KB文章,有關ECB模式如何導致未加密的代碼。

另請參見 Rook

純文本消息中的此類似帖子

alt text

使用ECB模式加密的同一條消息(使用的密碼無關緊要):alt text

使用CBC模式完全相同的消息(同樣,什麼都沒關係您使用的密碼):alt text

錯誤的方式

 公共靜態字符串Encrypt(字符串toEncrypt,字符串密鑰,布爾值使用哈希){ byte [] keyArray = UTF8Encoding.UTF8.GetBytes(key); byte [] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt); if(useHashing)keyArray = new MD5CryptoServiceProvider()。ComputeHash(keyArray); var tdes = new TripleDESCryptoServiceProvider( ){Key = keyArray,Mode = CipherMode.ECB,Padding = PaddingMode.PKCS7}; ICryptoTransform cTransform = tdes.CreateEncryptor(); byte [] resultArray = cTransform.TransformFinalBlock(toEncryptArray,0,toEncryptArray.Length);返回Convert.ToBase64String (resultArray,0,resultArray.Length);}  

錯誤在以下行中

{鍵= keyArray,模式= CipherMode.ECB ,填充= PaddingMode.PKCS7};


正確的方法

Microsoft的好夥伴向我發送了以下代碼,以更正上面鏈接的KB文章。案例號111021973179005

中對此進行了引用

此示例代碼使用AES加密數據,並且AES加密的密鑰是SHA256生成的哈希碼。 AES是高級加密標準(AES)算法。 AES算法基於排列和替換。排列是數據的重新排列,而替換則將一個數據單元替換為另一個數據單元。 AES使用幾種不同的技術執行置換和替換。有關AES的更多詳細信息,請參閱 http://msdn.microsoft.com/zh-cn/magazine/cc164055.aspx 。

SHA是安全哈希算法。現在建議使用SHA-2(SHA-224,SHA-256,SHA-384,SHA-512)。有關.NET Framework中哈希值的更多詳細信息,請參考 http://msdn.microsoft.com/zh-cn/library/92f9ye3s.aspx#hash_values

AesCryptoServiceProvider 的對稱算法的操作模式的默認值為CBC。 CBC是密碼塊鏈接模式。它介紹了反饋。在對每個純文本塊進行加密之前,通過按位異或運算將其與前一個塊的密文組合在一起。這樣可以確保即使純文本包含許多相同的塊,它們也將各自加密為不同的密文塊。在對該塊進行加密之前,通過按位異或運算將初始化向量與第一個純文本塊組合在一起。如果密文塊的單個位被修改,則相應的明文塊也將被修改。此外,後續塊中與原始錯位相同的位也將被錯位。有關 CipherMode 的更多詳細信息,請參考 http://msdn.microsoft.com/zh-cn/library/system.security.cryptography.ciphermode.aspx

這是示例代碼。

  //此功能用於使用密鑰和iv加密數據。
byte [] Encrypt(byte [] data,byte [] key,byte [] iv){//創建一個AESCryptoProvider。使用(var aesCryptoProvider = new AesCryptoServiceProvider()){//用密鑰和iv初始化AESCryptoProvider。 aesCryptoProvider.KeySize = key.Length * 8; aesCryptoProvider.IV = iv; aesCryptoProvider.Key =鍵; //從AESCryptoProvider創建加密器。使用(ICryptoTransform encryptionor = aesCryptoProvider.CreateEncryptor()){//創建內存流以存儲加密的數據。使用(MemoryStream stream = new MemoryStream()){//創建一個CryptoStream來加密數據。使用(CryptoStream cryptoStream = new CryptoStream(流,加密器,CryptoStreamMode.Write))//加密數據。 cryptoStream.Write(data,0,data.Length); //返回加密的數據。返回stream.ToArray(); }}}} //此函數用於通過密鑰和iv.byte [] Decrypt(byte [] data,byte [] key,byte [] iv){//創建AESCryptoServiceProvider。使用(var aesCryptoProvider = new AesCryptoServiceProvider()){//用密鑰和iv初始化AESCryptoServiceProvier。 aesCryptoProvider.KeySize = key.Length * 8; aesCryptoProvider.IV = iv; aesCryptoProvider.Key =鍵; //從AESCryptoServiceProvider創建解密器。使用(ICryptoTransform解密器= aesCryptoProvider.CreateDecryptor()){//創建一個包含加密數據的內存流。使用(MemoryStream stream = new MemoryStream(data)){//創建一個CryptoStream來解密加密的數據。使用(CryptoStream cryptoStream = new CryptoStream(流,解密器,CryptoStreamMode.Read)){//創建一個字節緩衝區數組。
byte [] readData =新的byte [1024]; int readDataCount = 0; //創建一個內存流來存儲解密的數據。使用(MemoryStream resultStream = new MemoryStream()){do {//解密數據並將數據寫入readData緩衝區數組。 readDataCount = cryptoStream.Read(readData,0,readData.Length); //將解密的數據寫入resultStream。 resultStream.Write(readData,0,readDataCount); } //檢查流中是否還有其他加密數據。 while(readDataCount > 0); //返回解密的數據。返回resultStream.ToArray(); //此函數用於使用UTF8編碼和SHA256哈希算法生成有效的密鑰二進製文件。byte [] GetKey(string key){//創建SHA256哈希算法類。使用(SHA256Managed sha256 = new SHA256Managed())//將字符串密鑰解碼為二進制併計算密鑰的哈希二進制。返回sha256.ComputeHash(Encoding.UTF8.GetBytes(key));}  

有關示例代碼中類的更多詳細信息,請參考以下鏈接:

· AesCryptoServiceProvider類

· SHA256託管類

· CryptoStream類

此外,還有幾篇文章可能有助於更好地理解.NET Framework中的加密,請參考以下鏈接:

·加密服務

· .NET Framework加密模型

·加密的簡單指南

·不使用加密即可秘密

我建議刪除“正確方法”之後的所有內容。 Coda Hale的建議有許多缺點。它會產生一些我在其他答案中記錄的錯誤:它使用沒有消息身份驗證的加密(嚴重的缺陷),將密鑰創建為密碼的哈希(嚴重的缺陷),沒有嘗試減慢詳盡的密鑰搜索(另一個嚴重缺陷)。我對答案的正確處理建議在答案的最後一段中描述,標題為“不要自行加密”。
我建議刪除“免責聲明”和“一些要點”之後的所有內容。我認為其中大多數與您避免使用歐洲央行的高級觀點無關,並且會分散您的注意力。簡明扼要。相反,我建議您以正確的方式提出建議:使用安全的操作模式,例如CBC模式或CTR模式。不要忘記遵循此頁面上的其他建議,包括使用消息身份驗證,適當地生成密鑰等。如果要將其設為社區Wiki,我很樂意相應地編輯此答案。
@D.W。是的,可以隨時將任何或所有答案編輯為CW。我不想讓CW整個問題都想激勵海報,但我會把這個決定留給大家。我只想學習正確的東西,而不學習不良做法
請注意,在Java中,使用 / ECB / PKCS5Padding作為默認設置(例如`Cipher.getInstance(“ AES”)`)的Java更容易出錯,如果切換到CBC,它將使用歸零IV (或多或少是NONCE,請參閱有關答案)默認情況下也是如此。
您如何加密圖像?
@Matt,表示該圖像是成功攻擊的結果。給定一個名為TUX.BMP的文件,假定攻擊者將嘗試查看它,但發現它已加密。然後,他查看加密的字節,並在看到非隨機模式後懷疑CBC。然後,他用已知良好的BMP文件頭替換前幾個塊,並對其進行調整,直到行和列對齊為止。幾年前,我在Blackhat看到一位研究人員使用一種工具來進行此操作,我認為該工具稱為rumint。
D.W.
2011-02-20 09:50:34 UTC
view on stackexchange narkive permalink

不要對加密和身份驗證使用相同的密鑰。

不要將密鑰用於多種用途;

例如,如果您有一個RSA私鑰/公鑰對,則不應同時將其用於加密(使用公鑰加密,使用私鑰解密)。

以及用於簽名(使用私鑰簽名,使用公鑰進行驗證):選擇一個目的並將其僅用於該目的。如果您同時需要這兩種能力,請生成兩個密鑰對,一個用於簽名,一個用於加密/解密。

類似地,對於對稱密碼,您應該使用一個密鑰進行加密,並使用單獨的獨立密鑰進行消息認證。請勿將相同的密鑰用於這兩個目的。

s / MIME是否違反此建議? AFAIK我只有一個密鑰,並且可以簽名和加密。
恕我直言,在兩種用法中使用相同密鑰的最大問題來自執法問題。現在,在許多轄區中,您都被要求交出加密密鑰,這實際上意味著它們可以登錄您的名字。
是的,很多算法使用相同的密鑰對進行簽名和加密,PGP和S / MIME是明顯的示例。這不一定是數學問題。
PGP **不**使用相同的密鑰對進行簽名和加密。而是,PGP私鑰由用於簽名的主密鑰和用於加密的一個或多個子密鑰組成。子鍵對用戶是隱藏的,因此很混亂,但是您可以使用`gpg --list-secret-keys`查看它們。
Chris Dale
2012-06-25 16:46:15 UTC
view on stackexchange narkive permalink

Kerckhoffs的原理:密碼系統應該是安全的,即使除密鑰之外,系統中的所有內容都是公共知識

錯誤的示例: LANMAN哈希

如果沒有人知道該算法,將很難弄清LANMAN哈希,但是一旦知道了該算法,現在破解起來就很容易了。

算法如下(來自維基百科):

  1. 用戶的ASCII密碼轉換為大寫。
  2. 此密碼為空,填充為14個字節
  3. “固定長度”密碼分為兩個七個字節的半個部分。
  4. 這些值用於創建兩個DES密鑰,一個從每個7字節的一半開始
  5. 兩個密鑰中的每個密鑰都用於對ASCII常量字符串KGS!@#$%進行DES加密,從而得到兩個8字節的密文值。
  6. 將這兩個密文值連接起來以形成一個16字節的值,即LM哈希值
  7. ol>

    因為您現在知道了這些事實的密文,所以您現在可以容易地將密文分為兩個密文,您知道它們是大寫的,從而導緻密碼可能是一組有限的字符。

    正確的示例: AES加密

  • 已知算法
  • 隨著技術的發展而擴展。需要更多加密功能時增加密鑰大小
D.W.
2011-02-20 11:39:43 UTC
view on stackexchange narkive permalink

嘗試避免使用密碼作為加密密鑰。

在許多系統中,常見的缺點是使用密碼或密碼短語,或密碼或密碼短語的哈希,例如加密/解密密鑰。問題在於,這往往很容易受到離線鍵搜索攻擊的影響。大多數用戶選擇的密碼沒有足夠的熵來抵抗這種攻擊。

最好的解決方法是使用真正隨機的加密/解密密鑰,而不是確定性地從密碼/口令生成的密鑰。

但是,如果您必須使用基於密碼/密碼的密碼,請使用適當的方案來減慢詳盡的按鍵搜索。我建議 PBKDF2,它使用迭代哈希(沿H(H(H(.... H(password)...))的行))來減慢字典搜索的速度。安排使用足夠多的迭代來使此過程在用戶的計算機上花費例如100ms的時間來生成密鑰。

作為一個初學者,我承認我已經做到了。如果密鑰是隨機的,因此無法記住,您是否建議將密鑰以物理形式存儲在某處?這是我看到的使用純隨機密鑰實現系統的唯一方法。
@AdamCross, *“如果密鑰是隨機的,因此難以記住,您是否建議將密鑰以物理形式存儲在某個地方?” *-可以以電子形式或物理形式存儲在某個地方。非電子形式不一定在所有情況下都比電子形式具有特權。舉個例子...您可以使用SSL安全地連接到網站。您使用的SSL會話密鑰不會以非電子形式存儲在任何地方,也不是從密碼短語派生的。
哈哈,用“身體形態”來闡明,我的意思是除了我的頭以外的地方-但這沒什麼意義,因為我的頭也是身體的。
curiousguy
2011-09-28 09:03:50 UTC
view on stackexchange narkive permalink

在密碼協議中:使每條經過身份驗證的消息都可識別:沒有兩條消息看起來應該相同

以下內容的概括/變體:

  • 在散列之前連接多個字符串時要小心。
  • 請勿重用鍵。
  • 請勿重用隨機數。

密碼協議的運行可以交換許多沒有秘密(密鑰或隨機數)就無法偽造的消息。接收者可以驗證這些消息,因為他知道一些公用(簽名)密鑰,或者因為只有他和發送者知道一些對稱密鑰或隨機數。這樣可以確保未修改這些消息。

但這不能確保在同一協議運行期間發出了這些消息:可能已經捕獲了一個對手這些消息之前或在協議的並發運行期間。對手可能會啟動多個並發運行的加密協議來捕獲有效消息並未經修改地重用它們。

通過巧妙地重放消息,可能可以在不破壞任何主鍵的情況下攻擊協議,而不會攻擊任何RNG。 ,任何密碼等。

通過使該協議的每條經過身份驗證的消息對接收者來說明顯不同,可以減少(未消除)重放未修改消息的機會。

實際上,隨機數不必是秘密,它只需要使用一次(在一定時間範圍內,例如相應秘密密鑰的有效性)。
-1
D.W.
2011-02-20 09:44:44 UTC
view on stackexchange narkive permalink

請勿使用不安全的密鑰長度。

確保您使用的密鑰長度足夠長的算法。

對於對稱密鑰加密,我d建議至少使用80位密鑰,如果可能的話,建議使用128位密鑰。不要使用40位加密;它很不安全,很容易被業餘愛好者破壞,只需徹底嘗試所有可能的鍵即可。不要使用56位DES;破解並不容易,但是專門的攻擊者可以破解DES。像AES這樣的128位算法並沒有比40位加密慢得多,因此您沒有藉口使用偽造的加密。

對於公鑰加密,密鑰長度建議取決於算法以及所需的安全級別。同樣,增加密鑰大小會損害性能,因此過大的殺傷力是不經濟的。因此,這比選擇對稱密鑰密鑰大小需要更多的思考。對於RSA,El Gamal或Diffie-Hellman,我建議密鑰至少為1024位,並且絕對最小值。但是,1024位密鑰處於短期內會變得容易破解的邊緣,通常不建議用於現代用途,因此,如果有可能,我建議使用1536位甚至2048位密鑰。對於橢圓曲線密碼學,160位密鑰顯得足夠,而224位密鑰則更好。您還可以參考已發布的準則,以建立對稱密鑰和公共密鑰大小之間的大致等效關係

NIST推薦截至2010年底的1024位以上的密鑰:http://securitymusings.com/article/1587/algorithm-and-key-length-deprecation
我唯一不同意的一句話是:““如今這是一個不太常見的錯誤”。。。。……在“不加密”和“滾動您自己的加密”之後,我仍然看到了最常見的加密錯誤之一。
-1
D.W.
2011-02-20 09:48:24 UTC
view on stackexchange narkive permalink

不要在兩個方向上使用相同的密鑰。

在網絡通信中,常見的錯誤是在A-> B方向上使用相同的密鑰進行通信至於B-> A方向。這是一個壞主意,因為它通常會啟用重播攻擊,從而將A發送給B的內容重播回A。

最安全的方法是協商兩個獨立的密鑰,每個方向協商一個密鑰。另外,您可以協商單個密鑰K,然後將K1 = AES(K,00..0)用於一個方向,將K2 = AES(K,11..1)用於另一個方向。

或者,您可以為每個加密(在半雙工通信中)增加一個SSC,一個安全會話計數器。我什至看過一個例子,其中另一方的密文的最後一個塊用作下一個塊的IV,但這可能會導致某些特殊的攻擊。
@owlstead,是,使用密文的最後一個塊作為下一個塊的IV以及CBC模式,導致對SSL的BEAST攻擊。附言SSC可以將兩個通道分開,但是您必須謹慎使用。您必須為發送和接收都增加它(使用兩個SSC,每個方向使用一個SSC會達到目的)。此外,SSC將要求雙方同步並且不會容忍丟包,這在某些設置中可能會出現問題。僅使用兩個獨立的鍵可能會更容易。
有趣的是,我知道一些使用該方案的存儲卡,其中密碼塊的最後一部分作為下一個的IV。我會調查一下。謝謝D.W,猜想我的預感是對的。
這也為Microsoft的PPTP雙重攻擊打開了大門。 PPTP的第一個版本在客戶端和服務器中使用相同的密鑰
Shane Hansen
2012-09-08 21:55:43 UTC
view on stackexchange narkive permalink

使用正確的模式

等效地,不要依賴庫的默認設置來保證安全。具體來說,許多實現AES的庫都實現了FIPS 197中描述的算法,即所謂的ECB(電子代碼簿)模式,該模式本質上是對以下內容的直接映射: ] byte,密鑰[32] byte)->密文[32] byte

是非常不安全的。推理很簡單,儘管密鑰空間中可能的密鑰數量非常大,但這裡的薄弱環節是消息中的熵量。與往常一樣,xkcd.com所描述的要比我 http://xkcd.com/257/

好。使用諸如CBC(密碼塊鏈接)之類的東西使密文[i]成為映射:

 密文[i] = SomeFunction(密文[i-1],消息[i],密鑰) 

只是指出一些容易犯這種錯誤的語言庫: http://golang.org/pkg/crypto/aes/提供了一個AES實現,如果天真地使用它會

在創建新的AES對象時,pycrypto庫默認為ECB模式。

OpenSSL,此操作正確。每個AES調用都明確說明操作模式。 IMO真正最安全的事情就是只是不要自己做這種低級加密。如果您被迫這樣做,請像小心地在碎玻璃板上行走那樣,繼續進行操作,並嘗試確保用戶有理由相信您,以保護他們的數據。

感謝您的回答,Shane!一個問題:另一個答案是否已涵蓋此問題?[不要將帶有ECB的分組密碼用於對稱加密](http://security.stackexchange.com/a/2203/971)?
D.W.
2012-10-17 19:57:20 UTC
view on stackexchange narkive permalink

請勿在許多設備上重複使用同一密鑰。

共享密碼密鑰的範圍越廣,保存密鑰的可能性就越小秘密。某些已部署的系統已將相同的對稱密鑰重新使用到系統上的每個設備上。問題在於,遲早有人會從單個設備中提取密鑰,然後他們便能夠攻擊所有其他設備。因此,請不要這樣做。

另請參閱本博客文章中的“對稱加密不要#6:不要在多個設備之間共享單個密鑰”。感謝Matthew Green。

John Deters
2013-05-15 22:04:48 UTC
view on stackexchange narkive permalink

如果密鑰是通過算法拉伸的,則一次性填充不是一次性填充。

標識符“一次性填充”(也稱為Vernam密碼)經常被誤用於各種加密解決方案,試圖聲稱其堅不可摧的安全性。但是根據定義,Vernam密碼只有在同時滿足以下三個條件的情況下才是安全的:

  • 密鑰材料確實是不可預測的。 AND
  • 密鑰材料的長度與明文的長度相同; AND
  • 密鑰材料永遠不會重複使用。

任何違反這些條件的行為都意味著它不再是一次性填充密碼。

常見的錯誤是使用算法擴展了短密鑰。此操作違反了不可預測性規則(不必擔心密鑰長度規則)。完成此操作後,一次性墊板將在數學上轉換為密鑰擴展算法。將短鍵和隨機字節組合在一起只會改變暴力破解鍵拉伸算法所需的搜索空間。同樣,使用“隨機生成”字節會將隨機數生成器算法轉換為安全性算法。

這裡是一個簡單的示例。我收到一條消息,我將使用“一次性密碼”加密,該密碼使用加密安全功能作為密鑰生成器。我選擇了一個秘密密鑰,然後在其中添加了一個隨機數字,以確保不會重複使用。由於我沒有重用密鑰,因此無法通過從另一消息中減去一條消息來攻擊密文。

 明文:1234567890123456789012345678901234567890密鑰材料:757578fbf23ffa4d748e0800dd7c424a46feb0ccOTP函數(xor):---- ------密文:67412E83622DCE1B0C1E1A348B04D25872A8C85C  

密鑰材料是使用SHA-1安全地生成的,用於對我的秘密密碼(加上隨機數)進行哈希處理以對其進行擴展。但是,任何知道所使用的擴展算法為SHA-1的攻擊者都可以通過嘗試將各種輸入SHA-1並將輸出與密文進行XOR來對其進行攻擊。現在猜測“ OTP”密鑰比猜測密碼算法的組合輸入更困難。無論選擇哪種基本密碼算法,採用何種度量複雜度,如何實現或設定種子,此屬性均成立。

您可能有一個很好的密鑰拉伸算法。您可能還具有非常安全的隨機數生成器。但是,根據定義,您的算法不是一次性的,因此不具有一次性的不可破壞的屬性。

*應用Kerckhoff原理意味著您必須假設攻擊者可以始終確定使用的算法。

您是否可以編輯“由於我不重用密鑰,因此無法通過從另一條消息中減去一條消息來攻擊密文。”並添加表明可能進行其他攻擊的文本?示例:兩個時間墊,錯誤的協議或其他偏差(分別為PPTP,WEP和RC4)。一個無知的外行可能會誤讀您所寫的內容,並認為OTP可以從另一個意義上說“完全保密”。另外,由於您正在研究該主題,因此介紹一些有效的PNG / PRG密鑰擴展器是有幫助的。
注意:OTP中沒有消息身份驗證。不會檢測到對OTP的修改。
注意:*安全PRG *類似於OTP。它是所有有效的統計檢驗,其結果可忽略不計,而且PRG不可能滿足所有理論統計檢驗。安全性的這種“放鬆”是效率所必需的,因為“完美保密”要求安全傳輸足夠大的OTP以匹配消息的大小。示例:所有OTP傳輸都要求安全地傳輸秘密(這是不確定的方式)。首先,使用該安全方法發送數據會更有效。
正是這種“相似性”使人們對不可破解性提出了怪異的主張,而正是這種“效率”打破了維南密碼的不可預測性。沒有人說過使用OTP進行密鑰生成,密鑰管理或密鑰分發是簡單或實用的-並非以上所有。儘管在數學上可以做到完美保密,但人們仍然很難使用其他密碼。任何“鍵拉伸”都不能改變這個事實。
可以使用“安全PRNG”來生成這些位,但是,如果它確實是安全的,那麼您仍然會遇到所有分發問題,因為您無法在接收方的計算機上複製它們的生成-如果可以的話,該狀態將是密鑰,而不是密鑰。位。
Watson Ladd
2012-09-08 21:05:27 UTC
view on stackexchange narkive permalink

不信任標準。

加密中存在許多標準,有時您必須使用它們。但是,請不要以為編寫標準的人充分理解了他們所需的加密技術。例如,EAX在網絡標準中進行了重新設計。 EAX有安全證明。重做的版本沒有。

MD5是標準的。現在壞了。由於具有豐富的危險功能,芯片和PIN屢屢被破壞。 GPG仍然支持DSA密鑰,該密鑰太短而無法舒適。 SSL具有不應使用的選項,並且需要避免使用它們。

對此可以採取什麼措施?保持謹慎,了解已知風險,並跟上新風險的研究。

MD5是一個標準,是真的。但是它已被更新的最新標準SHA取代。在大多數情況下,出於多種原因應遵循標準。互操作性是一個很大的因素。
這是一個非常令人誤解的陳述。該措辭暗示讀者應“信任非標準”,這顯然是不正確的。大多數安全標準只有在經過廣泛的實際測試之後才能出現。測試遠比任何單個組織用來“證明”其非標準系統的安全性都更為徹底。
goodguys_activate
2013-05-20 20:47:19 UTC
view on stackexchange narkive permalink

在磁盤加密中不使用OTP或流密碼

示例1

假設保存了兩個文件使用流密碼/ OTP。如果在進行較小的編輯後重新保存文件,則攻擊者可以看到僅某些位被更改,並推斷出有關文檔的信息。 (想像一下將稱呼“親愛的鮑勃”更改為“親愛的愛麗絲”)。

示例2

輸出中沒有完整性:攻擊者可以只需對數據進行異或,即可修改密文並修改數據的內容。

要點:密文的修改未被發現,並且對明文具有可預測的影響。

解決方案

在包括郵件完整性檢查在內的這些情況下使用分組密碼

goodguys_activate
2013-05-20 21:08:44 UTC
view on stackexchange narkive permalink

永遠不要一次使用一次Time Pad(OTP)或流密碼密鑰

一次應用兩次OTP意味著將對“完全保密”加密的數據進行解密並在清楚。發生這種情況是因為數據被異或兩次。

示例

假設正在重用具有相同密鑰的OTP /或流。

攻擊者收集了大量數據從客戶端發送到服務器,然後將一組兩個數據包進行XOR運算,直到兩個數據包互相解密(或其中的子集)。

ASCII編碼具有足夠的冗餘性,這意味著給定足夠的密文,就可以對原始消息進行解碼(以及秘密的OTP密鑰)。

真實世界的例子

  • 維羅納項目(1941-46),是俄羅斯人使用的一次性密碼的一個例子,隨後被由美國情報機構解密

  • Microsoft的PPTPv1客戶端和服務器均使用同一密鑰對數據進行加密。

  • WEP重用發送2 ^ 24個數據包或重置NIC卡後,將使用相同的密鑰。第一個問題是由於IV的長度為24位,導致在發送1600萬幀後創建了兩個時間間隔。第二個問題發生在硬件實現中,在重新上電之後,IV重置為零,導致兩個時間間隔。因為IV是明文發送的,所以這個問題很容易看到。

建議

  • 應該為每個會話(例如TLS)創建一個新密鑰。

  • 客戶端應與服務器使用一個OTP(或帶有PRG的流密碼),並且服務器在將數據加密到客戶端時,應該使用不同密鑰

  • 而不是生成許多密鑰,而是可以將單個密鑰擴展為長數據流使用PRG(假設您信任PRG)並將擴展的每個部分用作鍵。

  • 請注意,並非所有PRG都能在增量模式下工作,因此可能需要隨機輸入。 (RC4在增量模式下存在此問題)

goodguys_activate
2013-05-20 21:26:00 UTC
view on stackexchange narkive permalink

請勿使用RC4

RC4於1987年設計,用作流密碼。

存在弱點

  1. 初始輸出中存在偏差:Pr [2nd byte = 0] = 2/256
  2. li等於零的十六位的概率為1/256 ^ 2 + 1/256 ^ 3。在幾個Gig數據已加密之後,就會發生這種情況。
  3. 容易受到相關的密鑰攻擊,在這種攻擊中,僅IV發生了變化,但密鑰保持不變。
  4. ol>

    帶走如果必須使用RC4,請忽略前256個字節,因為它們有偏差。如果將RC4用作數據的Gig,則RC4中的偏差將允許攻擊所有以前的加密數據。

goodguys_activate
2013-05-20 21:49:46 UTC
view on stackexchange narkive permalink

使用可以在硬件或軟件中正常工作的現代流處理器

並非所有流密碼都設計為在硬件或軟件中實現。 線性反饋移位寄存器(LFSR)是易於破解的廣泛部署的硬件密碼的示例。

LFSR用於:

  • DVD加密(也稱為CSS)2 LFSR
  • GSM加密(A5 / 1.2)3 LSFR
  • 藍牙(E0):4 LFSR

上述硬件已廣泛部署,因此很難更新或達到現代標準。以上所有內容均已嚴重破壞,因此不值得用於安全通信。

攻擊:

由於在加密過程中密鑰被分為兩部分( 17位和25位),這些位用於加密相同的密文,可以使用MPEG格式的知識,並強行使用17位密鑰來推斷25位密鑰是什麼。

這是 FO>

解決方案:

eStream項目(2008年) )應使用合格的5個流密碼。顯著的區別在於,密碼使用的是密鑰,隨機數和計數器,而不是使用帶有IV的密鑰。 Salsa20以這種方式操作,旨在輕鬆在硬件和軟件中使用。具體來說,它包含在x86 SSE2指令集中。

此外

現代密碼不僅更安全,而且速度更快:

  PRG速度(MB /秒)RC4 126(已淘汰)Salsa20 / 12 643(現代)Sosemaunk 727(現代) 
goodguys_activate
2013-05-23 09:42:28 UTC
view on stackexchange narkive permalink

僅使用不易受到消息擴展攻擊的MAC

MAC是一種哈希代碼,可確保給定普通郵件的消息完整性(無修改等)文本。許多實現和已發布的標準未能保護MAC免受攻擊者的攻擊,因為攻擊者無法向MAC添加其他數據。

針對此問題的解決方案是MAC實現使用第二個(不同的)密鑰並重新加密最終輸出。

ECBC和NMAC是正確防止密碼洩露的密碼示例。郵件擴展攻擊。

解決方案:

  • 使用加密的CBC(ECBC)代替原始CBC
  • 使用 NMAC 代替 cascade


該問答將自動從英語翻譯而來。原始內容可在stackexchange上找到,我們感謝它分發的cc by-sa 2.0許可。
Loading...