0

如何将大整数转换为 Java 密码库的密钥?我正在尝试使用我自己生成的共享 diffie hellman 密钥作为 AES 加密的密钥值。

下面是我使用的代码

BigInteger bi; long value = 1000000000; 

bi = BigInteger.valueOf(value); 键键=新键(bi);

但是它没有用。我可以知道如何将 BigInteger 值转换为 Key 值吗?

提前致谢!

4

2 回答 2

2

首先,你不能施放它。BigInteger类和Key接口之间没有关系。

其次,Key是接口而不是类,因此您不能创建它的实例。您需要创建的是某个实现Key. 它很可能需要一个特定的实现类,而不是(比如说)一个匿名类。

最后一件事是 Java 加密 API 旨在隐藏密钥的表示。要从字节创建密钥,您需要创建一个KeySpec对象;eg SecretKeySpec(byte[] key, String algorithm)) 然后使用 aKeyFactory从中“生成”一个密钥。典型的KeySpec构造函数将 abyte[]作为参数,因此您首先需要从您的BigInteger实例中获取字节数组。

于 2013-07-20T05:35:25.277 回答
1

您需要将您的转换BigInteger为特定大小的字节数组,然后使用第一个(最左边的)字节来创建一个键。为此,您需要知道 DH 中使用的素数 p 的大小,因为该值需要左填充以表示一个键。我建议使用标准化的 DH 参数(或至少确保素数的大小可被 8 整除)。

请注意,使用检索的字节数组前面可能有一个零值字节,BigInteger.toByteArray()因为返回的值被编码为有符号(双补码)大端字节数组。如果结果大于素数(以字节为单位),则需要删除此字节。

public static byte[] encodeSharedSecret(final BigInteger sharedSecret, final int primeSizeBits) {

    // TODO assignment add additional tests on input

    final int sharedSecretSize = (primeSizeBits + Byte.SIZE - 1) / Byte.SIZE;

    final byte[] signedSharedSecretEncoding = sharedSecret.toByteArray();
    final int signedSharedSecretEncodingLength = signedSharedSecretEncoding.length;

    if (signedSharedSecretEncodingLength == sharedSecretSize) {
        return signedSharedSecretEncoding;
    }

    if (signedSharedSecretEncodingLength == sharedSecretSize + 1) {
        final byte[] sharedSecretEncoding = new byte[sharedSecretSize];
        System.arraycopy(signedSharedSecretEncoding, 1, sharedSecretEncoding, 0, sharedSecretSize);
        return sharedSecretEncoding;
    }

    if (signedSharedSecretEncodingLength < sharedSecretSize) {
        final byte[] sharedSecretEncoding = new byte[sharedSecretSize];
        System.arraycopy(signedSharedSecretEncoding, 0,
                sharedSecretEncoding, sharedSecretSize - signedSharedSecretEncodingLength, signedSharedSecretEncodingLength);
        return sharedSecretEncoding;
    }

    throw new IllegalArgumentException("Shared secret is too big");
}

之后,您需要使用某种密钥派生方案来派生密钥字节。您应该使用的标准取决于您正在实施的标准:

RFC 2631中所述

X9.42 提供了一种算法,用于从 ZZ 生成基本上任意数量的密钥材料。我们的算法是通过强制一些可选字段并省略其他字段从该算法派生而来的。

 KM = H ( ZZ || OtherInfo)

H 是消息摘要函数 SHA-1 [FIPS-180] ZZ 是在第 2.1.1 节中计算的共享秘密值。必须
保留前导零,以便 ZZ 占用与 p 一样多的八位字节。

请注意,我在 DH 实现中发现了最高 1.49 的 Bouncy Castle 库(这是当前版本)中关于秘密提取的错误 - 它确实去除了虚假的前导 00h 值字节,但它忘记了左填充结果直到素数大小 p。这将导致 192 次不正确的派生密钥 (!)

于 2013-07-20T12:16:27.170 回答