继前面一片《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. android 随手记之文件+参数上传请求
  2. 清单文件Manifest中的android:name
  3. Android SDK 源码
  4. Android之录制视频文件
  5. 【Android M】Monkey命令源码及是否处于monkey测试的判断方法
  6. 31、android打开文件夹并列出里面的文件
  7. Android应用程序消息处理机制(Looper、Handler)源码分析

随机推荐

  1. [Android] View动画特效(三)
  2. android添加开机声音
  3. Android(安卓)file.createNewFile方法问
  4. Android(安卓)打开系统蓝牙设置
  5. Android(安卓)启动 Launcher
  6. Android拍照得到的照片旋转了90度
  7. Android编译系统详解(一)
  8. Android(安卓)图片选择器用法
  9. Android(安卓)Studio 插件
  10. 理解Android中的Handler/Message