转自:http://blog.csdn.net/yangkai6121/article/details/38682321

为什么需要给Android系统签个名才能进行CTS认证呢?原来我们通过make -j4编译出来的system.img使用的是test key,这种类型的key只适用于开发阶段,而且这种秘钥是公开的,谁都可以使用。当发布一款android产品,就需要另外给整个系统签个名,防止被别 人盗用。这种系统就是release版本的Android系统。

一、 首先介绍关于签名的作用

1、 APK签名的作用:

a) 发送者的身份认证,由于开发商可能通过使用相同的Package Name来混淆替换已经安装的程序,以此保证签名不同的包不被替换。
    b) 保证信息传输的完整性,签名对于包中的每个文件进行处理,以此确保包中内容不被替换,防止交易中的抵赖发生,Market对软件的要求。

2、 Recovery签名作用:

Recovery进行签名的主要作用是用来验证数据的完整性。

3、要对Android系统进行签名,需要生成四种类型的key文件。

a)releasekey (或testkey)
    b)media
    c)shared
    d)platform
以上的四种,可以在源码的/build/target/product/security里面看到对应的密钥,其中shared.pk8代表私钥,shared.x509.pem公钥,一定是成对出现的。其中testkey是作为android编译的时候默认的签名key,如果系统中的apk的android.mk中没有设置LOCAL_CERTIFICATE的值,就默认使用testkey。而如果设置成:LOCAL_CERTIFICATE := platform 就代表使用platform来签名,这样的话这个apk就拥有了和system相同的签名,因为系统级别的签名也是使用的platform来签名,此时使用android:sharedUserId="android.uid.system"才有用!

二、 生成加密key文件

我们就拿releasekey为例简单介绍下生成过程。Android使用SHA1-RSA算法进行签名。可通过eclipse插件进行,可以通过keytool和jarsigner 用命令行执行。也可以在源码下进行签名。

1、以源码下签名方法来介绍生成密钥对方法:

直接执行development/tools/make_key releasekey  '/C=CN/ST=BeiJing/L=HaiDian View/O=JiuZhou/OU=PingTai/CN=lran/emailAddress=lran@jzby.com'生成releasekey.pk8和releasekey.x509.pem。其中releasekey  是指最后的加密方式为release方式,执行后显示如下:
development/tools$ sh make_key releasekey '/C=CN/ST=JiangSu/L=NanJing/O=Company/OU=Department/CN=YourName/emailAddress=YourE-mailAddress'
Enter password for 'releasekey' (blank for none; password will be visible): mypassword     <------- 设置你的密码(一般直接回车,要不每次签名apk,你还得手动输入签名密码,后面讲其他原因)
creating platform.pk8 with password [mypassword]
Generating RSA private key, 2048 bit long modulus
...............+++
........................................................+++
e is 3 (0x3)

key的名字很好理解,就是前面提到的4中类型的key,公司信息的参数比较多,它们的含义如下:
C   --->  Country Name (2 letter code)
ST  --->  State or Province Name (full name)
L   --->  Locality Name (eg, city)
O   --->  Organization Name (eg, company)
OU  --->  Organizational Unit Name (eg, section)
CN  --->  Common Name (eg, your name or your server’s hostname)
emailAddress --->  Contact email address
这样就生成了一组releasekey,另外3种类型的key的生成方法也基本一样。
生成后的结果如下:
/development/tools$ ls
makedict  media.pk8       mkstubs       platform.pk8       releasekey.pk8       shared.pk8   make_key  media.x509.pem    platform.x509.pem  releasekey.x509.pem  shared.x509.pem
*.pk8是生成的私钥,而*.x509.pem是公钥,生成时两者是成对出现的.
另外,如果出现 openssl : relocation error :openssl : symbol ...尝试用 sudo 执行命令, 问题解决了!
生成的密钥需要放到build/target/product/security/目录下面,因为之前系统里面写的test-keys的密钥就放在此处。我们是仿照系统的方法的方法放在此处,后面写系统签名刚好用到所以放到该文件夹最合适。

2、 make_key介绍

a)生成公钥
openssl genrsa -3 -out testkey.pem 2048
其中-3是算法的参数,2048是密钥长度,testkey.pem是输出的文件
b) 转成x509格式(含作者有效期等)
openssl req -new -x509 -key testkey.pem -out testkey.x509.pem -days 10000 -subj ‘/C=US/ST=California/L=MountainView/O=Android/OU=Android/CN=Android/emailAddress=android@android.com’
c) 生成私钥
openssl pkcs8 -in testkey.pem -topk8 -outform DER -out testkey.pk8 -nocrypt
把的格式转换成PKCS #8,这里指定了-nocryp,表示不加密,所以签名时不用输入密码

三、 如何签名

1、 对APK签名命令:

signapk publickey.x509[.pem] privatekey.pk8 input.apk output.apk
如上面就可以写为:java -jar signapk.jar releasekey.x509.pem releasekey.pk8 input.apk output.apk
签名后,输出文件的meta_inf目录下生长如下文件:
MANIFEST.MF:对非文件夹非签名文件的文件,逐个生成SHA1的数字签名信息
CERT.SF:对Manifest文件,使用SHA1-RSA算法,用私钥进行签名。
CERT.RSA:CERT.RSA文件中保存了公钥、所采用的加密算法等信息。
下图是eclipse中签名的过程。
 

2、 对recovery 签名命令:

signapk –w publickey.x509[.pem] privatekey.pk8 input.zip output.zip
- w参数表示对整个文件进行签名,目前看只是在制作recovery升级包时使用。
对升级包的签名可参考:http://blog.163.com/yi_yixinyiyi/blog/static/136286889201132533759563/

另外一种对系统的签名可以直接在源码加入编译的签名的路径不需要在去手动签名,其修改方法如下:
主要参考了:http://www.cnblogs.com/leaven/p/3860583.html 讲的很详细,也很有用。
a)修改/build/core/config.mk中变量DEFAULT_SYSTEM_DEV_CERTIFICATE ,修改方法如下:(红色为添加代码)
# The default key if not set as LOCAL_CERTIFICATE
ifdef PRODUCT_DEFAULT_DEV_CERTIFICATE
  DEFAULT_SYSTEM_DEV_CERTIFICATE := $(PRODUCT_DEFAULT_DEV_CERTIFICATE)
else
  DEFAULT_SYSTEM_DEV_CERTIFICATE := build/target/product/security/testkey
endif
#modify by lran jzby 指出密钥路径
  DEFAULT_SYSTEM_DEV_CERTIFICATE := build/target/product/security/releasekey
# ###############################################################
# Set up final options.
# ###############################################################

b) 在build/core/Makefile中添加:
    (1)mx中修改方法
ifeq ($(DEFAULT_SYSTEM_DEV_CERTIFICATE),build/target/product/security/testkey)
BUILD_KEYS := test-keys
else
BUILD_KEYS := dev-keys
endif
#modify by lran jzby 目的就是配置当前的名方式为release方式
ifeq ($(DEFAULT_SYSTEM_DEV_CERTIFICATE),build/target/product/security/releasekey)
BUILD_KEYS := release-keys
endif
BUILD_VERSION_TAGS += $(BUILD_KEYS)
.....
ifeq ($(BUILD_SECURE),true)
    OTA_PUBLIC_KEYS := device/*/$(TARGET_DEVICE)/releasekey.x509.pem
else
    OTA_PUBLIC_KEYS := $(SRC_TARGET_DIR)/product/security/testkey.x509.pem
endif
#modify by lran jzby  指向密钥
    OTA_PUBLIC_KEYS := build/target/product/security/releasekey.x509.pem
    (2)hisi中修改方法
ifeq ($(DEFAULT_SYSTEM_DEV_CERTIFICATE),build/target/product/security/testkey)
BUILD_VERSION_TAGS += test-keys
endif
#modify by lran jzby
ifeq ($(DEFAULT_SYSTEM_DEV_CERTIFICATE),build/target/product/security/releasekey)
BUILD_VERSION_TAGS += release-keys
else
BUILD_VERSION_TAGS += dev-keys
endif
BUILD_VERSION_TAGS := $(subst $(space),$(comma),$(sort $(BUILD_VERSION_TAGS)))
海斯中第二行不需要修改,因为海斯对应的该行以写成OTA_PUBLIC_KEYS := $(DEFAULT_SYSTEM_DEV_CERTIFICATE).x509.pem可以直接被自动替换

(3),其实在安装apk的package.mk中也有密钥的使用,不过他和海斯一样直接用DEFAULT_SYSTEM_DEV_CERTIFICATE替代了,所以不用修改。
ifeq ($(LOCAL_CERTIFICATE),)
    LOCAL_CERTIFICATE := $(DEFAULT_SYSTEM_DEV_CERTIFICATE)
endif
......
private_key := $(LOCAL_CERTIFICATE).pk8
certificate := $(LOCAL_CERTIFICATE).x509.pem

(4)修改完之后就要编译了,如果上面的这些key在制作的时候输入了password就会出现如下错误:
    Enter password for build/target/product/security/releasekey.pk8 (password will not be hidden): java.lang.NullPointerException  
        at com.android.signapk.SignApk.decryptPrivateKey(SignApk.java:142)  
        at com.android.signapk.SignApk.readPrivateKey(SignApk.java:166)  
        at com.android.signapk.SignApk.main(SignApk.java:531)  
        Enter password for build/target/product/security/releasekey.pk8 (password will not be hidden): make: ***     [out/target/product/gotechcn/obj/APPS/CalendarProvider_intermediates/package.apk] 错误 1  
        make: *** 正在等待未完成的任务....  
        Enter password for build/target/product/security/releasekey.pk8 (password will not be hidden): java.lang.NullPointerException  
        at com.android.signapk.SignApk.decryptPrivateKey(SignApk.java:142)  
        at com.android.signapk.SignApk.readPrivateKey(SignApk.java:166)  
        at com.android.signapk.SignApk.main(SignApk.java:531)  
        make: *** [out/target/product/gotechcn/obj/APPS/Calculator_intermediates/package.apk] 错误 1  
        Warning: AndroidManifest.xml already defines minSdkVersion (in http://schemas.android.com/apk/res/android); using existing value in manifest.  
        Warning: AndroidManifest.xml already defines targetSdkVersion (in http://schemas.android.com/apk/res/android); using existing value in manifest.  
         'out/target/common/obj/APPS/Calendar_intermediates/classes.dex' as 'classes.dex'...  
        Enter password for build/target/product/security/releasekey.pk8 (password will not be hidden): java.lang.NullPointerException  
        at com.android.signapk.SignApk.decryptPrivateKey(SignApk.java:142)  
        at com.android.signapk.SignApk.readPrivateKey(SignApk.java:166)  
        at com.android.signapk.SignApk.main(SignApk.java:531)  
        make: *** [out/target/product/gotechcn/obj/APPS/Calendar_intermediates/package.apk] 错误 1  
        ^Cmake: *** [out/target/product/gotechcn/obj/APPS/BasicDreams_intermediates/package.apk] 错误 130  
其实会出现这个错误的最根本的原因是多线程的问题。在编译的时候为了加速一般都会执行make -jxxx,这样本来需要手动输入密码的时候,由于其它线程的运行,就会导致影响当前的输入终端,所以就会导致密码无法输入的情况!再编译完成之后也可以在build.prop中查看到变量:ro.build.tags=release-keys  这样处理了之后编译出来的都是签名过的了,系统才算是release版本。我发现我这样处理之后,整个系统的算是全部按照我的要求签名了。

四、 签名的相关文件

1、 apk包中签名相关的文件在meta_INF目录下

CERT.SF:生成每个文件相对的密钥
MANIFEST.MF:数字签名信息
xxx.SF:这是JAR文件的签名文件,占位符xxx标识了签名者
xxx.DSA:对输出文件的签名和公钥

2、相关源码

development/tools/jarutils/src/com.anroid.jarutils/SignedJarBuilder.java
frameworks/base/services/java/com/android/server/PackageManagerService.java
frameworks/base/core/java/android/content/pm/PackageManager.java
frameworks/base/cmds/pm/src/com/android/commands/pm/Pm.java
dalvik/libcore/security/src/main/java/java/security/Sign*
build/target/product/security/platform.*
build/tools/signapk/*

五、  怎样验证签名

1、 APK验证:

安装apk时,通过CERT.RSA查找公钥和算法,并对CERT.SF进行解密和签名验证,确认MANIFEST.MF,最终对每个文件签名校验。
升级时,android也会进行签名验证。如果遇到以下情况,都不能完成升级:
a)两个应用,名字相同,签名不同
b)升级时前一版本签名,后一版本没签名。
c)升级时前一版本为DEBUG签名,后一个为自定义签名。
d)升级时前一版本为Android源码中的签名,后一个为DEBUG签名或自定义签名。
e)安装未签名的程序。
f)安装升级已过有效期的程序。
  一般在apk安装时提示出错:INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES
a)两个应用,名字相同,签名不同
b)升级时前一版本签名,后一版本没签名
c)升级时前一版本为DEBUG签名,后一个为自定义签名
d)升级时前一版本为Android源码中的签
以上可以看到,随便更换密钥对后签名生成的apk也是可以安装在任何平台的。因为公钥是放在apk里的。

2、 RECOVERY:

Recovery公钥是固定在代码里面。并没有采用CERT.RSA里面公钥。目前几乎所有的手机平台都是用testkey。固定公钥目的可能是为了确保其它平台的升级包不能被升级。比如我们统一更换了一个密钥对,那么recovery里面固定的公钥更改后,用testkey做成的升级包是无法升级成功的。
同时recovery只是对整个升级压缩文件进行签名校验(前面说过recovery签名使用的是-w)。
Recovery 代码里面使用的公钥是按照rsapublickey 数据结构存储。这个数据是通过dumppublickey工具从制作出来的x509证书文件中获得。Dumppublickey代码在网上可以查找到。

转载于:https://www.cnblogs.com/dirt2/p/6233057.html

android系统release签名相关推荐

  1. android系统APK签名生成大全

    最近要做一个重复开关机的专项测试,发现需要系统权限才能实现 1.需要SYSTEM USER       1> android:sharedUserId="android.uid.sys ...

  2. 生成release版本的Android系统

    1.使用platform密钥对apk进行签名 1.1.进入<Android_Source_Path>/build/target/product/security,找到[platform.p ...

  3. Android系统制作自定义签名

    1.简介 应客户要求为了是特殊定制的系统更具安全,系统ROM需要使用自己定义的签名,还有一些特殊的场景也会更改系统的签名比如在过cts认证测试的时候也会修改平台签名才能测试通过关于签名的问题.这是因为 ...

  4. android应用程序签名

    概述 Android系统要求,所有的程序经过数字签名后才能安装.Android系统使用这个证书来识别应用程序的作者,并且建立程序间的信任关系.证书不是用于用户控制哪些程序可以安装.证书不需要授权中心来 ...

  5. Android系统的JNI原理分析(二)- 数据类型转换和方法签名

    声明 前阶段在项目中使用了Android的JNI技术,在此文中做些技术知识总结. 本文参考了一些书籍的若干章节,比如<Android进阶解密-第9章-JNI原理>.<深入理解Andr ...

  6. Android系统签名jks文件

    Android Studio普通应用->系统应用 在android framework开发过程中,通常使用系统应用在验证某些功能,(系统功能权限大,可以通过反射获取hide接口,便于功能调试). ...

  7. Android系统签名生成Studio导入系统keystore

    一.Android签名文件简述 为什么要签名? 任何一个安装包都需要有签名.为App签名的本质是说明这个App是我开发的,不是别人.通过签名可以在应用和开发者之间建立可信任的关联. 通过签名,Andr ...

  8. android如何不用系统签名,更新Android系统应用程序,带/不带平台签名

    让我们首先澄清所有类型的应用程序之间的差异. 系统应用程序是位于/ system / app文件夹中的应用程序.这些应用程序具有一个标志ApplicationInfo.FLAG_SYSTEM集.在普通 ...

  9. Android系统安全 — 5.3-APK V2签名介绍

    1. V2签名原理 1. JAR V1签名是在apk文件(其实是ZIP文件)中添加META-INF目录,即需要修改数据区.中央目录,因为添加文件后会导致中央目录大小和偏移量发生变化,还需要修改中央目录 ...

最新文章

  1. 处理问题的方法--抽象和特例化
  2. 大数据下的电商新打法
  3. GUID和自增ID的比较_delete
  4. iOS:项目中用到的Cookie
  5. 聯想集團與NBA簽署營銷協議
  6. python创建一个有序链表_Python实现合并两个有序链表的方法示例
  7. go语言:函数参数传递详解
  8. SQL BETWEEN
  9. dom4j的操作(增删改查)
  10. java中Error(UnsatisfiedLinkError)与Exception是有差异的
  11. 银行业会计人员技能训练系统(含文字录入、小键盘、点钞)
  12. linux检测扩容卡,教你检测SD卡内存卡是否被扩容过的方法
  13. DNS NoteBook
  14. 少儿编程家长一定要看看这些值得参加的青少年专业权威赛考
  15. 1894 完美的牛栏
  16. 线性加权平均 c语言程序,【求助】编的一个加权平均分计算程序,总是出错。求高手指点~...
  17. 腾讯云发布php项目,利用腾讯云服务器进行微校开放平台开发
  18. Delphi 2005 失望的尝鲜!
  19. 机械结构day_13
  20. 30岁的问题,为什么有人说程序员只能干到30岁。

热门文章

  1. std string与线程安全_这才是现代C++单例模式简单又安全的实现
  2. linux系统查看CPU使用含义、IO、内存、硬盘使用、负载
  3. docker 如何加入kubernetes_使用 Kind 在 5 分钟内快速部署一个 Kubernetes 高可用集群...
  4. 控件不支持html5,javascript – HTML5视频控件不起作用
  5. linux查看wan的ip地址,查看wan口ip地址操作方法
  6. nerdctl命令tab键补齐方法
  7. Apache Flink 简介和编程模型
  8. 手动制造报错_一个订单管理系统帮你轻松应对复杂的生产订单管理
  9. php挖洞提权,记一次渗透挖洞提权实战
  10. java设置面板的颜色_java – 修改颜色选择器面板