I am trying to generate Key pairs with Bouncy Castle and use the following Bouncy implementation and code:
implementation 'org.bouncycastle:bcprov-jdk15to18:1.70'
According to: https://javadoc.io/static/org.bouncycastle/bcprov-jdk15on/1.70/org/bouncycastle/math/ec/rfc7748/X448.html
I create the following keyPair generator:
val keyPairGenerator =
KeyPairGenerator.getInstance("EC", BouncyCastleProvider.PROVIDER_NAME)
keyPairGenerator.initialize(XDHParameterSpec(XDHParameterSpec.X448))
val keyPair = keyPairGenerator.generateKeyPair()
val publicKey = byteArrayToHex(keyPair.public.encoded)
val privateKey = keyPair.private.encoded
But then I get the following error:
no such algorithm: EC for provider BC
I Tried diffrent providers but to no avail.
Am I missing something?
--
Removed after suggested to open a new Question
The issue is most likely caused by an older BC version being installed. This must first be removed with Security.removeProvider("BC")
.
Then the current BC version must be added with Security.addProvider(BouncyCastleProvider())
. Only then the instantiation of KeyPairGenerator
may be performed.
Furthermore, when instantiating KeyPairGenerator
, XDHParameterSpec.X448
must be specified as first parameter ("EC"
would generate a key pair for the EC curve prime239v1). The line keyPairGenerator.initialize(...)
can be removed (it is redundant).
The following implementation works on my machine:
import org.bouncycastle.jcajce.spec.XDHParameterSpec
import org.bouncycastle.jce.provider.BouncyCastleProvider
import java.security.KeyPairGenerator
...
Security.removeProvider("BC")
Security.addProvider(BouncyCastleProvider())
val keyPairGenerator = KeyPairGenerator.getInstance(XDHParameterSpec.X448, BouncyCastleProvider.PROVIDER_NAME)
val keyPair = keyPairGenerator.generateKeyPair()
val privateKey = keyPair.private
val publicKey = keyPair.public
println(Base64.getEncoder().encodeToString(privateKey.encoded)) // e.g. MIGBAgEBMAUGAytlbwQ6BDiMQCdpnzxOu7SN4Sgft8nsDLmbWLxWd7aDz4g3ht54NEuX2PyaGDK1mVJuTQ+v2bM9Sm9xyBN44YE5AHT/KcCEEdk/je/GU/6kg+vt8okKJAuLspjaHU1aK2KGXOKPS9GQXAHKjf/rBKj9b2IQnyesXMqU
println(Base64.getEncoder().encodeToString(publicKey.encoded)) // e.g. MEIwBQYDK2VvAzkAdP8pwIQR2T+N78ZT/qSD6+3yiQokC4uymNodTVorYoZc4o9L0ZBcAcqN/+sEqP1vYhCfJ6xcypQ=
privateKey.encoded
returns the DER encoded private key in PKCS#8 format (incl. public key), publicKey.encoded
returns the DER encoded key in X.509/SPKI format.
Alternatively, the X448 key pair can be generated as follows:
import java.security.SecureRandom
import org.bouncycastle.util.encoders.Hex
import org.bouncycastle.crypto.params.X448PrivateKeyParameters
...
val secureRandom = SecureRandom()
val privateKeyParams = X448PrivateKeyParameters(secureRandom)
val publicKeyParams = privateKeyParams.generatePublicKey()
println(Hex.toHexString(privateKeyParams.encoded)) // e.g. 0x7472d12245a698ac9a52be9bc9ea0c90aacb598f084f16a18ea917d56fa5411005a18e844a4aa4508272ad593ac8c1be53284d908d0fc4c6
println(Hex.toHexString(publicKeyParams.encoded)) // e.g. 0x9d49073bd1c0149b41cf66bd389ae743dca3bb59dc1988903c32b840fb68f8d67ccb3c56be4bc65687f11b1fc5f273d7cea329427d83a829
privateKeyParams.encoded
returns the raw private key (56 bytes), publicKeyParams.encoded
returns the raw public key (56 bytes).