mirror of
https://github.com/revanced/ARSCLib.git
synced 2025-04-30 06:14:25 +02:00
update signature block PADDING
This commit is contained in:
parent
f0c2ebb97d
commit
6e73da3326
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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";
|
||||||
}
|
}
|
||||||
|
@ -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()){
|
||||||
|
@ -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";
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user