将BigInteger转换为密钥

时间:2013-07-20 05:12:05

标签: java encryption aes

如何将Big Integer转换为java加密库的密钥? 我正在尝试使用我自己生成的共享diffie hellman密钥,用于AES加密的密钥值。

以下是我使用的代码

BigInteger bi; long value = 1000000000; 
     

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

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

提前致谢!

2 个答案:

答案 0 :(得分:2)

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

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

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

答案 1 :(得分:1)

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

请注意,使用BigInteger.toByteArray()检索的字节数组前面可能存在零值字节,因为返回的值是编码作为签名(两个-complement)big-endian字节数组。如果结果大于素数(以字节为单位),则需要删除此字节。

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占用尽可能多的八位字节。

请注意,我在DH实现中发现了Bouncy Castle库中的一个错误,最高可达1.49(这是当前当前的版本)关于秘密提取的错误 - 它确实剥离了假的前导00h有价值的字节,但它会忘记将结果左键填充到素数大小p。这将在192次(!)

中导致一次不正确的派生密钥