Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a1021890 authored by Hasib Prince's avatar Hasib Prince
Browse files

apk signature checking added for cleanapk

parent d8e9407d
Loading
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -150,6 +150,9 @@ dependencies {
    //logger
    //logger
    implementation 'com.jakewharton.timber:timber:5.0.1'
    implementation 'com.jakewharton.timber:timber:5.0.1'


    // Bouncy Castle
    implementation 'org.bouncycastle:bcpg-jdk15on:1.60'

    // Retrofit
    // Retrofit
    def retrofit_version = "2.9.0"
    def retrofit_version = "2.9.0"
    implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
    implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
+7.83 KiB

File added.

No diff preview for this file type.

+100 −0
Original line number Original line Diff line number Diff line
/*
 *  Copyright (C) 2022  ECORP
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

package foundation.e.apps.api.cleanapk

import android.content.Context
import org.bouncycastle.jce.provider.BouncyCastleProvider
import org.bouncycastle.openpgp.PGPCompressedData
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection
import org.bouncycastle.openpgp.PGPSignature
import org.bouncycastle.openpgp.PGPSignatureList
import org.bouncycastle.openpgp.PGPUtil
import org.bouncycastle.openpgp.jcajce.JcaPGPObjectFactory
import org.bouncycastle.openpgp.operator.bc.BcPGPContentVerifierBuilderProvider
import org.bouncycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator
import java.io.BufferedInputStream
import java.io.FileInputStream
import java.io.InputStream
import java.security.Security

object ApkSignatureManager {
    fun verifyFdroidSignature(context: Context, apkFilePath: String, signature: String): Boolean {
        Security.addProvider(BouncyCastleProvider())
        return verifyAPKSignature(
            BufferedInputStream(FileInputStream(apkFilePath)),
            signature.byteInputStream(Charsets.UTF_8),
            context.assets.open("f-droid.org-signing-key.gpg")
        )
    }

    private fun verifyAPKSignature(
        apkInputStream: BufferedInputStream,
        apkSignatureInputStream: InputStream,
        publicKeyInputStream: InputStream
    ): Boolean {
        try {
            val signature = extractSignature(apkSignatureInputStream)
            val pgpPublicKeyRingCollection =
                PGPPublicKeyRingCollection(
                    PGPUtil.getDecoderStream(publicKeyInputStream),
                    JcaKeyFingerprintCalculator()
                )

            val key = pgpPublicKeyRingCollection.getPublicKey(signature.keyID)
            signature.init(BcPGPContentVerifierBuilderProvider(), key)
            updateSignature(apkInputStream, signature)
            return signature.verify()
        } catch (e: Exception) {
            e.printStackTrace()
        } finally {
            apkInputStream.close()
            apkSignatureInputStream.close()
            publicKeyInputStream.close()
        }

        return false
    }

    private fun extractSignature(apkSignatureInputStream: InputStream): PGPSignature {
        var jcaPGPObjectFactory =
            JcaPGPObjectFactory(PGPUtil.getDecoderStream(apkSignatureInputStream))
        val pgpSignatureList: PGPSignatureList

        val pgpObject = jcaPGPObjectFactory.nextObject()
        if (pgpObject is PGPCompressedData) {
            jcaPGPObjectFactory = JcaPGPObjectFactory(pgpObject.dataStream)
            pgpSignatureList = jcaPGPObjectFactory.nextObject() as PGPSignatureList
        } else {
            pgpSignatureList = pgpObject as PGPSignatureList
        }
        val signature = pgpSignatureList.get(0)
        return signature
    }

    private fun updateSignature(
        apkInputStream: BufferedInputStream,
        signature: PGPSignature
    ) {
        val buff = ByteArray(1024)
        var read = apkInputStream.read(buff)
        while (read != -1) {
            signature.update(buff, 0, read)
            read = apkInputStream.read(buff)
        }
    }
}
+5 −1
Original line number Original line Diff line number Diff line
@@ -18,6 +18,7 @@


package foundation.e.apps.api.cleanapk
package foundation.e.apps.api.cleanapk


import android.os.Build
import android.util.Log
import android.util.Log
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
@@ -161,7 +162,10 @@ object RetrofitModule {
    fun provideInterceptor(): Interceptor {
    fun provideInterceptor(): Interceptor {
        return Interceptor { chain ->
        return Interceptor { chain ->
            val builder = chain.request().newBuilder()
            val builder = chain.request().newBuilder()
            builder.header("Accept-Language", Locale.getDefault().language)
            builder.header(
                "User-Agent",
                "Dalvik/2.1.0 (Linux; U; Android ${Build.VERSION.RELEASE};)"
            ).header("Accept-Language", Locale.getDefault().language)
            try {
            try {
                return@Interceptor chain.proceed(builder.build())
                return@Interceptor chain.proceed(builder.build())
            } catch (e: ConnectException) {
            } catch (e: ConnectException) {
+2 −1
Original line number Original line Diff line number Diff line
package foundation.e.apps.api.fdroid
package foundation.e.apps.api.fdroid


import foundation.e.apps.api.fdroid.models.FdroidApiModel
import foundation.e.apps.api.fdroid.models.FdroidApiModel
import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.GET
import retrofit2.http.Path
import retrofit2.http.Path


@@ -15,5 +16,5 @@ interface FdroidApiInterface {
    }
    }


    @GET("{packageName}.yml")
    @GET("{packageName}.yml")
    suspend fun getFdroidInfoForPackage(@Path("packageName") packageName: String): FdroidApiModel?
    suspend fun getFdroidInfoForPackage(@Path("packageName") packageName: String): Response<FdroidApiModel?>
}
}
Loading