前言: 给旧手机刷机,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是怎么计算的呢?很简单:
为 MANIFEST.MF 计算 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;
}
为 CERT.SF 计算 SHA1
和上面同一个流程,只不过第一步从文件获取摘要变成了从字节数组获取摘要:
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换行)
The End
完整代码
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;
}
}