true if both representations are equal, false otherwisebool secureEqual(R1, R2)(R1 r1, R2 r2) if (isInputRange!R1 && isInputRange!R2 && !isInfinite!R1 && !isInfinite!R2 &&
(isIntegral!(ElementEncodingType!R1) || isSomeChar!(ElementEncodingType!R1)) &&
!is(CommonType!(ElementEncodingType!R1, ElementEncodingType!R2) == void))Securely compares two digest representations while protecting against timing attacks. Do not use `==` to compare digest representations.
The attack happens as follows:
requires a integrity HMAC SHA1 token signed with a secret.
so the attacker first sends "0000000000000000000000000000000000000000", then "1000000000000000000000000000000000000000", and so on.
`==` string comparison, which returns false as soon as the first wrong element is found. If a wrong element is found, then a rejection is sent back to the sender.
the correct token because the sever takes slightly longer to return a rejection. This is due to the comparison moving on to second item in the two arrays, seeing they are different, and then sending the rejection.
to notice, but security researchers have shown that differences as small as 20µs can be reliably distinguished even with network inconsistencies.
correct token and the server accepts the harmful data. This can be done in a week with the attacker pacing the attack to 10 requests per second with only one client.
This function defends against this attack by always comparing every single item in the array if the two arrays are the same length. Therefore, this function is always n for ranges of the same length.
This attack can also be mitigated via rate limiting and banning IPs which have too many rejected requests. However, this does not completely solve the problem, as the attacker could be in control of a bot net. To fully defend against the timing attack, rate limiting, banning IPs, and using this function should be used together.
r1 | A digest representation |
r2 | A digest representation |
true if both representations are equal, false otherwise