package com.gantix.JailMonkey.SignatureCheck;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.os.Build;

import androidx.annotation.NonNull;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import com.google.common.io.BaseEncoding;

public class SignatureCheck {
    private static List<String> getSignatures(@NonNull PackageManager pm, @NonNull String packageName) {
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                PackageInfo packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNING_CERTIFICATES);
                if (packageInfo == null
                        || packageInfo.signingInfo == null) {
                    return null;
                }
                if(packageInfo.signingInfo.hasMultipleSigners()){
                    return signatureDigest(packageInfo.signingInfo.getApkContentsSigners());
                }
                else{
                    return signatureDigest(packageInfo.signingInfo.getSigningCertificateHistory());
                }
            }
            else {
                @SuppressLint("PackageManagerGetSignatures")
                PackageInfo packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
                if (packageInfo == null
                        || packageInfo.signatures == null
                        || packageInfo.signatures.length == 0
                        || packageInfo.signatures[0] == null) {
                    return null;
                }
                return signatureDigest(packageInfo.signatures);
            }
        } catch (PackageManager.NameNotFoundException e) {
            return null;
        }
    }

    private static String signatureDigest(Signature sig) {
        byte[] signature = sig.toByteArray();
        try {
            MessageDigest md = MessageDigest.getInstance("SHA1");
            byte[] digest = md.digest(signature);
            return BaseEncoding.base16().lowerCase().encode(digest);
        } catch (NoSuchAlgorithmException e) {
            return null;
        }
    }
    private static List<String> signatureDigest(Signature[] sigList) {
        List<String> signaturesList = new ArrayList<>();
        for (Signature signature: sigList) {
            if(signature!=null) {
                signaturesList.add(signatureDigest(signature));
            }
        }
        return signaturesList;
    }

    public static boolean verifyAppSignature(Context context,String currentSignatureCheck) {
        //you should load approvedSignatures from a secure place not plain text
        currentSignatureCheck = currentSignatureCheck.replace(":","");
        currentSignatureCheck = currentSignatureCheck.toLowerCase();
        List<String> approvedSignatures = new ArrayList<>();
        approvedSignatures.add(currentSignatureCheck);


        List<String> currentSignatures = getSignatures(context.getPackageManager(), context.getPackageName());
        if(currentSignatures!=null && currentSignatures.size()>0) {
            //first checking if no unapproved signatures exist
            for (String signatureHex : currentSignatures) {
                if (!approvedSignatures.contains(signatureHex)) {
                    return false;
                }
            }
            //now checking if any of approved signatures exist
            for (String signatureHex : currentSignatures) {
                if (approvedSignatures.contains(signatureHex)) {
                    return true;
                }
            }
        }
        return false;
    }
}
