如何将HmacSHA256截断为128位?

时间:2014-10-23 22:38:50

标签: java hmac sha256 javax.crypto

Java支持三种MAC算法:

  • HMACMD5
  • HMACSHA1
  • HmacSHA256

但我需要使用HMAC-SHA256-128签名,这是HmacSHA256但截断为128位。

此示例和变体已在stackoverflow上传播:

String MAC = hmacHelper.calculatePlainMAC("00000000", "HmacSHA256");

String bgSecretKey="1234567890ABCDEF1234567890ABCDEF";

public String calculatePlainMAC(String ascii, String algorithm)
{
  Mac mac = null;
  final Charset asciiCs = Charset.forName("US-ASCII");
  try
  {
    SecretKeySpec signingKey = new SecretKeySpec(bgcSecretKey.getBytes(), algorithm);
    mac = Mac.getInstance(algorithm);
    mac.init(signingKey);
    byte[] rawHmac = mac.doFinal(asciiCs.encode(ascii).array());

    String result = "";
    for (final byte element : rawHmac)
    {
      result += Integer.toString((element & 0xff) + 0x100, 16);//.substring(1);
    }
    log.debug("Result: " + result);
    return result;
  }
  catch (NoSuchAlgorithmException e)
  {
    e.printStackTrace();
    return null;
  }
  catch (InvalidKeyException e)
  {
    e.printStackTrace();
    return null;
  }
}

结果:

1051cd18118219e1261f41401891fd1911a91cf1bc1751db13e10617c1221131231c31ab15613f14412c1681d7132178

这一切都很好,除了我需要一个128位的结果,我知道是

FF365893D899291C3BF505FB3175E880

我不知道他们是如何达到这个结果的。我所知道的是使用的HMAC算法是HmacSHA256-128。根据我的理解,这个算法将生成一个256位的结果,问题是,如何将其截断为128位结果,返回上面的已知结果?

2 个答案:

答案 0 :(得分:0)

以下行总是在字符串中添加3个字符,以' 1'开头。注释的子字符串(1)删除1.它被使用,以便单个字符结果获得预先设置为零。

result += Integer.toString((element & 0xff) + 0x100, 16);//.substring(1);

但是,即使您修复此问题,结果也不会包含您期望的截断结果。

05cd81829e26f44089fd91a9cfbc75db3e067c221323c3ab563f442c68d73278

这当然取决于bgcSecretKey的值。

您需要使用与导出预期结果相同的键/算法/截断。

答案 1 :(得分:0)

问题在于“键”应该转换为二进制表示形式,而不是字符串值的二进制表示形式!

即。 bgcSecretKey.getBytes()应该是javax.xml.bind.DatatypeConverter.parseHexBinary(bgcSecretKey)或您希望将十六进制转换为二进制值的任何函数。 然后一切正常。整个代码:

Key