CertificateUtils to kotlin

Bug: 383243644
Test: run terminal
Change-Id: I977b9cc90f6a207a5a201f47df5c9c45b8ac0d60
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/CertificateUtils.java b/android/TerminalApp/java/com/android/virtualization/terminal/CertificateUtils.java
deleted file mode 100644
index e3d1a67..0000000
--- a/android/TerminalApp/java/com/android/virtualization/terminal/CertificateUtils.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.virtualization.terminal;
-
-import static com.android.virtualization.terminal.MainActivity.TAG;
-
-import android.content.Context;
-import android.security.keystore.KeyGenParameterSpec;
-import android.security.keystore.KeyProperties;
-import android.util.Base64;
-import android.util.Log;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.KeyPairGenerator;
-import java.security.KeyStore;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.CertificateExpiredException;
-import java.security.cert.CertificateNotYetValidException;
-import java.security.cert.X509Certificate;
-
-public class CertificateUtils {
-    private static final String ALIAS = "ttyd";
-
-    public static KeyStore.PrivateKeyEntry createOrGetKey() {
-        try {
-            KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
-            ks.load(null);
-
-            if (!ks.containsAlias(ALIAS)) {
-                Log.d(TAG, "there is no keypair, will generate it");
-                createKey();
-            } else if (!(ks.getCertificate(ALIAS) instanceof X509Certificate)) {
-                Log.d(TAG, "certificate isn't X509Certificate or it is invalid");
-                createKey();
-            } else {
-                try {
-                    ((X509Certificate) ks.getCertificate(ALIAS)).checkValidity();
-                } catch (CertificateExpiredException | CertificateNotYetValidException e) {
-                    Log.d(TAG, "certificate is invalid", e);
-                    createKey();
-                }
-            }
-            return ((KeyStore.PrivateKeyEntry) ks.getEntry(ALIAS, null));
-        } catch (Exception e) {
-            throw new RuntimeException("cannot generate or get key", e);
-        }
-    }
-
-    private static void createKey()
-            throws NoSuchAlgorithmException,
-                    NoSuchProviderException,
-                    InvalidAlgorithmParameterException {
-        KeyPairGenerator kpg =
-                KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore");
-        kpg.initialize(
-                new KeyGenParameterSpec.Builder(
-                                ALIAS, KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY)
-                        .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
-                        .build());
-
-        kpg.generateKeyPair();
-    }
-
-    public static void writeCertificateToFile(Context context, Certificate cert) {
-        String certFileName = "ca.crt";
-        File certFile = new File(context.getFilesDir(), certFileName);
-        try (FileOutputStream writer = new FileOutputStream(certFile)) {
-            String cert_begin = "-----BEGIN CERTIFICATE-----\n";
-            String end_cert = "-----END CERTIFICATE-----\n";
-            String output =
-                    cert_begin
-                            + Base64.encodeToString(cert.getEncoded(), Base64.DEFAULT)
-                                    .replaceAll("(.{64})", "$1\n")
-                            + end_cert;
-            writer.write(output.getBytes());
-        } catch (IOException | CertificateEncodingException e) {
-            throw new RuntimeException("cannot write certs", e);
-        }
-    }
-}
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/CertificateUtils.kt b/android/TerminalApp/java/com/android/virtualization/terminal/CertificateUtils.kt
new file mode 100644
index 0000000..53809e5
--- /dev/null
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/CertificateUtils.kt
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.virtualization.terminal
+
+import android.content.Context
+import android.security.keystore.KeyGenParameterSpec
+import android.security.keystore.KeyProperties
+import android.util.Base64
+import android.util.Log
+import java.io.File
+import java.io.FileOutputStream
+import java.io.IOException
+import java.lang.Exception
+import java.lang.RuntimeException
+import java.security.InvalidAlgorithmParameterException
+import java.security.KeyPairGenerator
+import java.security.KeyStore
+import java.security.NoSuchAlgorithmException
+import java.security.NoSuchProviderException
+import java.security.cert.Certificate
+import java.security.cert.CertificateEncodingException
+import java.security.cert.CertificateExpiredException
+import java.security.cert.CertificateNotYetValidException
+import java.security.cert.X509Certificate
+
+object CertificateUtils {
+    private const val ALIAS = "ttyd"
+
+    @JvmStatic
+    fun createOrGetKey(): KeyStore.PrivateKeyEntry {
+        try {
+            val ks = KeyStore.getInstance("AndroidKeyStore")
+            ks.load(null)
+
+            if (!ks.containsAlias(ALIAS)) {
+                Log.d(MainActivity.TAG, "there is no keypair, will generate it")
+                createKey()
+            } else if (ks.getCertificate(ALIAS) !is X509Certificate) {
+                Log.d(MainActivity.TAG, "certificate isn't X509Certificate or it is invalid")
+                createKey()
+            } else {
+                try {
+                    (ks.getCertificate(ALIAS) as X509Certificate).checkValidity()
+                } catch (e: CertificateExpiredException) {
+                    Log.d(MainActivity.TAG, "certificate is invalid", e)
+                    createKey()
+                } catch (e: CertificateNotYetValidException) {
+                    Log.d(MainActivity.TAG, "certificate is invalid", e)
+                    createKey()
+                }
+            }
+            return ks.getEntry(ALIAS, null) as KeyStore.PrivateKeyEntry
+        } catch (e: Exception) {
+            throw RuntimeException("cannot generate or get key", e)
+        }
+    }
+
+    @Throws(
+        NoSuchAlgorithmException::class,
+        NoSuchProviderException::class,
+        InvalidAlgorithmParameterException::class,
+    )
+    private fun createKey() {
+        val kpg = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore")
+        kpg.initialize(
+            KeyGenParameterSpec.Builder(
+                    ALIAS,
+                    KeyProperties.PURPOSE_SIGN or KeyProperties.PURPOSE_VERIFY,
+                )
+                .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
+                .build()
+        )
+
+        kpg.generateKeyPair()
+    }
+
+    @JvmStatic
+    fun writeCertificateToFile(context: Context, cert: Certificate) {
+        val certFile = File(context.getFilesDir(), "ca.crt")
+        try {
+            FileOutputStream(certFile).use { writer ->
+                val certBegin = "-----BEGIN CERTIFICATE-----\n"
+                val certEnd = "-----END CERTIFICATE-----\n"
+                val output =
+                    (certBegin +
+                        Base64.encodeToString(cert.encoded, Base64.DEFAULT)
+                            .replace("(.{64})".toRegex(), "$1\n") +
+                        certEnd)
+                writer.write(output.toByteArray())
+            }
+        } catch (e: IOException) {
+            throw RuntimeException("cannot write certs", e)
+        } catch (e: CertificateEncodingException) {
+            throw RuntimeException("cannot write certs", e)
+        }
+    }
+}