Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e950a4b2 authored by Alex Klyubin's avatar Alex Klyubin Committed by Android Git Automerger
Browse files

am e19b76cb: Merge "Add more examples of generating/importing keys to Javadocs." into mnc-dev

* commit 'e19b76cb':
  Add more examples of generating/importing keys to Javadocs.
parents c7f2030f e19b76cb
Loading
Loading
Loading
Loading
+110 −20
Original line number Diff line number Diff line
@@ -38,27 +38,35 @@ import javax.security.auth.x500.X500Principal;
/**
 * {@link AlgorithmParameterSpec} for initializing a {@link KeyPairGenerator} or a
 * {@link KeyGenerator} of the <a href="{@docRoot}training/articles/keystore.html">Android Keystore
 * system</a>. The spec determines whether user authentication is required for using the key, what
 * uses the key is authorized for (e.g., only for signing -- decryption not permitted), the key's
 * validity start and end dates.
 * system</a>. The spec determines authorized uses of the key, such as whether user authentication
 * is required for using the key, what operations are authorized (e.g., signing, but not
 * decryption) and with what parameters (e.g., only with a particular padding scheme or digest), the
 * key's validity start and end dates. Key use authorizations expressed in the spec apply only to
 * secret keys and private keys -- public keys can be used for any supported operations.
 *
 * <p>To generate an asymmetric key pair or a symmetric key, create an instance of this class using
 * the {@link Builder}, initialize a {@code KeyPairGenerator} or a {@code KeyGenerator} of the
 * desired key type (e.g., {@code EC} or {@code AES} -- see
 * {@link KeyProperties}.{@code KEY_ALGORITHM} constants) from the {@code AndroidKeyStore} provider
 * with the {@code KeyPairGeneratorSpec} instance, and then generate a key or key pair using
 * {@link KeyPairGenerator#generateKeyPair()}.
 * with the {@code KeyGenParameterSpec} instance, and then generate a key or key pair using
 * {@link KeyGenerator#generateKey()} or {@link KeyPairGenerator#generateKeyPair()}.
 *
 * <p>The generated key pair or key will be returned by the generator and also stored in the Android
 * Keystore system under the alias specified in this spec. To obtain the secret or private key from
 * the Android KeyStore use {@link java.security.KeyStore#getKey(String, char[]) KeyStore.getKey(String, null)}
 * Keystore under the alias specified in this spec. To obtain the secret or private key from the
 * Android Keystore use {@link java.security.KeyStore#getKey(String, char[]) KeyStore.getKey(String, null)}
 * or {@link java.security.KeyStore#getEntry(String, java.security.KeyStore.ProtectionParameter) KeyStore.getEntry(String, null)}.
 * To obtain the public key from the Android Keystore system use
 * To obtain the public key from the Android Keystore use
 * {@link java.security.KeyStore#getCertificate(String)} and then
 * {@link Certificate#getPublicKey()}.
 *
 * <p>To help obtain algorithm-specific public parameters of key pairs stored in the Android
 * Keystore, generated private keys implement {@link java.security.interfaces.ECKey} or
 * {@link java.security.interfaces.RSAKey} interfaces whereas public keys implement
 * {@link java.security.interfaces.ECPublicKey} or {@link java.security.interfaces.RSAPublicKey}
 * interfaces.
 *
 * <p>For asymmetric key pairs, a self-signed X.509 certificate will be also generated and stored in
 * the Android KeyStore. This is because the {@link java.security.KeyStore} abstraction does not
 * the Android Keystore. This is because the {@link java.security.KeyStore} abstraction does not
 * support storing key pairs without a certificate. The subject, serial number, and validity dates
 * of the certificate can be customized in this spec. The self-signed certificate may be replaced at
 * a later time by a certificate signed by a Certificate Authority (CA).
@@ -82,27 +90,60 @@ import javax.security.auth.x500.X500Principal;
 *
 * <p>Instances of this class are immutable.
 *
 * <p><h3>Example: Asymmetric key pair</h3>
 * The following example illustrates how to generate an EC key pair in the Android KeyStore system
 * under alias {@code key1} authorized to be used only for signing using SHA-256, SHA-384,
 * or SHA-512 digest and only if the user has been authenticated within the last five minutes.
 * <p><h3>Example: NIST P-256 EC key pair for signing/verification using ECDSA</h3>
 * This example illustrates how to generate a NIST P-256 (aka secp256r1 aka prime256v1) EC key pair
 * in the Android KeyStore system under alias {@code key1} where the private key is authorized to be
 * used only for signing using SHA-256, SHA-384, or SHA-512 digest and only if the user has been
 * authenticated within the last five minutes. The use of public key is unrestricted, thus
 * permitting signature verification using any padding schemes and digests, and without user
 * authentication.
 * <pre> {@code
 * KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
 *         KeyProperties.KEY_ALGORITHM_EC,
 *         "AndroidKeyStore");
 *         KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore");
 * keyPairGenerator.initialize(
 *         new KeyGenParameterSpec.Builder(
 *                 "key1",
 *                 KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY)
 *                 KeyProperties.PURPOSE_SIGN)
 *                 .setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1"))
 *                 .setDigests(KeyProperties.DIGEST_SHA256,
 *                         KeyProperties.DIGEST_SHA384,
 *                         KeyProperties.DIGEST_SHA512)
 *                 // Only permit this key to be used if the user authenticated
 *                 // Only permit the private key to be used if the user authenticated
 *                 // within the last five minutes.
 *                 .setUserAuthenticationRequired(true)
 *                 .setUserAuthenticationValidityDurationSeconds(5 * 60)
 *                 .build());
 * KeyPair keyPair = keyPairGenerator.generateKeyPair();
 * Signature signature = Signature.getInstance("SHA256withECDSA");
 * signature.initSign(keyPair.getPrivate());
 * ...
 *
 * // The key pair can also be obtained from the Android Keystore any time as follows:
 * KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
 * keyStore.load(null);
 * PrivateKey privateKey = (PrivateKey) keyStore.getKey("key1", null);
 * PublicKey publicKey = keyStore.getCertificate("key1").getPublicKey();
 * }</pre>
 *
 * <p><h3>Example: RSA key pair for signing/verification using RSA-PSS</h3>
 * This example illustrates how to generate an RSA key pair in the Android KeyStore system under
 * alias {@code key1} authorized to be used only for signing using the RSA-PSS signature padding
 * scheme with SHA-256 or SHA-512 digests. The use of public key is unrestricted, thus permitting
 * signature verification using any padding schemes and digests.
 * <pre> {@code
 * KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
 *         KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");
 * keyPairGenerator.initialize(
 *         new KeyGenParameterSpec.Builder(
 *                 "key1",
 *                 KeyProperties.PURPOSE_SIGN)
 *                 .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
 *                 .setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PSS)
 *                 .build());
 * KeyPair keyPair = keyPairGenerator.generateKeyPair();
 * Signature signature = Signature.getInstance("SHA256withRSA/PSS");
 * signature.initSign(keyPair.getPrivate());
 * ...
 *
 * // The key pair can also be obtained from the Android Keystore any time as follows:
 * KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
@@ -111,14 +152,40 @@ import javax.security.auth.x500.X500Principal;
 * PublicKey publicKey = keyStore.getCertificate("key1").getPublicKey();
 * }</pre>
 *
 * <p><h3>Example: Symmetric key</h3>
 * <p><h3>Example: RSA key pair for encryption/decryption using RSA OAEP</h3>
 * This example illustrates how to generate an RSA key pair in the Android KeyStore system under
 * alias {@code key1} where the private key is authorized to be used only for decryption using RSA
 * OAEP encryption padding scheme with SHA-256 or SHA-512 digests. The use of public key is
 * unrestricted, thus permitting encryption using any padding schemes and digests.
 * <pre> {@code
 * KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
 *         KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");
 * keyPairGenerator.initialize(
 *         new KeyGenParameterSpec.Builder(
 *                 "key1",
 *                 KeyProperties.PURPOSE_DECRYPT)
 *                 .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
 *                 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP)
 *                 .build());
 * KeyPair keyPair = keyPairGenerator.generateKeyPair();
 * Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
 * cipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
 * ...
 *
 * // The key pair can also be obtained from the Android Keystore any time as follows:
 * KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
 * keyStore.load(null);
 * PrivateKey privateKey = (PrivateKey) keyStore.getKey("key1", null);
 * PublicKey publicKey = keyStore.getCertificate("key1").getPublicKey();
 * }</pre>
 *
 * <p><h3>Example: AES key for encryption/decryption in GCM mode</h3>
 * The following example illustrates how to generate an AES key in the Android KeyStore system under
 * alias {@code key2} authorized to be used only for encryption/decryption in GCM mode with no
 * padding.
 * <pre> {@code
 * KeyGenerator keyGenerator = KeyGenerator.getInstance(
 *         KeyProperties.KEY_ALGORITHM_AES,
 *         "AndroidKeyStore");
 *         KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
 * keyGenerator.initialize(
 *         new KeyGenParameterSpec.Builder("key2",
 *                 KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
@@ -127,6 +194,29 @@ import javax.security.auth.x500.X500Principal;
 *                 .build());
 * SecretKey key = keyGenerator.generateKey();
 *
 * Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
 * cipher.init(Cipher.ENCRYPT_MODE, key);
 * ...
 *
 * // The key can also be obtained from the Android Keystore any time as follows:
 * KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
 * keyStore.load(null);
 * key = (SecretKey) keyStore.getKey("key2", null);
 * }</pre>
 *
 * <p><h3>Example: HMAC key for generating a MAC using SHA-256</h3>
 * This example illustrates how to generate an HMAC key in the Android KeyStore system under alias
 * {@code key2} authorized to be used only for generating an HMAC using SHA-256.
 * <pre> {@code
 * KeyGenerator keyGenerator = KeyGenerator.getInstance(
 *         KeyProperties.KEY_ALGORITHM_HMAC_SHA256, "AndroidKeyStore");
 * keyGenerator.initialize(
 *         new KeyGenParameterSpec.Builder("key2", KeyProperties.PURPOSE_SIGN).build());
 * SecretKey key = keyGenerator.generateKey();
 * Mac mac = Mac.getInstance("HmacSHA256");
 * mac.init(key);
 * ...
 *
 * // The key can also be obtained from the Android Keystore any time as follows:
 * KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
 * keyStore.load(null);
+117 −18
Original line number Diff line number Diff line
@@ -33,28 +33,36 @@ import javax.crypto.Mac;

/**
 * Specification of how a key or key pair is secured when imported into the
 * <a href="{@docRoot}training/articles/keystore.html">Android KeyStore facility</a>. This class
 * specifies parameters such as whether user authentication is required for using the key, what uses
 * the key is authorized for (e.g., only in {@code GCM} mode, or only for signing -- decryption not
 * permitted), the key's and validity start and end dates.
 *
 * <p>To import a key or key pair into the Android KeyStore, create an instance of this class using
 * <a href="{@docRoot}training/articles/keystore.html">Android Keystore system</a>. This class
 * specifies authorized uses of the imported key, such as whether user authentication is required
 * for using the key, what operations the key is authorized for (e.g., decryption, but not signing)
 * and with what parameters (e.g., only with a particular padding scheme or digest), the key's and
 * validity start and end dates. Key use authorizations expressed in this class apply only to secret
 * keys and private keys -- public keys can be used for any supported operations.
 *
 * <p>To import a key or key pair into the Android Keystore, create an instance of this class using
 * the {@link Builder} and pass the instance into {@link java.security.KeyStore#setEntry(String, java.security.KeyStore.Entry, ProtectionParameter) KeyStore.setEntry}
 * with the key or key pair being imported.
 *
 * <p>To obtain the secret/symmetric or private key from the Android KeyStore use
 * <p>To obtain the secret/symmetric or private key from the Android Keystore use
 * {@link java.security.KeyStore#getKey(String, char[]) KeyStore.getKey(String, null)} or
 * {@link java.security.KeyStore#getEntry(String, java.security.KeyStore.ProtectionParameter) KeyStore.getEntry(String, null)}.
 * To obtain the public key from the Android KeyStore use
 * To obtain the public key from the Android Keystore use
 * {@link java.security.KeyStore#getCertificate(String)} and then
 * {@link Certificate#getPublicKey()}.
 *
 * <p>NOTE: The key material of keys stored in the Android KeyStore is not accessible.
 * <p>To help obtain algorithm-specific public parameters of key pairs stored in the Android
 * Keystore, its private keys implement {@link java.security.interfaces.ECKey} or
 * {@link java.security.interfaces.RSAKey} interfaces whereas its public keys implement
 * {@link java.security.interfaces.ECPublicKey} or {@link java.security.interfaces.RSAPublicKey}
 * interfaces.
 *
 * <p>NOTE: The key material of keys stored in the Android Keystore is not accessible.
 *
 * <p>Instances of this class are immutable.
 *
 * <p><h3>Example: Symmetric Key</h3>
 * The following example illustrates how to import an AES key into the Android KeyStore under alias
 * <p><h3>Example: AES key for encryption/decryption in GCM mode</h3>
 * This example illustrates how to import an AES key into the Android KeyStore under alias
 * {@code key1} authorized to be used only for encryption/decryption in GCM mode with no padding.
 * The key must export its key material via {@link Key#getEncoded()} in {@code RAW} format.
 * <pre> {@code
@@ -71,15 +79,41 @@ import javax.crypto.Mac;
 *                 .build());
 * // Key imported, obtain a reference to it.
 * SecretKey keyStoreKey = (SecretKey) keyStore.getKey("key1", null);
 * // The original key can now be thrown away.
 * // The original key can now be discarded.
 *
 * Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
 * cipher.init(Cipher.ENCRYPT_MODE, keyStoreKey);
 * ...
 * }</pre>
 *
 * <p><h3>Example: HMAC key for generating MACs using SHA-512</h3>
 * This example illustrates how to import an HMAC key into the Android KeyStore under alias
 * {@code key1} authorized to be used only for generating MACs using SHA-512 digest. The key must
 * export its key material via {@link Key#getEncoded()} in {@code RAW} format.
 * <pre> {@code
 * SecretKey key = ...; // HMAC key of algorithm "HmacSHA512".
 *
 * KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
 * keyStore.load(null);
 * keyStore.setEntry(
 *         "key1",
 *         new KeyStore.SecretKeyEntry(key),
 *         new KeyProtection.Builder(KeyProperties.PURPOSE_SIGN).build());
 * // Key imported, obtain a reference to it.
 * SecretKey keyStoreKey = (SecretKey) keyStore.getKey("key1", null);
 * // The original key can now be discarded.
 *
 * Mac mac = Mac.getInstance("HmacSHA512");
 * mac.init(keyStoreKey);
 * ...
 * }</pre>
 *
 * <p><h3>Example: Asymmetric Key Pair</h3>
 * The following example illustrates how to import an EC key pair into the Android KeyStore under
 * alias {@code key2} authorized to be used only for signing with SHA-256 digest and only if
 * the user has been authenticated within the last ten minutes. Both the private and the public key
 * must export their key material via {@link Key#getEncoded()} in {@code PKCS#8} and {@code X.509}
 * format respectively.
 * <p><h3>Example: EC key pair for signing/verification using ECDSA</h3>
 * This example illustrates how to import an EC key pair into the Android KeyStore under alias
 * {@code key2} with the private key authorized to be used only for signing with SHA-256 or SHA-512
 * digests. The use of public key is unrestricted, thus permitting signature verification using any
 * digests. Both the private and the public key must export their key material via
 * {@link Key#getEncoded()} in {@code PKCS#8} and {@code X.509} format respectively.
 * <pre> {@code
 * PrivateKey privateKey = ...;   // EC private key
 * Certificate[] certChain = ...; // Certificate chain with the first certificate
@@ -91,7 +125,39 @@ import javax.crypto.Mac;
 *         "key2",
 *         new KeyStore.PrivateKeyEntry(privateKey, certChain),
 *         new KeyProtection.Builder(KeyProperties.PURPOSE_SIGN)
 *                 .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
 *                 .build());
 * // Key pair imported, obtain a reference to it.
 * PrivateKey keyStorePrivateKey = (PrivateKey) keyStore.getKey("key2", null);
 * PublicKey publicKey = keyStore.getCertificate("key2").getPublicKey();
 * // The original private key can now be discarded.
 *
 * Signature signature = Signature.getInstance("SHA256withECDSA");
 * signature.initSign(keyStorePrivateKey);
 * ...
 * }</pre>
 *
 * <p><h3>Example: RSA key pair for signing/verification using PKCS#1 padding</h3>
 * This example illustrates how to import an RSA key pair into the Android KeyStore under alias
 * {@code key2} with the private key authorized to be used only for signing using the PKCS#1
 * signature padding scheme with SHA-256 digest and only if the user has been authenticated within
 * the last ten minutes. The use of public key is unrestricted, thus permitting signature
 * verification using any padding schemes and digests, and without user authentication. Both the
 * private and the public key must export their key material via {@link Key#getEncoded()} in
 * {@code PKCS#8} and {@code X.509} format respectively.
 * <pre> {@code
 * PrivateKey privateKey = ...;   // RSA private key
 * Certificate[] certChain = ...; // Certificate chain with the first certificate
 *                                // containing the corresponding RSA public key.
 *
 * KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
 * keyStore.load(null);
 * keyStore.setEntry(
 *         "key2",
 *         new KeyStore.PrivateKeyEntry(privateKey, certChain),
 *         new KeyProtection.Builder(KeyProperties.PURPOSE_SIGN)
 *                 .setDigests(KeyProperties.DIGEST_SHA256)
 *                 .setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1)
 *                 // Only permit this key to be used if the user
 *                 // authenticated within the last ten minutes.
 *                 .setUserAuthenticationRequired(true)
@@ -100,7 +166,40 @@ import javax.crypto.Mac;
 * // Key pair imported, obtain a reference to it.
 * PrivateKey keyStorePrivateKey = (PrivateKey) keyStore.getKey("key2", null);
 * PublicKey publicKey = keyStore.getCertificate("key2").getPublicKey();
 * // The original private key can now be thrown away.
 * // The original private key can now be discarded.
 *
 * Signature signature = Signature.getInstance("SHA256withRSA");
 * signature.initSign(keyStorePrivateKey);
 * ...
 * }</pre>
 *
 * <p><h3>Example: RSA key pair for encryption/decryption using PKCS#1 padding</h3>
 * This example illustrates how to import an RSA key pair into the Android KeyStore under alias
 * {@code key2} with the private key authorized to be used only for decryption using the PKCS#1
 * encryption padding scheme. The use of public key is unrestricted, thus permitting encryption
 * using any padding schemes and digests. Both the private and the public key must export their key
 * material via {@link Key#getEncoded()} in {@code PKCS#8} and {@code X.509} format respectively.
 * <pre> {@code
 * PrivateKey privateKey = ...;   // RSA private key
 * Certificate[] certChain = ...; // Certificate chain with the first certificate
 *                                // containing the corresponding RSA public key.
 *
 * KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
 * keyStore.load(null);
 * keyStore.setEntry(
 *         "key2",
 *         new KeyStore.PrivateKeyEntry(privateKey, certChain),
 *         new KeyProtection.Builder(KeyProperties.PURPOSE_DECRYPT)
 *                 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
 *                 .build());
 * // Key pair imported, obtain a reference to it.
 * PrivateKey keyStorePrivateKey = (PrivateKey) keyStore.getKey("key2", null);
 * PublicKey publicKey = keyStore.getCertificate("key2").getPublicKey();
 * // The original private key can now be discarded.
 *
 * Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
 * cipher.init(Cipher.DECRYPT_MODE, keyStorePrivateKey);
 * ...
 * }</pre>
 */
public final class KeyProtection implements ProtectionParameter {