From 92ad4e1bd5d591a6b2538905c0e1aa2dcf1c93c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bram=20Bonn=C3=A9?= Date: Fri, 12 Feb 2021 12:23:21 +0100 Subject: Expand documentation for PURPOSE_AGREE_KEY Bug: 180015526 Test: mmma -j . Change-Id: Ie3847ff68c21588c4caed450f00006919f5d2769 --- .../security/keystore/KeyGenParameterSpec.java | 41 ++++++++++++++++++++++ .../android/security/keystore/KeyProperties.java | 9 +++++ 2 files changed, 50 insertions(+) (limited to 'keystore') diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java index e92eaca2b6e9..2b0d7e53b749 100644 --- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java +++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java @@ -236,6 +236,47 @@ import javax.security.auth.x500.X500Principal; * keyStore.load(null); * key = (SecretKey) keyStore.getKey("key2", null); * } + * + *

Example: EC key for ECDH key agreement

+ * This example illustrates how to generate an elliptic curve key pair, used to establish a shared + * secret with another party using ECDH key agreement. + *
 {@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 {
 
diff --git a/keystore/java/android/security/keystore/KeyProperties.java b/keystore/java/android/security/keystore/KeyProperties.java
index 3ebca6ad302d..293ab05e0b10 100644
--- a/keystore/java/android/security/keystore/KeyProperties.java
+++ b/keystore/java/android/security/keystore/KeyProperties.java
@@ -100,6 +100,15 @@ public abstract class KeyProperties {
 
     /**
      * Purpose of key: creating a shared ECDH secret through key agreement.
+     *
+     * 

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 here). + * See this + * article for a more detailed explanation. */ public static final int PURPOSE_AGREE_KEY = 1 << 6; -- cgit v1.2.3