Skip to content
Snippets Groups Projects
Commit 92ad4e1b authored by Bram Bonné's avatar Bram Bonné
Browse files

Expand documentation for PURPOSE_AGREE_KEY

Bug: 180015526
Test: mmma -j .
Change-Id: Ie3847ff68c21588c4caed450f00006919f5d2769
parent a36c8d2b
No related branches found
No related tags found
No related merge requests found
......@@ -236,6 +236,47 @@ import javax.security.auth.x500.X500Principal;
* keyStore.load(null);
* key = (SecretKey) keyStore.getKey("key2", null);
* }</pre>
*
* <p><h3 id="example:ecdh">Example: EC key for ECDH key agreement</h3>
* This example illustrates how to generate an elliptic curve key pair, used to establish a shared
* secret with another party using ECDH key agreement.
* <pre> {@code
* KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
* KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore");
* keyPairGenerator.initialize(
* new KeyGenParameterSpec.Builder(
* "eckeypair",
* KeyProperties.PURPOSE_AGREE_KEY)
* .setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1"))
* .build());
* KeyPair myKeyPair = keyPairGenerator.generateKeyPair();
*
* // Exchange public keys with server. A new ephemeral key MUST be used for every message.
* PublicKey serverEphemeralPublicKey; // Ephemeral key received from server.
*
* // Create a shared secret based on our private key and the other party's public key.
* KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH", "AndroidKeyStore");
* keyAgreement.init(myKeyPair.getPrivate());
* keyAgreement.doPhase(serverEphemeralPublicKey, true);
* byte[] sharedSecret = keyAgreement.generateSecret();
*
* // sharedSecret cannot safely be used as a key yet. We must run it through a key derivation
* // function with some other data: "salt" and "info". Salt is an optional random value,
* // omitted in this example. It's good practice to include both public keys and any other
* // key negotiation data in info. Here we use the public keys and a label that indicates
* // messages encrypted with this key are coming from the server.
* byte[] salt = {};
* ByteArrayOutputStream info = new ByteArrayOutputStream();
* info.write("ECDH secp256r1 AES-256-GCM-SIV\0".getBytes(StandardCharsets.UTF_8));
* info.write(myKeyPair.getPublic().getEncoded());
* info.write(serverEphemeralPublicKey.getEncoded());
*
* // This example uses the Tink library and the HKDF key derivation function.
* AesGcmSiv key = new AesGcmSiv(Hkdf.computeHkdf(
* "HMACSHA256", sharedSecret, salt, info.toByteArray(), 32));
* byte[] associatedData = {};
* return key.decrypt(ciphertext, associatedData);
* }
*/
public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAuthArgs {
......
......@@ -100,6 +100,15 @@ public abstract class KeyProperties {
/**
* Purpose of key: creating a shared ECDH secret through key agreement.
*
* <p>A key having this purpose can be combined with the elliptic curve public key of another
* party to establish a shared secret over an insecure channel. It should be used as a
* parameter to {@link javax.crypto.KeyAgreement#init(java.security.Key)} (a complete example is
* available <a
* href="{@docRoot}reference/android/security/keystore/KeyGenParameterSpec#example:ecdh"
* >here</a>).
* See <a href="https://en.wikipedia.org/wiki/Elliptic-curve_Diffie%E2%80%93Hellman">this
* article</a> for a more detailed explanation.
*/
public static final int PURPOSE_AGREE_KEY = 1 << 6;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment