update signature block PADDING

This commit is contained in:
REAndroid 2023-04-26 18:34:31 +02:00
parent f0c2ebb97d
commit 6e73da3326
7 changed files with 142 additions and 43 deletions

View File

@ -120,12 +120,4 @@ public class Archive {
String name = archiveEntry.getName().replace('/', File.separatorChar);
return new File(dir, name);
}
// for test
public void writeSignatureData(File dir) throws IOException{
ApkSignatureBlock apkSignatureBlock = getApkSignatureBlock();
if(apkSignatureBlock == null){
throw new IOException("Does not have signature block");
}
apkSignatureBlock.writeSignatureData(dir);
}
}

View File

@ -16,21 +16,61 @@
package com.reandroid.archive2.block;
import com.reandroid.archive2.block.pad.SchemePadding;
import com.reandroid.arsc.io.BlockReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class ApkSignatureBlock extends LengthPrefixedList<SignatureInfo> {
public class ApkSignatureBlock extends LengthPrefixedList<SignatureInfo>
implements Comparator<SignatureInfo> {
public ApkSignatureBlock(SignatureFooter signatureFooter){
super(true);
setBottomBlock(signatureFooter);
}
public ApkSignatureBlock(){
this(new SignatureFooter());
}
public List<SignatureInfo> getSignatures(){
return super.getElements();
}
public int countSignatures(){
return super.getElementsCount();
}
public void sortSignatures(){
sort(this);
}
public void updatePadding(){
SchemePadding schemePadding = getOrCreateSchemePadding();
schemePadding.setPadding(0);
sortSignatures();
refresh();
int size = countBytes();
int alignment = 4096;
int padding = (alignment - (size % alignment)) % alignment;
schemePadding.setPadding(padding);
refresh();
}
private SchemePadding getOrCreateSchemePadding(){
SignatureInfo signatureInfo = getSignature(SignatureId.PADDING);
if(signatureInfo == null){
signatureInfo = new SignatureInfo();
signatureInfo.setId(SignatureId.PADDING);
signatureInfo.setSignatureScheme(new SchemePadding());
add(signatureInfo);
}
SignatureScheme scheme = signatureInfo.getSignatureScheme();
if(!(scheme instanceof SchemePadding)){
scheme = new SchemePadding();
signatureInfo.setSignatureScheme(scheme);
}
return (SchemePadding) scheme;
}
public SignatureInfo getSignature(SignatureId signatureId){
for(SignatureInfo signatureInfo:getSignatures()){
if(signatureInfo.getId().equals(signatureId)){
@ -53,26 +93,69 @@ public class ApkSignatureBlock extends LengthPrefixedList<SignatureInfo> {
super.onRefreshed();
footer.setSignatureSize(getDataSize());
}
// for test
public void writeSignatureData(File dir) throws IOException{
for(SignatureInfo signatureInfo:getElements()){
signatureInfo.writeToDir(dir);
}
}
private static final long CONTENT_DIGESTED_CHUNK_MAX_SIZE_BYTES = 1024 * 1024;
public static final int ANDROID_COMMON_PAGE_ALIGNMENT_BYTES = 4096;
private static final byte[] APK_SIGNING_BLOCK_MAGIC = new byte[] {
0x41, 0x50, 0x4b, 0x20, 0x53, 0x69, 0x67, 0x20,
0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x34, 0x32,
public void writeRaw(File file) throws IOException{
refresh();
File dir = file.getParentFile();
if(dir != null && !dir.exists()){
dir.mkdirs();
}
FileOutputStream outputStream = new FileOutputStream(file);
writeBytes(outputStream);
outputStream.close();
}
public List<File> writeSplitRawToDirectory(File dir) throws IOException{
refresh();
List<SignatureInfo> signatureInfoList = getElements();
List<File> writtenFiles = new ArrayList<>(signatureInfoList.size());
for(SignatureInfo signatureInfo:signatureInfoList){
File file = signatureInfo.writeRawToDirectory(dir);
writtenFiles.add(file);
}
return writtenFiles;
}
public void read(File file) throws IOException {
super.readBytes(new BlockReader(file));
}
public void scanSplitFiles(File dir) throws IOException {
if(!dir.isDirectory()){
throw new IOException("No such directory");
}
FileFilter filter = new FileFilter() {
@Override
public boolean accept(File file) {
if(!file.isFile()){
return false;
}
String name = file.getName().toLowerCase();
return name.endsWith(SignatureId.FILE_EXT_RAW);
}
};
public static final int VERSION_SOURCE_STAMP = 0;
public static final int VERSION_JAR_SIGNATURE_SCHEME = 1;
public static final int VERSION_APK_SIGNATURE_SCHEME_V2 = 2;
public static final int VERSION_APK_SIGNATURE_SCHEME_V3 = 3;
public static final int VERSION_APK_SIGNATURE_SCHEME_V31 = 31;
public static final int VERSION_APK_SIGNATURE_SCHEME_V4 = 4;
File[] files = dir.listFiles(filter);
if(files == null){
return;
}
for(File file:files){
addSplitRaw(file);
}
sortSignatures();
}
public SignatureInfo addSplitRaw(File signatureInfoFile) throws IOException {
SignatureInfo signatureInfo = new SignatureInfo();
signatureInfo.read(signatureInfoFile);
add(signatureInfo);
return signatureInfo;
}
@Override
public int compare(SignatureInfo info1, SignatureInfo info2) {
if(SignatureId.PADDING.equals(info1.getId())){
return 0;
}
if(SignatureId.PADDING.equals(info2.getId())){
return 1;
}
return 0;
}
public static final String FILE_EXT = ".signature.block.bin";
}

View File

@ -25,6 +25,7 @@ import com.reandroid.arsc.item.IntegerItem;
import com.reandroid.arsc.item.LongItem;
import java.io.IOException;
import java.util.Comparator;
import java.util.List;
public abstract class LengthPrefixedList<T extends Block> extends FixedBlockContainer
@ -75,6 +76,9 @@ public abstract class LengthPrefixedList<T extends Block> extends FixedBlockCont
public boolean remove(T element){
return this.elements.remove(element);
}
public void sort(Comparator<T> comparator){
this.elements.sort(comparator);
}
@Override
public void onReadBytes(BlockReader reader) throws IOException{
if(!reader.isAvailable()){

View File

@ -35,9 +35,9 @@ public class SignatureId {
}
public String toFileName() {
if (this.name != null) {
return name + FILE_EXTENSION;
return name + FILE_EXT_RAW;
}
return String.format("0x%08x", id) + FILE_EXTENSION;
return String.format("0x%08x", id) + FILE_EXT_RAW;
}
@Override
public boolean equals(Object obj) {
@ -66,7 +66,7 @@ public class SignatureId {
if (name == null) {
return null;
}
String ext = FILE_EXTENSION;
String ext = FILE_EXT_RAW;
if (name.endsWith(ext)) {
name = name.substring(0, name.length() - ext.length());
}
@ -105,5 +105,5 @@ public class SignatureId {
V2, V3, V31, STAMP_V1, STAMP_V2, PADDING, NULL
};
private static final String FILE_EXTENSION = ".bin";
public static final String FILE_EXT_RAW = ".signature.info.bin";
}

View File

@ -28,6 +28,7 @@ import com.reandroid.arsc.io.BlockReader;
import com.reandroid.arsc.item.IntegerItem;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
@ -87,8 +88,7 @@ public class SignatureInfo extends LengthPrefixedBlock implements BlockLoad {
}
schemeContainer.setItem(scheme);
}
// for test
public void writeData(File file) throws IOException{
public void writeRaw(File file) throws IOException{
File dir = file.getParentFile();
if(dir != null && !dir.exists()){
dir.mkdirs();
@ -97,12 +97,15 @@ public class SignatureInfo extends LengthPrefixedBlock implements BlockLoad {
writeBytes(outputStream);
outputStream.close();
}
// for test
public File writeToDir(File dir) throws IOException{
File file = new File(dir, getId().toFileName());
writeData(file);
public File writeRawToDirectory(File dir) throws IOException{
String name = getIndex() + "_" + getId().toFileName();
File file = new File(dir, name);
writeRaw(file);
return file;
}
public void read(File file) throws IOException {
super.readBytes(new BlockReader(file));
}
@Override
public String toString() {
return getId() + ", scheme: " + getSignatureScheme();

View File

@ -30,6 +30,19 @@ public class SchemePadding extends SignatureScheme {
this.byteArray = new ByteArray();
addChild(this.byteArray);
}
public int getPadding(){
return byteArray.size();
}
public void setPadding(int padding){
byteArray.setSize(padding);
}
public byte[] getPaddingBytes() {
return byteArray.getBytes();
}
public void setPadding(byte[] bytes){
byteArray.set(bytes);
}
@Override
public void onReadBytes(BlockReader reader) throws IOException{
SignatureInfo signatureInfo = getSignatureInfo();
@ -37,4 +50,8 @@ public class SchemePadding extends SignatureScheme {
byteArray.setSize(size);
super.onReadBytes(reader);
}
@Override
public String toString(){
return "padding = " + getPadding();
}
}

View File

@ -99,13 +99,13 @@ public class ApkWriter extends ZipFileOutput {
logMessage("Writing signature block ...");
long offset = position();
int alignment = 4096;
int padding = (int) ((alignment - (offset % alignment)) % alignment);
int filesPadding = (int) ((alignment - (offset % alignment)) % alignment);
OutputStream outputStream = getOutputStream();
if(padding > 0){
outputStream.write(new byte[padding]);
if(filesPadding > 0){
outputStream.write(new byte[filesPadding]);
}
signatureBlock.refresh();
logVerbose("padding = " + padding + ", signatures = " + signatureBlock.countBytes());
logMessage("files padding = " + filesPadding);
signatureBlock.updatePadding();
signatureBlock.writeBytes(outputStream);
}
private BufferFileInput writeBuffer(List<OutputSource> outputList) throws IOException {