前言: 给旧手机刷机,rom.zip 直接解压魔改,完后再压缩为zip刷入手机。其间遇到了 MANIFEST.MF / CERT.SF 这两个文件,看看是怎么回事吧。
MANIFEST.MF
Manifest-Version: 1.0 Created-By: 1.0 (Android SignApk) ... Name: system/app/webview/webview.apk SHA1-Digest: zjehQbk00n2eu+YoBb1LZdieREo=
CERT.SF
Name: system/app/webview/webview.apk SHA1-Digest: fH0N47kRuw8L0flpR4GW0c3mq58=
这两个SHA1是怎么计算的呢?很简单:
直接从文件摘录SHA1,结果为字节数组,将这个字节数组用Java自带的base64编码器编码一下,结果仍然为字节数组,最后从此字节数组构建字符串,即为Android SignApk
为MANIFEST.MF
生成的SHA摘要。
代码:
@Test public void toSHA1() throws IOException { byte[] dig = Digest_SHA1(new FileInputStream("C:\\Users\\TEST\\Desktop\\desktop\\ceshi\\7to-cm13-christer12-bo1318\\system\\priv-app\\InputDevices\\InputDevices.apk")); dig = Digest_SHA1(new FileInputStream("C:\\Users\\TEST\\Desktop\\desktop\\ceshi\\7to-cm13-christer12-bo1318\\system/app/webview/webview.apk")); CMN.Log(new String(Base64.getEncoder().encode(dig))); } byte[] Digest_SHA1(InputStream input) { try (InputStream data_in = input){ MessageDigest digest =MessageDigest.getInstance("SHA"); byte[] buffer = new byte[4096]; int len; while((len=data_in.read(buffer))>=0) { digest.update(buffer, 0, len); } return digest.digest(); } catch (NoSuchAlgorithmException | IOException e) { CMN.Log(e); } return ArrayUtils.EMPTY_BYTE_ARRAY; }
和上面同一个流程,只不过第一步从文件获取摘要变成了从字节数组获取摘要:
dig=Digest_SHA1(new ByteArrayInputStream("Name: system/app/webview/webview.apk\r\nSHA1-Digest: zjehQbk00n2eu+YoBb1LZdieREo=\r\n\r\n".getBytes())); CMN.Log(new String(Base64.getEncoder().encode(dig)));
也就是说从以下MANIFETS.MF中的文本获取摘要:
Name: system/app/webview/webview.apk(\r\n换行) SHA1-Digest: zjehQbk00n2eu+YoBb1LZdieREo=(\r\n换行) (\r\n换行)
package test.privateTest.DebugBuilder; import org.apache.commons.lang.ArrayUtils; import org.junit.Test; import test.CMN; import java.io.*; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Base64; public class SHA_Android_Manifest_Test { @Test public void test() throws IOException { String name="system/priv-app/InputDevices/InputDevices.apk"; name="system/app/webview/webview.apk"; byte[] dig = Digest_SHA1(new FileInputStream("C:\\Users\\TEST\\Desktop\\desktop\\ceshi\\7to-cm13-christer12-bo1318\\"+name)); String digStr = new String(Base64.getEncoder().encode(dig), StandardCharsets.UTF_8); CMN.Log(digStr); dig=Digest_SHA1(new ByteArrayInputStream(("Name: "+name+"\r\nSHA1-Digest: "+digStr+"\r\n\r\n").getBytes())); CMN.Log(new String(Base64.getEncoder().encode(dig))); } private String BytesToHexString(byte[] value) { StringBuilder hexValue = new StringBuilder(value.length*2); for (byte b : value) { int val = ((int) b) & 0xff; if (val < 16) { hexValue.append("0"); } hexValue.append(Integer.toHexString(val).toUpperCase()); } return hexValue.toString(); } private byte[] HexStringToBytes(String value) { byte[] ret = new byte[value.length()/2]; for (int i = 0; i < ret.length; i++) { ret[i] = (byte) Integer.parseInt(value.substring(i*2, i*2+2), 16); } return ret; } byte[] Digest_SHA1(InputStream input) { try (InputStream data_in = input){ MessageDigest digest =MessageDigest.getInstance("SHA"); byte[] buffer = new byte[4096]; int len; while((len=data_in.read(buffer))>=0) { digest.update(buffer, 0, len); } return digest.digest(); } catch (NoSuchAlgorithmException | IOException e) { CMN.Log(e); } return ArrayUtils.EMPTY_BYTE_ARRAY; } }