SHA3​​-512用Java生成密钥

时间:2018-04-26 21:31:29

标签: java security bouncycastle blockchain sha-3

是否可以使用SHA3-512(Java9中可用的keccak的子集)在Java中生成密钥?

我搜索过很多噪音和文档,试图弄明白这一点。 目前似乎SHA3-512可用作MessageDigest的哈希,但不能用于生成密钥。我下面的代码试图以可预测的方式生成密钥(用于钱包目的,如BIP32,但超出货币到区块链使用)

https://github.com/devssh/BlockchainFullNode/blob/d2978e598b4cdecdf4b3337713b2c3e839a6b181/src/main/java/app/model/Keyz.java#L111-L128

    public static String GenerateSeed() throws Exception {
        SecureRandom random = new SecureRandom();
        byte[] seed = random.generateSeed(512);
        return Base64.getEncoder().encodeToString(seed);
    }

    public static Keyz GenerateKey(String seedString) {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        KeyPairGenerator keyGen1 = KeyPairGenerator.getInstance("ECDSA");
        ECGenParameterSpec ecSpec = new ECGenParameterSpec("secp256k1");
        SecureRandom random1 = SecureRandom.getInstance("SHA1PRNG");
        random1.setSeed(Base64.getDecoder().decode(seedString));
        keyGen1.initialize(ecSpec, random1);
        KeyPair keyPair1 = keyGen1.generateKeyPair();
        PublicKey pub1 = keyPair1.getPublic();
        PrivateKey priv1 = keyPair1.getPrivate();
        //Keyz is a simple model that stores the 3 fields below and overrides equals and hashcode on those fields
        return new Keyz("random", pub1, priv1);
    }

正如您所看到的,它使用SHA1PRNG可预测地确定性地生成密钥对(我对这方面的安全性问题很好),以便可以确定性地重新创建密钥。

这是一个JUnit测试,用于确保密钥是确定性的(适用于SHA1PRNG,需要在SHA3PRNG中工作)。理想情况下,需要的是GenerateSeed中的SHA3-512 TRNG和GenerateKey中的SHA3PRNG。由于密钥生成器需要SecureRandom,如果java.Security.SecureRandom仍然像SHA1PRNG那样不安全,我会感到惊讶。

https://github.com/devssh/BlockchainFullNode/blob/d2978e598b4cdecdf4b3337713b2c3e839a6b181/test/main/java/app/model/KeyzTest.java#L16-L22

    @Test
    public void shouldReturnDeterministicKeys() throws Exception {
        String seedString = GenerateSeed();
        Keyz random1 = GenerateKey(seedString);
        Keyz random2 = GenerateKey(seedString);
        //This assertion works as we override equals and hashcode
        assertEquals(random1, random2);
    }

有人可以告诉我他们是否想办法让这个工作

1 个答案:

答案 0 :(得分:2)

看起来你想要的东西不是开箱即用的:

请注意,SHA1SHA1PRNG不相同。虽然前者是散列算法,但后者是伪随机生成算法(当然,使用SHA1来更新其内部状态。)这种差异的一个微不足道的结果是,SHA1输出一个固定的位大小,SHA1PRNG输出任意多个位。

由于存在这种差异,SHA3-512不能直接用作PRNG,尽管它在Java中可用。您需要做的是,使用PRNG实现SHA3-512算法(这部分非常棘手,因为生成伪随机流非常困难。)并通过自定义Security Provider注册它(例如Bouncy Castle),名称为MySHA3PRNG。之后,您可以像MySHA3PRNG一样获取名称为SHA1PRNG的实例。其余的仍然是原样。

这个棘手部分的一个主要问题可能如下:引自here

  

论文" Sponge-based pseudo-random number generators"谈到这一点,它还描述了一种干净有效的方法来构建具有(Keccak)海绵功能的重新种子PRNG。您将获得的是基于加密哈希函数的PRNG ......具有通常的安全隐患。

     

例如:本文明确指出您应该定期重新定位并使用足够的熵来防止攻击者在PRNG期间(这可能是您已经听过的内容)倒退。

但是,您需要的是PRNG算法,不需要重新播种。我希望您有足够的理论背景证明您的自定义PRNG算法是安全的。

祝你好运!

相关问题