在 .NET 中使用 FixedTimeEquals 應對計時攻擊

? 計時攻擊??

在計算機安全中,計時攻擊(Timing attack)是旁道攻擊 (Side-channel attack) 的一種,而旁道攻擊是根據計算機處理過程發出的信息進行分析,包括耗時,聲音,功耗等等,這和一般的暴力破解或者利用加密算法本身的弱點進行攻擊是不一樣的。

? 舉個例子??

假如您有一個后端 webapi, GetConfig 接口用來獲取配置信息,調用時需要在 Header 中傳入一個秘鑰,然后判斷是否正確并進行返回,如下

X-Api-Key:?x123
[HttpGet]
public?IActionResult?GetConfig()
{var?key?=?Request.Headers["X-Api-Key"].FirstOrDefault();if?(key?!=?"x123"){return?Unauthorized();}return?Ok(configuration);
}

注意,這里我們為了判斷兩個字符串相等,通常會使用 == 或者 != , 實際上背后使用了 String 的 Equals() 方法,如下

//?Determines?whether?two?Strings?match.
public?static?bool?Equals(string??a,?string??b)
{if?(object.ReferenceEquals(a,?b)){return?true;}if?(a?is?null?||?b?is?null?||?a.Length?!=?b.Length){return?false;}return?EqualsHelper(a,?b);
}

而內部又使用了 SequenceEqual() 方法

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private?static?bool?EqualsHelper(string?strA,?string?strB)
{Debug.Assert(strA?!=?null);Debug.Assert(strB?!=?null);Debug.Assert(strA.Length?==?strB.Length);return?SpanHelpers.SequenceEqual(ref?Unsafe.As<char,?byte>(ref?strA.GetRawStringData()),ref?Unsafe.As<char,?byte>(ref?strB.GetRawStringData()),((uint)strA.Length)?*?sizeof(char));
}

大概的邏輯是,先判斷兩個字符串長度是否一致,如果不是,直接返回 false,然后循環字符串進行逐位對比,一旦發現不相同,直接返回 false,偽代碼如下

public?bool?Equals(string?str1,?string?str2)
{if?(str1.Length?!=?str2.Length)?{return?false;}?for?(var?i?=?0;?i?<?str1.Length;?i++){if?(str1[i]?!=?str2[i]){return?false;}}?return?true;
}

這里有一個問題是,如果字符串第一位不相同,直接就返回 false,如果最后一位不相同,那就需要遍歷到最后,然后返回 false。不一樣的字符串,計算的時長可能不一致。

? 嘗試破解??

假如用戶知道了我們的秘鑰的固定長度是 4 位。

GET?/GetConfig??
X-Api-Key:a000
Cost:?2ns

本次耗時了 2ns, 接下來又輸入 b000, c000....

GET?/GetConfig??
X-Api-Key:b000
Cost:?2nsGET?/GetConfig??
X-Api-Key:c000
Cost:?2ns?...GET?/GetConfig??
X-Api-Key:x000
Cost:?4ns

直到輸入了 x000, 發現其他的耗時都是 2ns, 而這里是 4ns,大概率判定第一位是 x。

注意,這里的測試進行了放大,可能每個 case 分別調用了 100 次,然后統計了 P50(中位數)得出的結果。

然后用同樣的方法,測試第二位,第三位....., 最終破解拿到了秘鑰。

? 使用固定時間的算法??

雖然看上去有點扯,但確實是真實存在的,包括大名鼎鼎的針對 TLS 的 Lucky 13 攻擊,有興趣的同學可以看一下。在安全性要求比較高的場景中,確實要考慮到計時攻擊,當涉及到安全時,還是寧可信其有。

所以我們的算法的執行耗時應該是固定的,不應該在不匹配時,就立即返回,我們嘗試改造一下代碼

public?bool?Equals(string?str1,?string?str2)
{if?(str1.Length?!=?str2.Length){return?false;}bool?reult?=?true;for?(var?i?=?0;?i?<?str1.Length;?i++){if?(str1[i]?!=?str2[i]){reult?=?false;}}return?reult;
}

不管怎么樣,都會遍歷完整個字符串,然后返回結果,看上去沒什么問題,時間總是固定的,但在現代的 CPU 和 .NET 上卻不是的,因為我們要考慮到分支預測,特別是 if 條件。

好吧,那我們調整一下代碼

public?bool?Equals(string?str1,?string?str2)
{if?(str1.Length?!=?str2.Length){return?false;}bool?reult?=?true;for?(var?i?=?0;?i?<?str1.Length;?i++){?reult?&=?str1[i]?==?str2[i];?}return?reult;
}

我們用了運算符 &,來代替 If, 只有全部為 true 時,才會返回 true,其中任意一個字符不匹配,就會返回 false,看上去不錯。

但是,還有一些問題,對于bool類型的 result (true/false), 我們的 .NET JIT 和 x86 指令執行仍然會進行一些優化,我們再調整一下代碼

public?bool?Equals(string?str1,?string?str2)
{if?(str1.Length?!=?str2.Length){return?false;}int?reult?=?0;for?(var?i?=?0;?i?<?str1.Length;?i++){?reult?|=?str1[i]?^?str2[i];?}return?reult?==?0;
}

我們把 bool 改成了 int 類型,然后使用了運算符 ^ 和 |,同樣的,只有字符串全部匹配時,result 為 0,,才會返回 true, 其中任意一個不匹配,result 就不為 0,會返回 false。

最后,為了防止 JIT 對我們的代碼進行其他的優化,我們可以加一個特性,告訴 JIT 不要管它,就像這樣

[MethodImpl(MethodImplOptions.NoInlining?|?MethodImplOptions.NoOptimization)]
public?bool?Equals(string?str1,?string?str2)
{if?(str1.Length?!=?str2.Length){return?false;}int?reult?=?0;for?(var?i?=?0;?i?<?str1.Length;?i++){?reult?|=?str1[i]?^?str2[i];?}return?reult?==?0;
}

上面我們實現了一個針對字符串比較的固定時間的算法,來應對計時攻擊。

實際上, 從 .NET Core 2.1 開始就已經做了內置支持,我們可以直接使用 FixedTimeEquals 方法, 看一下它的實現

[MethodImpl(MethodImplOptions.NoInlining?|?MethodImplOptions.NoOptimization)]
public?static?bool?FixedTimeEquals(ReadOnlySpan<byte>?left,?ReadOnlySpan<byte>?right)
{?if?(left.Length?!=?right.Length){return?false;}int?length?=?left.Length;int?accum?=?0;for?(int?i?=?0;?i?<?length;?i++){accum?|=?left[i]?-?right[i];}return?accum?==?0;
}

現在用起來也很方便:

var?result?=?CryptographicOperations.FixedTimeEquals(Encoding.UTF8.GetBytes(str1),?Encoding.UTF8.GetBytes(str2)
);

? 總結??

在安全性比較高的場景中,應該要考慮到計時攻擊,可以使用固定時間的算法來應對。在其他的開發語言中,也都有本文中類似的算法,而在 .NET 中,現在我們可以直接使用 CryptographicOperations.FixedTimeEquals。

f5986f626179afa1202db4d69a1f1c41.png

07b62a816e79366b41361ae249e5fd7d.gif

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/286635.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/286635.shtml
英文地址,請注明出處:http://en.pswp.cn/news/286635.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

解讀大型網站系統架構的演化

解讀大型網站系統架構的演化 大型網站的架構是根據業務需求不斷完善的&#xff0c;根據不同的業務特征會做特定的設計和考慮&#xff0c;本文只是講述一個常規大型網站會涉及的一些技術和手段。作者&#xff1a;李平來源&#xff1a;LEE的博客前言 一個成熟的大型網站&#xff…

【ArcGIS風暴】西北地區氣象臺站年均NDVI與年均氣溫和降水的相關性分析

在研究植被動態變化與氣候的關系時,通常通過計算植被NDVI值與氣溫和降水的相關系數來描述相關性的大小。如下圖所示,計算了西北地區分布的氣象臺站與氣溫和降水的相關性并作圖可視化。 下面詳細說明整個實現過程。 一、計算相關系數 1. 原理分析 通過計算年均N…

python 全解坦克大戰 輔助類 附完整代碼【雛形】

我正在博客之星評選&#xff0c;歡迎投票給我 會從投票人中抽獎機械鍵盤書&#xff0c;中了會私聊地址 投票連接是&#xff1a;https://bbs.csdn.net/topics/603955346 投票連接是&#xff1a;https://bbs.csdn.net/topics/603955346 投票連接是&#xff1a;https://bbs.csdn.…

vc++ mfc中拖動效果的實現 借助于CImageList

拖動是界面編程頻繁使用的一個效果&#xff0c;在windows系統下可謂大行其道。縱觀時下的應用軟件幾乎各個都支持各種各樣拖動的效果&#xff0c;windows7更是把拖動做到了極致。其實說起來拖動的實現也很簡單&#xff0c;對于有句柄的對象都可以通過MoveWindow或SetWindowPos實…

從瀏覽器地址欄輸入url到顯示頁面的步驟

從瀏覽器地址欄輸入url到顯示頁面的步驟(以HTTP為例)- 在瀏覽器地址欄輸入URL- 瀏覽器查看緩存&#xff0c;如果請求資源在緩存中并且新鮮&#xff0c;跳轉到轉碼步驟 - 如果資源未緩存&#xff0c;發起新請求 - 如果已緩存&#xff0c;檢驗是否足夠新鮮&#xff0c;足夠…

有序的Map集合--LinkedHashMap

提出問題&#xff1a; 在寫一個dao的時候&#xff0c;我的需求是這個dao是一個萬能的&#xff0c;目前的方法只有一個查詢出實體類對應的表中所有的數據&#xff0c;通過傳入的對象&#xff0c;利用反射獲取實體類中的屬性名&#xff0c;屬性類型&#xff0c;利用字符串拼接獲取…

Leetcode之僅僅反轉字母

1 題目 給定一個字符串 S,返回 “反轉后的” 字符串,其中不是字母的字符都保留在原地,而所有字母的位置發生反轉。 示例 1:輸入:"ab-cd" 輸出:"dc-ba" 示例 2:輸入:"a-bC-dEf-ghIj" 輸出:"j-Ih-gfE-dCba" 示例 3:輸入:&qu…

【SignalR全套系列】之在.Net Core 中實現長輪詢

微信公眾號&#xff1a;趣編程ACE關注可了解更多的.NET日常實戰開發技巧&#xff0c;如需源碼 請后臺留言 源碼;前文回顧【SignalR全套系列】之在.Net Core 中實現Server-Send Events消息推送【SignalR全套系列】之在.NetCore中實現WebSocket雙工通信【SignalR全套系列】之在.N…

完美解決ArcGIS10.2和Erdas9.2軟件沖突的方法:共存!

用過ArcGIS和Erdas軟件的都知道&#xff0c;二者存在著服務的沖突&#xff0c;為了解決共存的問題&#xff0c;筆者曾多次重裝系統&#xff0c;但未能如愿以償。其實不需要相互關閉服務如此麻煩。那如何在安裝有arcgis的電腦安裝erdas并解決沖突呢&#xff1f;直接上視頻教程。…

架構師之路16年精選50篇

2016精選索引&#xff0c;點擊標題閱讀相關文章。【方法論】《秒殺系統架構優化思路》《分布式ID生成器》《互聯網架構&#xff0c;如何進行容量設計》《線程數究竟設多少合理》《單點系統架構的可用性與性能優化》《關于負載均衡的一切》《異構服務器負載均衡及過載保護》《LV…

yii 前后臺分離及登陸驗證

2019獨角獸企業重金招聘Python工程師標準>>> 比較合理的做法其實是分成兩個框架來布署&#xff1b;然而這樣說法也太絕對。 事實上是針對不同系統&#xff0c;應采用不同的方法。如為CMS系統&#xff0c;則不需很復雜的權限管理&#xff0c;但如果有管理員與會員之分…

雙谷人才財務管理(序)

IT是一個迅速發展的行業&#xff0c;教育是一個良心的行業&#xff0c;兩者交集——IT培訓&#xff0c;在整個市場中占有一個不可或缺的地位。好多大學生&#xff0c;抱怨找不到工作&#xff1b;好多企業找不到合適的程序員&#xff0c;這幾年這個問題越來越嚴重。。。。于是IT…

Android之打開手機系統相冊

1、需求 打開系統相冊&#xff0c;獲取圖片進行掃描操作 2、代碼實現 Intent pickIntent new Intent(Intent.ACTION_PICK,MediaStore.Images.Media.EXTERNAL_CONTENT_URI);pickIntent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");Ca…

Kibana

2019獨角獸企業重金招聘Python工程師標準>>> Kibana是一個基于瀏覽器頁面的Elasticsearch前端展示工具。Kibana全部使用HTML語言和Javascript編寫的&#xff0c;查詢語法是基于Lucene的查詢語法。允許布爾運算符、通配符和字段篩選。注意關鍵字要大寫 全文搜索 在搜…

電腦QQ能登上,網頁打不開的解決辦法

打開360衛士&#xff0c;在功能大全里選擇網絡優化&#xff0c;斷網急救箱。 可以看到DNS服務異常、瀏覽器配置異常&#xff0c;點擊立即修復。

個人黑名單 抄襲恥辱墻

抄襲恥辱墻 博主抄襲文原文我愛Python數據挖掘https://blog.csdn.net/weixin_38037405/article/details/125862095https://blog.csdn.net/A757291228/article/details/117464313黃埔數據分析https://blog.csdn.net/weixin_39060517/article/details/118024847https://blog.csdn…

快速掌握 ASP.NET 身份認證框架 Identity(一)

推薦關注「碼俠江湖」加星標&#xff0c;時刻不忘江湖事ASP.NET Core 內置了一個強大的身份認證框架 Identity&#xff0c;掌握它可以讓我們快速開發高安全的身份認證功能&#xff0c;不僅如此&#xff0c;它還是一個基于數據庫的用戶管理系統&#xff0c;其中包含了大量的輔助…

淺談大型web系統架構

動態應用&#xff0c;是相對于網站靜態內容而言&#xff0c;是指以c/c、php、Java、perl、.net等服務器端語言開發的網絡應用軟件&#xff0c;比如論壇、網絡相冊、交友、BLOG等常見應用。動態應用系統通常與數據庫系統、緩存系統、分布式存儲系統等密不可分。   大型動態應用…

Android之webview長按超鏈接類型獲取鏈接文字及url、長按圖片鏈接類型分別獲取圖片和鏈接的url

1 、需求 webview長按超鏈接獲取鏈接文字及urlwebview長按圖片鏈接類型獲分別獲取圖片和鏈接的url 2、解決辦法 1)、設置webview的OnLongClickListener事件,關鍵代碼如下 companion object {const val LINK_TYPE = 1const val IMAGE_LINK_TYPE = 2}var mHandler = object :…

PostgreSQL 統計信息pg_statistic格式及導入導出dump_stat - 兼容Oracle

標簽 PostgreSQL , dump_stat , 統計信息 , 導出導入 背景 《PostgreSQL 規格評估 - 微觀、宏觀、精準 多視角估算數據庫性能(選型、做預算不求人)》 EXPLAIN是PG數據庫用于輸出SQL執行計劃的語法&#xff0c; 1、生成的執行計劃中包含COST一項。 如果校準了成本因子&#xff0…