Android数字签名解析(二)
来源:互联网 发布:linux 目录权限 编辑:程序博客网 时间:2024/06/05 06:21
在Android数字签名解析(一)中,介绍了android进行签名的两种方式,其中用密钥对进行签名用到了signapk.jar这个java库,下面我们就看看signapk签名实现过程,signapk的源码在build/tools/signapk/下。
一、生成MANIFEST.MF文件//对apk包中的每个文件(非文件夹和非签名文件),生成SHA1的摘要信息,再对这个信息进行Base64编码。 Manifest manifest = addDigestsToManifest(inputJar);//将上面得到的信息,写入MANIFEST.MF je = new JarEntry(JarFile.MANIFEST_NAME); je.setTime(timestamp); outputJar.putNextEntry(je); manifest.write(outputJar);二、 生成CERT.SF文件je = new JarEntry(CERT_SF_NAME); je.setTime(timestamp); outputJar.putNextEntry(je); ByteArrayOutputStream baos = new ByteArrayOutputStream(); writeSignatureFile(manifest, baos); byte[] signedData = baos.toByteArray(); outputJar.write(signedData);对 整个 MANIFEST.MF 进行 SHA1 计算,并将摘要信息存入 CERT.SF 中 。然后对之前计算的所有摘要信息使用SHA1再次计算,将结果也写入 CERT.SF 中, 关键代码在 writeSignatureFile(manifest, baos)中,/** Write a .SF file with a digest of the specified manifest. */ private static void writeSignatureFile(Manifest manifest, OutputStream out) throws IOException, GeneralSecurityException { Manifest sf = new Manifest(); Attributes main = sf.getMainAttributes(); main.putValue("Signature-Version", "1.0"); main.putValue("Created-By", "1.0 (Android SignApk)"); MessageDigest md = MessageDigest.getInstance("SHA1"); PrintStream print = new PrintStream( new DigestOutputStream(new ByteArrayOutputStream(), md), true, "UTF-8"); // Digest of the entire manifest manifest.write(print); print.flush(); main.putValue("SHA1-Digest-Manifest", new String(Base64.encode(md.digest()), "ASCII")); Map<String, Attributes> entries = manifest.getEntries(); for (Map.Entry<String, Attributes> entry : entries.entrySet()) { // Digest of the manifest stanza for this entry. print.print("Name: " + entry.getKey() + "\r\n"); for (Map.Entry<Object, Object> att : entry.getValue().entrySet()) { print.print(att.getKey() + ": " + att.getValue() + "\r\n"); } print.print("\r\n"); print.flush(); Attributes sfAttr = new Attributes(); sfAttr.putValue("SHA1-Digest", new String(Base64.encode(md.digest()), "ASCII")); sf.getEntries().put(entry.getKey(), sfAttr); } CountOutputStream cout = new CountOutputStream(out); sf.write(cout); // A bug in the java.util.jar implementation of Android platforms // up to version 1.6 will cause a spurious IOException to be thrown // if the length of the signature file is a multiple of 1024 bytes. // As a workaround, add an extra CRLF in this case. if ((cout.size() % 1024) == 0) { cout.write('\r'); cout.write('\n'); } }三、生成CERT.RSA文件<span style="white-space:pre"></span>je = new JarEntry(CERT_RSA_NAME); je.setTime(timestamp); outputJar.putNextEntry(je); writeSignatureBlock(new CMSProcessableByteArray(signedData), publicKey, privateKey, outputJar);关键代码在writeSignatureBlock(new CMSProcessableByteArray(signedData)中/** Sign data and write the digital signature to 'out'. */ private static void writeSignatureBlock( CMSTypedData data, X509Certificate publicKey, PrivateKey privateKey, OutputStream out) throws IOException, CertificateEncodingException, OperatorCreationException, CMSException { ArrayList<X509Certificate> certList = new ArrayList<X509Certificate>(1); certList.add(publicKey); JcaCertStore certs = new JcaCertStore(certList); CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA") .setProvider(sBouncyCastleProvider) .build(privateKey); gen.addSignerInfoGenerator( new JcaSignerInfoGeneratorBuilder( new JcaDigestCalculatorProviderBuilder() .setProvider(sBouncyCastleProvider) .build()) .setDirectSignature(true) .build(sha1Signer, publicKey)); gen.addCertificates(certs); CMSSignedData sigData = gen.generate(data, false); ASN1InputStream asn1 = new ASN1InputStream(sigData.getEncoded()); DEROutputStream dos = new DEROutputStream(out); dos.writeObject(asn1.readObject()); }把之前生成的CERT.SF文件,用私有密钥计算出签名, 然后将签名以及公钥信息写入 CERT.RSA 中保存。
1 0
- Android数字签名解析(二)
- Android数字签名解析(一)
- Android数字签名解析(三)
- Android 数字签名
- Android 数字签名
- Android 数字签名
- Android 数字签名
- Android 数字签名
- Android 数字签名
- Android数字签名
- Android数字签名
- android 数字签名
- Android 数字签名
- Android 数字签名
- android数字签名
- Android 数字签名
- Android 数字签名
- Android数字签名
- SpringMVC强大的数据绑定(2)——第六章 注解式控制器详解——跟着开涛学SpringMVC
- 【转】初识linux平台C++开发
- java多线程:ReentrantReadWriteLock读写锁的使用
- 设计模式学习笔记(二):门面模式【Facade】(二) 问题的改进
- tomcat起步在80端口 Permission denied <null>80
- Android数字签名解析(二)
- 第1次实验——NPC问题(回溯算法、聚类分析)
- [Android]SQLite 学习笔记
- 嵌入式Linux的技术分析
- 解码GL\x4f\x42A\x4c\x53类加密实例
- Insert Interval
- IOS开发之保存图片到Documents目录及PNG,JPEG格式相互转换
- Linux--线程编程
- 解决PLSQL报错"动态执行表不可访问,本会话的自动统计被禁止"