SHA3-512 to Generate Keys in Java
是否有可能使用Java 3-512(JavaC9中可用的KECAK子集)在Java中生成密钥?
我搜索了大量的噪音和文档,试图找出这个问题。目前,似乎sha3-512可以作为messagedigest的哈希,但不能用于生成密钥。我下面的代码试图以可预测的方式生成密钥(用于钱包目的,如bip32,但超出了货币到区块链的使用范围)
http://Github.com/DevsS/BlockchainFullNode /BoB/D29 78E598B4CCDDF4B336713B2C3E839 A6B181/SRC/MON/JAVA/APP/MID/KEZZ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| 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)。理想情况下,需要的是一个sha3-512 trng在生成和sha3prng在生成键。因为keygenerator需要一个secureRandom,所以如果java.security.secureRandom仍然像sha1prng一样不安全,我会感到惊讶。
http://Github.com/DevsS/BlockchainFullNode /BoB/D29 78E598B4CCDDF4B336713B2C3E839 A6B181/Test/Maule/Java/APP/My/KEZZTest.JavaSyL16-L22
1 2 3 4 5 6 7 8
| @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 );
} |
号
有人能告诉我他们有没有办法让这个工作
- 你所说的"确定性"是什么意思?sha1prng作为后缀,用于产生伪随机数。所以您的代码在每次运行时(几乎)生成不同的键。我想你错过了什么。
- sha3是一个散列;它不生成键,它生成字节。
- 不是@ram,我需要它对给定的种子具有确定性。假设我产生了一个具有足够随机性的种子。现在,我想存储种子,在将来的任何时候重新创建密钥并获得相同的公私密钥对。sha1prng让我设置secureRandom的种子,它尊重我的种子值而不是忽略它。现在假设我有一百万个拥有多个密钥的用户,我只需要存储根种子而不是所有的密钥。请阅读bip32了解更多上下文。这部分在我的代码中解决了。我想把它从hashing with sha1prng移到sha3-512。
- @詹姆斯,是的,我已经在这个问题上添加了更多的代码来说明如何处理这个问题。
- 你的提议有很大的问题。sha1prng没有很好地定义,可能会在实现之间发生更改。其他Java版本可能不使用EDCOX1 0来实际设置种子。有多种方法可以从随机数生成器生成一个数字;生成器在为ECDSA派生私钥的其他变体中的使用可能有所不同(好吧,这更像是一个理论上的观点,但仍然可以想象在大和小endian平台上有一个本机密钥)。重新播种也是一种你不想遇到的可能性。
- 最好使用kdf、流密码或xof来生成私钥的值s,然后使用point addition和g来计算公共点。你可能需要弹性城堡。"我对这方面的安全问题很满意:"我认为这最好是幼稚的,最坏是疏忽大意的。
- @是的,因为我预见到了这个问题,所以我确保在Gradle中修复我所有的版本。我还审查了我的Java版本。
- @Maarten安全问题是无效的,因为我们永远不会在公共场合使用这些密钥。我们将使用这些密钥作为生成器来生成更多永远不会重复的密钥。所以用例很重要,也不是一个集中的系统。我只是提供一个实现,如果有人想要自己制作密钥,将它们保密并用于签名,那么他们应该在我的区块链中。至于突破性的变化,这就是为什么我要编写测试来确保它不会发生的原因。
您要找的似乎不是现成的:
注意,SHA1和SHA1PRNG不是等效的。前者是散列算法,后者是一种伪随机生成算法(当然,它使用SHA1来更新其内部状态)。这种差异的一个微不足道的结果是,SHA1输出固定大小的位,其中SHA1PRNG输出任意多的位。
由于这种差异,EDCOX1〔5〕不能直接用作EDCOX1〔6〕,虽然在Java中是可用的。您需要做的是,使用SHA3-512实现一个PRNG算法(这部分非常困难,因为生成一个伪随机流非常困难),并通过您的自定义Security Provider注册它(就像Bouncy Castle做的那样),使用一些名称MySHA3PRNG注册它。之后,您可以得到一个名为MySHA3PRNG的实例,就像您对SHA1PRNG所做的那样。其余的仍保持原样。
这个棘手部分的一个主要问题可能是:从这里引用,
The paper"Sponge-based pseudo-random number generators" talks about just that and it also describes a clean and efficient way to construct a re-seedable PRNG with a (Keccak) sponge function. What you'll get is a PRNG based on a cryptographic hash function… with the usual security implications.
For example: the paper explicitly states that you should reseed regularly with sufficient entropy to prevent an attacker from going backwards on the period of the PRNG (which is probably what you've been hearing about).
号
但是,您需要的是一个不需要重新播种的PRNG算法。我希望您有足够的理论背景来证明您的自定义PRNG算法是安全的。
祝你好运!
- 您不需要创建自定义安全提供程序。您只需要(小心地)子类SecureRandom并传递它的实例。但是你不能使用SecureRandom.getInstance(),你必须使用new MySecureRandom()。
- @jameskpolk这可能是一个选项,尽管提供商的解决方案在我看来更优雅。不管怎样,关键的部分是从哈希实现prng。
- @RAM谢谢,我已经放弃了java.security,并在ECDSA上实现了自己的密钥生成和签名算法。有时候你只需要自己写代码就可以得到你需要的。顺便说一句,只是为了说明我不是因为问这个特性而疯狂,而是在Ripple用Java实现的一个页面。Github.com/纹波/纹波LIB Java/BLB/主/纹波核心/SR和ZWNJ;
- @如果james securelrandom()初始化为new securelrandom(),则需要对其进行序列化和存储。请参阅stackoverflow.com/questions/7608089/…下面的alexbt回复。
- sha1prng的问题是它使用了256位,这可以被强制执行。通过给伪随机部分一个具有足够随机性的种子来处理伪随机部分。这就是为什么我们需要sha3,它对于一个给定的种子是固有的确定性的,同时足够随机,只要种子是随机的。
- @RAM我打算在用户之间充分地重新设置它。我只是不打算为单个用户重新设定种子,除非他们要求重新设定种子或提供单独的种子,或者绕过我的客户,让他们自己的客户签署资料。
- @devssh:在问题、答案或注释中的任何地方都没有提到序列化。我看不到任何序列化的理由,当然,如果你想重新生成相同的Random序列,你需要保存种子。哦,你不能强行256位。
- 要在Oracle Java 9中实现提供程序,请检查此链接
- @jameskpolk这里是stackoverflow.com/questions/36791447/…系列化的帖子,这里是一篇关于如何在sha1上实现暴力冲突的文章thehacker news.com/2017/02/sha1-collision-attack.html
- 好吧,没有理由序列化,不管是哪篇文章,请序列化反序列化并不能保证工作正常。而且您完全误解了sha1的冲突弱点的安全含义,以及它们与sha1prng的关系。