Android otapackage流程分析四

前三篇文章可以说流程基本说完,还差一点那就是签名问题。看完前面文章会发现不管是全量升级包还是增量升级包中还有几个文件并没有说到

META-INF目录下
CERT.RSA
CERT.SF
MANIFEST.MF

还有META-INF\com\android 目录下otacert

这些文件怎么来的的,第二篇中有一个 SignOutput ,当全量或者增量流程走完时候进行签名流程,

  def SignOutput(temp_zip_name, output_zip_name):
    key_passwords = common.GetKeyPasswords([OPTIONS.package_key])                                                                    
    pw = key_passwords[OPTIONS.package_key]
  
    common.SignFile(temp_zip_name, output_zip_name, OPTIONS.package_key, pw,
                    whole_file=True)

      elif o in ("-k", "--package_key"):                                                                                             
        OPTIONS.package_key = a

key是命令传进来的,我们可以看到 common.py 脚本中

OPTIONS.signapk_path = "framework/signapk.jar"  # Relative to search_path
OPTIONS.extra_signapk_args = []
OPTIONS.java_path = "java"  # Use the one on the path by default.                                                                    
OPTIONS.java_args = "-Xmx2048m" # JVM Args
OPTIONS.public_key_suffix = ".x509.pem"
OPTIONS.private_key_suffix = ".pk8"

def GetKeyPasswords(keylist):

       p = Run(["openssl", "pkcs8", "-in", k+OPTIONS.private_key_suffix,
             "-inform", "DER", "-nocrypt"],
            stdin=devnull.fileno(),
            stdout=devnull.fileno(),
            stderr=subprocess.STDOUT)

def SignFile(input_name, output_name, key, password, align=None,
             whole_file=False):

 cmd = [OPTIONS.java_path, OPTIONS.java_args, "-jar",os.path.join(OPTIONS.search_path, OPTIONS.signapk_path)]
 cmd.extend(OPTIONS.extra_signapk_args)

其实运行命令如下

  running:  openssl pkcs8 -in build/target/product/security/testkey.pk8 -inform DER -nocrypt

running: java -Xmx2048m -jar out/host/linux-x86/framework/signapk.jar -w build/target/product/security/testkey.x509.pem build/target/product/security/testkey.pk8 /tmp/tmp1MmnV9 /home/yexiang/MSTAR_Android/yx_bak/updata_ota.zip

我们看 signapk.jar jar包,

使用方法:
signapk.jar -w <公钥> <私钥> <输入文件> <输出文件>

其中:-w表示对整个文件进行签名。

签名算法:
1. 程序遍历update.apk包中的所有文件(entry),对非文件夹非签名文件的文件,逐个生成SHA1的数字签名信息,再用Base64进行编码。写入manifest对象
2. 如果-w整包签,则将 证书testkey.x509.pem 复制到 META-INF/com/android/otacert; 
并在manifest对象中增加META-INF/com/android/otacert的SHA1摘要
3. 之后将manifest对象写入MANIFEST.MF文件。
4. 对前一步生成的Manifest,使用SHA1-RSA算法,用私钥进行签名。
5. 在CERT.RSA文件中保存公钥、所采用的加密算法等信息。
签名后,apk(zip)文件中多了下列文件

META-INF/com/android/otacert  // testkey.x509.pem
META-INF/MANIFEST.MF  // 各个entry的签名编码 里面有很多项
META-INF/CERT.SF
META-INF/CERT.RSA

最后要签名的命令是例如:
java -Xmx2048m -jar ./signapk.jar -w ./testkey.x509.pem ./testkey.pk8 ./tmp.zip ./out/update.zip
otacert 就是 testkey.x509.pem 的数据

通过 openssl pkcs7 -inform DER -in CERT.RSA -noout -print_certs -text 命令 可以查看CERT.RSA证书的内容

MANIFEST.MF 里面的各项是文件的SHA1值进行BASE64编码得到的
例如 sha1sum bfe_app.bin 得到SHA1值c3118f5209cf272e526628ac10d30ca043d65e31 把这个以二进制写到文件中去
然后 base64 这个文件得到 wxGPUgnPJy5SZiisENMMoEPWXjE= ,可以看到文件中也是一样的

CERT.SF 文件
最开始的一项是 MANIFEST.MF SHA1值进行BASE64编码的结果
是把MANIFEST.MF 里面的各个项再次保存到文件中算SHA1,然后以二进制写到文件中去
再次算BASE64的值,但这里有点不同 ,截取MANIFEST.MF 一个片段

Name: system/media/audio/ringtones/ArgoNavis.ogg
SHA1-Digest: umXNRCtBFkcNXqvPHpQCBLw7YgY=

Name: system/media/audio/ringtones/RomancingTheTone.ogg
SHA1-Digest: 1KjCt72M1Cqk5UEkVYRnRjOEMh4=

Name: system/etc/security/cacerts/35105088.0
SHA1-Digest: u9DXXHn7S70nNpMiT3vNmChqspU=

这里的一个项是这样
Name: system/media/audio/ringtones/ArgoNavis.ogg
SHA1-Digest: umXNRCtBFkcNXqvPHpQCBLw7YgY=

那么把一个项写到文件中并且添加两行空格,也就是整个文件是四行,这时候进行SHA1,然后BASE64 得到结果,大家可以自行验证。

猜你喜欢

转载自blog.csdn.net/yexiangcsdn/article/details/79198274