Android KeyGenParameterSpec.Builder 当不在安全硬件中时忽略 setCertificateNotBefore 和 setCertificateNotAfter

Android KeyGenParameterSpec.Builder ignoring setCertificateNotBefore and setCertificateNotAfter when not in Secure Hadware

我创建了以下创建密钥对并记录证书详细信息的方法:

@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());
}

当我在带有安全硬件 (TEE) 的设备中执行时,它会按预期创建证书,但是当我在没有 TEE 的设备或模拟器中执行时,它会记录以下内容:

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 

如您所见,Not Before 和 Not After 中的日期与预期不符。

有人知道可能是什么原因吗?

嗨, 我试过你是本地代码,结果和你已经说过的一样。我还尝试操纵开始和结束日期以获得:

java.lang.IllegalArgumentException: certificateNotAfter < certificateNotBefore
        at android.security.keystore.KeyGenParameterSpec.<init>(KeyGenParameterSpec.java:328)
        at android.security.keystore.KeyGenParameterSpec$Builder.build(KeyGenParameterSpec.java:1340)
        at org.chickenhook.binderfuzzy.MainActivity.createRSAKeyPairtWithChallenge(MainActivity.kt:47)
        at org.chickenhook.binderfuzzy.MainActivity.onCreate(MainActivity.kt:28)
        at android.app.Activity.performCreate(Activity.java:7802)
        at android.app.Activity.performCreate(Activity.java:7791)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016) 
        at android.os.Handler.dispatchMessage(Handler.java:107) 
        at android.os.Looper.loop(Looper.java:214) 
        at android.app.ActivityThread.main(ActivityThread.java:7356) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930) 

这只是告诉我们您的参数设置正确并且 Android OS 在非 TEE 设备上也能正确解释。

我还检查了 Android 文档,发现并非所有 Keystore 实现都可能关心 "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. "

这并没有回答你的问题是确定性的,而是告诉你并不是所有的环境都关心时间有效性,因为它不是 "secure"。因此,最好不要提供时间有效性,以表明它没有安全性,而不是提供没有真正帮助的模因验证时间。

请考虑 23:59:59 1969 等意味着 time_t notBefore(time_t)-1 而 1970 意味着 time_t notAfter=(time_t) 0。所以我相信他们禁用了有效性,但需要 notebefore < notAfter.

但这不是一个确定性的答案,仍在搜索详细解释此问题的文档:(.