zoukankan      html  css  js  c++  java
  • android APK签名过程之MANIFEST.MF分析

    一、手工验证

    用winrar打开签名过的apk包,发现多了一个META-INF文件夹:

    解压缩后打开META-INF目录,有三个文件:MANIFEST.MF,CERT.SF,CERT.RSA



    本文只讲解MANIFEST.MF的生成,用记事本打开MANIFEST.MF文件:
    Manifest-Version: 1.0
    Created-By: 1.0 (Android)
    
    Name: res/drawable-xhdpi/ic_launcher.png
    SHA1-Digest: AfPh3OJoypH966MludSW6f1RHg4=
    
    Name: res/menu/main.xml
    SHA1-Digest: wXc4zBe0Q2LPi4bMr25yy5JJQig=
    
    Name: AndroidManifest.xml
    SHA1-Digest: k3QiLyii25nxkE9q59pXGWI2aTo=
    
    Name: res/drawable-mdpi/ic_launcher.png
    SHA1-Digest: RRxOSvpmhVfCwiprVV/wZlaqQpw=
    
    Name: res/drawable-hdpi/ic_launcher.png
    SHA1-Digest: Nq8q3HeTluE5JNCBpVvNy3BXtJI=
    
    Name: res/layout/activity_main.xml
    SHA1-Digest: qVW+nHovqmEmKpssXKUBidrNDDA=
    
    Name: resources.arsc
    SHA1-Digest: luJu2wwHeH7XAJwms2gIq/pco40=
    
    Name: lib/armeabi/libhello-jni.so
    SHA1-Digest: uFb6Vfi3T/Rq0dvjgCqW7fKKrzM=
    
    Name: classes.dex
    SHA1-Digest: zaipAFvc+AzMSc2nJJG9zIrrfqE=
    
    Name: res/drawable-xxhdpi/ic_launcher.png
    SHA1-Digest: GVIfdEOBv4gEny2T1jDhGGsZOBo=
    


    以文件res/menu/main.xml做验证,用HashTab查看该文件的SHA-1值是C17738CC17B44362CF8B86CCAF6E72CB92494228


    复制该二进制串到WINHEX中:


    使用“Base64编码解码工具”对此二进制文件计算base64编码:


    打开输出文件中的base64编码为:
    wXc4zBe0Q2LPi4bMr25yy5JJQig=

    是和MANIFEST.MF文件中res/menu/main.xml对应的SHA1-Digest值是一样的。

    也就是说MANIFEST.MF中保存了所有其他文件的SHA-1并base64编码后的值。




    二、android源码验证

    打开android源码build/tools/signapk/SignApk.java分析,没有下载android源码的可以在线参考: https://github.com/OESF/Embedded-Master-MIPS/blob/370863733b500b7f0ded111f4b800bce990d69a5/build/tools/signapk/SignApk.java


                // MANIFEST.MF
                Manifest manifest = addDigestsToManifest(inputJar);
                je = new JarEntry(JarFile.MANIFEST_NAME);
                je.setTime(timestamp);
                outputJar.putNextEntry(je);
                manifest.write(outputJar);
    

      
        /** Add the SHA1 of every file to the manifest, creating it if necessary. */
        private static Manifest addDigestsToManifest(JarFile jar)
                throws IOException, GeneralSecurityException {
            Manifest input = jar.getManifest();
            Manifest output = new Manifest();
            Attributes main = output.getMainAttributes();
            if (input != null) {
                main.putAll(input.getMainAttributes());
            } else {
                main.putValue("Manifest-Version", "1.0");
                main.putValue("Created-By", "1.0 (Android SignApk)");
            }
    
            BASE64Encoder base64 = new BASE64Encoder();
            MessageDigest md = MessageDigest.getInstance("SHA1");
            byte[] buffer = new byte[4096];
            int num;
    
            // We sort the input entries by name, and add them to the
            // output manifest in sorted order.  We expect that the output
            // map will be deterministic.
            TreeMap<String, JarEntry> byName = new TreeMap<String, JarEntry>();
    
            for (Enumeration<JarEntry> e = jar.entries(); e.hasMoreElements(); ) {
                JarEntry entry = e.nextElement();
                byName.put(entry.getName(), entry);
            }
    
            for (JarEntry entry: byName.values()) {
                String name = entry.getName();
                if (!entry.isDirectory() && !name.equals(JarFile.MANIFEST_NAME) &&
                    !name.equals(CERT_SF_NAME) && !name.equals(CERT_RSA_NAME) &&
                    (stripPattern == null ||
                     !stripPattern.matcher(name).matches())) {
                    InputStream data = jar.getInputStream(entry);
                    while ((num = data.read(buffer)) > 0) {
                        md.update(buffer, 0, num);
                    }
    
                    Attributes attr = null;
                    if (input != null) attr = input.getAttributes(name);
                    attr = attr != null ? new Attributes(attr) : new Attributes();
                    attr.putValue("SHA1-Digest", base64.encode(md.digest()));
                    output.getEntries().put(name, attr);
                }
            }
    
            return output;
        }
    

    也可以看出MANIFEST.MF中保存了所有其他文件的SHA-1并base64编码后的值。

    转自:http://blog.csdn.net/asmcvc/article/details/9311827
  • 相关阅读:
    Threejs学习 一
    Mapbox的表达式
    mapbox 不加载地图
    SQL Server将查询出数据进行列转行操作
    SQL Server 常用近百条SQL语句(收藏版)
    SQL Server DATEDIFF() 函数用法
    SQL Server 数据库开启日志CDC记录,导致SQL Server 数据库日志异常增大
    查询SQL Server数据库使用的版本号信息
    windows 无法启动 SQL Server (MSSQLSERVER) 服务(位于本地计算机上)。错误 1069由于登入失败而无法启动 。
    SQL Server 不同数据间建立链接服务器进行连接查询
  • 原文地址:https://www.cnblogs.com/xieyuan/p/3787271.html
Copyright © 2011-2022 走看看