比较两个字节数组以防止时序攻击
Comparing two byte arrays guarding against timing attacks
我想写一个比较两个字节数组的方法,但是我不想用these solutions,因为我希望这个方法能够抵抗定时攻击。我的方法本质上是这样的:
static bool AreEqual(byte[] a1, byte[] a2)
{
bool result = true;
for (int i = 0; i < a1.Length; ++i)
{
if (a1[i] != a2[i])
result = false;
}
return result;
}
(假设a1
和a2
长度相同)
我担心的是,如果 result
被设置为 false,足够智能的即时编译器可能会通过提前返回来优化这一点。
我 have checked .NET 4.0.30319 生成的 JITted 汇编代码,它不:
; `bool result = true;'
00e000d1 bb01000000 mov ebx,1
; `int i = 0;'
00e000d6 33f6 xor esi,esi
; store `a1.Length' in eax and at dword ptr [ebp-10h]
00e000d8 8b4104 mov eax,dword ptr [ecx+4]
00e000db 8945f0 mov dword ptr [ebp-10h],eax
; if `a1.Length' is 0, then jump to `return result;'
00e000de 85c0 test eax,eax
00e000e0 7e18 jle 00e000fa
; `if (a1[i] != a2[i])'
00e000e2 0fb6443108 movzx eax,byte ptr [ecx+esi+8]
00e000e7 3b7704 cmp esi,dword ptr [edi+4]
00e000ea 7316 jae 00e00102
00e000ec 3a443708 cmp al,byte ptr [edi+esi+8]
00e000f0 7402 je 00e000f4
; `result = false;'
00e000f2 33db xor ebx,ebx
; `++i'
00e000f4 46 inc esi
; check: `a1.Length > i'
00e000f5 3975f0 cmp dword ptr [ebp-10h],esi
00e000f8 7fe8 jg 00e000e2
; `return result;'
00e000fa 8bc3 mov eax,ebx
00e000fc 59 pop ecx
00e000fd 5b pop ebx
00e000fe 5e pop esi
00e000ff 5f pop edi
00e00100 5d pop ebp
00e00101 c3 ret
00e00102 e81f7a1772 call clr!CreateHistoryReader+0x8e97c (72f77b26)
00e00107 cc int 3
00e00108 0000 add byte ptr [eax],al
00e0010a 0000 add byte ptr [eax],al
00e0010c 0000 add byte ptr [eax],al
00e0010e 0000 add byte ptr [eax],al
...
不过,我认为这可能会在未来发生变化。
有没有办法阻止JIT编译器优化这个方法?或者,有没有我可以使用的库函数专门检查两个字节数组是否相等,但能抵抗时序攻击?
您可以像这样使用 MethodImplAttribute
-Class of the System.Runtime.CompilerServices
namespace with the MethodImplOptions.NoOptimization
选项:
[MethodImpl(MethodImplOptions.NoOptimization)]
static bool AreEqual(byte[] a1, byte[] a2)
{
// ...
}
我想写一个比较两个字节数组的方法,但是我不想用these solutions,因为我希望这个方法能够抵抗定时攻击。我的方法本质上是这样的:
static bool AreEqual(byte[] a1, byte[] a2)
{
bool result = true;
for (int i = 0; i < a1.Length; ++i)
{
if (a1[i] != a2[i])
result = false;
}
return result;
}
(假设a1
和a2
长度相同)
我担心的是,如果 result
被设置为 false,足够智能的即时编译器可能会通过提前返回来优化这一点。
我 have checked .NET 4.0.30319 生成的 JITted 汇编代码,它不:
; `bool result = true;' 00e000d1 bb01000000 mov ebx,1 ; `int i = 0;' 00e000d6 33f6 xor esi,esi ; store `a1.Length' in eax and at dword ptr [ebp-10h] 00e000d8 8b4104 mov eax,dword ptr [ecx+4] 00e000db 8945f0 mov dword ptr [ebp-10h],eax ; if `a1.Length' is 0, then jump to `return result;' 00e000de 85c0 test eax,eax 00e000e0 7e18 jle 00e000fa ; `if (a1[i] != a2[i])' 00e000e2 0fb6443108 movzx eax,byte ptr [ecx+esi+8] 00e000e7 3b7704 cmp esi,dword ptr [edi+4] 00e000ea 7316 jae 00e00102 00e000ec 3a443708 cmp al,byte ptr [edi+esi+8] 00e000f0 7402 je 00e000f4 ; `result = false;' 00e000f2 33db xor ebx,ebx ; `++i' 00e000f4 46 inc esi ; check: `a1.Length > i' 00e000f5 3975f0 cmp dword ptr [ebp-10h],esi 00e000f8 7fe8 jg 00e000e2 ; `return result;' 00e000fa 8bc3 mov eax,ebx 00e000fc 59 pop ecx 00e000fd 5b pop ebx 00e000fe 5e pop esi 00e000ff 5f pop edi 00e00100 5d pop ebp 00e00101 c3 ret 00e00102 e81f7a1772 call clr!CreateHistoryReader+0x8e97c (72f77b26) 00e00107 cc int 3 00e00108 0000 add byte ptr [eax],al 00e0010a 0000 add byte ptr [eax],al 00e0010c 0000 add byte ptr [eax],al 00e0010e 0000 add byte ptr [eax],al ...
不过,我认为这可能会在未来发生变化。
有没有办法阻止JIT编译器优化这个方法?或者,有没有我可以使用的库函数专门检查两个字节数组是否相等,但能抵抗时序攻击?
您可以像这样使用 MethodImplAttribute
-Class of the System.Runtime.CompilerServices
namespace with the MethodImplOptions.NoOptimization
选项:
[MethodImpl(MethodImplOptions.NoOptimization)]
static bool AreEqual(byte[] a1, byte[] a2)
{
// ...
}