【问题标题】:How to pass unsigned bytes to SecretKeySpec()?如何将无符号字节传递给 SecretKeySpec()?
【发布时间】:2016-01-13 12:01:11
【问题描述】:

我需要使用 Java 的 SecretKeySpec() 和大于 127 的数字数组。

如果我执行以下操作:

new byte[] { (byte)0xD9, (byte)0xDF, (byte)0x85 }

数字被转换为字节,它们将是负数。

当然我可以用0xFF & 他们并将它们保存在short 数组中并保存它们的值,但是我将无法将此数组传递给SecretKeySpec(),因为它只接收bytes[] 数组。

有什么想法吗?

【问题讨论】:

  • 如果 SecretKeySpec 需要一个字节[],那么您必须假设它正确处理 > 127 的值。你的实际问题是什么?
  • 这样写:new byte[] { 0xD9, 0xDF, 0x85 } 会产生错误。它需要是这样的:new byte[] { (byte)0xD9, (byte)0xDF, (byte)0x85 }。如果是这样,则将数字转换为带符号的数字。所以我已经传递了一个错误的数组...
  • 你不能有一个等于 128 的字节,因为没有无符号字节。所以 SecretKeySpec 必须相应地处理它。为什么说是错误的数组?
  • { 0xD9, 0xDF, 0x85 } = {217, 223, 133},但{ (byte)0xD9, (byte)0xDF, (byte)0x85 } = {-39, -33, -123}
  • 应该是这样。那是什么错误造成的。如果您只想显示未签名的版本,您可以使用 Byte.toUnsignedInt。

标签: java byte unsigned


【解决方案1】:

这实际上只是一个渲染问题。 SecretKeySpec 使用字节数组,构造字节数组没有问题。唯一的问题是如何将大 (>127) 整数表示为 java 字节,或者等效地,将“217”表示为一个字节。

你可以使用任何你想要的映射,但是 Java 有一个非常自然的选择——将整数转换为字节,使用强制转换,(byte)i,然后转换回来,使用Byte.toUnsignedInt(b)。如您所见,这恢复了原始值:

public static void main( String[] args )
{
    for (int count = 0; count<256; count++){
        System.out.println(count+" : "+(byte)count+" => "+Byte.toUnsignedInt((byte)count));
    }
}

【讨论】:

  • 问题是我将什么传递给SecretKeySpec()?从文档中:为指定的密钥数据和算法名称创建一个新的 SecretKeySpec。 所以它在数字 217 和 -39 上的工作方式不同。我需要它在 217 上工作
  • 我看到“这个类只对可以表示为字节数组的原始密钥有用......”。而且我的示例中的数字不能表示为字节数组,所以我想这是不可能的
  • 可以将 217 表示为一个字节,唯一的问题是哪个字节,并且有一种自然的规范方法可以做到这一点。此外,仅当您尝试复制从另一个来源创建的 SecretKeySpec 时,映射才重要 - 这就是您想要做的吗?
  • C# 中使用了一些硬编码密钥进行加密,我需要在 Java 中使用相同的硬编码密钥, C# 的解密算法(我无法更改)以处理生成的 Java 加密数据。而 C# 中的 bytes 是未签名的...
  • 我想说这很可能是在那里使用的映射。不是 100%,但要确保您必须深入研究 C# 文档并查看其整数的二进制表示如何对应于 Java。 (或者只是试试看)
【解决方案2】:

似乎没有必要这样做。 我确实将带符号的值写入 Java 中的 byte[] 数组,并在 C# 中将它们读取为无符号(例如,Java 的 -16 在 C# 中读取 240)。但解密仍然有效。似乎这在 Rijndael 算法中得到了处理。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-14
    • 2010-11-15
    相关资源
    最近更新 更多