2021年6月10日 星期四

寫一個 Makefile 利用 openssl 產生自我簽章(selfsign)的證書(certification) 讓 Android SSLServerSocket 正常運作

將下列文字存成 Makefile, 複製到 Android 專案目錄內, 接著在終端機下指令 Make, 就會產生一個鑰匙庫(keystore.p12)放在 app/src/main/res/raw 目錄內, 而私鑰則放在 key 目錄下:
#Makefile
storepass=PKCS12_keystore_for_android_app
tempDir=/dev/shm
saveDir=app/src/main/res/raw
privateDir=key

gen: keystore.p12

keystore.p12: selfsign
    openssl pkcs12 -export -inkey $(privateDir)/prvkey.pem -passout pass:$(storepass) -in $(tempDir)/$< -out $(saveDir)/$@
    
selfsign: buildDirectory
    openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout $(privateDir)/prvkey.pem -subj "/C=TW/ST=Taiwan/L=TaipeiCity/CN=localhost" -out $(tempDir)/$@
    
buildDirectory:
    [ -d $(saveDir) ] || mkdir $(saveDir)
    [ -d $(privateDir) ] || mkdir $(privateDir)

clean:
    rm -rf $(tempDir)/selfsign

Android app 可以利用 resources 將它載入, 之後就能讓 SSL Server Socket 正常運作:

        // ...
        val tls = SSLContext.getInstance("TLS").apply {
            val keyStore = KeyStore.getInstance("PKCS12")
            val storepass = "PKCS12_keystore_for_android_app"//pass phrase define in Makefile
            resources.openRawResource(R.raw.keystore).apply {
                keyStore.load(this, storepass.toCharArray())
                close()
            }
            val kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()).apply {
                init(keyStore, storepass.toCharArray())
            }
            init(kmf.keyManagers, null, null)
        }
        val sslServer = tls.serverSocketFactory.createServerSocket(8443) .apply{
            setReuseAddress(true)
        }

如果寫的是 ssl client 端程式, 則要將信任網站的簽署檔(cert file) 放入 keystore, 交由 TrustManager 來管理, Android 可以使用 BKS 格式檔:

        val tls = SSLContext.getInstance("TLS").apply {
            val keyStore = KeyStore.getInstance("PKCS12")
            val storepass = "PKCS12_keystore_for_android_app"//pass phrase define in Makefile
            resources.openRawResource(R.raw.keystore).apply {
                keyStore.load(this, storepass.toCharArray())
                close()
            }
            val kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()).apply {
                init(keyStore, storepass.toCharArray())
            }
            val trustStore = KeyStore.getInstance("BKS")
            val storepass = "PKCS12_keystore_for_android_app"//pass phrase define in Makefile
            resources.openRawResource(R.raw.truststore).apply {
                trustStore.load(this, storepass.toCharArray())
                close()
            }
            val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()).apply {
                init(trustStore)
            }
            init(kmf.keyManagers, tmf.trustManagers, SecureRandom())
        }

沒有留言:

張貼留言

使用 pcie 轉接器連接 nvme SSD

之前 AM4 主機板使用 pcie ssd, 但主機板故障了沒辦法上網, 只好翻出以前買的 FM2 舊主機板, 想辦法讓老主機復活, 但舊主機板沒有 nvme 的界面, 因此上網買了 pcie 轉接器用來連接 nvme ssd, 遺憾的是 grub2 bootloader 無法識...