首页 > 解决方案 > SHA3-512 to Generate Keys in Java

问题描述

Is it possible to use SHA3-512(a subset of keccak available in Java9) to generate keys in Java?

I have searched through a lot of noise and documentation to try to figure this out. Currently it seems SHA3-512 is available as a hash for MessageDigest but not for generating keys. My code below tries to generate keys predictably(for wallet purposes like BIP32 but beyond currency to blockchain uses)

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);
    }

As you can see, it uses SHA1PRNG to predictably generate keypair deterministically(I am fine with the security concerns on this) so that the keys can be recreated deterministically.

Here is a JUnit test to make sure the keys are deterministic(works for SHA1PRNG, needs to work in SHA3PRNG). Ideally what is needed is a SHA3-512 TRNG in the GenerateSeed and a SHA3PRNG in the GenerateKey. Since the keygenerator needs a SecureRandom I would be surprised if java.Security.SecureRandom is still on something as insecure as 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);
    }

Can someone please let me know if they figured a way to get this to work

标签: javasecuritybouncycastleblockchainsha-3

解决方案


您正在寻找的东西似乎不是开箱即用的:

请注意SHA1SHA1PRNG不等价。前者是散列算法,后者是伪随机生成算法(SHA1当然,它用于更新其内部状态。)这种差异的一个简单结果是,SHA1输出固定大小的位,其中SHA1PRNG输出与你喜欢。

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

这个棘手部分的一个主要问题可能如下:从这里引用,

论文“基于海绵的伪随机数生成器”讨论了这一点,它还描述了一种干净有效的方法来构建PRNG具有 (Keccak) 海绵函数的可重复种子。你会得到一个PRNG基于加密哈希函数的......具有通常的安全含义。

例如:该论文明确指出,您应该定期使用足够的熵重新播种,以防止攻击者在该周期内倒退PRNG(这可能是您所听说的)。

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

祝你好运!


推荐阅读