Skip to content

Commit

Permalink
Add ByteVector#equalsConstantTime
Browse files Browse the repository at this point in the history
  • Loading branch information
mpilquist committed Aug 18, 2024
1 parent a3383d1 commit f82638c
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 0 deletions.
15 changes: 15 additions & 0 deletions core/shared/src/main/scala/scodec/bits/ByteVector.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1293,6 +1293,21 @@ sealed abstract class ByteVector
case _ => false
}

/** Like [[equals]] but compares all bytes instead of returning after first non-matching byte.
* @group collection
*/
def equalsConstantTime(other: ByteVector): Boolean =
if (this.size != other.size) false
else {
var result, idx = 0
val s = this.size
while (idx < s) {
result = result | (this(idx) ^ other(idx))
idx += 1
}
result == 0
}

/** Display the size and bytes of this `ByteVector`. For bit vectors beyond a certain size, only a
* hash of the contents are shown.
* @group collection
Expand Down
7 changes: 7 additions & 0 deletions core/shared/src/test/scala/scodec/bits/ByteVectorTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ class ByteVectorTest extends BitsSuite {
forAll((b: ByteVector, b2: ByteVector) => assert((b == b2) == (b === b2)))
}

property("equalsConstantTime") {
forAll(bytesWithIndex) { case (b, m) =>
assert((b.take(m) ++ b.drop(m)).equalsConstantTime(b))
} &&
forAll((b: ByteVector, b2: ByteVector) => assert((b === b2) == (b.equalsConstantTime(b2))))
}

test("compact is a no-op for already compact byte vectors") {
val b = ByteVector(0x80)
assert((b.compact eq b.compact) == true)
Expand Down

0 comments on commit f82638c

Please sign in to comment.