Skip to content

Commit

Permalink
fix: ensure HEX values with additional characters are also parsed cor…
Browse files Browse the repository at this point in the history
…rectly
  • Loading branch information
augi committed Aug 18, 2020
1 parent 7fc0073 commit c12529c
Show file tree
Hide file tree
Showing 7 changed files with 24 additions and 4 deletions.
2 changes: 1 addition & 1 deletion src/main/scala/com/avast/scala/hashes/MD5.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ case class MD5(bytes: Array[Byte]) {

object MD5 {
private val bytesLength = 16
def apply(hexOrBase64: String): MD5 = MD5(if (hexOrBase64.length == 2 * bytesLength) hex2bytes(hexOrBase64) else base642bytes(hexOrBase64))
def apply(hexOrBase64: String): MD5 = MD5(tryHex2bytes(hexOrBase64, bytesLength).getOrElse(base642bytes(hexOrBase64)))
}
2 changes: 1 addition & 1 deletion src/main/scala/com/avast/scala/hashes/Sha1.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ case class Sha1(bytes: Array[Byte]) {

object Sha1 {
private val bytesLength = 20
def apply(hexOrBase64: String): Sha1 = Sha1(if (hexOrBase64.length == 2 * bytesLength) hex2bytes(hexOrBase64) else base642bytes(hexOrBase64))
def apply(hexOrBase64: String): Sha1 = Sha1(tryHex2bytes(hexOrBase64, bytesLength).getOrElse(base642bytes(hexOrBase64)))
}
2 changes: 1 addition & 1 deletion src/main/scala/com/avast/scala/hashes/Sha256.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ case class Sha256(bytes: Array[Byte]) {

object Sha256 {
private val bytesLength = 32
def apply(hexOrBase64: String): Sha256 = Sha256(if (hexOrBase64.length == 2 * bytesLength) hex2bytes(hexOrBase64) else base642bytes(hexOrBase64))
def apply(hexOrBase64: String): Sha256 = Sha256(tryHex2bytes(hexOrBase64, bytesLength).getOrElse(base642bytes(hexOrBase64)))
}
10 changes: 9 additions & 1 deletion src/main/scala/com/avast/scala/hashes/package.scala
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
package com.avast.scala

import java.util.Base64
import java.util.regex.Pattern

package object hashes {
def hex2bytes(hex: String): Array[Byte] = hex.replaceAll("[^0-9A-Fa-f]", "").sliding(2, 2).toArray.map(Integer.parseInt(_, 16).toByte)

private val hexAllowedCharactersRegex = Pattern.compile("[^0-9A-Fa-f]")
def hex2bytes(hex: String): Array[Byte] = hexbytesUnchecked(hexAllowedCharactersRegex.matcher(hex).replaceAll(""))
private def hexbytesUnchecked(hex: String): Array[Byte] = hex.sliding(2, 2).toArray.map(Integer.parseInt(_, 16).toByte)
def tryHex2bytes(maybeHex: String, expectedBytes: Int): Option[Array[Byte]] = {
val clean = hexAllowedCharactersRegex.matcher(maybeHex).replaceAll("")
if (clean.length == 2 * expectedBytes) Some(hexbytesUnchecked(clean)) else None
}

def bytes2hex(bytes: Array[Byte], sep: Option[String] = None): String =
sep match {
Expand Down
4 changes: 4 additions & 0 deletions src/test/scala/com/avast/scala/hashes/MD5Test.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,8 @@ class MD5Test extends AnyFlatSpec with Matchers {
it should "convert MD5 to lower-case" in {
MD5("6A18B3C45107538DE9D430F83A6AF988").toString() shouldBe "6a18b3c45107538de9d430f83a6af988"
}

it should "convert hex value with additional characters" in {
MD5("\"6A18B3C45107538DE9D430F83A6AF988 \"").toString() shouldBe "6a18b3c45107538de9d430f83a6af988"
}
}
4 changes: 4 additions & 0 deletions src/test/scala/com/avast/scala/hashes/Sha1Test.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,8 @@ class Sha1Test extends AnyFlatSpec with Matchers {
it should "convert the Sha1 to lower-case string" in {
Sha1("0FD08A268F6032CE2A83A17AC8ADCEAF82ADE5E3").toString() shouldBe "0fd08a268f6032ce2a83a17ac8adceaf82ade5e3"
}

it should "convert hex value with additional characters" in {
Sha1("\"0FD08A268F6032CE2A83A17AC8ADCEAF82ADE5E3 \"").toString() shouldBe "0fd08a268f6032ce2a83a17ac8adceaf82ade5e3"
}
}
4 changes: 4 additions & 0 deletions src/test/scala/com/avast/scala/hashes/Sha256Test.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ class Sha256Test extends AnyFlatSpec with Matchers {
Sha256("6A18B3C45107538DE9D430F83A6AF988EDBDDEB4E5A6BDB16F223A2FA37EE446").toString() shouldBe "6a18b3c45107538de9d430f83a6af988edbddeb4e5a6bdb16f223a2fa37ee446"
}

it should "convert hex value with additional characters" in {
Sha256("\"6A18B3C45107538DE9D430F83A6AF988EDBDDEB4E5A6BDB16F223A2FA37EE446 \"").toString() shouldBe "6a18b3c45107538de9d430f83a6af988edbddeb4e5a6bdb16f223a2fa37ee446"
}

it should "generate base64 of the same length for random SHA256" in {
(1 to 32).map(_ => Sha256(HashesMother.randomHexString(64)).toBase64String.length) shouldBe (1 to 32).map(_ => 44)
}
Expand Down

0 comments on commit c12529c

Please sign in to comment.