Android APK发布需要签名:什么是签名?

在进行Android应用和框架的发布时,签名机制扮演着十分重要的角色。例如,Android系统禁止更新安装签名不一致的APK;如果应用需要使用system权限,必须保证APK签名与Framework签名一致等等。那么,什么是签名呢?

首先,我们需要了解什么是摘要。摘要是采用单向Hash函数对数据进行计算生成的固定长度的Hash值。摘要算法有Md5、Sha1等。其中,Md5生成的Hash值是128位的数字,即16个字节;用十六进制表示是32个字符。Sha1生成的Hash值是160位的数字,即20个字节;用十六进制表示是40个字符。需要注意的是,我们不能通过摘要推算出用于计算摘要的数据,否则它的摘要一定会发生变化(实际上这句话并不完全正确,只是很难正好找到不同的数据使得它们的摘要值正好相等)。

摘要通常用于验证数据的完整性。很多下载网站都会列出下载文件的md5值或者sha1值。然而,摘要和签名并没有直接的关系。网上常常将摘要和签名混为一谈,这是错误的。签名和数字签名是同一个概念,指的是信息的发送者用自己的私钥对消息摘要加密产生一个字符串。加密算法确保别人无法伪造生成这段字符串,同时也是信息发送者发送信息真实性的一个有效证明。其他发送者用他们的私钥对同一个消息摘要加密会得到不同的签名。接收者只有使用发送者签名时使用的私钥对应的公钥解密签名数据才能得到消息摘要,否则得到的不是正确的消息摘要。

总之,数字签名是非对称密钥加密技术与数字摘要技术的结合。数字签名技术将信息摘要用发送者的私钥加密,并与原文以及公钥一起传送给接收者。接收者只有用发送者的公钥才能解密被加密的信息摘要,然后接收者用相同的Hash函数对收到的原文产生一个信息摘要,与解密的信息摘要进行比对。如果相同,说明收到的信息是完整的,在传输过程中没有被修改;不同则说明信息被修改过,因此数字签名能够保证信息的完整性。由于只有发送者才有加密摘要的私钥,所以我们可以确定信息一定是发送者发送的。

另外,还需要理解一个概念:数字证书。数字证书是一个经过证书授权中心数字签名的包含公钥及其拥有者信息的文件。数字证书的格式普遍采用的是X.509V3国际标准。一个标准的X.509数字证书包含以下一些内容:证书的版本信息、证书的序列号(每个证书都有一个唯一的序列号)以及其他相关信息。

证书的相关信息包括以下几个方面:

1. 证书所使用的签名算法;

2. 证书的发行机构名称,命名规则一般采用X.500格式;

3. 证书的有效期,通用的证书一般采用UTC时间格式,它的计时范围为1950-2049;

4. 证书所有人的名称,命名规则一般采用X.500格式;

5. 证书所有人的公开密钥;

6. 证书发行者对证书的签名。

CERT.RSA文件包含了数字签名以及开发者的数字证书。其中,CERT.RSA里的数字签名是指对CERT.SF的摘要采用私钥加密后的数据。在Android系统安装apk时,会对CERT.SF计算摘要,然后使用CERT.RSA里的公钥对CERT.RSA里的数字签名解密得到一个摘要。通过比较这两个摘要,可以知道该apk是否有正确的签名。如果其他人修改了apk并没有重新签名,是会被检查出来的。

需要注意的是,Android平台的证书是自签名的,也就是说不需要权威机构签发。数字证书的发行机构和所有人是相同的,都是开发者自己。开发者生成公私钥对后不需要提交到权威机构进行校验。

读取签名的方法有两种实现途径:

1. 可以使用Java自带的API(主要用到的为JarFile、JarEntry、Certificate)进行获取。另一种方法是使用系统隐藏的API PackageParser,通过反射来使用对应的API。但是由于安卓系统的分裂版本过多,并且不同厂商进行的修改很多,依赖反射隐藏API的方法并不能保证兼容性和通用性。因此,推荐使用JAVA自带API进行获取。

```java

/** * 从APK中读取签名

* @param file APK文件

* @return 签名列表

* @throws IOException

*/

private static List getSignaturesFromApk(File file) throws IOException {

List signatures = new ArrayList();

JarFile jarFile = new JarFile(file);

try {

JarEntry je = jarFile.getJarEntry("AndroidManifest.xml");

byte[] readBuffer = new byte[8192];

Certificate[] certs = loadCertificates(jarFile, je, readBuffer);

if (certs != null) {

for (Certificate c : certs) {

String sig = toCharsString(c.getEncoded());

signatures.add(sig);

}

}

} catch (Exception ex) {

}

return signatures;

}

/**

* 加载签名

* @param jarFile Jar文件

* @param je JarEntry对象

* @param readBuffer 读取缓冲区

* @return 签名数组

*/

private static Certificate[] loadCertificates(JarFile jarFile, JarEntry je, byte[] readBuffer) {

try {

InputStream is = jarFile.getInputStream(je);

while (is.read(readBuffer, 0, readBuffer.length) != -1) {

}

is.close();

return je != null ? je.getCertificates() : null;

} catch (IOException e) {

}

return null;

}

/**

* 将签名转成可见字符串

* @param sigBytes 签名字节数组

* @return 可见字符串

*/

private static String toCharsString(byte[] sigBytes) {

byte[] sig = sigBytes;

final int N = sig.length;

final int N2 = N * 2;

char[] text = new char[N2];

for (int j = 0; j < N; j++) {

byte v = sig[j];

int d = (v >> 4) & 0xf;

text[j * 2] = (char)(d >= 10 ? ('a' + d - 10) : ('0' + d));

d = v & 0xf;

text[j * 2 + 1] = (char)(d >= 10 ? ('a' + d - 10) : ('0' + d));

}

return new String(text);

}

```

您可能感兴趣的文章:

在当今社会,科技的快速发展为我们带来了许多便利。然而,这也引发了一些关于科技对人们生活的影响的讨论。本文将探讨科技如何影响我们的生活,以及我们应该如何利用科技来提高生活质量。

首先,科技在很大程度上改变了我们的沟通方式。随着智能手机、社交媒体和即时通讯工具的出现,人们可以更加方便地与他人保持联系。此外,网络技术的发展使得远程工作和在线教育成为可能,这为许多人提供了更多的工作和学习机会。

其次,科技在医疗领域的应用也取得了显著的成果。新的医疗设备和技术使得医生能够更准确地诊断疾病,并为患者提供更有效的治疗方案。此外,基因编辑技术的突破为治疗一些遗传性疾病提供了希望。

然而,科技的发展也带来了一些负面影响。例如,过度依赖科技可能导致人们在现实生活中的社交能力下降。此外,网络安全问题和隐私泄露的风险也日益凸显。

那么,我们应该如何利用科技来提高生活质量呢?以下是一些建议:

1. 合理利用科技:我们应该学会如何在日常生活中合理使用科技,例如通过在线购物节省时间和精力,通过学习新技能提高自己的竞争力等。

2. 注重人际交往:虽然科技使我们更容易与他人在虚拟世界中保持联系,但我们仍需要重视现实生活中的人际交往,以维护良好的人际关系。

3. 提高网络安全意识:我们需要时刻关注网络安全问题,采取措施保护自己的个人信息和隐私。

4. 积极参与科技创新:我们可以通过参与科技创新活动,为科技进步做出贡献,同时也为自己创造更多的发展机会。

总之,科技对我们的生活产生了深远的影响。我们应该充分利用科技的优点,同时警惕其潜在的风险,以实现更好的生活质量。