From dc75456b24f0637fe6452488a2da1b872c3d5f4c Mon Sep 17 00:00:00 2001 From: ArtificialPB Date: Wed, 11 Dec 2024 15:18:29 +0100 Subject: [PATCH] feat(signers): add support for creating random `PrivateKeySigner` additionally, re-use cached SecureRandom instance --- .../src/main/kotlin/io/ethers/crypto/Hashing.kt | 10 ++++++++++ .../kotlin/io/ethers/crypto/bip39/MnemonicCode.kt | 7 +++---- .../main/kotlin/io/ethers/signers/PrivateKeySigner.kt | 11 +++++++++++ 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/ethers-crypto/src/main/kotlin/io/ethers/crypto/Hashing.kt b/ethers-crypto/src/main/kotlin/io/ethers/crypto/Hashing.kt index d3a5dbc2..9ccca7ec 100644 --- a/ethers-crypto/src/main/kotlin/io/ethers/crypto/Hashing.kt +++ b/ethers-crypto/src/main/kotlin/io/ethers/crypto/Hashing.kt @@ -6,10 +6,20 @@ import org.bouncycastle.crypto.macs.HMac import org.bouncycastle.crypto.params.KeyParameter import org.bouncycastle.jcajce.provider.digest.Keccak import org.bouncycastle.jcajce.provider.digest.SHA256 +import java.security.SecureRandom object Hashing { private val MESSAGE_PREFIX = "\u0019Ethereum Signed Message:\n".toByteArray() private const val VERSIONED_HASH_VERSION_KZG = 0x01.toByte() + private val secureRandom by lazy { SecureRandom() } + + /** + * Get cached [SecureRandom] instance. Instance is created on first access. + * */ + @JvmStatic + fun secureRandom(): SecureRandom { + return secureRandom + } /** * Construct and hash [message] based on [EIP-191](https://eips.ethereum.org/EIPS/eip-191) standard (version 0x01). diff --git a/ethers-crypto/src/main/kotlin/io/ethers/crypto/bip39/MnemonicCode.kt b/ethers-crypto/src/main/kotlin/io/ethers/crypto/bip39/MnemonicCode.kt index b6d2f9cb..789dacc6 100644 --- a/ethers-crypto/src/main/kotlin/io/ethers/crypto/bip39/MnemonicCode.kt +++ b/ethers-crypto/src/main/kotlin/io/ethers/crypto/bip39/MnemonicCode.kt @@ -1,11 +1,11 @@ package io.ethers.crypto.bip39 +import io.ethers.crypto.Hashing import org.bouncycastle.crypto.digests.SHA512Digest import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator import org.bouncycastle.crypto.params.KeyParameter import org.bouncycastle.jcajce.provider.digest.SHA256 import java.nio.charset.StandardCharsets -import java.security.SecureRandom import java.util.Collections /** @@ -130,7 +130,7 @@ class MnemonicCode @JvmOverloads constructor( private const val SEED_ITERATIONS = 2048 /** - * Create a new mnemonic code from random entropy, using [SecureRandom]. + * Create a new mnemonic code from random entropy, using [Hashing.secureRandom]. * */ @JvmStatic @JvmOverloads @@ -138,9 +138,8 @@ class MnemonicCode @JvmOverloads constructor( bitsOfEntropy: Int = 256, wordList: MnemonicWordList = MnemonicWordListEnglish, ): MnemonicCode { - val rand = SecureRandom() val entropy = ByteArray(bitsOfEntropy / 8) - rand.nextBytes(entropy) + Hashing.secureRandom().nextBytes(entropy) return fromEntropy(entropy, wordList) } diff --git a/ethers-signers/src/main/kotlin/io/ethers/signers/PrivateKeySigner.kt b/ethers-signers/src/main/kotlin/io/ethers/signers/PrivateKeySigner.kt index c1e84d8f..2e7d4a18 100644 --- a/ethers-signers/src/main/kotlin/io/ethers/signers/PrivateKeySigner.kt +++ b/ethers-signers/src/main/kotlin/io/ethers/signers/PrivateKeySigner.kt @@ -4,6 +4,7 @@ import io.ethers.core.FastHex import io.ethers.core.types.Address import io.ethers.core.types.Bytes import io.ethers.core.types.Signature +import io.ethers.crypto.Hashing import io.ethers.crypto.Secp256k1 /** @@ -59,5 +60,15 @@ class PrivateKeySigner(val signingKey: Secp256k1.SigningKey) : Signer { return Secp256k1.SigningKey(bytes) } + + /** + * Create a new [PrivateKeySigner] from random entropy, using [Hashing.secureRandom]. + * */ + @JvmStatic + fun random(): PrivateKeySigner { + val privateKey = ByteArray(32) + Hashing.secureRandom().nextBytes(privateKey) + return PrivateKeySigner(privateKey) + } } }