【问题标题】:Java integer/double to unsigned byteJava整数/双精度到无符号字节
【发布时间】:2017-10-17 03:01:49
【问题描述】:

现在我知道 java 没有无符号字节,但如果没有,我不确定如何解决这个问题。 我正在尝试在 java 中实现 SHA256 散列,并且我正在处理将消息转换为 512 位。

int l = bytes.length; //total amount of bytes in the original message
int k = 0;
while((l+1+k) % 512 != 448) {
        k++;
}
//k is the total amount of 0's to be padded
int rest = k % 8;  //get the amount of 0's to be added in the byte with the 1
byte tmp =(byte) Math.pow(2, rest);

所以关键指令是最后一行,如果 rest = 7 结果 int 是 128,但是字节在 java 中是有符号的,所以字节变成 0x80 而不是 0xF0。 如何在 Java 中实现这一点?

如果有人知道如何实现这部分,请告诉我。

【问题讨论】:

  • 为什么 128 会是 0xF0
  • RIght,rest 应该是一个从 0 到 7 的数字,它们都已经是正数并且适合 byte 的范围。我认为您可能还有其他问题。
  • 仅作记录:这是为了学习目的?您知道在现实世界中实现自己的密码学最有可能是一个非常糟糕的主意吗?
  • 顺便说一句,你最好使用1<<rest 而不是Math.pow(2, rest)
  • “Java 没有无符号字节”并没有直接错误,但它通常没有抓住重点。有符号字节仍然有 8 位,您可以(小心地)将它们视为无符号字节。 (byte)128 仍然是正确的结果,即使它在调试器中看起来像 -128。无论哪种方式都是 0x80。

标签: java int byte unsigned sha256


【解决方案1】:

从您的消息由字节组成的假设开始,填充总是作为 8 位的多个,也就是字节。这确保了最高有效填充位始终位于消息后面的第一个填充字节的第 7 位,因此填充(如果有)始终从 0x80 开始,然后根据需要跟随尽可能多的 0x00。

这可以通过非常简单的方式实现:

public static byte[] padMsg(byte[] rawMsg) {
    int rawLen = rawMsg.length;
    int padLen = (64 - (rawLen & 0x3F)) & 0x3F;
    if (padLen == 0)
        return rawMsg;
    // all extra bytes in padded msg are zeros.
    byte[] paddedMsg = Arrays.copyOf(rawMsg, rawLen + padLen);
    // ensure topmost pad bit is a one
    paddedMsg[rawLen] = (byte) 0x80;
    return paddedMsg;
}

这将获取消息长度并获取余数。 2 的幂的余数(在本例中为 64),最有效的方法是用 (power - 1) 简单地与掩码得到,这就是代码中的 0x3F 来自 (= 64 - 1) 的地方。 在计算 (64 - 余数) 作为初步填充长度后再次取余数,以捕捉余数为 0 的特殊情况,导致 64 字节的错误填充长度(应为 0 填充)。

一旦知道以字节为单位的填充长度,就会捕获 padding = 0 的情况。在任何其他情况下,消息长度都会增加(使用 0x00 字节,Arrays.copyOf 会自动执行此操作)。然后将第一个填充字节替换为 0x80,并返回现在保证长度为 64 字节的倍数的填充消息。

【讨论】:

    猜你喜欢
    • 2014-02-04
    • 1970-01-01
    • 2013-05-18
    • 1970-01-01
    • 2019-06-07
    • 2011-02-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多