一点笔记
转载请注明出处
========================================================================================
系统APK验证流程:
PackageManagerService :: collectCertificatesLI
PackageParser :: collectCertificates
-- if ((flags&PARSE_IS_SYSTEM) != 0)
// If this package comes from the system image, then we
// can trust it... we'll just use the AndroidManifest.xml
// to retrieve its signatures, not validating all of the files.
for system apk only, just verify AndroidManifest.xml, otherwise, verify all entry except "META-INF/"
JarFile jarFile = new JarFile(pkg);
JarEntry je = jarFile.getJarEntry("AndroidManifest.xml");
jarFile.getInputStream(je)
-- JarFile.getInputStream(ZipEntry) line: 378
-- JarVerifier.readCertificates() line: 258
-- JarVerifier.verifyCertificate(String) line: 330
-- JarVerifier.verify(Attributes, String, byte[], int, int, boolean, boolean) line: 405
1. Use .SF to verify the mainAttributes of the manifest
2. Use .SF to verify the whole manifest.
3. associate signatures with .SF and entries of manifest.
-- JarFile.getInputStream(ZipEntry) line: 395
-- JarVerifier.initEntry(String) line: 213
1. init entry digest method and it's hashbytes.
read inputStream
-- BufferedInputStream.read(byte[], int, int) line: 304
-- JarFile$JarFileInputStream.read(byte[], int, int) line: 119
-- JarVerifier$VerifierEntry.verify() line: 121
<<<
byte[] d = digest.digest();
if (!MessageDigest.isEqual(d, Base64.decode(hash))) {
throw invalidDigest(JarFile.MANIFEST_NAME, name, jarName);
}
verifiedEntries.put(name, certificates);
>>>>
1. hash content of jarEntry, cmp the digest with hashbytes already saved.
if they're identical, associate entry name with certificates.
Certificate[] certs = je.getCertificates();
-- JarEntry.getCertificates() line: 108
-- JarVerifier.getCertificates(String) line: 422
<<<
Certificate[] verifiedCerts = verifiedEntries.get(name);
>>>
------------------------------------------------------------------------------------------------------------------
Source snippet:
String pkg = "/mnt/asec/com.speedsoftware.rootexplorer-1/pkg.apk";
JarFile jarFile = new JarFile(pkg);
JarEntry je = jarFile.getJarEntry("AndroidManifest.xml");
byte[] readBuffer = new byte[8192];
try {
// We must read the stream for the JarEntry to retrieve
// its certificates.
InputStream is = new BufferedInputStream(jarFile.getInputStream(je));
while (is.read(readBuffer, 0, readBuffer.length) != -1) {
// not using
}
is.close();
Certificate[] certs = je.getCertificates();
Log.e(TAG, certs.toString());
} catch (IOException e) {
Slog.w(TAG, "Exception reading " + je.getName() + " in "
+ jarFile.getName(), e);
} catch (RuntimeException e) {
Slog.w(TAG, "Exception reading " + je.getName() + " in "
+ jarFile.getName(), e);
}
} catch (IOException e2) {
e2.printStackTrace();
}