继前面一片《android APK签名过程之MANIFEST.MF分析》分析APK签名中的CERT.SF文件



MANIFEST.MF文件内容:
Manifest-Version: 1.0Created-By: 1.0 (Android)Name: res/drawable-xhdpi/ic_launcher.pngSHA1-Digest: AfPh3OJoypH966MludSW6f1RHg4=Name: res/menu/main.xmlSHA1-Digest: wXc4zBe0Q2LPi4bMr25yy5JJQig=Name: AndroidManifest.xmlSHA1-Digest: k3QiLyii25nxkE9q59pXGWI2aTo=Name: res/drawable-mdpi/ic_launcher.pngSHA1-Digest: RRxOSvpmhVfCwiprVV/wZlaqQpw=Name: res/drawable-hdpi/ic_launcher.pngSHA1-Digest: Nq8q3HeTluE5JNCBpVvNy3BXtJI=Name: res/layout/activity_main.xmlSHA1-Digest: qVW+nHovqmEmKpssXKUBidrNDDA=Name: resources.arscSHA1-Digest: luJu2wwHeH7XAJwms2gIq/pco40=Name: lib/armeabi/libhello-jni.soSHA1-Digest: uFb6Vfi3T/Rq0dvjgCqW7fKKrzM=Name: classes.dexSHA1-Digest: zaipAFvc+AzMSc2nJJG9zIrrfqE=Name: res/drawable-xxhdpi/ic_launcher.pngSHA1-Digest: GVIfdEOBv4gEny2T1jDhGGsZOBo=

CERT.SF文件内容:
Signature-Version: 1.0Created-By: 1.0 (Android)SHA1-Digest-Manifest: KYIkAR4PbCA4w3MLMr7ViERYEC0=Name: res/menu/main.xmlSHA1-Digest: 4zwSAYv23t3kqpzCDB/SFXeI+fE=Name: res/drawable-xhdpi/ic_launcher.pngSHA1-Digest: cIga++hy5wqjHl9IHSfbg8tqCug=Name: AndroidManifest.xmlSHA1-Digest: FZ/sx6NI+BZkCi/hVlBHDLFbKxM=Name: res/drawable-mdpi/ic_launcher.pngSHA1-Digest: VY7kOF8E3rn8EUTvQC/DcBEN6kQ=Name: res/drawable-hdpi/ic_launcher.pngSHA1-Digest: stS7pUucSY0GgAVoESyO3Y7SanU=Name: res/layout/activity_main.xmlSHA1-Digest: bl4WBWN5ooqlzio7tNRqDWt3oWM=Name: resources.arscSHA1-Digest: tnBvelvdDz0kEBfPf+RjqGfpdn4=Name: classes.dexSHA1-Digest: lxB86ol+PFq8rG2IpToRpZi2JcI=Name: lib/armeabi/libhello-jni.soSHA1-Digest: +rWr7fBTZjm2JnvJytCJCdmdLso=Name: res/drawable-xxhdpi/ic_launcher.pngSHA1-Digest: KKqaLh/DVvFp+v1KoaDw7xETvrI=

比较发现CERT.SF比MANIFEST.MF多了一个SHA1-Digest-Manifest的值,这个值其实是MANIFEST.MF文件的SHA1并base64编码的值,可以手动验证,也可以从android源码分析。

打开android源码build/tools/signapk/SignApk.java分析,没有下载android源码的可以在线参考: https://github.com/OESF/Embedded-Master-MIPS/blob/370863733b500b7f0ded111f4b800bce990d69a5/build/tools/signapk/SignApk.java
// CERT.SF            Signature signature = Signature.getInstance("SHA1withRSA");            signature.initSign(privateKey);            je = new JarEntry(CERT_SF_NAME);            je.setTime(timestamp);            outputJar.putNextEntry(je);            writeSignatureFile(manifest,                    new SignatureOutputStream(outputJar, signature));

    /** Write a .SF file with a digest the specified manifest. */    private static void writeSignatureFile(Manifest manifest, OutputStream out)            throws IOException, GeneralSecurityException {        Manifest sf = new Manifest();        Attributes main = sf.getMainAttributes();        main.putValue("Signature-Version", "1.0");        main.putValue("Created-By", "1.0 (Android SignApk)");        BASE64Encoder base64 = new BASE64Encoder();        MessageDigest md = MessageDigest.getInstance("SHA1");        PrintStream print = new PrintStream(                new DigestOutputStream(new ByteArrayOutputStream(), md),                true, "UTF-8");        // Digest of the entire manifest        manifest.write(print);        print.flush();        main.putValue("SHA1-Digest-Manifest", base64.encode(md.digest()));        Map<String, Attributes> entries = manifest.getEntries();        for (Map.Entry<String, Attributes> entry : entries.entrySet()) {            // Digest of the manifest stanza for this entry.            print.print("Name: " + entry.getKey() + "\r\n");            for (Map.Entry<Object, Object> att : entry.getValue().entrySet()) {                print.print(att.getKey() + ": " + att.getValue() + "\r\n");            }            print.print("\r\n");            print.flush();            Attributes sfAttr = new Attributes();            sfAttr.putValue("SHA1-Digest", base64.encode(md.digest()));            sf.getEntries().put(entry.getKey(), sfAttr);        }        sf.write(out);    }

通过代码可以发现SHA1-Digest-Manifest是MANIFEST.MF文件的SHA1并base64编码的结果。
后面的for循环是对每一项再次SHA1并base64编码,例如:
Name: res/menu/main.xmlSHA1-Digest: wXc4zBe0Q2LPi4bMr25yy5JJQig=
     注意最后是两个"\r\n",手动验证也很简单,把上面的字符串保存为文件,并查看文件的HASH值是:E33C12018BF6DEDDE4AA9CC20C1FD2157788F9F1,将其保存为二进制文件并对文件进行一次base64编码,可得4zwSAYv23t3kqpzCDB/SFXeI+fE=          


参考:
取得签名工具加载证书库, 取得签名证书链和私钥: http://www.oschina.net/code/snippet_1434_1503
从CERT.RSA中提取证书 : http://www.wangchen.org/2011/01/%E4%BB%8Ecert-rsa%E4%B8%AD%E6%8F%90%E5%8F%96%E8%AF%81%E4%B9%A6/

更多相关文章

  1. NPM 和webpack 的基础使用
  2. 【阿里云镜像】使用阿里巴巴DNS镜像源——DNS配置教程
  3. 清单文件Manifest中的android:name
  4. Android之录制视频文件
  5. Android之离线词典
  6. Android全屏设置的两种方式
  7. android 模拟器使用指导
  8. android操作xml
  9. Android(安卓)TextView背景色、圆角、内部填充设置

随机推荐

  1. Mysql 查询JSON结果的相关函数汇总
  2. Mysql 实现字段拼接的三个函数
  3. 阿里云centos7安装mysql8.0.22的详细教程
  4. 浅谈MySQL中的自增主键用完了怎么办
  5. MySQL 查询的排序、分页相关
  6. MySql索引使用策略分析
  7. mysql 如何动态修改复制过滤器
  8. MySQL ddl语句的使用
  9. MySQL中使用binlog时格式该如何选择
  10. mysql 8.0.22 安装配置图文教程