安卓系统启动安全

 签名版本以供发布  |  Android 开源项目  |  Android Open Source Project

对 OTA 更新包进行签名

您可以按照以下步骤将已签名的目标文件 zip 转换为已签名的 OTA 更新 zip:

/data/recovery/ota.zip

ota_from_target_files \
-k  (--package_key) 
signed-target_files.zip \
signed-ota_update.zip

签名和旁加载

旁加载不会绕过 Recovery 流程中的正常软件包签名验证机制。在安装一个软件包之前,Recovery 会验证该软件包是否由与 Recovery 分区中存储的公钥相匹配的私钥进行签名,这与利用无线方式传输的软件包的处理方式一样。

从主系统收到的更新包通常要经过两次验证:一次是由主系统使用 Android API 中的 RecoverySystem.verifyPackage() 方法进行验证,另一次是通过 Recovery 进行验证。RecoverySystem API 对照存储在主系统的 /system/etc/security/otacerts.zip 文件(默认情况下)中的签名检查签名。Recovery 对照存储在 Recovery 分区 RAM 磁盘中的 /res/keys 文件内的签名检查签名。

默认情况下,由此版本生成的目标文件 .zip 会将 OTA 证书设置为与测试密钥相匹配。在发布的映像上,必须使用不同的证书,这样设备才能验证更新包的真实性。如前面一部分所示,将 -o 标志传递给 sign_target_files_apks 即可将测试密钥证书替换成您的证书目录中的发布密钥证书。

/**
 * Verify the cryptographic signature of a system update package before installing it.  Note that
@param packageFile  the package to be verified  
                    要验证的包
@param listener     an object to receive periodic progress
 updates as verification proceeds.  May be null.
                    作为验证过程的一个对象,可以接收定期的进度更新。可能是null。
@param deviceCertsZipFile  the zip file of certificates whose
 public keys we will accept.  Verification succeeds if the
 package is signed by the private key corresponding to any
default file (currently "/system/etc/security/otacerts.zip").

@throws IOException if there were any errors reading the
  package or certs files.
@throws GeneralSecurityException if verification failed

使用winHex检查升级包zip文件是否包含签名,倒数3 4都为 ff

 

 

public static void verifyPackage(File packageFile,ProgressListener listener,File deviceCertsZipFile) throws IOException, GeneralSecurityException {  
        long fileLen = packageFile.length();  
        RandomAccessFile raf = new RandomAccessFile(packageFile, "r");  
        try {  
        int lastPercent = 0;  
        long lastPublishTime = System.currentTimeMillis();  
        if (listener != null) {  
        listener.onProgress(lastPercent);  
        }  
        raf.seek(fileLen - 6);  
        byte[] footer = new byte[6];  
        raf.readFully(footer);  
//升级包是否含有系统签名信息-sunst2019-6-8注释  
  if (footer[2] != (byte) 0xff || footer[3] != (byte) 0xff) {  
        throw new SignatureException("no signature in file (no footer)");  
        }  

        int commentSize = (footer[4] & 0xff) | ((footer[5] & 0xff) << 8);  
//签名的起始位置-sunst2019-6-8注释  
  int signatureStart = (footer[0] & 0xff) | ((footer[1] & 0xff) << 8);  
        Log.v(TAG, String.format("comment size %d; signature start %d", commentSize, signatureStart));  

        byte[] eocd = new byte[commentSize + 22];  
        raf.seek(fileLen - (commentSize + 22));  
        raf.readFully(eocd);  

        if (eocd[0] != (byte) 0x50 || eocd[1] != (byte) 0x4b ||  
        eocd[2] != (byte) 0x05 || eocd[3] != (byte) 0x06) {  
        throw new SignatureException("no signature in file (bad footer)");  
        }  

        for (int i = 4; i < eocd.length - 3; ++i) {  
        if (eocd[i] == (byte) 0x50 && eocd[i + 1] == (byte) 0x4b &&  
        eocd[i + 2] == (byte) 0x05 && eocd[i + 3] == (byte) 0x06) {  
        throw new SignatureException("EOCD marker found after start of EOCD");  
        }  
        } 

通常情况下,系统映像和 Recovery 映像存储的是相同的 OTA 公钥集。通过将密钥仅添加至 Recovery 密钥集,可对只能通过旁加载安装的 apk 包(假设主系统的更新下载机制正确地对照 otacerts.zip 进行验证)签名。您可以通过在产品定义中设置 PRODUCT_EXTRA_RECOVERY_KEYS 变量来指定其他仅可纳入 Recovery 中的密钥:

vendor/yoyodyne/tardis/products/tardis.mk
 [...]

PRODUCT_EXTRA_RECOVERY_KEYS := vendor/yoyodyne/security/tardis/sideload

这包括恢复密钥文件中的公钥 vendor/yoyodyne/security/tardis/sideload.x509.pem,因此它可以安装用此密钥签名的软件包。但 otacerts.zip 中不包含额外的密钥,因此正确验证下载包的系统不会针对用此密钥签名的 apk 包调用 Recovery。

证书和私钥

每个密钥都包含两个文件:一个是扩展名为 .x509.pem 的证书,另一个是扩展名为 .pk8 的私钥。 私钥需要加以保密,并用于对 apk 包进行签名。 密钥本身也可能受密码保护。相比之下,证书只包含公开的一半密钥,因此可以大范围地分发。证书用于验证某个 apk 包是否由相应的私钥进行签名。

标准 Android build 使用四个密钥,所有这些密钥都位于 build/target/product/security 中:

testkey

适用于未另外指定密钥的 apk 包的通用默认密钥。

平台

适用于核心平台所包含的 apk 包的测试密钥。

共享

适用于家庭/联系人进程中的共享内容的测试密钥。

media

适用于媒体/下载系统所包含的 apk 包的测试密钥。

networkstack

适用于网络系统所包含的 apk 包的测试密钥。networkstack 密钥用于为设计为模块化系统组件 的二进制文件签名。如果您的模块更新是单独构建的,并且以预构建的形式集成到设备映像中,您可能就不需要在 Android 源代码树中生成 networkstack 密钥。

单个 apk 包会在其 Android.mk 文件中设置 LOCAL_CERTIFICATE 以指定其中一个密钥。(如果未设置此变量,则使用 testkey。) 您还可以通过路径名指定完全不同的密钥,例如:

device/yoyodyne/apps/SpecialApp/Android.mk
 [...]

LOCAL_CERTIFICATE := device/yoyodyne/security/special

现在,构建使用 device/yoyodyne/security/special.{x509.pem,pk8} 密钥对 SpecialApp.apk 进行签名。此版本仅可使用不受密码保护的私钥。

Bootloader

avb校验在一次启动过程中总共进行了两次,

第一次是在bootloader中进行校验,通过上面的接口校验各个分区的根hash和签名。

第二次是在上层init中进行的,这次校验也是调用相同的接口,可能个别传入的参数会有不同。

AVB2.0被用于启动引导,此用法添加一个“vbmeta.img”镜像。public key被编译到bootloader中用于校验vbmeta数据,vbmeta.img包含应由此public key验证的签名。

vbmeta.img包含用于验证的public key,但只有bootloader验证过vbmeta.img才会可信,就好比认证一样,包含可信public key和签名。

Android Verified Boot 2.0简要 - 程序员大本营

AVB2.0被用于启动引导,此用法添加一个“vbmeta.img”镜像。public key被编译到bootloader中用于校验vbmeta数据,vbmeta.img包含应由此public key验证的签名。

vbmeta.img包含用于验证的public key,但只有bootloader验证过vbmeta.img才会可信,就好比认证一样,包含可信public key和签名。

 ROM 签名文件

CERT.RSA

CERT.SF

MANIFEST.MF

 CERT.RSA重命名为P7B可以用windows直接查看

(1)MANIFEST.MF:这是摘要文件。程序遍历Apk/ROM 包中的所有文件(entry),对非文件夹非签名文件的文件,逐个用SHA1生成摘要信息,再用Base64进行编码。如果你改变了apk包中的文件,那么在apk安装校验时,改变后的文件摘要信息与MANIFEST.MF的检验信息不同,于是程序就不能成功安装。

说明:如果攻击者修改了程序的内容,有重新生成了新的摘要,那么就可以通过验证,所以这是一个非常简单的验证。

WIN 查看文件SHA1方法

certutil -hashfile D:\test.txt SHA1


BTFM.bin SHA1>base64实践 参考android APK签名过程之MANIFEST.MF分析_大星星的专栏-CSDN博客_android apk manifest

C:\Users\Administrator\Desktop\miui_DAVINCI_V12.5.1.0.RFJCNXM_d03c1be4ec_11.0\firmware-update>certutil -hashfile BTFM.bin SHA1
SHA1 的 BTFM.bin 哈希:
f89045e946ee225f26bacd600c36d985d76ec10d
CertUtil: -hashfile 命令成功完成。

16进制编码使用winhex转换成2进制

WinHex: Hex Editor & Disk Editor, Computer Forensics & Data Recovery Software

 二进制文件保存成文件然后使用在线base64网站把文件进行编码

Base64文件在线编解码工具

(2)CERT.SF:这是对摘要的签名文件。对前一步生成的MANIFEST.MF,使用SHA1-RSA算法,用开发者的私钥进行签名。在安装时只能使用公钥才能解密它。解密之后,将它与未加密的摘要信息(即,MANIFEST.MF文件)进行对比,如果相符,则表明内容没有被异常修改。

说明:在这一步,即使开发者修改了程序内容,并生成了新的摘要文件,但是攻击者没有开发者的私钥,所以不能生成正确的签名文件(CERT.SF)。系统在对程序进行验证的时候,用开发者公钥对不正确的签名文件进行解密,得到的结果和摘要文件(MANIFEST.MF)对应不起来,所以不能通过检验,不能成功安装文件。

(3)CERT.RSA文件中保存了公钥、所采用的加密算法等信息。

说明:系统对签名文件进行解密,所需要的公钥就是从这个文件里取出来的。

结论:从上面的总结可以看出,META-INFO里面的说那个文件环环相扣,从而保证Android程序的安全性。(只是防止开发者的程序不被攻击者修改,如果开发者的公私钥对对攻击者得到或者开发者开发出攻击程序,Android系统都无法检测出来。)

 

Android P中的AVB2.0校验_BingKing88的专栏-CSDN博客_avb2.0

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值