代码之家  ›  专栏  ›  技术社区  ›  ziyasal

如何将一个按网络字节顺序将四个字符视为无符号长字符的BigInt打包为Ruby的。在Scala中,pack(N)做什么?

  •  0
  • ziyasal  · 技术社区  · 7 年前

    这是Ruby等价物

    [Digest::MD5.hexdigest("Data to pack").to_i(16)].pack("N")
    

    输出: "\x1AP0\\"

    生成的大整数为(md5哈希);

    321255238386231367014342192054081171548
    

    在Scala中,我得到了如下BigInt;

    def md5Hash(input: String): String = md5HashArr(input.getBytes(StandardCharsets.UTF_8))
    def md5HashArr(bytes: Array[Byte]): String = {
        val digest = java.security.MessageDigest.getInstance("MD5")
        digest.reset()
        digest.update(bytes)
        digest.digest().map(0xFF & _).map {
          "%02x".format(_)
        }.foldLeft("") {
          _ + _
        }
      }
    
    def hex2dec(hex: String): BigInt = {
        hex.toLowerCase().toList.map(
          "0123456789abcdef".indexOf(_)).map(
          BigInt(_)).reduceLeft(_ * 16 + _)
     }
    
    def bytes2hexStr(bytes: Array[Byte], sep: String = ""): String = bytes.map("0x%02x".format(_)).mkString(sep)
    
    
    val result: BigInt = hex2dec(md5Hash("Data to pack"))
    val resultAsByteArray: Array[Byte] = result.toByteArray
    

    在转换为十六进制str之前,如下所示;

    val hexStr:String = bytes2hexStr(resultAsByteArray)
    

    在Scala中,我该怎么做呢?

    谢谢你的帮助。

    1 回复  |  直到 7 年前
        1
  •  1
  •   Artavazd Balayan    7 年前

    对于Ruby中的BigNum,似乎pack方法将只打包最后32位(4字节)。因此,对于这个散列f1af822290cfcac4ce476a69 1a50305c

    [Digest::MD5.hexdigest("Data to pack").to_i(16)]
    .pack("N")
    .each_byte.map { |b| sprintf("0x%02X ",b) }.join
    

    显示 0x1A 0x50 0x30 0x5C ,是最后4个字节

    具有相同行为的Scala实现:

    import java.security.MessageDigest
    import java.nio._
    import java.io._
    
    import scala.annotation.tailrec
    
    object MD5 {
      def main(args: Array[String]) =  {
        val str = "Data to pack"
        val md5Bytes = calcMd5(str)
        val md5Str = md5Bytes.map(b => "%02x".format(b)).mkString
        println(s"$str => $md5Str")
    
        // Get last 4-bytes
        val byteArr = md5Bytes.slice(12, 16)
    
        // Print it
        print(s"Last 4-bytes => ")
        byteArr.foreach { r =>
          print("%02X ".format(r))
        }
        println
    
      }  
    
      def calcMd5(str: String): Array[Byte] = {
        MessageDigest.getInstance("MD5")
        .digest(str.getBytes)
      }
    }