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); String name = archiveEntry.getName().replace('/', File.separatorChar);
return new File(dir, name); 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; 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.File;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List; import java.util.List;
public class ApkSignatureBlock extends LengthPrefixedList<SignatureInfo> { public class ApkSignatureBlock extends LengthPrefixedList<SignatureInfo>
implements Comparator<SignatureInfo> {
public ApkSignatureBlock(SignatureFooter signatureFooter){ public ApkSignatureBlock(SignatureFooter signatureFooter){
super(true); super(true);
setBottomBlock(signatureFooter); setBottomBlock(signatureFooter);
} }
public ApkSignatureBlock(){
this(new SignatureFooter());
}
public List<SignatureInfo> getSignatures(){ public List<SignatureInfo> getSignatures(){
return super.getElements(); return super.getElements();
} }
public int countSignatures(){ public int countSignatures(){
return super.getElementsCount(); 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){ public SignatureInfo getSignature(SignatureId signatureId){
for(SignatureInfo signatureInfo:getSignatures()){ for(SignatureInfo signatureInfo:getSignatures()){
if(signatureInfo.getId().equals(signatureId)){ if(signatureInfo.getId().equals(signatureId)){
@ -53,26 +93,69 @@ public class ApkSignatureBlock extends LengthPrefixedList<SignatureInfo> {
super.onRefreshed(); super.onRefreshed();
footer.setSignatureSize(getDataSize()); 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 void writeRaw(File file) throws IOException{
public static final int ANDROID_COMMON_PAGE_ALIGNMENT_BYTES = 4096; refresh();
File dir = file.getParentFile();
private static final byte[] APK_SIGNING_BLOCK_MAGIC = new byte[] { if(dir != null && !dir.exists()){
0x41, 0x50, 0x4b, 0x20, 0x53, 0x69, 0x67, 0x20, dir.mkdirs();
0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x34, 0x32, }
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);
}
}; };
File[] files = dir.listFiles(filter);
public static final int VERSION_SOURCE_STAMP = 0; if(files == null){
public static final int VERSION_JAR_SIGNATURE_SCHEME = 1; return;
public static final int VERSION_APK_SIGNATURE_SCHEME_V2 = 2; }
public static final int VERSION_APK_SIGNATURE_SCHEME_V3 = 3; for(File file:files){
public static final int VERSION_APK_SIGNATURE_SCHEME_V31 = 31; addSplitRaw(file);
public static final int VERSION_APK_SIGNATURE_SCHEME_V4 = 4; }
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 com.reandroid.arsc.item.LongItem;
import java.io.IOException; import java.io.IOException;
import java.util.Comparator;
import java.util.List; import java.util.List;
public abstract class LengthPrefixedList<T extends Block> extends FixedBlockContainer 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){ public boolean remove(T element){
return this.elements.remove(element); return this.elements.remove(element);
} }
public void sort(Comparator<T> comparator){
this.elements.sort(comparator);
}
@Override @Override
public void onReadBytes(BlockReader reader) throws IOException{ public void onReadBytes(BlockReader reader) throws IOException{
if(!reader.isAvailable()){ if(!reader.isAvailable()){

View File

@ -35,9 +35,9 @@ public class SignatureId {
} }
public String toFileName() { public String toFileName() {
if (this.name != null) { 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 @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
@ -66,7 +66,7 @@ public class SignatureId {
if (name == null) { if (name == null) {
return null; return null;
} }
String ext = FILE_EXTENSION; String ext = FILE_EXT_RAW;
if (name.endsWith(ext)) { if (name.endsWith(ext)) {
name = name.substring(0, name.length() - ext.length()); name = name.substring(0, name.length() - ext.length());
} }
@ -105,5 +105,5 @@ public class SignatureId {
V2, V3, V31, STAMP_V1, STAMP_V2, PADDING, NULL 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 com.reandroid.arsc.item.IntegerItem;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
@ -87,8 +88,7 @@ public class SignatureInfo extends LengthPrefixedBlock implements BlockLoad {
} }
schemeContainer.setItem(scheme); schemeContainer.setItem(scheme);
} }
// for test public void writeRaw(File file) throws IOException{
public void writeData(File file) throws IOException{
File dir = file.getParentFile(); File dir = file.getParentFile();
if(dir != null && !dir.exists()){ if(dir != null && !dir.exists()){
dir.mkdirs(); dir.mkdirs();
@ -97,12 +97,15 @@ public class SignatureInfo extends LengthPrefixedBlock implements BlockLoad {
writeBytes(outputStream); writeBytes(outputStream);
outputStream.close(); outputStream.close();
} }
// for test public File writeRawToDirectory(File dir) throws IOException{
public File writeToDir(File dir) throws IOException{ String name = getIndex() + "_" + getId().toFileName();
File file = new File(dir, getId().toFileName()); File file = new File(dir, name);
writeData(file); writeRaw(file);
return file; return file;
} }
public void read(File file) throws IOException {
super.readBytes(new BlockReader(file));
}
@Override @Override
public String toString() { public String toString() {
return getId() + ", scheme: " + getSignatureScheme(); return getId() + ", scheme: " + getSignatureScheme();

View File

@ -30,6 +30,19 @@ public class SchemePadding extends SignatureScheme {
this.byteArray = new ByteArray(); this.byteArray = new ByteArray();
addChild(this.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 @Override
public void onReadBytes(BlockReader reader) throws IOException{ public void onReadBytes(BlockReader reader) throws IOException{
SignatureInfo signatureInfo = getSignatureInfo(); SignatureInfo signatureInfo = getSignatureInfo();
@ -37,4 +50,8 @@ public class SchemePadding extends SignatureScheme {
byteArray.setSize(size); byteArray.setSize(size);
super.onReadBytes(reader); 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 ..."); logMessage("Writing signature block ...");
long offset = position(); long offset = position();
int alignment = 4096; int alignment = 4096;
int padding = (int) ((alignment - (offset % alignment)) % alignment); int filesPadding = (int) ((alignment - (offset % alignment)) % alignment);
OutputStream outputStream = getOutputStream(); OutputStream outputStream = getOutputStream();
if(padding > 0){ if(filesPadding > 0){
outputStream.write(new byte[padding]); outputStream.write(new byte[filesPadding]);
} }
signatureBlock.refresh(); logMessage("files padding = " + filesPadding);
logVerbose("padding = " + padding + ", signatures = " + signatureBlock.countBytes()); signatureBlock.updatePadding();
signatureBlock.writeBytes(outputStream); signatureBlock.writeBytes(outputStream);
} }
private BufferFileInput writeBuffer(List<OutputSource> outputList) throws IOException { private BufferFileInput writeBuffer(List<OutputSource> outputList) throws IOException {