I've created the following method that creates a KeyPair and logs the Certificate details:
@RequiresApi(api = Build.VERSION_CODES.N)
public void createRSAKeyPairtWithChallenge(final String alias, final String attestationChallenge) throws NoSuchProviderException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, KeyStoreException, CertificateException, IOException {
Calendar start = Calendar.getInstance();
Calendar end = new GregorianCalendar(2025,03,24);
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");
keyPairGenerator.initialize(
new KeyGenParameterSpec.Builder(alias, KeyProperties.PURPOSE_DECRYPT)
.setAlgorithmParameterSpec(new RSAKeyGenParameterSpec(1024, RSAKeyGenParameterSpec.F4))
.setCertificateNotBefore(start.getTime())
.setCertificateNotAfter(end.getTime())
.setAttestationChallenge(attestationChallenge.getBytes())
.build());
keyPairGenerator.generateKeyPair();
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
Certificate cert = keyStore.getCertificate(alias);
Log.d(TAG,cert.toString());
}
When I execute in a device with a Secure Hardware (TEE) it creates the cert as expected, but when I execute in a device whithout TEE or in emulator it logs the following:
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 1 (0x1)
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=Android Keymaster
Validity
Not Before: Jan 1 00:00:00 1970 GMT
Not After : Dec 31 23:59:59 1969 GMT
Subject: CN=A Keymaster Key
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (1024 bit)
Modulus:
00:8c:d1:bf:0e:22:ea:62:ad:e6:6d:9c:41:5c:d6:
f1:a1:17:6a:e4:e2:12:f7:45:21:70:ef:c0:c5:d7:
18:41:35:9c:42:c4:c6:11:48:0a:2d:97:a4:2a:54:
a0:7f:01:61:22:2e:2b:df:76:99:6c:e1:84:b9:ad:
f5:97:65:a7:f9:2b:bf:97:32:f8:b1:f2:06:3b:2b:
67:cb:ff:28:e4:1b:74:01:47:e9:91:0b:41:ec:17:
fe:4a:b4:3a:f5:0c:db:9b:fa:f3:c1:ef:e0:f5:bf:
e8:37:f9:b2:23:86:96:c4:50:5d:64:ba:b7:1b:61:
3f:65:54:2f:39:9b:d4:98:91
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage:
Key Encipherment, Data Encipherment
1.3.6.1.4.1.11129.2.1.17:
0b...
.....
....test-cert-challenge..0..=........+L0...1.................H........w.....>......?...
X509v3 Authority Key Identifier:
keyid:D4:0C:10:1B:F8:CD:63:B9:F7:39:52:B5:0E:13:5C:A6:D7:99:93:86
Signature Algorithm: sha256WithRSAEncryption
40:79:42:eb:a2:22:e7:e5:95:8f:98:c8:de:35:80:b5:7b:fe:
20:19:00:39:5b:59:3a:49:e0:10:06:c4:c4:a1:3e:52:69:7a:
09:7b:39:67:28:3c:6a:94:96:9e:86:72:58:51:d9:96:0e:a8:
1a:d9:d9:bf:24:6f:79:58:28:a5:1a:7d:14:ae:32:04:9c:e4:
bf:1b:80:d3:4a:85:c2:e0:ab:b3:2c:b9:10:b2:ad:b2:36:00:
68:eb:1b:52:85:b6:d0:0c:93:d5:bc:a5:35:1a:0c:02:a6:af:
86:ee:2c:92:ef:25:5e:56:99:77:4f:72:8a:80:1a:54:33:1f:
78:98
As you can see the dates in Not Before and Not After are not as expected.
Does anybody know what could be the reason?
Hy, I tried you're code locally and had the same results as you already told. I also tried to manipulate the start and end dates to get:
This just tells us that you're params are set correctly and correctly interpreted by the Android OS also on non TEE devices.
Also I checked the Android documentation and found out that not all Keystore implementations may care about start and end date in a "secure manner" (https://developer.android.com/training/articles/keystore).
"Temporal validity interval authorizations are unlikely to be enforced by the secure hardware because it normally doesn't have an independent secure real-time clock. "
This doesn't answer you're question deterministic but tells that not all environments care about time validity because it's just not "secure". So it's better to give no time validity in order to tell there is no security for it rather than to meme validation time that doesn't really help.
Please consider that 23:59:59 1969 etc. means time_t notBefore(time_t)-1 and the 1970 means time_t notAfter=(time_t)0. So I beleve they disabled the validity but it's required that notebefore < notAfter.
However this not a deterministic answer, still searching for documentation explaining this issue in detail :(.