原帖地址:http://www.devdiv.com/forum.php?mod=viewthread&tid=46552&extra=page%3D2%26filter%3Ddigest%26digest%3D1%26digest%3D1
程序签名运行后,能不能读取签名的信息呢?如keystore 的 alias或者 validity等信息?谢谢
补充内容 (2011-1-16 23:30):
或者谁能详细说明下:
.apk包中的META-INF\XXXX.RSA和META-INF\XXXX.RSA和META-INF\MANIFEST.MF
中是否有记录着签名信息呢?
使用Android系统隐藏api 读取*.apk 程序安装包信息
前提:我们需要得到Android系统源码编译输出的一个文件
out\target\common\obj\JAVA_LIBRARIES\framework_intermediates\classes.jar
这个包里面包含所有的系统api, 隐藏的, 公开的
添加 jar方法
右键功能菜单->Properties->Java Build Path
Libraries选项卡
这时应该有一个列表, 如果你没有添加过, 应该只有一项, 就是系统自带的Android SDK, 选中后,右手边有一个删除, 先删除系统添加的sdk.
点Add Library -> User Library
选择User Library 按钮, 新建一个User Library 将刚才那个文件 classes.jar 和系统本身的文件都导入进来, 调整下顺序, 将 classes.jar 调到前面
这样添加了之后, 就可以使用系统隐藏的api了
使用隐藏api, 有个前提:
许多api涉及到系统权限问题, 比如 后台安装文件 api PackageManager.installPackage 要求有安装程序的权限, 而这个安装程序权限不是随便有的, 只有经ROM签名认证的才可以使用这个权限. 虽然说可以在配置文件里面添加这个权限, 但是悲剧的是你仍然不能拥有这个权限, 在这点上, Google做的真绝..
好了, 虽然我们不能安装, 但用api去查看apk总该可以了吧?
Google没有公开这个Api, 但又了上面这个方法, 我们可以使用了
- //apk包的文件路径
- String apkPath = "/sdcard/qq.apk";
- //这是一个Package 解释器, 是隐藏的
- //构造函数的参数只有一个, apk文件的路径
- PackageParser packageParser = new PackageParser(apkPath);
- //这个是与显示有关的, 里面涉及到一些像素显示等等, 我们使用默认的情况
- DisplayMetrics metrics = new DisplayMetrics();
- metrics.setToDefaults();
- //这里就是解析了, 四个参数,
- //源文件File,
- //目的文件路径(这个我也没搞清楚怎么回事, 看Android安装器源码, 用的是源文件路径, 但名字却是destFileName)
- //显示, DisplayMetrics metrics
- //flags, 这个真不知道是啥
- PackageParser.Package mPkgInfo = packageParser.parsePackage(new File(apkPath),
- apkPath, metrics, 0);
-
- //应用程序信息包, 这个公开的, 不过有些函数, 变量没公开
- ApplicationInfo info = mPkgInfo.applicationInfo;
-
- //Resources 是用来获取资源的 , 而这里获取的资源是在本程序之外的
- //至于为什么这么弄, 我搞不懂.
- Resources pRes = getResources();
- AssetManager assmgr = new AssetManager();
- assmgr.addAssetPath(apkPath);
- Resources res = new Resources(assmgr, pRes.getDisplayMetrics(), pRes.getConfiguration());
-
- CharSequence label = null;
- if (info.labelRes != 0) {
- try {
- label = res.getText(info.labelRes);
- } catch (Resources.NotFoundException e) {
- }
- }
- if (label == null) {
- label = (info.nonLocalizedLabel != null) ?
- info.nonLocalizedLabel : info.packageName;
- }
-
-
- //这里就是读取一个apk程序的图标
- if (info.icon != 0){
- Drawable icon = res.getDrawable(info.icon);
- ImageView image = (ImageView) findViewById(R.id.iv_test);
- image.setVisibility(View.VISIBLE);
- image.setImageDrawable(icon);
- }
- }
复制代码
但是上面的方法似乎不行 - -#
扩展名改为zip,解压后用文本文件编辑器打开看看就知道了
.mf文件是manifest文件,里面记录目录、资源、图标等,与签名无关
***.sf是每个被签名文件的hash值
***.rsa里面有很多关于密钥相关的东西
.sf文件和.rsa文件。
你用不同的签名找找rsa文件内容的规律
按理说是除了hash值外,应该有签名的一些比较信息的,否则公钥怎么匹配呢
感谢曾阳提供的代码:
现补充如下:
- import sun.security.pkcs.PKCS7;
- import java.io.FileInputStream;
- import java.io.FileNotFoundException;
- import java.io.IOException;
- import java.io.InputStream;
- import java.security.GeneralSecurityException;
- import java.security.cert.X509Certificate;
- class SignApk {
- public static X509Certificate readSignatureBlock(InputStream in)
- throws IOException, GeneralSecurityException {
- PKCS7 pkcs7 = new PKCS7(in);
- return pkcs7.getCertificates()[0];
- }
- public static void main(String[] args) throws FileNotFoundException,
- IOException, GeneralSecurityException {
- X509Certificate publicKey = readSignatureBlock(new FileInputStream(
- "D:\cert.rsa"));
- System.out.println("issuer:" + publicKey.getIssuerDN());
- System.out.println("subject:" + publicKey.getSubjectDN());
- System.out.println(publicKey.getPublicKey());
- }
- }
复制代码
补充内容 (2011-1-18 13:59):
输出内容如下:
issuer:CN=Zhang zm
subject:CN=Zhang zm
Sun RSA public key, 1024 bits
modulus: 1543085941444687053482947604843962642184531......
刚又看到一个方法:
来自:
<sdk_path>/docs/guide/publishing/app-signing.html#signapp
jarsigner -verify -verbose -certs my_application.apk
输出如下:
- D:\>jarsigner -verify -verbose -certs cn.zzm.ringermode.apk
- sm 2587 Sat Jan 08 17:35:30 CST 2011 res/drawable/ic_menu_help.png
- X.509, CN=Zhang zm
- [证书的有效期为 10-7-26 下午5:50 至 40-7-18 下午5:50]
- sm 1897 Sat Jan 08 17:35:30 CST 2011 res/drawable/ic_menu_info_details.png
- X.509, CN=Zhang zm
- [证书的有效期为 10-7-26 下午5:50 至 40-7-18 下午5:50]
- sm 12967 Sat Jan 08 17:35:30 CST 2011 res/drawable/icon.png
- X.509, CN=Zhang zm
- [证书的有效期为 10-7-26 下午5:50 至 40-7-18 下午5:50]
- sm 4616 Sat Jan 08 17:35:30 CST 2011 res/layout/main_add_item.xml
- X.509, CN=Zhang zm
- [证书的有效期为 10-7-26 下午5:50 至 40-7-18 下午5:50]
- sm 4892 Sat Jan 08 17:35:30 CST 2011 res/layout/main_main.xml
- X.509, CN=Zhang zm
- [证书的有效期为 10-7-26 下午5:50 至 40-7-18 下午5:50]
- sm 3944 Sat Jan 08 17:35:30 CST 2011 AndroidManifest.xml
- X.509, CN=Zhang zm
- [证书的有效期为 10-7-26 下午5:50 至 40-7-18 下午5:50]
- sm 10952 Sat Jan 08 17:35:30 CST 2011 resources.arsc
- X.509, CN=Zhang zm
- [证书的有效期为 10-7-26 下午5:50 至 40-7-18 下午5:50]
- sm 180272 Sat Jan 08 17:35:30 CST 2011 classes.dex
- X.509, CN=Zhang zm
- [证书的有效期为 10-7-26 下午5:50 至 40-7-18 下午5:50]
- 0 Wed Jan 19 10:23:16 CST 2011 META-INF/
- 683 Sat Jan 08 17:35:30 CST 2011 META-INF/CERT.rsa
- 712 Sat Jan 08 17:35:30 CST 2011 META-INF/CERT.sf
- 659 Sat Jan 08 17:35:30 CST 2011 META-INF/MANIFEST.MF
- s = 已验证签名
- m = 在清单中列出条目
- k = 在密钥库中至少找到了一个证书
- i = 在身份作用域内至少找到了一个证书
- jar 已验证。
复制代码
(转载一个文章,不解释,同一系列的)
From:http://android-dls.com/wiki/index.php?title=Generating_Keys
When publishing an app for everyone to use, be it with a custom ROM or on the Android market, you need to sign the .apk with a personal private key. The old way of doing this was to use keytool and then sign it with jarsigner, but the way detailed below is a lot easier for most people and uses a standard toolset that should be available on almost any operating system.
One tool for signing .apk is a utility aptly named "SignApk.jar", which is just about the easiest way to sign .apk files. SignApk.jar comes with some test keys, but it's generally advised that you generate your own. The steps below can be used to create some personal private keys and a certificate for use with SignApk.jar.
The "SignApk.jar" file may be downloaded from the Git repo, or you can use Google to search for "AndroidMod.zip download", which also contains the tool.
- openssl genrsa -out key.pem 1024
- openssl req -new -key key.pem -out request.pem
- openssl x509 -req -days 9999 -in request.pem -signkey key.pem -out certificate.pem
- openssl pkcs8 -topk8 -outform DER -in key.pem -inform PEM -out key.pk8 -nocrypt
复制代码
Then, you can sign an .apk file using the SignApk.jar tool and the key.pk8 and certificate.pem files you created
- java -jar SignApk.jar certificate.pem key.pk8 Application.apk Application_signed.apk
复制代码
About "AndroidMod.zip":
http://forum.xda-developers.com/ ... =442480&page=83
xyz_lmn 发表于 2011-2-23 13:38 
回复 Sodino 的帖子
Sodino哥,在android的程序中怎么获得签名。
APK包内的RSA文件签名加密信息可以通过以下方法获得:
- android.content.pm.Signature[] sigs = getBaseContext()
- .getPackageManager().getPackageInfo(
- "lab.sodino.lab", 64).signatures;
- Log.d("ANDROID_LAB", "sigs.len=" + sigs.length);
- Log.d("ANDROID_LAB",sigs[0].toCharsString());
复制代码
但我目前还没找着将这些二进制转化成楼上那些信息的方法
补充内容 (2011-2-23 14:31):
可以研究下源码中的CertInstall试试,不过不知道会不会有结果