Working with Keys¶
Keys are created by algorithms and used for operations. This page covers generation, encoding and decoding, standard key formats, and accessing public keys from private keys.
Assumed imports
All examples assume the following:
import dev.whyoleg.cryptography.*
import dev.whyoleg.cryptography.algorithms.*
import dev.whyoleg.cryptography.BinarySize.Companion.bits
val provider = CryptographyProvider.Default
Generation¶
Symmetric Keys¶
Symmetric algorithms produce a single shared key:
val aesGcm = provider.get(AES.GCM)
val key = aesGcm.keyGenerator().generateKey()
Some algorithms accept an optional key size parameter:
val key = aesGcm.keyGenerator(AES.Key.Size.B256).generateKey()
Asymmetric Key Pairs¶
Asymmetric algorithms produce a key pair containing a public key and a private key. EC algorithms require a curve, RSA algorithms accept a key size:
val ecdsa = provider.get(ECDSA)
val ecKeyPair = ecdsa.keyPairGenerator(EC.Curve.P256).generateKey()
val rsa = provider.get(RSA.OAEP)
val rsaKeyPair = rsa.keyPairGenerator(4096.bits).generateKey()
Generators are reusable – call generateKey() multiple times on the same generator to produce
independent keys without re-specifying parameters.
Key Formats¶
| Format | Encoding | Description |
|---|---|---|
| RAW | Binary | Raw key bytes, no metadata, minimal overhead 1 |
| DER | Binary | ASN.1 binary (PKIX/SPKI for public, PKCS#8 for private) 2 |
| PEM | Text (Base64) | Base64-wrapped DER with BEGIN/END headers 2 |
| JWK | JSON | JSON Web Key (RFC 7517) 3 |
Encoding¶
All keys implement Encodable. Call encodeToByteArray(format) to get a ByteArray,
or encodeToByteString(format) to get a ByteString. For text formats (PEM, JWK), the
bytes are UTF-8 encoded text.
Symmetric¶
val key = provider.get(AES.GCM).keyGenerator().generateKey()
val raw = key.encodeToByteArray(AES.Key.Format.RAW)
val jwk = key.encodeToByteArray(AES.Key.Format.JWK)
Asymmetric¶
Public and private keys are encoded separately:
val ecdsa = provider.get(ECDSA)
val keyPair = ecdsa.keyPairGenerator(EC.Curve.P256).generateKey()
val publicDer = keyPair.publicKey.encodeToByteArray(EC.PublicKey.Format.DER)
val privateDer = keyPair.privateKey.encodeToByteArray(EC.PrivateKey.Format.DER)
Decoding¶
Decoding reconstructs a key object from encoded bytes. Each algorithm provides decoder methods
that return a Decoder instance.
Symmetric¶
val aesGcm = provider.get(AES.GCM)
val key = aesGcm.keyDecoder().decodeFromByteArray(AES.Key.Format.RAW, bytes)
Asymmetric¶
Public and private keys have separate decoders. Decoders may require algorithm-specific parameters (curve for EC, digest for HMAC, etc.):
val ecdsa = provider.get(ECDSA)
val publicKey = ecdsa.publicKeyDecoder(EC.Curve.P256)
.decodeFromByteArray(EC.PublicKey.Format.DER, publicKeyBytes)
val privateKey = ecdsa.privateKeyDecoder(EC.Curve.P256)
.decodeFromByteArray(EC.PrivateKey.Format.DER, privateKeyBytes)
Use decodeFromByteString(format, byteString) when working with ByteString instead of
ByteArray.
Accessing Public Key from Private Key¶
For asymmetric algorithms, the public key can be retrieved from a private key:
val privateKey: ECDSA.PrivateKey = keyPair.privateKey
val publicKey: ECDSA.PublicKey = privateKey.publicKey
This is useful when you have only the private key (e.g., loaded from storage) and need the corresponding public key for verification or sharing.
JDK provider limitation
On the JDK provider, privateKey.publicKey may throw an exception unless the key pair was
generated via the library, the private key was decoded from a format containing the public
key, or BouncyCastle is on the classpath.
Other providers (CryptoKit, WebCrypto, OpenSSL3) support this without restrictions.
-
Apple (CommonCrypto): EC PrivateKey RAW encoding is supported, but decoding is not. EC PublicKey RAW.Compressed is not supported. ↩
-
Apple (CommonCrypto): EC PrivateKey decoding requires the
publicKeyfield to be present in theEcPrivateKeystructure per RFC 5915. Not all implementations include this optional field. JDK / WebCrypto: EdDSA/XDH PrivateKey decoding may fail for formats that contain an embedded public key. ↩↩ -
JDK: EC/EdDSA/XDH PrivateKey JWK format is only supported if the public key is available (i.e., the key pair was generated via the library, decoded from a format containing the public key, or BouncyCastle is on the classpath). ↩