java - Java 加密与 And .NET 的十六进制生成问题

标签 java c# .net hex modulus

我正在从 Java 和 .NET 系统生成模数和指数,但两者存在差异。我需要像java中的.NET那样的结果。 Java 在模数的十六进制转换中添加两个额外的零,并在指数中删除 1 个零,但 .NET 生成正确。请参阅以下来自 .Net 和 Java 的结果。

<小时/>

如果我使用 toString(16) 那么它会生成以下结果。 toString(16) 不是在模数中添加两个零,而是从指数中删除一个零,其中.NET 在指数中添加一个 0 并从模数中删除两个零,这就是我想要的。

String modlusHexString = publicKey.getModulus().toString(16).toUpperCase();
String exponentHexString = publicKey.getPublicExponent().toString(16).toUpperCase();

模数十六进制转字符串(16): D9B4E023A7CEF604499E184CBA7B7847FE35A824D15FF902EADB952FB54620158A564EFDDB0A66A7647CBDB339359BF6756F5851A73CC1D248 59A064DD7AE30B2330F965C54682B10E886D35FE005F42B056C7ABF64D3F6D592AEDC0234417507A0A1432E51C7867E3ACC4867A1AE03EF9E62050180882B18771D57 03C8BADCB3AC767CD1A1C0F9344F10B8C82EF5D0ACA4422512EA3ECCB5B71097BDEDAD9BBBE11697D1E61814CF3BBDEB48BDC2C95AA10DFC3F7F794E307D49B5455F928A9BB3ED2F2 8D6E2974238EFB2D9A822EC1832177CB988206204DF1D9DB7D291E2816576BEBD669184894B526F0B5D10C7D19FA67E79DADDF97D4A3082D4812A27B

指数十六进制转字符串(16): 10001

<小时/>

我尝试了下面的方法也将模数和指数的 BigInteger 转换为十六进制,但没有运气-

static String toHex(byte[] ba) {
        StringBuilder hex = new StringBuilder(ba.length * 2);
        for (byte b : ba) {
            hex.append(String.format("%02x", b, 0xff));
        }
        return hex.toString().toUpperCase();
    }

模数十六进制: 00D9B4E023A7CEF604499E184CBA7B7847FE35A824D15FF902EADB952FB54620158A564EFDDB0A66A7647CBDB339359BF6756F5851A73CC1D24859A 064DD7AE30B2330F965C54682B10E886D35FE005F42B056C7ABF64D3F6D592AEDC0234417507A0A1432E51C7867E3ACC4867A1AE03EF9E62050180882B18771D5703C 8BADCB3AC767CD1A1C0F9344F10B8C82EF5D0ACA4422512EA3ECCB5B71097BDEDAD9BBBE11697D1E61814CF3BBDEB48BDC2C95AA10DFC3F7F794E307D49B5455F928A9BB3ED2F28D6 E2974238EFB2D9A822EC1832177CB988206204DF1D9DB7D291E2816576BEBD669184894B526F0B5D10C7D19FA67E79DADDF97D4A3082D4812A27B

指数: 010001

<小时/>

以下是 .NET 生成的公钥模数和指数的十六进制,这是正确的

  • .NET

十六进制模数: F86020AFD75A03911BE8818BCB506B5DAC2760C68BB46F2A53E10E3E0972A7FFFFF71EAC0E0D73E8FDB4C332C759E781E54C0F1F4637656E6E995873B9580027F496 06811C7B5DB458C1BAC3E3D6EB7B77BFE1E55A822F23797E4CB27C7BD88C1B782AEF5235DAE55B937ABB0FFD30AF64F8D69DA07946441D9E4704FA98BD026E00A92851FABC8 AB347AB75615ACC8A7CCFDE56B0797DDB70FCA1F28F23F86548AABE6DD89B5CC859BC6352D077F765AACF15695215850A8D7E1F9DF187AE0EF1934E096B739E884757F810B33 20EFA72BBE2A957CE465E2010A5FD9C96A5F6456658D3BA0DF51B472AFEBEF31C3609B58C6A03C671DA33650039822465179

指数: 010001

最佳答案

您遇到的问题是由方法 BigInteger.toString(int radix)BigInteger.toByteArray() 的行为造成的。

当您调用BigInteger.toString(int radix)方法时,它仅返回数字的有效数字。因此,例如,如果该值应为 05ABFF,则它仅返回 5ABFF。当基数为 10 时,这是很自然的(我们不希望大整数 13 被转换为类似 013 的东西),但是当基数是 16,因为您期望输出具有偶数长度,每个字节恰好有两个字符。但事实并非如此。

但是当您调用自己的 toHex() 方法时,它基于从 BigInteger.toByteArray() 返回的值。在这里你还有另一个问题。此方法始终返回表示数字所需的字节数,包括符号位。现在考虑数字0xD9B4E023。如果它被视为整数,那么它实际上是一个负数,但如果它被 BigInt 视为正数,则需要一个额外的字节来表示符号。因此,在您的方法中,附加字节会转换为 00

我可以想到两种可能的解决方案:

static String toHex(byte[] ba) {
    StringBuilder hex = new StringBuilder(ba.length * 2);
    boolean skipZeroBytes = true;
    for (byte b : ba) {
        // As soon as we hit the first non-zero byte, we stop skipping bytes
        if (b != 0) {
            skipZeroBytes = false;
        }
        // If the current byte is zero, and we are in skipping mode, skip
        if (skipZeroBytes) {
            continue;
        }
        hex.append(String.format("%02X", b, 0xff));
    }
    if (skipZeroBytes) {
        // If we are still in skipping mode, it means all the bytes in the
        // array were zero and we skipped them all. So just return the
        // representation of a zero.
        return "00";
    } else {
        return hex.toString();
    }
}

我们在这里所做的是跳过所有初始零字节,直到我们到达第一个非零字节,然后才开始解释它。小提示:使用格式 %02X 和大写的 X 可以为您提供大写的十六进制数字,并且无需稍后调用 toUpperCase()

另一种更简单的方法是将缺少的零添加到 BigInteger.toString(int radix) 的结果中:

static String toHex2(BigInteger bi) {
    String hex = bi.toString(16).toUpperCase();
    if (hex.length() % 2 == 1) {
        return "0" + hex;
    } else {
        return hex;
    }
}

关于java - Java 加密与 And .NET 的十六进制生成问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27641519/

相关文章:

c# - 处理大型查询的超时

java - 减少属性树

java - 如何制作 GridView 项目( TextView )的 .setText() onItemSelected?

Java:成对对象的高效集合概念

c# - 字符串与 StringBuilder

c# - 我如何知道 WindowsFormsHost 何时在 WPF 中调整大小?

java - 如何使用superdev模式进行调试?

C# 使用 LINQ 查询更新字典 <string,string>

c# - 带参数的异步 lambda 表达式

.net - XslTransform 与 XslCompiledTransform