【问题标题】:Serialize BigInteger in Java, deserialize with Botan?用Java序列化BigInteger,用Botan反序列化?
【发布时间】:2018-07-18 10:29:14
【问题描述】:

问题:如何在 Java 中转换 BigInteger 以匹配 Botan BigInt 编码?

我使用 Botan 在 Java 和 C++ 应用程序之间进行通信。 Botan 有一个 BigInt 类,与 BigInteger 相当。但是,转换为字节数组时,编码会有所不同。

在 Botan 中,BigInt 编码如下:

void BigInt::binary_encode(uint8_t output[]) const
{
   //bytes just returns the # of bytes, in my case its 32 always
   const size_t sig_bytes = bytes();
   for(size_t i = 0; i != sig_bytes; ++i)
      output[sig_bytes-i-1] = byte_at(i);
}

在 Java 中,它的编码:

 public byte[] toByteArray() {
        int byteLen = bitLength()/8 + 1;
        byte[] byteArray = new byte[byteLen];

        for (int i=byteLen-1, bytesCopied=4, nextInt=0, intIndex=0; i >= 0; i--) {
            if (bytesCopied == 4) {
                nextInt = getInt(intIndex++);
                bytesCopied = 1;
            } else {
                nextInt >>>= 8;
                bytesCopied++;
            }
            byteArray[i] = (byte)nextInt;
        }
        return byteArray;
    }

【问题讨论】:

  • 标题错误。目前想不出更好的,但它会吸引巨魔。我能想到的最好的事情是序列化为中性编码,然后将其读回特定编码。对于愚蠢的概念证明,我会使用一串 ASCII 数字。
  • Javadocs 非常仔细和准确地描述了BigInteger.toByteArray() 的输出。博坦呢?
  • 在每个系统上都有来自相同输入的样本输出会更有用,这样我们就可以给你一个有意义的答案。我知道我无法使用 Botan 进行测试。正如@matt 所建议的那样,事情可能会因为 Java 没有无符号数据类型而被抛弃。
  • 您要序列化的整数是负数吗? Java 在编码时使用 2s 补码表示,而 Botan 在编码时有效地忽略符号,编码绝对值。对于非负整数,Botan 应该毫无问题地解码 Java 的 toByteArray 的输出。另一个可能的问题是,Java 还假设 byte[] 构造函数的输入是 2s 补码。因此,如果您在 Botan 中使用设置的高位对整数进行编码,它将输出一个设置了前导 1 位的数组。 Java 会将其解释为负整数。使用 0x00 字节的前缀来解决这个问题。

标签: java c++ encryption biginteger botan


【解决方案1】:

你可以

  • 将大整数右移long(以位为单位)的大小,并转换为long(删除所有高位字节)。这将为您提供最低顺序的肢体(类似于数字,除了long 而不是位)。
  • 重复上述操作,直到移位后的大整数(不仅仅是低位字节)的值为 0。你会想要
  • 将循环中的longs 存储在一个数组中。这个longs 数组可以通过 JNI 或您使用的任何跨语言接口传递。
  • 在另一种语言中,进行相反的操作:初始化一个空的大整数作为累加器,将数组从高位循环到低位,将当前累加向左移动long 的大小,然后按位-或当前多头值到低位。后续迭代的移动将使肢体进入其最终位置。

这些算法应该适用于任何大型整数库(假设它们提供基本操作,如移位和转换为长整数),我想在任何语言中。这应该比转换为文本表示更快,但这种方法在更简单的实现方面更胜一筹。

【讨论】: