Document user authentication restrictions on public keys.

A Keystore bug causes user authentication to be required to use public
keys from key pairs that are authentication-bound.  Because it's too
late to fix Keystore we're instead documenting the behavior.

Bug: 23792178
Change-Id: Iee3a78d6cbf25949e890b1c50841580ce748da2e
This commit is contained in:
Shawn Willden
2015-09-08 17:47:38 -06:00
parent 586f56aa79
commit a3762c873a
2 changed files with 33 additions and 16 deletions

View File

@@ -40,9 +40,9 @@ import javax.security.auth.x500.X500Principal;
* {@link KeyGenerator} of the <a href="{@docRoot}training/articles/keystore.html">Android Keystore
* 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.
* decryption), with what parameters (e.g., only with a particular padding scheme or digest), and
* 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
@@ -90,13 +90,22 @@ import javax.security.auth.x500.X500Principal;
*
* <p>Instances of this class are immutable.
*
* <p><h3>Known issues</h3>
* A known bug in Android 6.0 (API Level 23) causes user authentication-related authorizations to be
* enforced even for public keys. To work around this issue extract the public key material to use
* outside of Android Keystore. For example:
* <pre> {@code
* PublicKey unrestrictedPublicKey =
* KeyFactory.getInstance(publicKey.getAlgorithm()).generatePublic(
* new X509EncodedKeySpec(publicKey.getEncoded()));
* }</pre>
*
* <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.
* authenticated within the last five minutes. The use of the public key is unrestricted (See Known
* Issues).
* <pre> {@code
* KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
* KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore");
@@ -128,8 +137,7 @@ import javax.security.auth.x500.X500Principal;
* <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.
* scheme with SHA-256 or SHA-512 digests. The use of the public key is unrestricted.
* <pre> {@code
* KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
* KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");
@@ -155,8 +163,8 @@ import javax.security.auth.x500.X500Principal;
* <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.
* OAEP encryption padding scheme with SHA-256 or SHA-512 digests. The use of the public key is
* unrestricted.
* <pre> {@code
* KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
* KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");

View File

@@ -36,7 +36,7 @@ import javax.crypto.Mac;
* <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
* with what parameters (e.g., only with a particular padding scheme or digest), and the key's
* 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.
*
@@ -61,6 +61,16 @@ import javax.crypto.Mac;
*
* <p>Instances of this class are immutable.
*
* <p><h3>Known issues</h3>
* A known bug in Android 6.0 (API Level 23) causes user authentication-related authorizations to be
* enforced even for public keys. To work around this issue extract the public key material to use
* outside of Android Keystore. For example:
* <pre> {@code
* PublicKey unrestrictedPublicKey =
* KeyFactory.getInstance(publicKey.getAlgorithm()).generatePublic(
* new X509EncodedKeySpec(publicKey.getEncoded()));
* }</pre>
*
* <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.
@@ -111,9 +121,9 @@ import javax.crypto.Mac;
* <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.
* digests. The use of the public key is unrestricted. 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
@@ -141,8 +151,7 @@ import javax.crypto.Mac;
* 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
* the last ten minutes. The use of the public key is unrestricted (see Known Issues). 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