4.3.3 防重放攻擊
重放攻擊即為:攻擊者“重放”一則在網絡上“竊聽”到,或者在區塊鏈中“偷窺”到的消息。重放攻擊是一個很大的問題,因為它們可以引發驗證節點重做一次計算密集型處理(即調用智能合約),同時可能影響到相應合約的狀態。而這些過程,并不需要或只需要耗費攻擊者很少的資源。如果一個事務是處理支付的,那么問題就會更加嚴重,消息重放可能會引發支付又被處理一遍,并且不需要原始支付者的參與。現有的系統防重放攻擊有如下方式:
* 在系統中記錄事務哈希值。這個方案需要驗證者維護一份哈希日志,記錄每一個已被網絡廣播的事務哈希值,然后每收到一個新的事務,就和本地存儲值進行對比。很明顯,這種方式無法擴展到大規模網絡環境中,并且很容易就會導致驗證者花費大量的時間檢查該事務是否屬于重放,而不是執行實際事務處理。
* 利用每個用戶身份標識維護的狀態(Ethereum的做法)。以太坊保存一些狀態,例如,為系統中每一個標識/昵稱 維護一個計數器(初始化為1)。用戶也為自己的每一個身份/昵稱 維護一個計數器(初始化為0)。每一次用戶使用一個身份/昵稱 發送事務時,他都會將本地計數器加1,并將結果添加到事務中。隨后使用用戶標識將事務進行簽名,并發布到網絡中。當收到這個事務時,驗證者就會核對包含在事務中的計數器值,并與他們本地存儲的值對比;如果相等,他們就將本地計數器值加1,同時接受該事務。否則,他們認為該事物非法或者屬于重放,并拒絕它。盡管在有限數量(比如,數量不太大)的用戶標識/昵稱前提下,這個方案表現不錯,但是當用戶每一個事務,都使用不同的身份標識(事務證書TCA)時,就會導致用戶昵稱數量正比于事務數量,那么此時,這種方案就從根本上,無法進行大規模擴展。
其它的資產管理系統,比如,比特幣,雖然并沒有直接處理重放攻擊,但是它們卻可以防止重放。在管理(數字)資產的系統中,狀態維護在每一個資產基礎中,例如,驗證者只用保存一條記錄,指示誰擁有什么。由于根據協議,事務重放會被立即判斷為非法,這樣就直接防止了重放攻擊,。(因為來自于資產的上一個擁有者的事務,只能用來顯示)。這么做對于資產管理系統是恰當的,但是作為一個比資產管理更加通用的區塊鏈系統,這樣做并不符合實際需要。
在fabric中,使用一種混合方法來防止重放攻擊。即,用戶在事務中添加一個nonce,根據事務是匿名事務(遵守TCA,并且由TCA簽名),還是非匿名事務(遵守長期有效的ECA,并且由其簽名),系統會使用不同的方式來生成nonce。具體來說:
* 當用戶使用他們的EC提交事務時,需要在該事務中包含一個nonce,它是上一次使用同樣證書,提交事務時使用的nonce的函數。(例如,可以是一個計數函數,或者是一個hash函數)。在第一次使用EC提交的事務中,nonce可以由系統預定(例如,包含在創世區塊中),也可以由用戶選定。前者,創世區塊需要包含nonceall,例如,一個固定數字,它和用戶使用EC簽名的第一次事務中的身份IDA,相互作用產生nonce:
$$ nonce_{round_{0}IDA} <- hash(IDA, nonce_{all}) $$
IDA存在EC中。從該點開始,后續使用EC提交的事務,都需要包含一個nonce,該nonce產生規則為:
$$ nonce_{round_{i}IDA} <- hash(nonce_{round_{\{i-1\}}IDA}) $$
即第i個事務使用的nonce,是第{i-1}個EC事務nonce的哈希值。只要滿足上述條件,驗證者就繼續處理該事務,并且更新數據庫中的nonce值。
存儲開銷:
* 用戶端:只需要存儲最近使用的nonce值
* 驗證者端:O(n),n是用戶數量
* 用戶使用TC提交事務時,需要在事務中包含一個隨機nonce,需要保證2個事務不能映射到同一哈希值。如果該事務的TC沒有過期,驗證者就將該事物的hash值存儲到本地數據庫,利用TC的有效期,來避免存儲大量的hash值。特別的,在當前或未來有效期內,驗證者會維護一個已接受事務哈希值的更新記錄。
存儲開銷(這里只涉及到驗證者):`O(m)`,m近似于一個對應標識符的有效期內的事務數量。
**Registrar API(member services)**
* POST /registrar
* GET /registrar/{enrollmentID}
* DELETE /registrar/{enrollmentID}
* GET /registrar/{enrollmentID}/ecert
* GET /registrar/{enrollmentID}/tcert
使用Registrar APIs管理終端用戶注冊CA服務。這些