Loading keystore/java/android/security/keystore/KeyGenParameterSpec.java +41 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading keystore/java/android/security/keystore/KeyProperties.java +9 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading
keystore/java/android/security/keystore/KeyGenParameterSpec.java +41 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading
keystore/java/android/security/keystore/KeyProperties.java +9 −0 Original line number Diff line number Diff line Loading @@ -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; Loading