package com.verifyApk;

import java.io.File;

public class Demo {
    public static void main(String[] args) throws Exception {

        File file = new File("C:\\Users\\dell\\Desktop\\verify_apk\\com.okinc.okex_5.3.16_liqucn.com.apk");

        ApkInfoEntity apkInfoEntity = VerifyUtil.verifyApk(file);
        System.out.println(apkInfoEntity);

    }
}
package com.verifyApk;

import net.dongliu.apk.parser.ApkFile;
import net.dongliu.apk.parser.bean.ApkMeta;
import net.dongliu.apk.parser.bean.Permission;
import sun.security.pkcs.PKCS7;

import java.io.*;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;

/**
 * 解析工具类
 */
public class VerifyUtil {

    private static final String KEYTOOL_ONE = "keytool -printcert -jarfile ";

    private static final String FILE_DIR = "C:\\Users\\dell\\Desktop\\verify_apk\\";

    public static ApkInfoEntity verifyApk(File file) throws Exception {
        ApkInfoEntity apkInfoEntity = new ApkInfoEntity();
        //获取解析对象
        ApkFile apkFile = new ApkFile(file);
        //获取parserApk元信息对象
        ApkMeta apkMeta = apkFile.getApkMeta();

        String originalName = file.getName();//原始文件名
        String md5 = MD5SHA1Util.getMd5(file);//md5
        String sha1 = MD5SHA1Util.getSha1(file);//sha1
        String apkPath = file.getPath();//存储路径
        String logoPath = apkMeta.getIcon();//app中logo的存储位置
        String displayName = apkMeta.getLabel();//app在手机中显示的名称
        String packageName = apkMeta.getPackageName();//应用包名
        Long versionCode = apkMeta.getVersionCode();
        System.out.println("versionCode : " + versionCode);
        String minSdkVersion = apkMeta.getMinSdkVersion();//支持的最低android版本
        String maxSdkVersion = apkMeta.getMaxSdkVersion();//支持的最高android版本

        List<Permission> permissionList = apkMeta.getPermissions();
        List<String> permission_string = new ArrayList<>();
        String permissions = null;

        if (permissionList.size()>0){
            for (Permission p : permissionList) {
                String permission = p.getName();
                permission_string.add(permission);
            }
            String permissions_string = String.valueOf(permission_string);
            permissions = permissions_string.substring(permissions_string.indexOf('[')+1, permissions_string.lastIndexOf(']'));//权限列表
        }

        //判断是否加固
        GetReinforcementMoth.initData();
        boolean isProtectedFlag = GetReinforcementMoth.getReinforcementMothByPaths(apkPath);//是否加固
        Integer isProtected = 0;
        if (isProtectedFlag==true){
            isProtected = 1;
        }

        StringBuffer cerDetail = new StringBuffer();
        List<String> cerDetailList = rsaInfo(apkPath);//证书详细信息
        for (String c : cerDetailList) {
            cerDetail.append(c);
        }
        System.out.println(cerDetail);

        //获取开发商
        String cerDetails = cerDetailList.get(5);
        String[] split = cerDetails.split(",");
        String CN = null;
        for (int i = 0; i < split.length; i++) {
            boolean contains = split[i].contains("CN=");
            if (contains==true) {
                CN = split[i];
                break;
            }
        }
        String developer = CN.substring(CN.indexOf("CN=") + 3);//开发商

        //获取证书公钥md5值
        String md5String = cerDetailList.get(9);
        String substringMd5 = md5String.substring(md5String.indexOf("MD5: ") + 5);
        String cert_md5 = substringMd5.replace(":", "");//证书公钥md5值

        //获取证书公钥sha1值
        String sha1String = cerDetailList.get(10);
        String substringSHA1 = sha1String.substring(sha1String.indexOf("SHA1: ") + 6);
        String cert_sha1 = substringSHA1.replace(":", "");//证书公钥sha1值

        //获取证书公钥sha256值
        String sha256String = cerDetailList.get(11);
        String substringSHA256 = sha256String.substring(sha256String.indexOf("SHA256: ") + 8);
        String cert_sha256 = substringSHA256.replace(":", "");//证书公钥sha1值

        //获取证书串号
        String cert_serial_string = cerDetailList.get(12);
        String cert_serial = cert_serial_string.substring(cert_serial_string.indexOf(": ") + 2);//证书证书串号

        //获取证书版本号
        String cert_version_string = cerDetailList.get(13);
        String cert_version = cert_version_string.substring(cert_version_string.indexOf(": ") + 2);//证书版本号


        //获取文件名字(不带后缀)
        String unzipName = apkPath.substring(0, apkPath.lastIndexOf('.'));
        File unzipFileDir = new File(unzipName);
        if (!unzipFileDir.exists()){
            unzipFileDir.exists();
        }
        //复制原来的apk文件并且改后缀为 zip
        String unzipPath = unzipName + ".zip";
        File copyFile = new File(unzipPath);
        if (!copyFile.exists()){
            FileUtils.copyFileUsingJava7Files(file, copyFile);
        }
        //解压apk文件
        ZipUtils.unZip(unzipPath, unzipName);
        //获取.RSA文件名
        String rsa_name = FileUtils.getfiles(unzipName + "/META-INF");
        FileInputStream fis =
                new FileInputStream(unzipName+"/META-INF/"+rsa_name);
        PKCS7 pkcs7 = new PKCS7(fis);
        X509Certificate publicKey = pkcs7.getCertificates()[0];
        byte[] signature = publicKey.getSignature();//证书签名(字节形式)

        //拷贝图标
        String logoInDirPath = FILE_DIR + displayName + logoPath.substring(logoPath.lastIndexOf('.'));
        saveBit(logoPath, apkPath, logoInDirPath);
        System.out.println(logoInDirPath);
        File logoFile = new File(logoInDirPath);

        System.gc();//清理缓存
//        Thread.sleep(10000);
//        logoFile.delete();//能删掉

        apkInfoEntity.setFileMd5(md5);
        apkInfoEntity.setFileSha1(sha1);
        apkInfoEntity.setApkPath(apkPath);
        apkInfoEntity.setLogoPath(logoInDirPath);
        apkInfoEntity.setOriginalName(originalName);
        apkInfoEntity.setDisplayName(displayName);
        apkInfoEntity.setPackageName(packageName);
        apkInfoEntity.setMinVersion(minSdkVersion);
        apkInfoEntity.setMaxVersion(maxSdkVersion);
        apkInfoEntity.setIsProtected(isProtected);
        apkInfoEntity.setPermissionList(String.valueOf(permissions));
        apkInfoEntity.setApkSignature(String.valueOf(signature));
        apkInfoEntity.setDeveloper(developer);
        apkInfoEntity.setCerHash(cert_sha256);
        apkInfoEntity.setCerDetail(String.valueOf(cerDetail));
        apkInfoEntity.setCerPubMd5(cert_md5);
        apkInfoEntity.setCerPubSha1(cert_sha1);
        apkInfoEntity.setCerVersion(cert_version);
        apkInfoEntity.setCerSerial(cert_serial);

        return apkInfoEntity;
    }

    /**
     * 证书详细信息
     * @param apkPath 文件路径
     * @return
     */
    private static List<String> rsaInfo(String apkPath){
        System.out.println("==============开始读取证书信息==============");
        List<String> rsa = new ArrayList<>();
        try {
            String str = KEYTOOL_ONE + apkPath;
            //执行批处理文件
            Process process = Runtime.getRuntime().exec(str);
            //取得命令结果的输出流
            InputStream fis = process.getInputStream();
            //用一个读输出流类去读
            BufferedReader br = new BufferedReader(new InputStreamReader(fis, "GBK"));
            String line = null;
            //逐行读取输出到控制台
            System.out.println("=======================证书详情=======================");
            while ((line = br.readLine()) != null) {
                rsa.add(line);
                System.out.println(line);
            }
            System.out.println("========================结 束========================");
            br.close();
            fis.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("==============读取证书信息结束==============");
        return rsa;
    }

    /**
     * 拷贝图标
     * @param Icon   图标路径
     * @param file_path   apk的绝对地址
     * @param file_name   拷贝出来的图片的绝对路径名
     * @throws IOException
     */
    private static String saveBit(String Icon, String file_path, String file_name) throws IOException {
        System.out.println("===============开始拷贝logo===============");
        ZipInputStream zin = null;
        try {
            //  访问apk 里面的文件
            ZipFile zf = new ZipFile(file_path);
            InputStream in = new BufferedInputStream(new FileInputStream(file_path));
            zin = new ZipInputStream(in);
            ZipEntry ze;
            while ((ze = zin.getNextEntry()) != null) {
                if (ze.getName().equals(Icon)) {
                    //  拷贝出图标
                    InputStream inStream = zf.getInputStream(ze);

                    ByteArrayOutputStream outStream = new ByteArrayOutputStream();
                    //创建一个Buffer字符串
                    byte[] buffer = new byte[1024];
                    //每次读取的字符串长度,如果为-1,代表全部读取完毕
                    int len = 0;
                    //使用一个输入流从buffer里把数据读取出来
                    while ((len = inStream.read(buffer)) != -1) {
                        //用输出流往buffer里写入数据,中间参数代表从哪个位置开始读,len代表读取的长度
                        outStream.write(buffer, 0, len);
                    }
                    System.out.println("===============拷 贝 中===============");
                    //关闭输入流
                    inStream.close();
                    //把outStream里的数据写入内存

                    //得到图片的二进制数据,以二进制封装得到数据,具有通用性
                    byte[] data = outStream.toByteArray();
                    //new一个文件对象用来保存图片,默认保存当前工程根目录
                    File imageFile = new File(file_name);
                    String logo_path = imageFile.getPath();

                    //创建输出流
                    FileOutputStream fileOutStream = new FileOutputStream(imageFile);
                    //写入数据
                    fileOutStream.write(data);
                    fileOutStream.close();
                    outStream.close();
                    System.out.println("===============拷贝结束===============");
                    return logo_path;
                }
            }
            in.close();
            zf.close();
            zin.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            zin.closeEntry();
        }
        System.out.println("===============拷贝结束===============");
        return null;
    }




}
package com.verifyApk;

import org.apache.tools.zip.ZipOutputStream;

import java.io.*;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

public class ZipUtils {

    /**
     * 文件解压
     * @param inputFile  待解压文件夹/文件
     * @param destDirPath  解压路径
     */
    public static void unZip(String inputFile,String destDirPath) throws Exception {
        File srcFile = new File(inputFile);//获取当前压缩文件
        // 判断源文件是否存在
        if (!srcFile.exists()) {
            throw new Exception(srcFile.getPath() + "所指文件不存在");
        }
        java.util.zip.ZipFile zipFile = new ZipFile(srcFile);//创建压缩文件对象
        //开始解压
        Enumeration<?> entries = zipFile.entries();
        while (entries.hasMoreElements()) {
            java.util.zip.ZipEntry entry = (ZipEntry) entries.nextElement();
            // 如果是文件夹,就创建个文件夹
            if (entry.isDirectory()) {
//                String dirPath = destDirPath + "/" + entry.getName();
                srcFile.mkdirs();
            } else {
                // 如果是文件,就先创建一个文件,然后用io流把内容copy过去
                File targetFile = new File(destDirPath + "/" + entry.getName());
                // 保证这个文件的父文件夹必须要存在
                if (!targetFile.getParentFile().exists()) {
                    targetFile.getParentFile().mkdirs();
                }
                targetFile.createNewFile();
                // 将压缩文件内容写入到这个文件中
                InputStream is = zipFile.getInputStream(entry);
                FileOutputStream fos = new FileOutputStream(targetFile);
                int len;
                byte[] buf = new byte[1024];
                while ((len = is.read(buf)) != -1) {
                    fos.write(buf, 0, len);
                }
                // 关流顺序,先打开的后关闭
                fos.close();
                is.close();
            }
        }
    }


}
package com.verifyApk;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * 生成文件的MD5值和SHA1值
 */

public class MD5SHA1Util {

    public static void main(String[] args) throws IOException, NoSuchAlgorithmException {
        File file = new File("C:\\Users\\dell\\Desktop\\test_data\\apks\\KugouPlayer_219_V10.9.0.apk");
        System.out.println(getMd5(file));//cd9a3d636b84079581e62b79f8a398c5
        System.out.println(getSha1(file));//8F694A916B14F5A3561B5D3160635780F8F77463
    }

    /**
     * 获取目标文件SHA1值
     * @param file 目标文件
     * @return
     * @throws OutOfMemoryError
     * @throws IOException
     * @throws NoSuchAlgorithmException
     */
    public static String getSha1(File file) throws OutOfMemoryError, IOException, NoSuchAlgorithmException {
        MessageDigest messagedigest = MessageDigest.getInstance("SHA-1");
        FileInputStream in = new FileInputStream(file);
        FileChannel ch = in.getChannel();
        MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0, file.length());
        messagedigest.update(byteBuffer);
        in.close();
        ch.close();
        return bufferToHex(messagedigest.digest());
    }

    /**
     * 获取目标文件MD5值
     * @param file 目标文件
     * @return
     * @throws FileNotFoundException
     */
    public static String getMd5(File file) throws FileNotFoundException {
        String value = null;
        FileInputStream in = null;
        try {
            in = new FileInputStream(file);
            MappedByteBuffer byteBuffer = in.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, file.length());
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            md5.update(byteBuffer);
            BigInteger bi = new BigInteger(1, md5.digest());
            value = bi.toString(16);
            byteBuffer.clear();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != in) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return value;
    }

    private static String bufferToHex(byte bytes[]) {
        return bufferToHex(bytes, 0, bytes.length);
    }

    private static String bufferToHex(byte bytes[], int m, int n) {
        StringBuffer stringbuffer = new StringBuffer(2 * n);
        int k = m + n;
        for (int l = m; l < k; l++) {
            appendHexPair(bytes[l], stringbuffer);
        }
        return stringbuffer.toString();
    }

    private static void appendHexPair(byte bt, StringBuffer stringbuffer) {
        char c0 = hexDigits[(bt & 0xf0) >> 4];
        char c1 = hexDigits[bt & 0xf];
        stringbuffer.append(c0);
        stringbuffer.append(c1);
    }

    /**
     * 用于16进制的数组
     */
    protected static char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E','F' };


}
package com.verifyApk;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 * 判断apk是否加固
 */
public class GetReinforcementMoth {

    public static void main(String[] args) throws IOException {
        initData();
//        String apkSourceCodeDir[] = {"C:\\Users\\dell\\Desktop\\test_data\\apks\\"};
        String apkSourceCodeDir = "C:\\Users\\dell\\Desktop\\verify_apk\\bookreader4faloo5.7.9.apk";

        boolean isProtected = getReinforcementMothByPaths(apkSourceCodeDir);
        System.out.println(isProtected);


//      ArrayList<String> apkSourceCodeDir= new ArrayList<String>();
//      apkSourceCodeDir.add("G:\\workspace\\...\\...\\..");
//      apkSourceCodeDir.add("G:\\workspace\\...\\...\\..");
//      apkSourceCodeDir.add("E:\\workspace\\...\\...\\...\\..");
//      getReinforcementMothByPaths(apkSourceCodeDir);
    }

    /**
     * 加固so集合
     */
    static HashMap<String, String> reinforcementSoMaps;

    /**
     * 为so集合添加值
     */
    public static void initData() {
        reinforcementSoMaps = new HashMap<>();
        reinforcementSoMaps.put("libsecexe.so", "梆梆加固免费版");
        reinforcementSoMaps.put("libsecmain.so", "梆梆加固免费版");
        reinforcementSoMaps.put("libSecShell.so", "梆梆加固免费版");
        reinforcementSoMaps.put("secData0.jar", "梆梆加固免费版");
        reinforcementSoMaps.put("libSecShell-x86.so", "梆梆加固免费版");

        reinforcementSoMaps.put("libDexHelper.so", "梆梆企业版");
        reinforcementSoMaps.put("libDexHelper-x86.so", "梆梆企业版");
        reinforcementSoMaps.put("classes.jar", "梆梆加固定制版");
        reinforcementSoMaps.put("DexHelper.so", "梆梆加固定制版");

        reinforcementSoMaps.put("libtup.so", "腾讯加固");
//        reinforcementSoMaps.put("libexec.so", "腾讯加固");
        reinforcementSoMaps.put("libshell.so", "腾讯加固");
        reinforcementSoMaps.put("mix.dex", "腾讯加固");
        reinforcementSoMaps.put("mixz.dex", "腾讯加固");
        reinforcementSoMaps.put("libshella-xxxx.so", "腾讯加固");
        reinforcementSoMaps.put("libshellx-xxxx.so", "腾讯加固");

        reinforcementSoMaps.put("libtosprotection.armeabi-v7a.so", "腾讯御安全");
        reinforcementSoMaps.put("libtosprotection.armeabi.so", "腾讯御安全");
        reinforcementSoMaps.put("libtosprotection.x86.so", "腾讯御安全");
        reinforcementSoMaps.put("tosversion", "腾讯御安全");
        reinforcementSoMaps.put("libTmsdk-xxx-mfr.so", "腾讯御安全");
        reinforcementSoMaps.put("aliprotect.dat", "阿里加固");
        reinforcementSoMaps.put("libsgmain.so", "阿里加固");
        reinforcementSoMaps.put("libsgsecuritybody.so", "阿里加固");
        reinforcementSoMaps.put("libmobisec.so", "阿里加固");
        reinforcementSoMaps.put("libfakejni.so", "阿里加固");
        reinforcementSoMaps.put("libzuma.so", "阿里加固");
        reinforcementSoMaps.put("libzumadata.so", "阿里加固");
        reinforcementSoMaps.put("libpreverify1.so", "阿里加固");

        reinforcementSoMaps.put("kdpdata.so", "几维加固");
        reinforcementSoMaps.put("dex.dat", "几维加固");
        reinforcementSoMaps.put("libkdp.so", "几维加固");
        reinforcementSoMaps.put("libkwscmm.so", "几维加固");
        reinforcementSoMaps.put("libkwscr.so", "几维加固");
        reinforcementSoMaps.put("libkwslinker.so", "几维加固");

        reinforcementSoMaps.put("libexec.so", "爱加密");
        reinforcementSoMaps.put("libexecmain.so", "爱加密");
        reinforcementSoMaps.put("ijiami.dat", "爱加密");
        reinforcementSoMaps.put("ijiami.ajm", "爱加密");
        reinforcementSoMaps.put("af.bin", "爱加密");
        reinforcementSoMaps.put("signed.bin", "爱加密");

        reinforcementSoMaps.put("libchaosvmp.so", "娜迦");
        reinforcementSoMaps.put("libddog.so", "娜迦");
        reinforcementSoMaps.put("libfdog.so", "娜迦");
        reinforcementSoMaps.put("libedog.so", "娜迦");

        reinforcementSoMaps.put("libprotectClass.so", "360加固");
        reinforcementSoMaps.put("libjiagu.so", "360加固");
        reinforcementSoMaps.put("libjiagu_art.so", "360加固");
        reinforcementSoMaps.put("libjiagu_x86.so", "360加固");

        reinforcementSoMaps.put("libcmvmp.so", "中国移动安全加固");
        reinforcementSoMaps.put("libmogosec_dex.so", "中国移动安全加固");
        reinforcementSoMaps.put("libmogosec_sodecrypt.so", "中国移动安全加固");
        reinforcementSoMaps.put("libmogosecurity.so", "中国移动安全加固");

        reinforcementSoMaps.put("libbaiduprotect.so", "百度加固");
        reinforcementSoMaps.put("baiduprotect1.jar", "百度加固");
        reinforcementSoMaps.put("baiduprotect.jar", "百度加固");

        reinforcementSoMaps.put("libuusafe.jar.so", "UU安全加固");
        reinforcementSoMaps.put("libuusafe.so", "UU安全加固");
        reinforcementSoMaps.put("libuusafeempty.so", "UU安全加固");

        reinforcementSoMaps.put("dp.arm-v7.so.dat", "DexProtect加固");
        reinforcementSoMaps.put("dp.arm.so.dat", "DexProtect加固");

        reinforcementSoMaps.put("libegis.so", "通付盾加固");
        reinforcementSoMaps.put("libNSaferOnly.so", "通付盾加固");

        reinforcementSoMaps.put("libreincp.so", "珊瑚灵御加固");
        reinforcementSoMaps.put("libreincp_x86.so", "珊瑚灵御加固");

        reinforcementSoMaps.put("libnqshield.so", "网秦加固");

        reinforcementSoMaps.put("libnesec.so", "网易易盾");

        reinforcementSoMaps.put("libAPKProtect.so", "APKProtect加固");

        reinforcementSoMaps.put("libx3g.so", "顶象技术加固");

        reinforcementSoMaps.put("libitsec.so", "海云安加固");

        reinforcementSoMaps.put("libapssec.so", "盛大加固");

        reinforcementSoMaps.put("librsprotect.so", "瑞星加固");

        reinforcementSoMaps.put("libapktoolplus_jiagu.so", "apktoolplus加固");
    }

    /**
     * 遍历 目标文件夹
     * @param dirPath 目标文件夹
     * @return
     * @throws IOException
     */
    public static boolean getReinforcementMothByPaths(String dirPath) throws IOException {
        boolean flag = false;
//        for (String dirPath : JavaSourceCodeDirs) {
            File fl = new File(dirPath);
            if (fl.exists()) {
                flag = getApkFileReinforcementMoth(fl);
            }
//        }
        return flag;
    }

    public static void getReinforcementMothByPaths(ArrayList<String> JavaSourceCodeDirs) throws IOException {
        for (String dirPath : JavaSourceCodeDirs) {
            File fl = new File(dirPath);
            if (fl.exists()) {
                getApkFileReinforcementMoth(fl);
            }
        }
    }

    /**
     * 判断目标app是否加固
     * @param fl 目标app文件
     * @return
     * @throws IOException
     */
    private static boolean getApkFileReinforcementMoth(File fl) throws IOException {
        boolean flag = true;
        if (fl != null && fl.exists()) {
            if (fl.isDirectory()) {
                File[] listFiles = fl.listFiles();
                for (File file : listFiles)
                    getApkFileReinforcementMoth(file);
            } else if (fl.isFile() && !fl.isHidden()) {
                if (fl.getName().endsWith(".apk")) {
                    Enumeration<? extends ZipEntry> entries = new ZipFile(fl).entries();
                    Set<String> libSo = new HashSet<>();
                    while (entries.hasMoreElements()) {
                        ZipEntry apk = entries.nextElement();
                        if (!apk.isDirectory() && apk.getName().startsWith("lib/"))
                            libSo.add(apk.getName().substring(apk.getName().lastIndexOf("/") + 1));
                    }
                    if (libSo.isEmpty()) { // 没有lib
                        System.out.println(fl.getName() + ":\t从lib中没有分析出加固方式");
                        return false;
                    }
                    Set<String> reinforcementMoth = new HashSet<>();
                    // 有so
                    for (String libFile : libSo)
                        if (reinforcementSoMaps.containsKey(libFile)) {
                            reinforcementMoth.add(reinforcementSoMaps.get(libFile));
                        }
                    if (reinforcementMoth.size() > 0) {
                        System.out.println(fl.getName() + ":\t分析出加固方式为:" + reinforcementMoth.toString());
                        flag = true;
                    } else {
                        System.out.println(fl.getName() + ":\t从lib中没有分析出加固方式");
                        flag = false;
                    }
                    reinforcementMoth.clear();
                }
            }
        }
        return flag;
    }
}
package com.verifyApk;

import java.io.*;
import java.nio.file.Files;

public class FileUtils {


    /**
     * 复制文件
     * @param source 被复制的文件
     * @param dest 复制后的文件
     * @throws IOException
     */
    public static void copyFileUsingJava7Files(File source, File dest) throws IOException {
        Files.copy(source.toPath(), dest.toPath());
    }

    public static void main(String[] args) throws IOException {
        String rsa_name = getfiles("C:\\Users\\dell\\Desktop\\verify_apk\\bookreader4faloo5.7.9\\META-INF");
        System.out.println(rsa_name);
    }

    /**
     * 获取 .RSA文件名
     * @param meta_info .RSA文件所在的文件夹
     * @return
     * @throws IOException
     */
    public static String getfiles(String meta_info) throws IOException {
        File desktop = new File(meta_info);
        String rsa_name = null;

        String[] arr = desktop.list(new FilenameFilter() {

            @Override
            public boolean accept(File dir, String name) {
                //把dir 和name都封装到一个文件对象里
                File file = new File(dir, name);
                return file.isFile() && file.getName().endsWith(".RSA");
            }
        });
        //遍历符合过滤器的数组
        for (String string : arr) {
            String suffix = string.substring(string.lastIndexOf('.'));
            if (suffix.equals(".RSA")){
                rsa_name = string;
            }
        }
        return rsa_name;
    }




    /**
     *  根据路径删除指定的目录或文件,无论存在与否
     *@param sPath  要删除的目录或文件
     *@return 删除成功返回 true,否则返回 false。
     */
    public static boolean DeleteFolder(String sPath) {
        boolean flag = false;
        File file = new File(sPath);
        // 判断目录或文件是否存在
        if (!file.exists()) {  // 不存在返回 false
            return flag;
        } else {
            // 判断是否为文件
            if (file.isFile()) {  // 为文件时调用删除文件方法
                return deleteFile(sPath);
            } else {  // 为目录时调用删除目录方法
                return deleteDirectory(sPath);
            }
        }
    }

    /**
     * 删除单个文件
     * @param   sPath    被删除文件的文件名
     * @return 单个文件删除成功返回true,否则返回false
     */
    public static boolean deleteFile(String sPath) {
        boolean flag = false;
        File file = new File(sPath);
        // 路径为文件且不为空则进行删除
        if (file.isFile() && file.exists()) {
            file.delete();
            flag = true;
        }
        return flag;
    }
    /**
     * 删除目录(文件夹)以及目录下的文件
     * @param   sPath 被删除目录的文件路径
     * @return  目录删除成功返回true,否则返回false
     */
    public static boolean deleteDirectory(String sPath) {
        //如果sPath不以文件分隔符结尾,自动添加文件分隔符
        if (!sPath.endsWith(File.separator)) {
            sPath = sPath + File.separator;
        }
        File dirFile = new File(sPath);
        //如果dir对应的文件不存在,或者不是一个目录,则退出
        if (!dirFile.exists() || !dirFile.isDirectory()) {
            return false;
        }
        boolean flag = true;
        //删除文件夹下的所有文件(包括子目录)
        File[] files = dirFile.listFiles();
        for (int i = 0; i < files.length; i++) {
            //删除子文件
            if (files[i].isFile()) {
                flag = deleteFile(files[i].getAbsolutePath());
                if (!flag) break;
            } //删除子目录
            else {
                flag = deleteDirectory(files[i].getAbsolutePath());
                if (!flag) break;
            }
        }
        if (!flag) return false;
        //删除当前目录
        if (dirFile.delete()) {
            return true;
        } else {
            return false;
        }
    }
}
package com.verifyApk;


public class ApkInfoEntity {

    /**
     * APk文件MD5值
     */
    private String fileMd5;

    /**
     * apk文件sha1值
     */
    private String fileSha1;

    /**
     * apk文件存储路径
     */
    private String apkPath;

    /**
     * app中logo的存储位置
     */
    private String logoPath;

    /**
     * 原始文件名(上传时名称)
     */
    private String originalName;

    /**
     * app在手机中显示的名称
     */
    private String displayName;

    /**
     * 应用包名
     */
    private String packageName;

    /**
     * 支持的最低android版本
     */
    private String minVersion;

    /**
     * 支持的最高android版本
     */
    private String maxVersion;

    /**
     * 代码是否加固
     */
    private Integer isProtected;

    /**
     * 权限列表
     */
    private String permissionList;

    /**
     * 证书签名
     */
    private String apkSignature;

    /**
     * 开发商
     */
    private String developer;

    /**
     * 证书文件的Hash值
     */
    private String cerHash;

    /**
     * 证书详细信息
     */
    private String cerDetail;

    /**
     * 证书公钥md5值
     */
    private String cerPubMd5;

    /**
     * 证书公钥sha1值
     */
    private String cerPubSha1;

    /**
     * 证书版本号
     */
    private String cerVersion;

    /**
     * 证书串号
     */
    private String cerSerial;

    @Override
    public String toString() {
        return "ApkInfoEntity{" +
                "\n\tfileMd5='" + fileMd5 + '\'' +
                ", \n\tfileSha1='" + fileSha1 + '\'' +
                ", \n\tapkPath='" + apkPath + '\'' +
                ", \n\tlogoPath='" + logoPath + '\'' +
                ", \n\toriginalName='" + originalName + '\'' +
                ", \n\tdisplayName='" + displayName + '\'' +
                ", \n\tpackageName='" + packageName + '\'' +
                ", \n\tminVersion='" + minVersion + '\'' +
                ", \n\tmaxVersion='" + maxVersion + '\'' +
                ", \n\tisProtected=" + isProtected +
                ", \n\tpermissionList='" + permissionList + '\'' +
                ", \n\tapkSignature='" + apkSignature + '\'' +
                ", \n\tdeveloper='" + developer + '\'' +
                ", \n\tcerHash='" + cerHash + '\'' +
                ", \n\tcerDetail='" + cerDetail + '\'' +
                ", \n\tcerPubMd5='" + cerPubMd5 + '\'' +
                ", \n\tcerPubSha1='" + cerPubSha1 + '\'' +
                ", \n\tcerVersion='" + cerVersion + '\'' +
                ", \n\tcerSerial='" + cerSerial + '\'' +
                "\n}";
    }

    public String getFileMd5() {
        return fileMd5;
    }

    public void setFileMd5(String fileMd5) {
        this.fileMd5 = fileMd5;
    }

    public String getFileSha1() {
        return fileSha1;
    }

    public void setFileSha1(String fileSha1) {
        this.fileSha1 = fileSha1;
    }

    public String getApkPath() {
        return apkPath;
    }

    public void setApkPath(String apkPath) {
        this.apkPath = apkPath;
    }

    public String getLogoPath() {
        return logoPath;
    }

    public void setLogoPath(String logoPath) {
        this.logoPath = logoPath;
    }

    public String getOriginalName() {
        return originalName;
    }

    public void setOriginalName(String originalName) {
        this.originalName = originalName;
    }

    public String getDisplayName() {
        return displayName;
    }

    public void setDisplayName(String displayName) {
        this.displayName = displayName;
    }

    public String getPackageName() {
        return packageName;
    }

    public void setPackageName(String packageName) {
        this.packageName = packageName;
    }

    public String getMinVersion() {
        return minVersion;
    }

    public void setMinVersion(String minVersion) {
        this.minVersion = minVersion;
    }

    public String getMaxVersion() {
        return maxVersion;
    }

    public void setMaxVersion(String maxVersion) {
        this.maxVersion = maxVersion;
    }

    public Integer getIsProtected() {
        return isProtected;
    }

    public void setIsProtected(Integer isProtected) {
        this.isProtected = isProtected;
    }

    public String getPermissionList() {
        return permissionList;
    }

    public void setPermissionList(String permissionList) {
        this.permissionList = permissionList;
    }

    public String getApkSignature() {
        return apkSignature;
    }

    public void setApkSignature(String apkSignature) {
        this.apkSignature = apkSignature;
    }

    public String getDeveloper() {
        return developer;
    }

    public void setDeveloper(String developer) {
        this.developer = developer;
    }

    public String getCerHash() {
        return cerHash;
    }

    public void setCerHash(String cerHash) {
        this.cerHash = cerHash;
    }

    public String getCerDetail() {
        return cerDetail;
    }

    public void setCerDetail(String cerDetail) {
        this.cerDetail = cerDetail;
    }

    public String getCerPubMd5() {
        return cerPubMd5;
    }

    public void setCerPubMd5(String cerPubMd5) {
        this.cerPubMd5 = cerPubMd5;
    }

    public String getCerPubSha1() {
        return cerPubSha1;
    }

    public void setCerPubSha1(String cerPubSha1) {
        this.cerPubSha1 = cerPubSha1;
    }

    public String getCerVersion() {
        return cerVersion;
    }

    public void setCerVersion(String cerVersion) {
        this.cerVersion = cerVersion;
    }

    public String getCerSerial() {
        return cerSerial;
    }

    public void setCerSerial(String cerSerial) {
        this.cerSerial = cerSerial;
    }

    public ApkInfoEntity(String fileMd5, String fileSha1, String apkPath, String logoPath, String originalName, String displayName, String packageName, String minVersion, String maxVersion, Integer isProtected, String permissionList, String apkSignature, String developer, String cerHash, String cerDetail, String cerPubMd5, String cerPubSha1, String cerVersion, String cerSerial) {
        this.fileMd5 = fileMd5;
        this.fileSha1 = fileSha1;
        this.apkPath = apkPath;
        this.logoPath = logoPath;
        this.originalName = originalName;
        this.displayName = displayName;
        this.packageName = packageName;
        this.minVersion = minVersion;
        this.maxVersion = maxVersion;
        this.isProtected = isProtected;
        this.permissionList = permissionList;
        this.apkSignature = apkSignature;
        this.developer = developer;
        this.cerHash = cerHash;
        this.cerDetail = cerDetail;
        this.cerPubMd5 = cerPubMd5;
        this.cerPubSha1 = cerPubSha1;
        this.cerVersion = cerVersion;
        this.cerSerial = cerSerial;
    }

    public ApkInfoEntity() {
    }
}