【问题标题】:How to correctly generate SHA-256 checksum for a string in scala?如何在scala中正确生成字符串的SHA-256校验和?
【发布时间】:2018-03-01 23:33:03
【问题描述】:

我需要从将作为 get 参数发送的字符串生成 SHA-256 校验和。

如果找到this link则生成校验和。

像这样生成校验和:

  val digest = MessageDigest.getInstance("SHA-256");      
  private def getCheckSum() = {
    println(new String(digest.digest(("Some String").getBytes(StandardCharsets.UTF_8))))        
  }

打印类似于这样的校验和:

*║┼¼┬]9AòdJb:#↓o6↓T╞B5C♀¼O~╟╙àÿG

我们需要将其发送到的 API 表示校验和应如下所示:

45e00158bc8454049b7208e76670466d49a5dfb2db4196

我做错了什么?

请指教。 谢谢。

【问题讨论】:

  • 她的消息摘要将返回原始字节。您期望的格式要求将它们编码为十六进制

标签: scala sha


【解决方案1】:

java.security.MessageDigest#digest 给出一个字节数组。

scala> import java.security.MessageDigest
scala> import java.math.BigInteger

scala> MessageDigest.getInstance("SHA-256").digest("some string".getBytes("UTF-8"))
res1: Array[Byte] = Array(97, -48, 52, 71, 49, 2, -41, -38, -61, 5, -112, 39, 112, 71, 31, -43, 15, 76, 91, 38, -10, -125, 26, 86, -35, -112, -75, 24, 75, 60, 48, -4)

要创建十六进制,请使用String.format

scala> val hash = String.format("%032x", new BigInteger(1, MessageDigest.getInstance("SHA-256").digest("some string".getBytes("UTF-8"))))
hash: String = 61d034473102d7dac305902770471fd50f4c5b26f6831a56dd90b5184b3c30fc

你可以在linux、unix中使用命令行工具验证hash

$ echo -n "some string" | openssl dgst -sha256
61d034473102d7dac305902770471fd50f4c5b26f6831a56dd90b5184b3c30fc

注意:

如果 java 返回长度小于 64 个字符的哈希,您可以使用0 填充。 (例如39

def hash64(data: String) = {
  val hash = String.format(
               "%032x", 
               new BigInteger(1, MessageDigest.getInstance("SHA-256").digest(data.getBytes("UTF-8")))
             )
  val hash64 = hash.reverse.padTo(64, "0").reverse.mkString 
  hash64      
}

【讨论】:

  • 这里的小错误,字符串表示缺少前导0,例如字符串39将返回b918943df0962bc7a1824c0555a389347b4febdc7cf9d1254406d80ce44e3f9而不是0b918943df0962bc7a1824c0555a389347b4febdc7cf9d1254406d80ce44e3f9
  • 似乎您打算使用"%064x" 而不是"%032x",这应该可以解决填充问题,因此您不需要padTo
【解决方案2】:

等效,但效率更高:

MessageDigest.getInstance("SHA-256")
  .digest("some string".getBytes("UTF-8"))
  .map("%02x".format(_)).mkString

【讨论】:

  • 使用您的方法生成的哈希码似乎与使用先前答案中的方法生成的不等效:imgur.com/a/a3Gfv
  • 是的,很抱歉。现已修复。
  • @Regressor 这是一个Sting.format 指令。 x 表示十六进制,02 表示两位数,必要时用 0 填充。所以,比如说,10(十六进制的a)打印为“0a”,而255(ff)是“ff”
【解决方案3】:

可以使用DatatypeConverter.printHexBinary

类似:

DatatypeConverter.printHexBinary(
  MessageDigest
    .getInstance(algorithm)
    .digest("some string").getBytes("UTF-8")))

【讨论】:

    猜你喜欢
    • 2016-03-13
    • 2023-01-25
    • 2021-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多