From 6c662a54dacbbe0312097a080e7463faea18477c Mon Sep 17 00:00:00 2001 From: cfig Date: Wed, 24 Feb 2021 20:14:37 +0800 Subject: [PATCH] lots of stuff - extract helper for more projects - kotlin 1.4.31 - gradle 6.8.3 - vendor_boot flash/pull - fix comanion vbmeta update: boot.img, vendor_boot.img - refine libavb --- .travis.yml | 8 +- README.md | 19 +- aosp/avb/avbtool.v1.2.py | 5 + aosp/build/tools/extract_kernel.py | 22 +- avbImpl/build.gradle | 2 +- avbImpl/src/avbVerifier/cpp/main.cpp | 30 +- avbImpl/src/avbx/cpp/CfigAvbOps.cpp | 31 +- bbootimg/build.gradle.kts | 11 +- bbootimg/src/main/kotlin/KeyUtil.kt | 47 --- bbootimg/src/main/kotlin/avb/Avb.kt | 109 +++++- bbootimg/src/main/kotlin/avb/blob/AuthBlob.kt | 62 +++- bbootimg/src/main/kotlin/avb/blob/AuxBlob.kt | 8 +- .../main/kotlin/avb/desc/UnknownDescriptor.kt | 2 +- bbootimg/src/main/kotlin/bootimg/Common.kt | 14 +- .../main/kotlin/bootimg/cpio/AndroidCpio.kt | 16 +- bbootimg/src/main/kotlin/bootimg/v2/BootV2.kt | 178 ++++----- bbootimg/src/main/kotlin/bootimg/v3/BootV3.kt | 5 +- bbootimg/src/main/kotlin/helper/KeyHelper.kt | 93 ----- .../kotlin/kernel_util/KernelExtractor.kt | 4 +- .../src/main/kotlin/packable/BootImgParser.kt | 56 +-- .../main/kotlin/packable/VendorBootParser.kt | 17 +- bbootimg/src/test/kotlin/HelperTest.kt | 126 ------- bbootimg/src/test/kotlin/KeyUtilTest.kt | 187 +++++++++- bbootimg/src/test/kotlin/avb/BlobTest.kt | 33 +- bbootimg/src/test/kotlin/avb/FooterTest.kt | 6 +- .../kotlin/bootimg/AndroidCpioEntryTest.kt | 5 +- .../bootloader_message/BootloaderMsgTest.kt | 2 - bbootimg/src/test/resources/data | Bin 0 -> 1024 bytes bbootimg/src/test/resources/testkey.pk8 | Bin 0 -> 1217 bytes build.gradle.kts | 24 +- gradle/wrapper/gradle-wrapper.jar | Bin 58910 -> 59203 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 2 +- gradlew.bat | 24 +- helper/build.gradle.kts | 32 ++ .../main/kotlin/cfig/helper/AndroidHelper.kt | 26 ++ .../src/main/kotlin/cfig}/helper/Helper.kt | 13 - .../src/main/kotlin/cfig/helper/KeyHelper.kt | 148 ++++++++ .../main/kotlin/cfig}/helper/KeyHelper2.kt | 76 +--- .../main/kotlin/cfig}/helper/OpenSslHelper.kt | 0 .../src/main/kotlin/cfig}/helper/ZipHelper.kt | 344 +++++++----------- .../src/main/kotlin/cfig/io/Struct3.kt | 0 .../kotlin/cfig/helper/OpenSslHelperTest.kt | 103 ++++++ .../test/kotlin/cfig/helper/ZipHelperTest.kt | 38 ++ .../src/test/kotlin/cfig/io/Struct3Test.kt | 0 helper/src/test/resources/appcompat.zip | Bin 0 -> 255157 bytes helper/src/test/resources/general.cfg | 0 helper/src/test/resources/platform.pk8 | Bin 0 -> 1216 bytes helper/src/test/resources/platform.x509.pem | 27 ++ helper/src/test/resources/testkey.pk8 | Bin 0 -> 1217 bytes helper/src/test/resources/testkey.pub | 9 + helper/src/test/resources/testkey.x509.pem | 27 ++ settings.gradle.kts | 1 + 53 files changed, 1151 insertions(+), 843 deletions(-) delete mode 100644 bbootimg/src/main/kotlin/KeyUtil.kt delete mode 100644 bbootimg/src/main/kotlin/helper/KeyHelper.kt delete mode 100644 bbootimg/src/test/kotlin/HelperTest.kt create mode 100644 bbootimg/src/test/resources/data create mode 100644 bbootimg/src/test/resources/testkey.pk8 create mode 100644 helper/build.gradle.kts create mode 100644 helper/src/main/kotlin/cfig/helper/AndroidHelper.kt rename {bbootimg/src/main/kotlin => helper/src/main/kotlin/cfig}/helper/Helper.kt (95%) create mode 100644 helper/src/main/kotlin/cfig/helper/KeyHelper.kt rename {bbootimg/src/main/kotlin => helper/src/main/kotlin/cfig}/helper/KeyHelper2.kt (58%) rename {bbootimg/src/main/kotlin => helper/src/main/kotlin/cfig}/helper/OpenSslHelper.kt (100%) rename {bbootimg/src/main/kotlin => helper/src/main/kotlin/cfig}/helper/ZipHelper.kt (57%) rename {bbootimg => helper}/src/main/kotlin/cfig/io/Struct3.kt (100%) create mode 100644 helper/src/test/kotlin/cfig/helper/OpenSslHelperTest.kt create mode 100644 helper/src/test/kotlin/cfig/helper/ZipHelperTest.kt rename {bbootimg => helper}/src/test/kotlin/cfig/io/Struct3Test.kt (100%) create mode 100644 helper/src/test/resources/appcompat.zip create mode 100644 helper/src/test/resources/general.cfg create mode 100644 helper/src/test/resources/platform.pk8 create mode 100644 helper/src/test/resources/platform.x509.pem create mode 100644 helper/src/test/resources/testkey.pk8 create mode 100644 helper/src/test/resources/testkey.pub create mode 100644 helper/src/test/resources/testkey.x509.pem diff --git a/.travis.yml b/.travis.yml index 217b230..678b12d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,8 +19,8 @@ addons: - python-all before_install: - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update ; fi - - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew install lz4 dtc gradle; fi + - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew install lz4 dtc ; fi +before_script: + - ./gradlew check && ./gradlew clean script: - - ./gradlew check - - ./gradlew clean - - ./integrationTest.py + - ./integrationTest.py diff --git a/README.md b/README.md index b8ee27e..cb6e808 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Android_boot_image_editor -[![Build Status](https://travis-ci.org/cfig/Android_boot_image_editor.svg?branch=master)](https://travis-ci.org/cfig/Android_boot_image_editor) +[![Build Status](https://www.travis-ci.com/cfig/Android_boot_image_editor.svg?branch=master)](https://www.travis-ci.com/cfig/Android_boot_image_editor) [![License](http://img.shields.io/:license-apache-blue.svg?style=flat-square)](http://www.apache.org/licenses/LICENSE-2.0.html) A tool for reverse engineering Android ROM images. @@ -10,7 +10,7 @@ A tool for reverse engineering Android ROM images. Mac: `brew install lz4 xz` -Linux: `sudo apt install device-tree-compiler lz4 xz zlib1g-dev openjdk-11-jdk` +Linux: `sudo apt install git device-tree-compiler lz4 xz-utils zlib1g-dev openjdk-11-jdk gcc g++ python3` Windows: Make sure you have `python3`, `JDK9+` and `openssl` properly installed. An easy way is to install [Anaconda](https://www.anaconda.com/products/individual#windows) and [Oracle JDK 11](https://www.oracle.com/java/technologies/javase-jdk11-downloads.html), then run the program under anaconda PowerShell. @@ -60,7 +60,6 @@ Well done you did it! The last step is to star this repo :smile | boot images | boot.img, vendor_boot.img | | | recovery images | recovery.img, recovery-two-step.img | | | vbmeta images | vbmeta.img, vbmeta_system.img etc. | | -| sparse images | system.img, vendor.img etc. | | | dtbo images | dtbo.img | | Please note that the boot.img MUST follows AOSP verified boot flow, either [Boot image signature](https://source.android.com/security/verifiedboot/verified-boot#signature_format) in VBoot 1.0 or [AVB HASH footer](https://android.googlesource.com/platform/external/avb/+/master/README.md#The-VBMeta-struct) (a.k.a. AVB) in VBoot 2.0. @@ -106,20 +105,6 @@ cp vbmeta.img ``` Your boot.img.signed and vbmeta.img.signd will be updated together. -* sparse vendor.img - -```bash -cp vendor.img -./gradlew unpack -./gradlew pack -``` - -You get vendor.img.unsparse, then you can mount it. -```bash -mkdir mnt -sudo mount -o ro vendor.img mnt -``` - ## boot.img layout Read [layout](doc/layout.md) of Android boot.img and vendor\_boot.img. diff --git a/aosp/avb/avbtool.v1.2.py b/aosp/avb/avbtool.v1.2.py index 1211df3..13f5594 100755 --- a/aosp/avb/avbtool.v1.2.py +++ b/aosp/avb/avbtool.v1.2.py @@ -27,6 +27,7 @@ import argparse import binascii import bisect +import binascii import hashlib import json import math @@ -577,6 +578,7 @@ def verify_vbmeta_signature(vbmeta_header, vbmeta_blob): ha.update(header_blob) ha.update(aux_blob) computed_digest = ha.digest() + print("computed %s hash : %s" % (alg.hash_name, binascii.hexlify(computed_digest))) if computed_digest != digest_blob: return False @@ -586,6 +588,7 @@ def verify_vbmeta_signature(vbmeta_header, vbmeta_blob): (num_bits,) = struct.unpack('!I', pubkey_blob[0:4]) modulus_blob = pubkey_blob[8:8 + num_bits//8] modulus = decode_long(modulus_blob) + print("modulus = %s" % modulus) exponent = 65537 # We used to have this: @@ -2528,6 +2531,8 @@ class Avb(object): if not verify_vbmeta_signature(header, vbmeta_blob): raise AvbError('Signature check failed for {} vbmeta struct {}' .format(alg_name, image_filename)) + else: + print("Sig check done") if key_blob: # The embedded public key is in the auxiliary block at an offset. diff --git a/aosp/build/tools/extract_kernel.py b/aosp/build/tools/extract_kernel.py index df2d741..44fbcdf 100755 --- a/aosp/build/tools/extract_kernel.py +++ b/aosp/build/tools/extract_kernel.py @@ -69,7 +69,7 @@ def dump_from_release(input_bytes, key): value = get_from_release(input_bytes, idx, key) if value: - return value + return value.encode() idx += len(LINUX_BANNER_PREFIX) @@ -176,16 +176,18 @@ def dump_to_file(f, dump_fn, input_bytes, desc): if f is not None: o = decompress_dump(dump_fn, input_bytes) if o: - if isinstance(o, str): - f.write(o.encode()) - else: - f.write(o) + f.write(o) else: sys.stderr.write( "Cannot extract kernel {}".format(desc)) return False return True +def to_bytes_io(b): + """ + Make b, which is either sys.stdout or sys.stdin, receive bytes as arguments. + """ + return b.buffer if sys.version_info.major == 3 else b def main(): parser = argparse.ArgumentParser( @@ -197,35 +199,35 @@ def main(): help='Input kernel image. If not specified, use stdin', metavar='FILE', type=argparse.FileType('rb'), - default=sys.stdin) + default=to_bytes_io(sys.stdin)) parser.add_argument('--output-configs', help='If specified, write configs. Use stdout if no file ' 'is specified.', metavar='FILE', nargs='?', type=argparse.FileType('wb'), - const=sys.stdout) + const=to_bytes_io(sys.stdout)) parser.add_argument('--output-version', help='If specified, write version. Use stdout if no file ' 'is specified.', metavar='FILE', nargs='?', type=argparse.FileType('wb'), - const=sys.stdout) + const=to_bytes_io(sys.stdout)) parser.add_argument('--output-release', help='If specified, write kernel release. Use stdout if ' 'no file is specified.', metavar='FILE', nargs='?', type=argparse.FileType('wb'), - const=sys.stdout) + const=to_bytes_io(sys.stdout)) parser.add_argument('--output-compiler', help='If specified, write the compiler information. Use stdout if no file ' 'is specified.', metavar='FILE', nargs='?', type=argparse.FileType('wb'), - const=sys.stdout) + const=to_bytes_io(sys.stdout)) parser.add_argument('--tools', help='Decompression tools to use. If not specified, PATH ' 'is searched.', diff --git a/avbImpl/build.gradle b/avbImpl/build.gradle index 8d786d1..58b060d 100644 --- a/avbImpl/build.gradle +++ b/avbImpl/build.gradle @@ -37,7 +37,7 @@ model { task v1(type:Exec) { workingDir "." - environment preloads: "vbmeta boot", requests: "boot dtbo", suffix: "" + environment preloads: "vbmeta boot", requests: "boot dtbo vendor_boot", suffix: "" commandLine "./build/exe/avbVerifier/avbVerifier" } diff --git a/avbImpl/src/avbVerifier/cpp/main.cpp b/avbImpl/src/avbVerifier/cpp/main.cpp index aa54ee2..a0a924c 100644 --- a/avbImpl/src/avbVerifier/cpp/main.cpp +++ b/avbImpl/src/avbVerifier/cpp/main.cpp @@ -69,9 +69,9 @@ int main(int, char**) { } } - bool isDeviceLocked = true; - cfigOps.avb_ops_.read_is_device_unlocked(NULL, &isDeviceLocked); - if (isDeviceLocked) { + bool isDeviceUnlocked = false; + cfigOps.avb_ops_.read_is_device_unlocked(NULL, &isDeviceUnlocked); + if (isDeviceUnlocked) { flags |= AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR; } std::cout << "[" << __FUNCTION__ << "]: flags: " << flags << std::endl; @@ -94,6 +94,28 @@ int main(int, char**) { std::cout << "Run:\n python -m json.tool " << outFile << std::endl; } if (slotData) { avb_slot_verify_data_free(slotData); } - std::cerr << "\n\tVerify Result: " << toString(result) << std::endl; + std::cout << "\n\tVerify Result: " << toString(result) << std::endl; + if (isDeviceUnlocked) { + switch (result) { + case AVB_SLOT_VERIFY_RESULT_OK: + std::cout << "\tVerify Flow: [orange] continue"; + break; + case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION: + case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED: + case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX: + std::cout << "\tVerify Flow: [orange] allowed errors found: " << toString(result) << std::endl; + break; + default: + std::cout<< "\tVerify Flow: [orange] but fatal errors found" << std::endl; + } + } else { + switch (result) { + case AVB_SLOT_VERIFY_RESULT_OK: + std::cout << "\tVerify Flow: [green] continue"; + break; + default: + std::cout << "\tVerify Flow: [?????] halt"; + } + } return 0; } diff --git a/avbImpl/src/avbx/cpp/CfigAvbOps.cpp b/avbImpl/src/avbx/cpp/CfigAvbOps.cpp index fb5b0ee..5669a06 100644 --- a/avbImpl/src/avbx/cpp/CfigAvbOps.cpp +++ b/avbImpl/src/avbx/cpp/CfigAvbOps.cpp @@ -44,11 +44,10 @@ static AvbIOResult read_is_device_unlockedX(AvbOps *, bool *out_is_unlocked) { std::string line = read_line(lockStatusFile); if ("0" == line) { *out_is_unlocked = true; - std::cout << "[" << __FUNCTION__ << "], device is unlocked" << std::endl; } else { *out_is_unlocked = false; - std::cout << "[" << __FUNCTION__ << "], device is locked" << std::endl; } + std::cout << "[" << __FUNCTION__ << "], device is " << ((*out_is_unlocked) ? "unlocked" : "locked") << std::endl; return AVB_IO_RESULT_OK; } @@ -152,16 +151,16 @@ static AvbIOResult get_size_of_partitionX(AvbOps *, auto file_size = get_file_size(partitionFile.c_str()); if (-1 == file_size) { std::cout << "[" << __FUNCTION__ << "(" << partition << ")]: "; - std::cout << ": error when accessing file [" << partitionFile << "]" << std::endl; + std::cout << "error when accessing file [" << partitionFile << "]" << std::endl; return AVB_IO_RESULT_ERROR_IO; } else { std::cout << "[" << __FUNCTION__ << "(" << partition << ")]: "; - std::cout << ": partition " << partitionFile << " size: " << file_size << std::endl; + std::cout << "partition " << partitionFile << " size: " << file_size << std::endl; if (out_size_num_bytes != nullptr) { *out_size_num_bytes = file_size; } else { std::cerr << "[" << __FUNCTION__ << "(" << partition << ")]: "; - std::cerr << ": size is not passed back" << std::endl; + std::cerr << "size is not passed back" << std::endl; } } return AVB_IO_RESULT_OK; @@ -215,7 +214,7 @@ static AvbIOResult read_from_partitionX(AvbOps *, return AVB_IO_RESULT_ERROR_IO; } ssize_t num_read = read(fd, buffer, num_bytes); - if (num_read < 0 || num_read != num_bytes) { + if (num_read < 0) { fprintf(stderr, "[%s()]: Error reading %zd bytes from pos %" PRId64 " in file %s: %s\n", __FUNCTION__, @@ -230,11 +229,21 @@ static AvbIOResult read_from_partitionX(AvbOps *, if (out_num_read != nullptr) { *out_num_read = num_read; } - fprintf(stdout, - "[%s()]: Read %ld bytes from partition %s\n", - __FUNCTION__, - num_read, - partition); + if (num_read != num_bytes) { + fprintf(stderr, + "[%s()]: read fewer bytes from pos %" PRId64 " in file %s: exp=%zd, act=%zd\n", + __FUNCTION__, + offset, + partitionFile.c_str(), + num_bytes, + num_read); + } else { + fprintf(stdout, + "[%s()]: Read %ld bytes from partition %s\n", + __FUNCTION__, + num_read, + partition); + } // cout << hexStr((unsigned char *) buffer, num_read) << endl; return AVB_IO_RESULT_OK; diff --git a/bbootimg/build.gradle.kts b/bbootimg/build.gradle.kts index 3228ecb..ba12742 100644 --- a/bbootimg/build.gradle.kts +++ b/bbootimg/build.gradle.kts @@ -1,7 +1,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { - kotlin("jvm") version "1.4.21" + kotlin("jvm") version "1.4.31" application } @@ -12,19 +12,19 @@ repositories { dependencies { implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") implementation("org.jetbrains.kotlin:kotlin-reflect") - implementation("org.slf4j:slf4j-simple:1.7.30") implementation("org.slf4j:slf4j-api:1.7.30") - implementation("com.fasterxml.jackson.core:jackson-annotations:2.11.3") - implementation("com.fasterxml.jackson.core:jackson-databind:2.11.3") + implementation("com.fasterxml.jackson.core:jackson-annotations:2.12.1") + implementation("com.fasterxml.jackson.core:jackson-databind:2.12.1") implementation("com.google.guava:guava:18.0") implementation("org.apache.commons:commons-exec:1.3") implementation("org.apache.commons:commons-compress:1.20") implementation("org.tukaani:xz:1.8") implementation("commons-codec:commons-codec:1.15") implementation("junit:junit:4.12") - implementation("org.bouncycastle:bcprov-jdk15on:1.57") + implementation("org.bouncycastle:bcprov-jdk15on:1.68") implementation("de.vandermeer:asciitable:0.3.2") + implementation(project(":helper")) testImplementation("org.jetbrains.kotlin:kotlin-test") testImplementation("org.jetbrains.kotlin:kotlin-test-junit") @@ -46,6 +46,7 @@ tasks { } from(configurations.runtimeClasspath.get().map({ if (it.isDirectory) it else zipTree(it) })) excludes.addAll(mutableSetOf("META-INF/*.RSA", "META-INF/*.SF", "META-INF/*.DSA")) + dependsOn(":helper:jar") } test { testLogging { diff --git a/bbootimg/src/main/kotlin/KeyUtil.kt b/bbootimg/src/main/kotlin/KeyUtil.kt deleted file mode 100644 index ead062a..0000000 --- a/bbootimg/src/main/kotlin/KeyUtil.kt +++ /dev/null @@ -1,47 +0,0 @@ -package cfig - -import org.bouncycastle.asn1.pkcs.RSAPrivateKey -import org.bouncycastle.util.io.pem.PemReader -import java.io.InputStream -import java.io.InputStreamReader -import java.math.BigInteger -import java.security.KeyFactory -import java.security.PrivateKey -import java.security.PublicKey -import java.security.spec.PKCS8EncodedKeySpec -import java.security.spec.RSAPrivateKeySpec -import java.security.spec.RSAPublicKeySpec - -class KeyUtil { - companion object { - @Throws(IllegalArgumentException::class) - fun parsePemPrivateKey(inputStream: InputStream): RSAPrivateKey { - val p = PemReader(InputStreamReader(inputStream)).readPemObject() - if ("RSA PRIVATE KEY" != p.type) { - throw IllegalArgumentException("input is not valid 'RSA PRIVATE KEY'") - } - return RSAPrivateKey.getInstance(p.content) - } - - fun parsePemPrivateKey2(inputStream: InputStream): PrivateKey { - val rsa = parsePemPrivateKey(inputStream) - return generateRsaPrivateKey(rsa.modulus, rsa.privateExponent) - } - - @Throws(Exception::class) - fun parsePk8PrivateKey(inputData: ByteArray): PrivateKey { - val spec = PKCS8EncodedKeySpec(inputData) - return KeyFactory.getInstance("RSA").generatePrivate(spec) - } - - @Throws(Exception::class) - private fun generateRsaPublicKey(modulus: BigInteger, publicExponent: BigInteger): PublicKey { - return KeyFactory.getInstance("RSA").generatePublic(RSAPublicKeySpec(modulus, publicExponent)) - } - - @Throws(Exception::class) - private fun generateRsaPrivateKey(modulus: BigInteger, privateExponent: BigInteger): PrivateKey { - return KeyFactory.getInstance("RSA").generatePrivate(RSAPrivateKeySpec(modulus, privateExponent)) - } - } -} \ No newline at end of file diff --git a/bbootimg/src/main/kotlin/avb/Avb.kt b/bbootimg/src/main/kotlin/avb/Avb.kt index f1b1133..6ea12fd 100644 --- a/bbootimg/src/main/kotlin/avb/Avb.kt +++ b/bbootimg/src/main/kotlin/avb/Avb.kt @@ -9,6 +9,7 @@ import avb.blob.Header import avb.desc.* import cfig.helper.Helper import cfig.helper.Helper.Companion.paddingWith +import cfig.helper.KeyHelper import cfig.io.Struct3 import com.fasterxml.jackson.databind.ObjectMapper import org.apache.commons.codec.binary.Hex @@ -30,10 +31,12 @@ class Avb { private val DEBUG = false //migrated from: avbtool::Avb::addHashFooter - fun addHashFooter(image_file: String, - partition_size: Long, //aligned by Avb::BLOCK_SIZE - partition_name: String, - newAvbInfo: AVBInfo) { + fun addHashFooter( + image_file: String, + partition_size: Long, //aligned by Avb::BLOCK_SIZE + partition_name: String, + newAvbInfo: AVBInfo + ) { log.info("addHashFooter($image_file) ...") imageSizeCheck(partition_size, image_file) @@ -115,8 +118,10 @@ class Avb { } footer?.let { FileOutputStream(File(image_file), true).channel.use { fc -> - log.info("original image $image_file has AVB footer, " + - "truncate it to original SIZE: ${it.originalImageSize}") + log.info( + "original image $image_file has AVB footer, " + + "truncate it to original SIZE: ${it.originalImageSize}" + ) fc.truncate(it.originalImageSize) } } @@ -126,8 +131,10 @@ class Avb { //image size sanity check val maxMetadataSize = MAX_VBMETA_SIZE + MAX_FOOTER_SIZE if (partition_size < maxMetadataSize) { - throw IllegalArgumentException("Parition SIZE of $partition_size is too small. " + - "Needs to be at least $maxMetadataSize") + throw IllegalArgumentException( + "Parition SIZE of $partition_size is too small. " + + "Needs to be at least $maxMetadataSize" + ) } val maxImageSize = partition_size - maxMetadataSize log.info("max_image_size: $maxImageSize") @@ -135,14 +142,18 @@ class Avb { //TODO: typical block size = 4096L, from avbtool::Avb::ImageHandler::block_size //since boot.img is not in sparse format, we are safe to hardcode it to 4096L for now if (partition_size % BLOCK_SIZE != 0L) { - throw IllegalArgumentException("Partition SIZE of $partition_size is not " + - "a multiple of the image block SIZE 4096") + throw IllegalArgumentException( + "Partition SIZE of $partition_size is not " + + "a multiple of the image block SIZE 4096" + ) } val originalFileSize = File(image_file).length() if (originalFileSize > maxImageSize) { - throw IllegalArgumentException("Image size of $originalFileSize exceeds maximum image size " + - "of $maxImageSize in order to fit in a partition size of $partition_size.") + throw IllegalArgumentException( + "Image size of $originalFileSize exceeds maximum image size " + + "of $maxImageSize in order to fit in a partition size of $partition_size." + ) } } @@ -169,7 +180,7 @@ class Avb { fis.skip(vbMetaOffset) vbMetaHeader = Header(fis) } - log.info(vbMetaHeader.toString()) + log.debug(vbMetaHeader.toString()) log.debug(ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(vbMetaHeader)) val authBlockOffset = vbMetaOffset + Header.SIZE @@ -262,6 +273,39 @@ class Avb { } } + //FIXME + val declaredAlg = Algorithms.get(ai.header!!.algorithm_type) + if (declaredAlg!!.public_key_num_bytes > 0) { + if (AuxBlob.encodePubKey(declaredAlg).contentEquals(ai.auxBlob!!.pubkey!!.pubkey)) { + log.warn("VERIFY: vbmeta is signed with the same key as us") + val calcHash = + AuthBlob.calcHash(ai.header!!.encode(), ai.auxBlob!!.encode(declaredAlg), declaredAlg.name) + val calcSig = AuthBlob.calcSignature(calcHash, declaredAlg.name) + if (Helper.toHexString(calcHash) != ai.authBlob!!.hash) { + log.error("calculated AuthBlob hash mismatch") + throw IllegalArgumentException("calculated AuthBlob hash mismatch") + } else { + log.info("VERIFY: AuthBlob hash matches") + } + if (Helper.toHexString(calcSig) != ai.authBlob!!.signature) { + log.error("calculated AuthBlob signature mismatch") + throw IllegalArgumentException("calculated AuthBlob signature mismatch") + } else { + log.info("VERIFY: AuthBlob signature matches") + } + } else { + val custPubKey = KeyHelper.decodeRSAkey(ai.auxBlob!!.pubkey!!.pubkey) + log.warn("VERIFY: vbmeta is signed with different key as us") + log.debug("modulus :" + custPubKey.modulus) + log.debug("exponent :" + custPubKey.publicExponent) + } + //FIXME + ai.auxBlob!!.pubkey + } else { + log.debug("no key for current algorithm") + } + //FIXME + if (dumpFile) { ObjectMapper().writerWithDefaultPrettyPrinter().writeValue(File(jsonFile), ai) log.info("vbmeta info of [$image_file] has been analyzed") @@ -284,7 +328,8 @@ class Avb { val headerBlob = ai.header!!.apply { auxiliary_data_block_size = auxBlob.size.toLong() authentication_data_block_size = Helper.round_to_multiple( - (alg.hash_num_bytes + alg.signature_num_bytes).toLong(), 64) + (alg.hash_num_bytes + alg.signature_num_bytes).toLong(), 64 + ) descriptors_offset = 0 descriptors_size = ai.auxBlob?.descriptorSize?.toLong() ?: 0 @@ -348,5 +393,41 @@ class Avb { throw IllegalArgumentException("$fileName failed integrity check by \"$cmdline\"") } } + + fun updateVbmeta(fileName: String) { + if (File("vbmeta.img").exists()) { + log.info("Updating vbmeta.img side by side ...") + val partitionName = + ObjectMapper().readValue(File(getJsonFileName(fileName)), AVBInfo::class.java).let { + it.auxBlob!!.hashDescriptors.get(0).partition_name + } + val newHashDesc = Avb().parseVbMeta("$fileName.signed", dumpFile = false) + assert(newHashDesc.auxBlob!!.hashDescriptors.size == 1) + var seq = -1 //means not found + //main vbmeta + ObjectMapper().readValue(File(getJsonFileName("vbmeta.img")), AVBInfo::class.java).apply { + val itr = this.auxBlob!!.hashDescriptors.iterator() + while (itr.hasNext()) { + val itrValue = itr.next() + if (itrValue.partition_name == partitionName) { + log.info("Found $partitionName in vbmeta, update it") + seq = itrValue.sequence + itr.remove() + break + } + } + if (-1 == seq) { + log.warn("main vbmeta doesn't have $partitionName hashDescriptor, skip") + } else { + val hd = newHashDesc.auxBlob!!.hashDescriptors.get(0).apply { this.sequence = seq } + this.auxBlob!!.hashDescriptors.add(hd) + Avb().packVbMetaWithPadding("vbmeta.img", this) + log.info("Updating vbmeta.img side by side (partition=$partitionName, seq=$seq) done") + } + } + } else { + log.info("no companion vbmeta.img") + } + } } } diff --git a/bbootimg/src/main/kotlin/avb/blob/AuthBlob.kt b/bbootimg/src/main/kotlin/avb/blob/AuthBlob.kt index 06bfb51..0d77817 100644 --- a/bbootimg/src/main/kotlin/avb/blob/AuthBlob.kt +++ b/bbootimg/src/main/kotlin/avb/blob/AuthBlob.kt @@ -1,24 +1,59 @@ package avb.blob +import avb.alg.Algorithm import avb.alg.Algorithms import cfig.helper.Helper +import cfig.helper.KeyHelper import cfig.helper.KeyHelper2 import cfig.io.Struct3 import org.slf4j.LoggerFactory import java.nio.file.Files import java.nio.file.Paths import java.security.MessageDigest +import java.security.PrivateKey @OptIn(ExperimentalUnsignedTypes::class) data class AuthBlob( - var offset: Long = 0, - var size: Long = 0, - var hash: String? = null, - var signature: String? = null) { + var offset: Long = 0, + var size: Long = 0, + var hash: String? = null, + var signature: String? = null +) { companion object { - fun createBlob(header_data_blob: ByteArray, - aux_data_blob: ByteArray, - algorithm_name: String): ByteArray { + fun calcHash( + header_data_blob: ByteArray, + aux_data_blob: ByteArray, + algorithm_name: String + ): ByteArray { + val alg = Algorithms.get(algorithm_name)!! + return if (alg.name == "NONE") { + log.debug("calc hash: NONE") + byteArrayOf() + } else { + MessageDigest.getInstance(Helper.pyAlg2java(alg.hash_name)).apply { + update(header_data_blob) + update(aux_data_blob) + }.digest().apply { + log.debug("calc hash = " + Helper.toHexString(this)) + } + } + } + + fun calcSignature(hash: ByteArray, algorithm_name: String): ByteArray { + val alg = Algorithms.get(algorithm_name)!! + return if (alg.name == "NONE") { + byteArrayOf() + } else { + val k = KeyHelper.parse(Files.readAllBytes(Paths.get(alg.defaultKey.replace(".pem", ".pk8")))) as PrivateKey + KeyHelper2.rawSign(k, Helper.join(alg.padding, hash)) + } + } + + fun createBlob( + header_data_blob: ByteArray, + aux_data_blob: ByteArray, + algorithm_name: String + ): ByteArray { val alg = Algorithms.get(algorithm_name)!! val authBlockSize = Helper.round_to_multiple((alg.hash_num_bytes + alg.signature_num_bytes).toLong(), 64) if (0L == authBlockSize) { @@ -27,17 +62,8 @@ data class AuthBlob( } //hash & signature - var binaryHash: ByteArray = byteArrayOf() - var binarySignature: ByteArray = byteArrayOf() - if (algorithm_name != "NONE") { - val hasher = MessageDigest.getInstance(Helper.pyAlg2java(alg.hash_name)) - binaryHash = hasher.apply { - update(header_data_blob) - update(aux_data_blob) - }.digest() - val k = KeyHelper2.parseRsaPk8(Files.readAllBytes(Paths.get(alg.defaultKey.replace(".pem", ".pk8")))) - binarySignature = KeyHelper2.rawSign(k, Helper.join(alg.padding, binaryHash)) - } + val binaryHash = calcHash(header_data_blob, aux_data_blob, algorithm_name) + var binarySignature = calcSignature(binaryHash, algorithm_name) val authData = Helper.join(binaryHash, binarySignature) return Helper.join(authData, Struct3("${authBlockSize - authData.size}x").pack(0)) } diff --git a/bbootimg/src/main/kotlin/avb/blob/AuxBlob.kt b/bbootimg/src/main/kotlin/avb/blob/AuxBlob.kt index 7ae0b26..1605c1c 100644 --- a/bbootimg/src/main/kotlin/avb/blob/AuxBlob.kt +++ b/bbootimg/src/main/kotlin/avb/blob/AuxBlob.kt @@ -7,7 +7,9 @@ import cfig.helper.KeyHelper import cfig.helper.KeyHelper2 import cfig.io.Struct3 import com.fasterxml.jackson.annotation.JsonIgnoreProperties +import org.bouncycastle.asn1.pkcs.RSAPrivateKey import org.slf4j.LoggerFactory +import java.io.ByteArrayInputStream import java.nio.file.Files import java.nio.file.Paths @@ -91,13 +93,13 @@ class AuxBlob( companion object { fun encodePubKey(alg: Algorithm, key: ByteArray? = null): ByteArray { var encodedKey = byteArrayOf() - var algKey: ByteArray? = key if (alg.public_key_num_bytes > 0) { + var algKey: ByteArray? = key if (key == null) { algKey = Files.readAllBytes((Paths.get(alg.defaultKey))) } - encodedKey = KeyHelper.encodeRSAkey(algKey!!) - log.info("encodePubKey(): size = ${alg.public_key_num_bytes}, algorithm key size: ${encodedKey.size}") + val rsa = KeyHelper.parse(algKey!!) as RSAPrivateKey //BC RSA + encodedKey = KeyHelper.encodeRSAkey(rsa) assert(alg.public_key_num_bytes == encodedKey.size) } else { log.info("encodePubKey(): No key to encode for algorithm " + alg.name) diff --git a/bbootimg/src/main/kotlin/avb/desc/UnknownDescriptor.kt b/bbootimg/src/main/kotlin/avb/desc/UnknownDescriptor.kt index 796ddfa..0447609 100644 --- a/bbootimg/src/main/kotlin/avb/desc/UnknownDescriptor.kt +++ b/bbootimg/src/main/kotlin/avb/desc/UnknownDescriptor.kt @@ -82,7 +82,7 @@ class UnknownDescriptor(var data: ByteArray = byteArrayOf()) : Descriptor(0, 0, } fun parseDescriptors2(stream: InputStream, totalSize: Long): List { - log.info("Parse descriptors stream, SIZE = $totalSize") + log.debug("Parse descriptors stream, SIZE = $totalSize") val ret: MutableList = mutableListOf() var currentSize = 0L var seq = 0 diff --git a/bbootimg/src/main/kotlin/bootimg/Common.kt b/bbootimg/src/main/kotlin/bootimg/Common.kt index a433963..bd65879 100644 --- a/bbootimg/src/main/kotlin/bootimg/Common.kt +++ b/bbootimg/src/main/kotlin/bootimg/Common.kt @@ -124,14 +124,14 @@ class Common { Files.move( Paths.get(s.dumpFile), Paths.get(s.dumpFile + ".gz"), java.nio.file.StandardCopyOption.REPLACE_EXISTING) - ZipHelper.unGnuzipFile(s.dumpFile + ".gz", s.dumpFile) + ZipHelper.zcat(s.dumpFile + ".gz", s.dumpFile) } - ZipHelper.isLZ4(s.dumpFile) -> { + ZipHelper.isLz4(s.dumpFile) -> { log.info("ramdisk is compressed lz4") Files.move( Paths.get(s.dumpFile), Paths.get(s.dumpFile + ".lz4"), java.nio.file.StandardCopyOption.REPLACE_EXISTING) - ZipHelper.decompressLZ4Ext(s.dumpFile + ".lz4", s.dumpFile) + ZipHelper.lz4cat(s.dumpFile + ".lz4", s.dumpFile) ret = "lz4" } else -> { @@ -220,10 +220,10 @@ class Common { } when { ramdiskGz.endsWith(".gz") -> { - ZipHelper.gnuZipFile2(ramdiskGz, ByteArrayInputStream(outputStream.toByteArray())) + ZipHelper.minigzip(ramdiskGz, ByteArrayInputStream(outputStream.toByteArray())) } ramdiskGz.endsWith(".lz4") -> { - ZipHelper.compressLZ4(ramdiskGz, ByteArrayInputStream(outputStream.toByteArray())) + ZipHelper.lz4(ramdiskGz, ByteArrayInputStream(outputStream.toByteArray())) } else -> { throw IllegalArgumentException("$ramdiskGz is not supported") @@ -240,12 +240,12 @@ class Common { ramdiskGz.endsWith(".gz") -> { val f = ramdiskGz.removeSuffix(".gz") AndroidCpio().pack(rootDir, f, fsConfig) - ZipHelper.gnuZipFile2(ramdiskGz, FileInputStream(f)) + ZipHelper.minigzip(ramdiskGz, FileInputStream(f)) } ramdiskGz.endsWith(".lz4") -> { val f = ramdiskGz.removeSuffix(".lz4") AndroidCpio().pack(rootDir, f, fsConfig) - ZipHelper.compressLZ4(ramdiskGz, FileInputStream(f)) + ZipHelper.lz4(ramdiskGz, FileInputStream(f)) } else -> { throw IllegalArgumentException("$ramdiskGz is not supported") diff --git a/bbootimg/src/main/kotlin/bootimg/cpio/AndroidCpio.kt b/bbootimg/src/main/kotlin/bootimg/cpio/AndroidCpio.kt index 39046b2..eb7d8e7 100644 --- a/bbootimg/src/main/kotlin/bootimg/cpio/AndroidCpio.kt +++ b/bbootimg/src/main/kotlin/bootimg/cpio/AndroidCpio.kt @@ -8,6 +8,7 @@ import org.apache.commons.compress.archivers.cpio.CpioArchiveInputStream import org.apache.commons.compress.archivers.cpio.CpioConstants import org.slf4j.LoggerFactory import java.io.* +import java.nio.charset.Charset import java.nio.file.Files import java.nio.file.Paths import java.util.regex.Pattern @@ -246,18 +247,19 @@ class AndroidCpio { } val bytesRead = cis.bytesRead cis.close() - val fis = FileInputStream(cpioFile) - fis.skip(bytesRead - 128) - val remaining = fis.readAllBytes() - val foundIndex = String(remaining).lastIndexOf("070701") + val remaining = FileInputStream(cpioFile).use { fis -> + fis.skip(bytesRead - 128) + fis.readBytes() + } + val foundIndex = String(remaining, Charsets.UTF_8).lastIndexOf("070701") val entryInfo = AndroidCpioEntry( name = CpioConstants.CPIO_TRAILER, statMode = java.lang.Long.valueOf("755", 8) ) if (foundIndex != -1) { - entryInfo.statMode = - java.lang.Long.valueOf(String(remaining).substring(foundIndex + 14, foundIndex + 22), 16) - log.info("cpio trailer found, mode=" + String(remaining).substring(foundIndex + 14, foundIndex + 22)) + val statusModeStr = String(remaining, Charsets.UTF_8).substring(foundIndex + 14, foundIndex + 22) + entryInfo.statMode = java.lang.Long.valueOf(statusModeStr, 16) + log.info("cpio trailer found, mode=$statusModeStr") } else { log.error("no cpio trailer found") } diff --git a/bbootimg/src/main/kotlin/bootimg/v2/BootV2.kt b/bbootimg/src/main/kotlin/bootimg/v2/BootV2.kt index 03154f8..04c7e0a 100644 --- a/bbootimg/src/main/kotlin/bootimg/v2/BootV2.kt +++ b/bbootimg/src/main/kotlin/bootimg/v2/BootV2.kt @@ -1,6 +1,7 @@ package cfig.bootimg.v2 import cfig.Avb +import cfig.EnvironmentVerifier import cfig.bootimg.Common import cfig.bootimg.Common.Companion.deleleIfExists import cfig.bootimg.Common.Slice @@ -20,40 +21,43 @@ import java.nio.ByteOrder @OptIn(ExperimentalUnsignedTypes::class) data class BootV2( - var info: MiscInfo = MiscInfo(), - var kernel: CommArgs = CommArgs(), - var ramdisk: CommArgs = CommArgs(), - var secondBootloader: CommArgs? = null, - var recoveryDtbo: CommArgsLong? = null, - var dtb: CommArgsLong? = null + var info: MiscInfo = MiscInfo(), + var kernel: CommArgs = CommArgs(), + var ramdisk: CommArgs = CommArgs(), + var secondBootloader: CommArgs? = null, + var recoveryDtbo: CommArgsLong? = null, + var dtb: CommArgsLong? = null ) { data class MiscInfo( - var output: String = "", - var json: String = "", - var headerVersion: Int = 0, - var headerSize: Int = 0, - var loadBase: Long = 0, - var tagsOffset: Long = 0, - var board: String? = null, - var pageSize: Int = 0, - var cmdline: String = "", - var osVersion: String? = null, - var osPatchLevel: String? = null, - var hash: ByteArray? = byteArrayOf(), - var verify: String = "", - var imageSize: Long = 0) + var output: String = "", + var json: String = "", + var headerVersion: Int = 0, + var headerSize: Int = 0, + var loadBase: Long = 0, + var tagsOffset: Long = 0, + var board: String? = null, + var pageSize: Int = 0, + var cmdline: String = "", + var osVersion: String? = null, + var osPatchLevel: String? = null, + var hash: ByteArray? = byteArrayOf(), + var verify: String = "", + var imageSize: Long = 0 + ) data class CommArgs( - var file: String? = null, - var position: Long = 0, - var size: Int = 0, - var loadOffset: Long = 0) + var file: String? = null, + var position: Long = 0, + var size: Int = 0, + var loadOffset: Long = 0 + ) data class CommArgsLong( - var file: String? = null, - var position: Long = 0, - var size: Int = 0, - var loadOffset: Long = 0) + var file: String? = null, + var position: Long = 0, + var size: Int = 0, + var loadOffset: Long = 0 + ) companion object { private val log = LoggerFactory.getLogger(BootV2::class.java) @@ -168,25 +172,31 @@ data class BootV2( Common.dumpKernel(Slice(info.output, kernel.position.toInt(), kernel.size, kernel.file!!)) //ramdisk if (this.ramdisk.size > 0) { - val fmt = Common.dumpRamdisk(Slice(info.output, ramdisk.position.toInt(), ramdisk.size, ramdisk.file!!), - "${workDir}root") + val fmt = Common.dumpRamdisk( + Slice(info.output, ramdisk.position.toInt(), ramdisk.size, ramdisk.file!!), + "${workDir}root" + ) this.ramdisk.file = this.ramdisk.file!! + ".$fmt" //dump info again ObjectMapper().writerWithDefaultPrettyPrinter().writeValue(File(workDir + this.info.json), this) } //second bootloader secondBootloader?.let { - Helper.extractFile(info.output, - secondBootloader!!.file!!, - secondBootloader!!.position, - secondBootloader!!.size) + Helper.extractFile( + info.output, + secondBootloader!!.file!!, + secondBootloader!!.position, + secondBootloader!!.size + ) } //recovery dtbo recoveryDtbo?.let { - Helper.extractFile(info.output, - recoveryDtbo!!.file!!, - recoveryDtbo!!.position, - recoveryDtbo!!.size) + Helper.extractFile( + info.output, + recoveryDtbo!!.file!!, + recoveryDtbo!!.position, + recoveryDtbo!!.size + ) } //dtb this.dtb?.let { _ -> @@ -280,32 +290,34 @@ data class BootV2( "" } } - log.info("\n\t\t\tUnpack Summary of ${info.output}\n{}\n{}{}", - tableHeader.render(), tab.render(), tabVBMeta) + log.info( + "\n\t\t\tUnpack Summary of ${info.output}\n{}\n{}{}", + tableHeader.render(), tab.render(), tabVBMeta + ) return this } private fun toHeader(): BootHeaderV2 { return BootHeaderV2( - kernelLength = kernel.size, - kernelOffset = kernel.loadOffset, - ramdiskLength = ramdisk.size, - ramdiskOffset = ramdisk.loadOffset, - secondBootloaderLength = if (secondBootloader != null) secondBootloader!!.size else 0, - secondBootloaderOffset = if (secondBootloader != null) secondBootloader!!.loadOffset else 0, - recoveryDtboLength = if (recoveryDtbo != null) recoveryDtbo!!.size else 0, - recoveryDtboOffset = if (recoveryDtbo != null) recoveryDtbo!!.loadOffset else 0, - dtbLength = if (dtb != null) dtb!!.size else 0, - dtbOffset = if (dtb != null) dtb!!.loadOffset else 0, - tagsOffset = info.tagsOffset, - pageSize = info.pageSize, - headerSize = info.headerSize, - headerVersion = info.headerVersion, - board = info.board.toString(), - cmdline = info.cmdline, - hash = info.hash, - osVersion = info.osVersion, - osPatchLevel = info.osPatchLevel + kernelLength = kernel.size, + kernelOffset = kernel.loadOffset, + ramdiskLength = ramdisk.size, + ramdiskOffset = ramdisk.loadOffset, + secondBootloaderLength = if (secondBootloader != null) secondBootloader!!.size else 0, + secondBootloaderOffset = if (secondBootloader != null) secondBootloader!!.loadOffset else 0, + recoveryDtboLength = if (recoveryDtbo != null) recoveryDtbo!!.size else 0, + recoveryDtboOffset = if (recoveryDtbo != null) recoveryDtbo!!.loadOffset else 0, + dtbLength = if (dtb != null) dtb!!.size else 0, + dtbOffset = if (dtb != null) dtb!!.loadOffset else 0, + tagsOffset = info.tagsOffset, + pageSize = info.pageSize, + headerSize = info.headerSize, + headerVersion = info.headerVersion, + board = info.board.toString(), + cmdline = info.cmdline, + hash = info.hash, + osVersion = info.osVersion, + osPatchLevel = info.osPatchLevel ) } @@ -348,12 +360,16 @@ data class BootV2( Common.hashFileAndSize(kernel.file, ramdisk.file, secondBootloader?.file) } 1 -> { - Common.hashFileAndSize(kernel.file, ramdisk.file, - secondBootloader?.file, recoveryDtbo?.file) + Common.hashFileAndSize( + kernel.file, ramdisk.file, + secondBootloader?.file, recoveryDtbo?.file + ) } 2 -> { - Common.hashFileAndSize(kernel.file, ramdisk.file, - secondBootloader?.file, recoveryDtbo?.file, dtb?.file) + Common.hashFileAndSize( + kernel.file, ramdisk.file, + secondBootloader?.file, recoveryDtbo?.file, dtb?.file + ) } else -> { throw IllegalArgumentException("headerVersion ${info.headerVersion} illegal") @@ -370,23 +386,23 @@ data class BootV2( log.info("Writing data ...") val bytesV2 = ByteBuffer.allocate(1024 * 1024 * 64)//assume total SIZE small than 64MB - .let { bf -> - bf.order(ByteOrder.LITTLE_ENDIAN) - Common.writePaddedFile(bf, kernel.file!!, info.pageSize) - if (ramdisk.size > 0) { - Common.writePaddedFile(bf, ramdisk.file!!, info.pageSize) - } - secondBootloader?.let { - Common.writePaddedFile(bf, secondBootloader!!.file!!, info.pageSize) - } - recoveryDtbo?.let { - Common.writePaddedFile(bf, recoveryDtbo!!.file!!, info.pageSize) - } - dtb?.let { - Common.writePaddedFile(bf, dtb!!.file!!, info.pageSize) - } - bf + .let { bf -> + bf.order(ByteOrder.LITTLE_ENDIAN) + Common.writePaddedFile(bf, kernel.file!!, info.pageSize) + if (ramdisk.size > 0) { + Common.writePaddedFile(bf, ramdisk.file!!, info.pageSize) } + secondBootloader?.let { + Common.writePaddedFile(bf, secondBootloader!!.file!!, info.pageSize) + } + recoveryDtbo?.let { + Common.writePaddedFile(bf, recoveryDtbo!!.file!!, info.pageSize) + } + dtb?.let { + Common.writePaddedFile(bf, dtb!!.file!!, info.pageSize) + } + bf + } //write FileOutputStream("${info.output}.clear", true).use { fos -> fos.write(bytesV2.array(), 0, bytesV2.position()) @@ -404,8 +420,8 @@ data class BootV2( } private fun toCommandLine(): CommandLine { - val ret = CommandLine("python") - ret.addArgument(Helper.prop("mkbootimg")) + val cmdPrefix = if (EnvironmentVerifier().isWindows) "python " else "" + val ret = CommandLine(cmdPrefix + Helper.prop("mkbootimg")) ret.addArgument(" --header_version ") ret.addArgument(info.headerVersion.toString()) ret.addArgument(" --base ") diff --git a/bbootimg/src/main/kotlin/bootimg/v3/BootV3.kt b/bbootimg/src/main/kotlin/bootimg/v3/BootV3.kt index 6843c9b..a732e49 100644 --- a/bbootimg/src/main/kotlin/bootimg/v3/BootV3.kt +++ b/bbootimg/src/main/kotlin/bootimg/v3/BootV3.kt @@ -1,6 +1,7 @@ package cfig.bootimg.v3 import cfig.Avb +import cfig.EnvironmentVerifier import cfig.helper.Helper import cfig.bootimg.Common.Companion.deleleIfExists import cfig.bootimg.Common.Companion.getPaddingSize @@ -204,8 +205,8 @@ data class BootV3(var info: MiscInfo = MiscInfo(), } private fun toCommandLine(): CommandLine { - return CommandLine("python").let { ret -> - ret.addArgument(Helper.prop("mkbootimg")) + val cmdPrefix = if (EnvironmentVerifier().isWindows) "python " else "" + return CommandLine(cmdPrefix + Helper.prop("mkbootimg")).let { ret -> ret.addArgument("--header_version") ret.addArgument(info.headerVersion.toString()) if (kernel.size > 0) { diff --git a/bbootimg/src/main/kotlin/helper/KeyHelper.kt b/bbootimg/src/main/kotlin/helper/KeyHelper.kt deleted file mode 100644 index 0e1bde0..0000000 --- a/bbootimg/src/main/kotlin/helper/KeyHelper.kt +++ /dev/null @@ -1,93 +0,0 @@ -package cfig.helper - -import cfig.io.Struct3 -import com.google.common.math.BigIntegerMath -import org.apache.commons.codec.binary.Hex -import org.bouncycastle.util.io.pem.PemReader -import org.slf4j.LoggerFactory -import java.io.ByteArrayInputStream -import java.io.InputStream -import java.io.InputStreamReader -import java.math.BigInteger -import java.math.RoundingMode -import java.security.Security - -class KeyHelper { - companion object { - private val log = LoggerFactory.getLogger(KeyHelper::class.java) - - @Throws(IllegalArgumentException::class) - fun parsePemPubkey(inputStream: InputStream): org.bouncycastle.asn1.pkcs.RSAPublicKey { - val p = PemReader(InputStreamReader(inputStream)).readPemObject() - if ("RSA PUBLIC KEY" != p.type) { - throw IllegalArgumentException("input is not valid 'RSA PUBLIC KEY'") - } - return org.bouncycastle.asn1.pkcs.RSAPublicKey.getInstance(p.content) - } - - @Throws(IllegalArgumentException::class) - fun parsePemPrivateKeyBC(inputStream: InputStream): org.bouncycastle.asn1.pkcs.RSAPrivateKey { - val p = PemReader(InputStreamReader(inputStream)).readPemObject() - if ("RSA PRIVATE KEY" != p.type) { - throw IllegalArgumentException("input is not valid 'RSA PRIVATE KEY'") - } - return org.bouncycastle.asn1.pkcs.RSAPrivateKey.getInstance(p.content) - } - -// fun parsePemPrivateKey(inputStream: InputStream): java.security.PrivateKey { -// val rsa = BC.parsePemPrivateKeyBC(inputStream) -// return generateRsaPrivateKey(rsa.modulus, rsa.privateExponent) -// } - - - /* - read RSA private key - assert exp == 65537 - num_bits = log2(modulus) - - @return: AvbRSAPublicKeyHeader formatted bytearray - https://android.googlesource.com/platform/external/avb/+/master/libavb/avb_crypto.h#158 - from avbtool::encode_rsa_key() - */ - fun encodeRSAkey(key: ByteArray): ByteArray { - val rsa = parsePemPrivateKeyBC(ByteArrayInputStream(key)) - assert(65537.toBigInteger() == rsa.publicExponent) - val numBits: Int = BigIntegerMath.log2(rsa.modulus, RoundingMode.CEILING) - log.debug("modulus: " + rsa.modulus) - log.debug("numBits: $numBits") - val b = BigInteger.valueOf(2).pow(32) - val n0inv = (b - rsa.modulus.modInverse(b)).toLong() - log.debug("n0inv = $n0inv") - val r = BigInteger.valueOf(2).pow(numBits) - val rrModn = (r * r).mod(rsa.modulus) - log.debug("BB: " + numBits / 8 + ", mod_len: " + rsa.modulus.toByteArray().size + ", rrmodn = " + rrModn.toByteArray().size) - val unsignedModulo = rsa.modulus.toByteArray().sliceArray(1..numBits / 8) //remove sign byte - log.debug("unsigned modulo: " + Hex.encodeHexString(unsignedModulo)) - val ret = Struct3("!II${numBits / 8}b${numBits / 8}b").pack( - numBits, - n0inv, - unsignedModulo, - rrModn.toByteArray()) - log.debug("rrmodn: " + Hex.encodeHexString(rrModn.toByteArray())) - log.debug("RSA: " + Hex.encodeHexString(ret)) - return ret - } - - fun listAll() { - Security.getProviders().forEach { - val sb = StringBuilder("Provider: " + it.name + "{") - it.stringPropertyNames().forEach { key -> - sb.append(" (k=" + key + ",v=" + it.getProperty(key) + "), ") - } - sb.append("}") - log.info(sb.toString()) - } - - var i = 0 - for (item in Security.getAlgorithms("Cipher")) { - log.info("Cipher: $i -> $item") - i++ - } - } - } -} diff --git a/bbootimg/src/main/kotlin/kernel_util/KernelExtractor.kt b/bbootimg/src/main/kotlin/kernel_util/KernelExtractor.kt index 218c770..75efd5b 100644 --- a/bbootimg/src/main/kotlin/kernel_util/KernelExtractor.kt +++ b/bbootimg/src/main/kotlin/kernel_util/KernelExtractor.kt @@ -20,8 +20,8 @@ class KernelExtractor { val ret: MutableList = mutableListOf() val kernelVersionFile = Helper.prop("kernelVersionFile") val kernelConfigFile = Helper.prop("kernelConfigFile") - val cmd = CommandLine.parse("python").let { - it.addArgument(Helper.prop("kernelExtracter")) + val cmdPrefix = if (EnvironmentVerifier().isWindows) "python " else "" + val cmd = CommandLine.parse(cmdPrefix + Helper.prop("kernelExtracter")).let { it.addArgument("--input") it.addArgument(fileName) it.addArgument("--output-configs") diff --git a/bbootimg/src/main/kotlin/packable/BootImgParser.kt b/bbootimg/src/main/kotlin/packable/BootImgParser.kt index 1cd8385..895c3bc 100644 --- a/bbootimg/src/main/kotlin/packable/BootImgParser.kt +++ b/bbootimg/src/main/kotlin/packable/BootImgParser.kt @@ -29,18 +29,18 @@ class BootImgParser() : IPackable { log.info("header version $hv") if (hv == 3) { val b3 = BootV3 - .parse(fileName) - .extractImages() - .extractVBMeta() - .printSummary() + .parse(fileName) + .extractImages() + .extractVBMeta() + .printSummary() log.debug(b3.toString()) return } else { val b2 = BootV2 - .parse(fileName) - .extractImages() - .extractVBMeta() - .printSummary() + .parse(fileName) + .extractImages() + .extractVBMeta() + .printSummary() log.debug(b2.toString()) } } catch (e: IllegalArgumentException) { @@ -54,15 +54,14 @@ class BootImgParser() : IPackable { log.info("Loading config from $cfgFile") if (3 == probeHeaderVersion(fileName)) { ObjectMapper().readValue(File(cfgFile), BootV3::class.java) - .pack() - .sign(fileName) - updateVbmeta(fileName) + .pack() + .sign(fileName) } else { ObjectMapper().readValue(File(cfgFile), BootV2::class.java) - .pack() - .sign() - updateVbmeta(fileName) + .pack() + .sign() } + Avb.updateVbmeta(fileName) } override fun flash(fileName: String, deviceName: String) { @@ -93,34 +92,5 @@ class BootImgParser() : IPackable { companion object { private val log = LoggerFactory.getLogger(BootImgParser::class.java) - - fun updateVbmeta(fileName: String) { - if (File("vbmeta.img").exists()) { - log.info("Updating vbmeta.img side by side ...") - val partitionName = ObjectMapper().readValue(File(Avb.getJsonFileName(fileName)), AVBInfo::class.java).let { - it.auxBlob!!.hashDescriptors.get(0).partition_name - } - val newHashDesc = Avb().parseVbMeta("$fileName.signed", dumpFile = false) - assert(newHashDesc.auxBlob!!.hashDescriptors.size == 1) - val mainVBMeta = ObjectMapper().readValue(File(Avb.getJsonFileName("vbmeta.img")), AVBInfo::class.java).apply { - val itr = this.auxBlob!!.hashDescriptors.iterator() - var seq = 0 - while (itr.hasNext()) { - val itrValue = itr.next() - if (itrValue.partition_name == partitionName) { - log.info("Found $partitionName in vbmeta, update it") - seq = itrValue.sequence - itr.remove() - break - } - } - val hd = newHashDesc.auxBlob!!.hashDescriptors.get(0).apply { this.sequence = seq } - this.auxBlob!!.hashDescriptors.add(hd) - } - Avb().packVbMetaWithPadding("vbmeta.img", mainVBMeta) - } else { - log.info("no companion vbmeta.img") - } - } } } diff --git a/bbootimg/src/main/kotlin/packable/VendorBootParser.kt b/bbootimg/src/main/kotlin/packable/VendorBootParser.kt index 2f50387..fea0cbf 100644 --- a/bbootimg/src/main/kotlin/packable/VendorBootParser.kt +++ b/bbootimg/src/main/kotlin/packable/VendorBootParser.kt @@ -1,8 +1,8 @@ package cfig.packable +import cfig.Avb import cfig.helper.Helper import cfig.bootimg.v3.VendorBoot -import cfig.packable.BootImgParser.Companion.updateVbmeta import com.fasterxml.jackson.databind.ObjectMapper import org.slf4j.LoggerFactory import java.io.File @@ -31,6 +31,19 @@ class VendorBootParser : IPackable { ObjectMapper().readValue(File(cfgFile), VendorBoot::class.java) .pack() .sign() - updateVbmeta(fileName) + Avb.updateVbmeta(fileName) + } + + override fun pull(fileName: String, deviceName: String) { + super.pull(fileName, deviceName) + } + + override fun flash(fileName: String, deviceName: String) { + val stem = fileName.substring(0, fileName.indexOf(".")) + super.flash("$fileName.signed", stem) + + if (File("vbmeta.img.signed").exists()) { + super.flash("vbmeta.img.signed", "vbmeta") + } } } diff --git a/bbootimg/src/test/kotlin/HelperTest.kt b/bbootimg/src/test/kotlin/HelperTest.kt deleted file mode 100644 index aeec057..0000000 --- a/bbootimg/src/test/kotlin/HelperTest.kt +++ /dev/null @@ -1,126 +0,0 @@ -import avb.alg.Algorithms -import cfig.KeyUtil -import cfig.helper.KeyHelper2 -import com.google.common.math.BigIntegerMath -import org.apache.commons.codec.binary.Hex -import org.bouncycastle.jce.provider.BouncyCastleProvider -import org.junit.Assert.assertEquals -import org.junit.Test -import org.slf4j.LoggerFactory -import java.math.BigInteger -import java.math.RoundingMode -import java.nio.file.Files -import java.nio.file.Paths -import java.security.KeyFactory -import java.security.KeyPairGenerator -import java.security.Security -import java.security.Signature -import java.security.spec.PKCS8EncodedKeySpec -import java.security.spec.X509EncodedKeySpec -import javax.crypto.Cipher - - -@OptIn(ExperimentalUnsignedTypes::class) -class HelperTest { - private val log = LoggerFactory.getLogger(HelperTest::class.java) - - @Test - fun rawSignTest() { - val data = Hex.decodeHex("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d0609608648016503040201050004206317a4c8d86accc8258c1ac23ef0ebd18bc33010d7afb43b241802646360b4ab") - val expectedSig = "28e17bc57406650ed78785fd558e7c1861cc4014c900d72b61c03cdbab1039e713b5bb19b556d04d276b46aae9b8a3999ccbac533a1cce00f83cfb83e2beb35ed7329f71ffec04fc2839a9b44e50abd66ea6c3d3bea6705e93e9139ecd0331170db18eba36a85a78bc49a5447260a30ed19d956cb2f8a71f6b19e57fdca43e052d1bb7840bf4c3efb47111f4d77764236d2e013fbf3b2577e4a3e01c9d166a5e890ef96210882e6e88ceca2fe3a2201f4961210d4ec6167f5dfd0e038e4a146f960caecab7d15ba65f6edcf5dbd25f5af543cfb8da4338bdbc872eec3f8e72aa8db679099e70952d3f7176c0b9111bf20ad1390eab1d09a859105816fdf92fbb" - val privkFile = "../" + Algorithms.get("SHA256_RSA2048")!!.defaultKey.replace("pem", "pk8") - val k = KeyHelper2.parseRsaPk8(Files.readAllBytes(Paths.get(privkFile))) - val encData = KeyHelper2.rawSign(k, data) - assertEquals(expectedSig, Hex.encodeHexString(encData)) - } - - @Test - fun rawSignOpenSslTest() { - val data = Hex.decodeHex("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d0609608648016503040201050004206317a4c8d86accc8258c1ac23ef0ebd18bc33010d7afb43b241802646360b4ab") - val expectedSig = "28e17bc57406650ed78785fd558e7c1861cc4014c900d72b61c03cdbab1039e713b5bb19b556d04d276b46aae9b8a3999ccbac533a1cce00f83cfb83e2beb35ed7329f71ffec04fc2839a9b44e50abd66ea6c3d3bea6705e93e9139ecd0331170db18eba36a85a78bc49a5447260a30ed19d956cb2f8a71f6b19e57fdca43e052d1bb7840bf4c3efb47111f4d77764236d2e013fbf3b2577e4a3e01c9d166a5e890ef96210882e6e88ceca2fe3a2201f4961210d4ec6167f5dfd0e038e4a146f960caecab7d15ba65f6edcf5dbd25f5af543cfb8da4338bdbc872eec3f8e72aa8db679099e70952d3f7176c0b9111bf20ad1390eab1d09a859105816fdf92fbb" - val sig = KeyHelper2.rawSignOpenSsl("../" + Algorithms.get("SHA256_RSA2048")!!.defaultKey, data) - assertEquals(expectedSig, Hex.encodeHexString(sig)) - } - - @Test - fun test3() { - val data = Hex.decodeHex("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d0609608648016503040201050004206317a4c8d86accc8258c1ac23ef0ebd18bc3301033") - val signature = Signature.getInstance("NONEwithRSA") - val keyFile = "../" + Algorithms.get("SHA256_RSA2048")!!.defaultKey.replace("pem", "pk8") - val k = KeyUtil.parsePk8PrivateKey(Files.readAllBytes(Paths.get(keyFile))) - signature.initSign(k) - signature.update(data) - println("data size " + data.size) - println(signature.provider) - val sig = signature.sign() - println(sig) - } - - @Test - fun testCipher() { - Security.addProvider(BouncyCastleProvider()) - for (p in Security.getProviders()) { - println(p.toString()) - for (entry in p.entries) { - println("\t" + entry.key.toString() + " -> " + entry.value) - } - println() - } - } - - @Test - fun testKeys() { - val kp = KeyPairGenerator.getInstance("rsa") - .apply { this.initialize(2048) } - .generateKeyPair() - val pk8Spec = PKCS8EncodedKeySpec(kp.private.encoded) //kp.private.format == PKCS#8 - val x509Spec = X509EncodedKeySpec(kp.public.encoded) //kp.public.format == X.509 - - val kf = KeyFactory.getInstance("rsa") - val privk = kf.generatePrivate(pk8Spec) - val pubk = kf.generatePublic(x509Spec) - println(pubk) - - val cipher = Cipher.getInstance("RSA").apply { - this.init(Cipher.ENCRYPT_MODE, privk) - this.update("Good".toByteArray()) - } - val encryptedText = Hex.encodeHexString(cipher.doFinal()) - println(encryptedText) - } - - @Test - fun testRSA() { -// val r = BigIntegerMath.log2(BigInteger.valueOf(1024), RoundingMode.CEILING) -// println(r) -// println(BigInteger.valueOf(1024).mod(BigInteger.valueOf(2))) - - val p = BigInteger.valueOf(3) - val q = BigInteger.valueOf(7) - val modulus = p.multiply(q) - - val keyLength = BigIntegerMath.log2(modulus, RoundingMode.CEILING) - println("keyLength = $keyLength") - - //r = phi(n) = phi(p) * phi(q) = (p - 1)*(q - 1) - val r = (p.subtract(BigInteger.ONE)).multiply(q - BigInteger.ONE) - - //r ~ e - //e is released as the public key exponent - //most commonly e = 2^16 + 1 = 65,537 - val e = BigInteger.valueOf(5) - - //(d * e).mod(r) == 1 - //d is kept as the private key exponent - val d = e.modInverse(r) - - println("p = $p, q = $q, modulus = $modulus , r = $r, e = $e, d = $d") - assertEquals(1, d.multiply(e).mod(r).toInt()) - //private key: (modulus, d), d is calculated - //pub key: (modulus, e) , e is chosen - - val clearMsg = BigInteger.valueOf(10) - val encMsg = clearMsg.pow(e.toInt()).mod(modulus) - println("clear: $clearMsg, enc: $encMsg") - } -} diff --git a/bbootimg/src/test/kotlin/KeyUtilTest.kt b/bbootimg/src/test/kotlin/KeyUtilTest.kt index d37440d..8db5d18 100644 --- a/bbootimg/src/test/kotlin/KeyUtilTest.kt +++ b/bbootimg/src/test/kotlin/KeyUtilTest.kt @@ -1,22 +1,193 @@ import avb.alg.Algorithms -import cfig.KeyUtil -import org.apache.commons.codec.binary.Hex -import org.junit.Assert.* +import cfig.helper.Helper +import cfig.helper.KeyHelper +import cfig.helper.KeyHelper2 +import com.google.common.math.BigIntegerMath +import org.bouncycastle.jce.provider.BouncyCastleProvider +import org.junit.Assert.assertEquals import org.junit.Test -import java.io.FileInputStream +import java.io.File +import java.math.BigInteger +import java.math.RoundingMode import java.nio.file.Files import java.nio.file.Paths +import java.security.* +import java.security.interfaces.RSAPrivateKey +import java.security.spec.PKCS8EncodedKeySpec +import java.security.spec.X509EncodedKeySpec +import javax.crypto.Cipher @OptIn(ExperimentalUnsignedTypes::class) class KeyUtilTest { @Test fun parseKeys() { val keyFile = "../" + Algorithms.get("SHA256_RSA2048")!!.defaultKey - val k = KeyUtil.parsePk8PrivateKey(Files.readAllBytes(Paths.get(keyFile.replace("pem", "pk8")))) + println("Key: $keyFile") + val k = KeyHelper.parse(File(keyFile.replace("pem", "pk8")).readBytes()) as RSAPrivateKey + println(k.privateExponent) + println(k.modulus) + val k2 = KeyHelper.parse(File(keyFile).readBytes()) as org.bouncycastle.asn1.pkcs.RSAPrivateKey + println(k2.privateExponent) + println(k2.modulus) + //KeyHelper2.parseRsaPk8(FileInputStream(keyFile).readAllBytes()) + KeyHelper.parse(File(keyFile.replace("pem", "pk8")).readBytes()) + } + + @Test + fun x1() { + val p = BigInteger.valueOf(61L) + val q = BigInteger.valueOf(53L) + val modulus = p * q + println(modulus) + val exponent = 17 + val x = calcPrivateKey(p, q, exponent) + println(x) + //private key: modulus, x + //public key: modulus, exponent + + val data = 123L + val encryptedData = enc(data, exponent, modulus) + println("enc2 = " + encryptedData) + val decryptedData = dec(encryptedData, x, modulus) + println("dec2 data = " + decryptedData) + } + + fun calcPrivateKey(p: BigInteger, q: BigInteger, exponent: Int): Int { + val modulus = p * q + val phi = (p - BigInteger.ONE) * (q - BigInteger.ONE) + return BigInteger.valueOf(exponent.toLong()).modInverse(phi).toInt() + } + + //data^{exp} + fun enc(data: Long, exponent: Int, modulus: BigInteger): Long { + return BigInteger.valueOf(data).pow(exponent).rem(modulus).toLong() + } + + //data^{privateKey} + fun dec(data: Long, privateKey: Int, modulus: BigInteger): Long { + return BigInteger.valueOf(data).pow(privateKey).rem(modulus).toLong() + } + + @Test + fun rawSignTest() { + val data = + Helper.fromHexString("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d0609608648016503040201050004206317a4c8d86accc8258c1ac23ef0ebd18bc33010d7afb43b241802646360b4ab") + val expectedSig = + "28e17bc57406650ed78785fd558e7c1861cc4014c900d72b61c03cdbab1039e713b5bb19b556d04d276b46aae9b8a3999ccbac533a1cce00f83cfb83e2beb35ed7329f71ffec04fc2839a9b44e50abd66ea6c3d3bea6705e93e9139ecd0331170db18eba36a85a78bc49a5447260a30ed19d956cb2f8a71f6b19e57fdca43e052d1bb7840bf4c3efb47111f4d77764236d2e013fbf3b2577e4a3e01c9d166a5e890ef96210882e6e88ceca2fe3a2201f4961210d4ec6167f5dfd0e038e4a146f960caecab7d15ba65f6edcf5dbd25f5af543cfb8da4338bdbc872eec3f8e72aa8db679099e70952d3f7176c0b9111bf20ad1390eab1d09a859105816fdf92fbb" + val privkFile = "../" + Algorithms.get("SHA256_RSA2048")!!.defaultKey.replace("pem", "pk8") + val k = KeyHelper.parse(Files.readAllBytes(Paths.get(privkFile))) as PrivateKey + val encData = KeyHelper2.rawSign(k, data) + assertEquals(expectedSig, Helper.toHexString(encData)) + } + + @Test + fun rawSignOpenSslTest() { + val data = + Helper.fromHexString("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d0609608648016503040201050004206317a4c8d86accc8258c1ac23ef0ebd18bc33010d7afb43b241802646360b4ab") + val expectedSig = + "28e17bc57406650ed78785fd558e7c1861cc4014c900d72b61c03cdbab1039e713b5bb19b556d04d276b46aae9b8a3999ccbac533a1cce00f83cfb83e2beb35ed7329f71ffec04fc2839a9b44e50abd66ea6c3d3bea6705e93e9139ecd0331170db18eba36a85a78bc49a5447260a30ed19d956cb2f8a71f6b19e57fdca43e052d1bb7840bf4c3efb47111f4d77764236d2e013fbf3b2577e4a3e01c9d166a5e890ef96210882e6e88ceca2fe3a2201f4961210d4ec6167f5dfd0e038e4a146f960caecab7d15ba65f6edcf5dbd25f5af543cfb8da4338bdbc872eec3f8e72aa8db679099e70952d3f7176c0b9111bf20ad1390eab1d09a859105816fdf92fbb" + val sig = KeyHelper2.rawSignOpenSsl("../" + Algorithms.get("SHA256_RSA2048")!!.defaultKey, data) + assertEquals(expectedSig, Helper.toHexString(sig)) + } + + @Test + fun test3() { + val data = + Helper.fromHexString("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d0609608648016503040201050004206317a4c8d86accc8258c1ac23ef0ebd18bc3301033") + val signature = Signature.getInstance("NONEwithRSA") + val keyFile = "../" + Algorithms.get("SHA256_RSA2048")!!.defaultKey.replace("pem", "pk8") + val k = KeyHelper.parse(Files.readAllBytes(Paths.get(keyFile))) as PrivateKey + signature.initSign(k) + signature.update(data) + println("data size " + data.size) + println(signature.provider) + val sig = signature.sign() + println(sig) + } + + @Test + fun testCipher() { + Security.addProvider(BouncyCastleProvider()) + for (p in Security.getProviders()) { + println(p.toString()) + for (entry in p.entries) { + println("\t" + entry.key.toString() + " -> " + entry.value) + } + println() + } + } + + @Test + fun testKeys() { + val kp = KeyPairGenerator.getInstance("rsa") + .apply { this.initialize(2048) } + .generateKeyPair() + val pk8Spec = PKCS8EncodedKeySpec(kp.private.encoded) //kp.private.format == PKCS#8 + val x509Spec = X509EncodedKeySpec(kp.public.encoded) //kp.public.format == X.509 + val kf = KeyFactory.getInstance("rsa") + val privk = kf.generatePrivate(pk8Spec) + val pubk = kf.generatePublic(x509Spec) + println(pubk) - val k2 = KeyUtil.parsePemPrivateKey2(FileInputStream(keyFile)) - println(Hex.encodeHexString(k.encoded)) - println(Hex.encodeHexString(k2.encoded)) + val cipher = Cipher.getInstance("RSA").apply { + this.init(Cipher.ENCRYPT_MODE, privk) + this.update("Good".toByteArray()) + } + val encryptedText = Helper.toHexString(cipher.doFinal()) + println(encryptedText) + } + + @Test + fun testRSA() { +// val r = BigIntegerMath.log2(BigInteger.valueOf(1024), RoundingMode.CEILING) +// println(r) +// println(BigInteger.valueOf(1024).mod(BigInteger.valueOf(2))) + + val p = BigInteger.valueOf(3) + val q = BigInteger.valueOf(7) + val modulus = p.multiply(q) + + val keyLength = BigIntegerMath.log2(modulus, RoundingMode.CEILING) + println("keyLength = $keyLength") + + //r = phi(n) = phi(p) * phi(q) = (p - 1)*(q - 1) + val r = (p.subtract(BigInteger.ONE)).multiply(q - BigInteger.ONE) + + //r ~ e + //e is released as the public key exponent + //most commonly e = 2^16 + 1 = 65,537 + val e = BigInteger.valueOf(5) + + //(d * e).mod(r) == 1 + //d is kept as the private key exponent + val d = e.modInverse(r) + + println("p = $p, q = $q, modulus = $modulus , r = $r, e = $e, d = $d") + assertEquals(1, d.multiply(e).mod(r).toInt()) + //private key: (modulus, d), d is calculated + //pub key: (modulus, e) , e is chosen + + val clearMsg = BigInteger.valueOf(10) + val encMsg = clearMsg.pow(e.toInt()).mod(modulus) + println("clear: $clearMsg, enc: $encMsg") + } + + @Test + fun listAll() { + KeyHelper.listAll() + } + + @Test + fun signData() { + val data = KeyUtilTest::class.java.classLoader.getResourceAsStream("data").readAllBytes() + println(Helper.toHexString(data)) + val privKey = KeyHelper.parse( + KeyUtilTest::class.java.classLoader.getResourceAsStream("testkey.pk8").readAllBytes() + ) as PrivateKey + println("sha256=" + Helper.toHexString(KeyHelper2.sha256(data))) + val signedHash = KeyHelper2.sha256rsa(data, privKey) + println("Signed Hash: " + Helper.toHexString(signedHash)) } } + diff --git a/bbootimg/src/test/kotlin/avb/BlobTest.kt b/bbootimg/src/test/kotlin/avb/BlobTest.kt index b508bb7..3740a7a 100644 --- a/bbootimg/src/test/kotlin/avb/BlobTest.kt +++ b/bbootimg/src/test/kotlin/avb/BlobTest.kt @@ -2,33 +2,50 @@ package avb import avb.alg.Algorithms import avb.blob.AuxBlob +import cfig.helper.Helper +import cfig.helper.KeyHelper import org.apache.commons.codec.binary.Hex +import org.bouncycastle.asn1.pkcs.RSAPrivateKey import org.junit.Assert.assertEquals import org.junit.Test +import java.io.ByteArrayInputStream @OptIn(ExperimentalUnsignedTypes::class) class BlobTest { @Test fun testEncodedKey2048() { - val keyStr = "2d2d2d2d2d424547494e205253412050524956415445204b45592d2d2d2d2d0a4d4949456f77494241414b4341514541786c56523354496b6f75414f7648373976614a54674668706676564b514965566b46525a5056584b2f7a5930477672680a344a4171476a4a6f572f50667251763573644433367174484833612b4735684c5a364e692b742f6d74666a7563785a66754c4743336b6d4a3154335871454b5a0a67585849324952377656536f496d5245764451474544794a7774487a4c414e6c6b624767306367685668575a5343416e644f3842656e616c43327639342f72740a44666b50656b48366467553353663430543073425365535939346d4f7a5461714f52327066563172576c4c5264576d6f33337a654842763532526c627430644d0a755841757265585769487a746b6d35474342433164674d2b4361784e74697a4e45674339314b63443078755243434d325778482b72316c70737a79494a4463740a596272466d5645596c2f6b6a517061666879374e736b316671535479526472695a53596d5451494441514142416f49424151432b6b4a6761437558387759416e0a5358575130666d645a6c586e4d4e5270634630613070443053417a47623152645942584d615869717479686977633533505078734344644e65636a6179494d640a6a4a56585054774c685472754f674d532f6270336763675777563334554856344c4a58474f4741452b6a625330686244424d6975644f596d6a36526d567368700a7a3947317a5a4353514e4d584861577345596b58353958707a7a6f423338346e52756c3251674574777a554e5239586c707a67744a424c6b335341436b76734e0a6d512f445738495748584c6738764c6e314c7a564a32653342313648344d6f45325443487871664d67723033494452524a6f676b656e517551734668657659540a6f2f6d4a79485357617656677a4d48473949356d2b65657046345779686a31593457794b41754d492b39644841582f68374c74385846435143683544626b56470a7a47723334735742416f4742414f73376e37595a714e616167756f7666496452527378785a7231794a41794473723677337947496d445a596a753463345759390a3565734f326b50334641347030633746685146356f4f623172427548455070333663704c346147654b38376361715466713633575a41756a6f545a7072394c700a4252626b4c37772f7847376a70512f636c70413873487a484751732f6e656c786f4f744337453131384669526776442f6a64686c4d794c39416f4742414e66580a76796f4e3170706c665432785238514f6a535a2b513335532f2b5341744d75426e4878336c307148326262426a63764d314d4e44576a6e5244796159686952750a692b4b4137747166696230392b58704233673544364f76376c732f4c647830532f56636d565774696132484b387938694c47746f6b6f425a4b513541614658320a695155382b744334683639476e4a59514b714e776743557a68382b674858355934366f4469546d52416f474159704f78386c582b637a42382f4461364d4e72570a6d495a4e543861745a4c4573447332414e455652784453496354435a4a4964372b6d31572b6e526f6179634c54574e6f775a312b3245724c765231302b4147590a62375973373957673969645961593979476e396c6e5a734d7a4169754c6579497658635371676a76414b6c565772684f51464f756768764e5776466c383559790a6f5753434d6c5069544c747437434373434b73674b7545436759426764497036475a7349666b67636c4b653068716776526f65553454523367636a4a6c4d39410a6c42546f2b704b686142656374706c783952785238416e73506f626271776361486e496641754b447a6a6b356d45764b5a6a436c6e46584634484148627941460a6e527a5a457939586b57466863383054357252705a4f3743377164786d753261694b69784d3356334c332f3055353871554c4544627562484d773962456841540a5075644938514b4267484545694d6d2f687239543431686251692f4c59616e576e6c46773175652b6f734b75463862585175786e6e484e7546542f632b392f410a76576867714736624f4548752b702f495072596d3474424d596c77737968346e5843794767444a4c624c49667a4b774b4157437448394c776e794456684f6f770a474839736864522b7357334577393778656630324b414834566c4e414e456d42563473514e7157577673597263466d32724f644c0a2d2d2d2d2d454e44205253412050524956415445204b45592d2d2d2d2d0a" - val encodedKey = AuxBlob.encodePubKey(Algorithms.get("SHA512_RSA2048")!!, Hex.decodeHex(keyStr)) - val expectedKeyEnc = "00000800c9d87d7bc65551dd3224a2e00ebc7efdbda2538058697ef54a4087959054593d55caff36341afae1e0902a1a32685bf3dfad0bf9b1d0f7eaab471f76be1b984b67a362fadfe6b5f8ee73165fb8b182de4989d53dd7a842998175c8d8847bbd54a8226444bc3406103c89c2d1f32c036591b1a0d1c82156159948202774ef017a76a50b6bfde3faed0df90f7a41fa76053749fe344f4b0149e498f7898ecd36aa391da97d5d6b5a52d17569a8df7cde1c1bf9d9195bb7474cb9702eade5d6887ced926e460810b576033e09ac4db62ccd1200bdd4a703d31b910823365b11feaf5969b33c8824372d61bac599511897f92342969f872ecdb24d5fa924f245dae26526264d1efa3b53abc5d379532f66b82194669a936f3526438c8f96b9ffaccdf4006ebeb673548450854653d5dd43feb26a784079569f86f3d3813b3d409035329a517ff8c34bc7d6a1ca30fb1bfd270ab8644134c117dea1769aebcf0c50d913f50d0b2c9924cbb5b4f8c60ad026b15bfd4d44669db076aa799dc05c3b9436c18ffec9d25a6aa046e1a28b2f516151a3369183b4fbcda9403446988a1a91dfd92c3abf573a464620f2f0bc315e29fe5890325c6697999a8e1523eba947d363c618bb8ed2209f78af71b32e0889a1f17db130a0e61bbd6ec8f633e1dab0bd1641fe076f6e978b6a33d2d780036a4de70582281fef6aa9757ee14ee2955b4fe6dc03b981" - assertEquals(expectedKeyEnc, Hex.encodeHexString(encodedKey)) + val keyStr = + "2d2d2d2d2d424547494e205253412050524956415445204b45592d2d2d2d2d0a4d4949456f77494241414b4341514541786c56523354496b6f75414f7648373976614a54674668706676564b514965566b46525a5056584b2f7a5930477672680a344a4171476a4a6f572f50667251763573644433367174484833612b4735684c5a364e692b742f6d74666a7563785a66754c4743336b6d4a3154335871454b5a0a67585849324952377656536f496d5245764451474544794a7774487a4c414e6c6b624767306367685668575a5343416e644f3842656e616c43327639342f72740a44666b50656b48366467553353663430543073425365535939346d4f7a5461714f52327066563172576c4c5264576d6f33337a654842763532526c627430644d0a755841757265585769487a746b6d35474342433164674d2b4361784e74697a4e45674339314b63443078755243434d325778482b72316c70737a79494a4463740a596272466d5645596c2f6b6a517061666879374e736b316671535479526472695a53596d5451494441514142416f49424151432b6b4a6761437558387759416e0a5358575130666d645a6c586e4d4e5270634630613070443053417a47623152645942584d615869717479686977633533505078734344644e65636a6179494d640a6a4a56585054774c685472754f674d532f6270336763675777563334554856344c4a58474f4741452b6a625330686244424d6975644f596d6a36526d567368700a7a3947317a5a4353514e4d584861577345596b58353958707a7a6f423338346e52756c3251674574777a554e5239586c707a67744a424c6b335341436b76734e0a6d512f445738495748584c6738764c6e314c7a564a32653342313648344d6f45325443487871664d67723033494452524a6f676b656e517551734668657659540a6f2f6d4a79485357617656677a4d48473949356d2b65657046345779686a31593457794b41754d492b39644841582f68374c74385846435143683544626b56470a7a47723334735742416f4742414f73376e37595a714e616167756f7666496452527378785a7231794a41794473723677337947496d445a596a753463345759390a3565734f326b50334641347030633746685146356f4f623172427548455070333663704c346147654b38376361715466713633575a41756a6f545a7072394c700a4252626b4c37772f7847376a70512f636c70413873487a484751732f6e656c786f4f744337453131384669526776442f6a64686c4d794c39416f4742414e66580a76796f4e3170706c665432785238514f6a535a2b513335532f2b5341744d75426e4878336c307148326262426a63764d314d4e44576a6e5244796159686952750a692b4b4137747166696230392b58704233673544364f76376c732f4c647830532f56636d565774696132484b387938694c47746f6b6f425a4b513541614658320a695155382b744334683639476e4a59514b714e776743557a68382b674858355934366f4469546d52416f474159704f78386c582b637a42382f4461364d4e72570a6d495a4e543861745a4c4573447332414e455652784453496354435a4a4964372b6d31572b6e526f6179634c54574e6f775a312b3245724c765231302b4147590a62375973373957673969645961593979476e396c6e5a734d7a4169754c6579497658635371676a76414b6c565772684f51464f756768764e5776466c383559790a6f5753434d6c5069544c747437434373434b73674b7545436759426764497036475a7349666b67636c4b653068716776526f65553454523367636a4a6c4d39410a6c42546f2b704b686142656374706c783952785238416e73506f626271776361486e496641754b447a6a6b356d45764b5a6a436c6e46584634484148627941460a6e527a5a457939586b57466863383054357252705a4f3743377164786d753261694b69784d3356334c332f3055353871554c4544627562484d773962456841540a5075644938514b4267484545694d6d2f687239543431686251692f4c59616e576e6c46773175652b6f734b75463862585175786e6e484e7546542f632b392f410a76576867714736624f4548752b702f495072596d3474424d596c77737968346e5843794767444a4c624c49667a4b774b4157437448394c776e794456684f6f770a474839736864522b7357334577393778656630324b414834566c4e414e456d42563473514e7157577673597263466d32724f644c0a2d2d2d2d2d454e44205253412050524956415445204b45592d2d2d2d2d0a" + val encodedKey = AuxBlob.encodePubKey(Algorithms.get("SHA512_RSA2048")!!, Helper.fromHexString(keyStr)) + val expectedKeyEnc = + "00000800c9d87d7bc65551dd3224a2e00ebc7efdbda2538058697ef54a4087959054593d55caff36341afae1e0902a1a32685bf3dfad0bf9b1d0f7eaab471f76be1b984b67a362fadfe6b5f8ee73165fb8b182de4989d53dd7a842998175c8d8847bbd54a8226444bc3406103c89c2d1f32c036591b1a0d1c82156159948202774ef017a76a50b6bfde3faed0df90f7a41fa76053749fe344f4b0149e498f7898ecd36aa391da97d5d6b5a52d17569a8df7cde1c1bf9d9195bb7474cb9702eade5d6887ced926e460810b576033e09ac4db62ccd1200bdd4a703d31b910823365b11feaf5969b33c8824372d61bac599511897f92342969f872ecdb24d5fa924f245dae26526264d1efa3b53abc5d379532f66b82194669a936f3526438c8f96b9ffaccdf4006ebeb673548450854653d5dd43feb26a784079569f86f3d3813b3d409035329a517ff8c34bc7d6a1ca30fb1bfd270ab8644134c117dea1769aebcf0c50d913f50d0b2c9924cbb5b4f8c60ad026b15bfd4d44669db076aa799dc05c3b9436c18ffec9d25a6aa046e1a28b2f516151a3369183b4fbcda9403446988a1a91dfd92c3abf573a464620f2f0bc315e29fe5890325c6697999a8e1523eba947d363c618bb8ed2209f78af71b32e0889a1f17db130a0e61bbd6ec8f633e1dab0bd1641fe076f6e978b6a33d2d780036a4de70582281fef6aa9757ee14ee2955b4fe6dc03b981" + assertEquals(expectedKeyEnc, Helper.toHexString(encodedKey)) + run {//decode pub key and check + val decodedKey = KeyHelper.decodeRSAkey(encodedKey) + //val rsa = KeyHelper.parsePemPrivateKeyBC(ByteArrayInputStream(Helper.fromHexString(keyStr))) //BC RSA + val rsa = KeyHelper.parse(Helper.fromHexString(keyStr)) as RSAPrivateKey //BC RSA + assert(rsa.modulus.equals(decodedKey.modulus)) + assert(rsa.publicExponent.equals(decodedKey.publicExponent)) + } } @Test fun testEncodeKey4096() { - val keyStr = "2d2d2d2d2d424547494e205253412050524956415445204b45592d2d2d2d2d0a4d49494a4b51494241414b43416745413241537634394f456248344e695433436a4e4d5356656c697966455058737757637174456643786c53705331466973410a757762764577645454506c6b7553683647345359694e686e704350357030766353672f334f686975564b67562f724374724458614f36306e764b2f6f307938330a4e4e5a524b3278614a396557427139727549444b2b6a43307359577a546171717778593047726a6e782f7235435865726c355072524b3750494c7a77674248620a4977784863626c74316e74675234635756704f337769716173457742444444596b3466773757364c766a42623971617633594238525636506b5a4e65525036340a676766756563712f4d584e69574f504e784c7a434552326853722f2b4a333268396a576a587372635679382b384d6c64686d72347232616e37633234376146660a757075464774554a7270524f4f382f4c584d6c356750664d706b716f61746a544d52483539674a6a4b686f743052706d47785a42766233335463424b3553644a0a583339593479637435636c6d446c4934466a6a3746757454502b623936614a654a566e596555582f4130776d6f6742616a734a526f525835652f5263675a73590a527a58594c515870725138316442576a6a6f764d4a39703858655436424e4d4643376f36736b6c464c3066484455452f6c34424e5038473175334266707a65760a534349535253373144346553346f51422b5249504642556b7a6f6d5a37726e45463342774665712b786d7766597250304c5261482b315965526175754d7552650a6b6531545a6c36393761336d456a6b4e67386e6f6132777470653745576d61756a4a66584457784a782f58456b6a474c4365347a32716b33746b6b592b4135670a5263677a6b6538675678432b654332444a74624b59666b76344c38464d464a61456877417031334d664337466c59756a4f2f42444c6c3764414e7343417745410a41514b43416741576f4c38502f57736b746a755377623573592f764b74677a634848314172393432477379737554585044793638364c7046335238542f6a4e790a6e376b3255424169613878536f5743523642625275486556356f412b504c47654f704537516153666f6e422b79632b63793078334f7233737366714573752f710a746f47487037352f38445853365745304b303478393475317264433962397350727247426c57434c477a714d306b62754a667948586464336e32536f6641554f0a62355152536778442b327448557045726f4871486e574a436166344a30516567583435796b746c664f594e4b2f50484c44515856386c792f656a6333324d34590a5476376855744f4f4a54757138564367394f575a6d325a6f3151754d3958454a54504370356c332b6f35767a4f3679686b32676f7444764433324364412b336b0a744c4a525035344d31536e2b4958623167474b4e39724b4174474a62656e5749506c4e4f626851676b627747383951642b3572664d587369507631486c31744b0a2b7471776a4438322f48332f456c61614d6e77484370656f47537039354f626c416f426a7a6a4d50324b7362764b53644c384f2f7266316333754f77392b44460a6374683053413879335a7a493131674a746232514d475572436e79356e34735047476263337833384e644c6877626b504b5a7936304f69543467326b4e7064590a644969746d414d4c326f747474694634414a4d36417261506b3859567a6b504c546b736f4c33617a50427961356c496f444932483351765474537670586b58500a794b6368734453575962647166706c71432f5830446a70322f5a64386a704e3549362b3161536d70546d6277782f4a546c6c59314e383946525a4c4964786f680a326b38314c5069586845367552626a696f4a556c626e45574970593279324e32436c6d78706a68302f496358643158496d514b4341514541375a61692b796a6a0a387869743234614f395466336d5a4258426a5361446f646a43324b533179436341495870365337614830775a6970795a70516a7973337a614251794d525946470a625171496656416136696e5779446f6f6662414a484d7535425663484642505a765353355968446a6338585a3564715343787a497a396f70497141626d2b62340a6145562f3341334a6b6935447938792f356a323147414b3459346d71514f597a6e653762444769334879753034314d474d3471664963496b53354e31654857340a73445a4a68362b4b357475784e355458336e445a53706d396c754e48386d4c47674b415a313562314c715841744d3579636f4259394876303832737550506f6d0a4f2b72307962645258366e445348382b313179324b6950326b645649554843476b776c716772757835595a796a435a50774f764550687a536f4f532b764269460a555658413869646e784e4c6b31514b4341514541364d496968445358782b33353066577168512f3351633667412f74324331354a774a392b754657412b676a640a632f686e3548636d6e6d424a4e345230346e4c472f61553953517572383761346d6e432f4d70394a4941526a486c5a2f574e54345530734a79504556526735550a5a3956616a417563577769304a794a59434f31454d4d7936384a7038716c5472694b2f4c376e624438364a4a354153786a6f6a694e2f3070734b2f506b3630460a52722b73684b5069336a52513142446a447441784f666f346374662f6e4662554d34625930464e50514d50375765736f534b55304e42435252366430643274710a59666c4d6a495148782b4e373450356a4564534348545647516d2b646a3437705574336c4c504c576330625831472f47656b775850344e5573522f37304873690a6277786b4e6e4b325453477a6b743272634f6e757450313235724a753657705637534e727139726d37774b43415141664d524f636e625776694b48716e4450510a6864522f324b39554a54764568496e41534f5332555a5770692b733172657a394275536a69674f7834776261415a3474343450573743337579743834644866550a486b495162334935626738454e4d724a704b394e4e3333796b77757a6b44774d537746635a2b4763693937685375627a6f4d6c2f496b6569694e314d61704c340a47684c556773442b33554d564c2b593953796d4b383633374967796f434764694e44362f535873613853774c4a6f3356546a717834654b70583763766c53424c0a52725278633530546d775573416873643443446c39596e5341544c6a56764a4265596c664d32746246506159776c31615238762b50576b666e4b3065666d36300a66486b69333348456e47746542504b7547713476775659706e3662594777517a2b66363333352f4132444d665a484653706a56555248506352634862434d6c610a30635578416f4942415143323565594e6b4f3437386d6f2b62426245584a6c6b6f714c6d766a417947724e466f343846396c705648365930764e75576b584a4e0a5055674c556841753652596f746a47454e71473137727a387a742f505059394f6b325033734f783874303079316d496e2f686c445a58733535464d30664f4d750a505a616973634150733748447a76794f6d4461682b667a692b5a443848324d33445332572b5945306961654a6132765a4a5332743032573042475869444933330a495a44714d794c59767777506a4f6e53684a7964457a58494434784c6c30744e6a7a4c786f3347534e41376a59716c6d627456384358496337724d534c3657560a6b7449444b4b4a636e6d706e3354634b6558364d456a615349543832704e4f5333665933506d58754c2b434d7a6677382b75373745656371373866486154694c0a50354a474d393346366d7a693139455930746d496e55424d435774514c63454e416f494241514367304b614f6b6238543336717a5072746762666f75304532440a756664704c3175676d443465644f464b51423566444651684c6e534556534a71334b5567346b57735861705164734264366b4c6478532b4b364d51724c427a720a34746630633755434631417a576b3677584d45785a386d526232526b475a595142324464796846423354506d6e71394357384a43712b366b78672f776b5534730a764d344a587a676371566f53663432514a6c2b4239776165576867304254577830316c616c34647338384876454b6d4530696b354777694462723745764444770a453655625a745163496f535449495a4467597156466652324441686f3377584a52734f58683433336c454a3858376343447a726e674662516e6c4b7270774d4c0a58676d30534955632b4e6635706f4d4d3372664c464b3737742f6f6234772b355077524b636f536e69794178724864366277796b59413856757964760a2d2d2d2d2d454e44205253412050524956415445204b45592d2d2d2d2d0a" + val keyStr = + "2d2d2d2d2d424547494e205253412050524956415445204b45592d2d2d2d2d0a4d49494a4b51494241414b43416745413241537634394f456248344e695433436a4e4d5356656c697966455058737757637174456643786c53705331466973410a757762764577645454506c6b7553683647345359694e686e704350357030766353672f334f686975564b67562f724374724458614f36306e764b2f6f307938330a4e4e5a524b3278614a396557427139727549444b2b6a43307359577a546171717778593047726a6e782f7235435865726c355072524b3750494c7a77674248620a4977784863626c74316e74675234635756704f337769716173457742444444596b3466773757364c766a42623971617633594238525636506b5a4e65525036340a676766756563712f4d584e69574f504e784c7a434552326853722f2b4a333268396a576a587372635679382b384d6c64686d72347232616e37633234376146660a757075464774554a7270524f4f382f4c584d6c356750664d706b716f61746a544d52483539674a6a4b686f743052706d47785a42766233335463424b3553644a0a583339593479637435636c6d446c4934466a6a3746757454502b623936614a654a566e596555582f4130776d6f6742616a734a526f525835652f5263675a73590a527a58594c515870725138316442576a6a6f764d4a39703858655436424e4d4643376f36736b6c464c3066484455452f6c34424e5038473175334266707a65760a534349535253373144346553346f51422b5249504642556b7a6f6d5a37726e45463342774665712b786d7766597250304c5261482b315965526175754d7552650a6b6531545a6c36393761336d456a6b4e67386e6f6132777470653745576d61756a4a66584457784a782f58456b6a474c4365347a32716b33746b6b592b4135670a5263677a6b6538675678432b654332444a74624b59666b76344c38464d464a61456877417031334d664337466c59756a4f2f42444c6c3764414e7343417745410a41514b43416741576f4c38502f57736b746a755377623573592f764b74677a634848314172393432477379737554585044793638364c7046335238542f6a4e790a6e376b3255424169613878536f5743523642625275486556356f412b504c47654f704537516153666f6e422b79632b63793078334f7233737366714573752f710a746f47487037352f38445853365745304b303478393475317264433962397350727247426c57434c477a714d306b62754a667948586464336e32536f6641554f0a62355152536778442b327448557045726f4871486e574a436166344a30516567583435796b746c664f594e4b2f50484c44515856386c792f656a6333324d34590a5476376855744f4f4a54757138564367394f575a6d325a6f3151754d3958454a54504370356c332b6f35767a4f3679686b32676f7444764433324364412b336b0a744c4a525035344d31536e2b4958623167474b4e39724b4174474a62656e5749506c4e4f626851676b627747383951642b3572664d587369507631486c31744b0a2b7471776a4438322f48332f456c61614d6e77484370656f47537039354f626c416f426a7a6a4d50324b7362764b53644c384f2f7266316333754f77392b44460a6374683053413879335a7a493131674a746232514d475572436e79356e34735047476263337833384e644c6877626b504b5a7936304f69543467326b4e7064590a644969746d414d4c326f747474694634414a4d36417261506b3859567a6b504c546b736f4c33617a50427961356c496f444932483351765474537670586b58500a794b6368734453575962647166706c71432f5830446a70322f5a64386a704e3549362b3161536d70546d6277782f4a546c6c59314e383946525a4c4964786f680a326b38314c5069586845367552626a696f4a556c626e45574970593279324e32436c6d78706a68302f496358643158496d514b4341514541375a61692b796a6a0a387869743234614f395466336d5a4258426a5361446f646a43324b533179436341495870365337614830775a6970795a70516a7973337a614251794d525946470a625171496656416136696e5779446f6f6662414a484d7535425663484642505a765353355968446a6338585a3564715343787a497a396f70497141626d2b62340a6145562f3341334a6b6935447938792f356a323147414b3459346d71514f597a6e653762444769334879753034314d474d3471664963496b53354e31654857340a73445a4a68362b4b357475784e355458336e445a53706d396c754e48386d4c47674b415a313562314c715841744d3579636f4259394876303832737550506f6d0a4f2b72307962645258366e445348382b313179324b6950326b645649554843476b776c716772757835595a796a435a50774f764550687a536f4f532b764269460a555658413869646e784e4c6b31514b4341514541364d496968445358782b33353066577168512f3351633667412f74324331354a774a392b754657412b676a640a632f686e3548636d6e6d424a4e345230346e4c472f61553953517572383761346d6e432f4d70394a4941526a486c5a2f574e54345530734a79504556526735550a5a3956616a417563577769304a794a59434f31454d4d7936384a7038716c5472694b2f4c376e624438364a4a354153786a6f6a694e2f3070734b2f506b3630460a52722b73684b5069336a52513142446a447441784f666f346374662f6e4662554d34625930464e50514d50375765736f534b55304e42435252366430643274710a59666c4d6a495148782b4e373450356a4564534348545647516d2b646a3437705574336c4c504c576330625831472f47656b775850344e5573522f37304873690a6277786b4e6e4b325453477a6b743272634f6e757450313235724a753657705637534e727139726d37774b43415141664d524f636e625776694b48716e4450510a6864522f324b39554a54764568496e41534f5332555a5770692b733172657a394275536a69674f7834776261415a3474343450573743337579743834644866550a486b495162334935626738454e4d724a704b394e4e3333796b77757a6b44774d537746635a2b4763693937685375627a6f4d6c2f496b6569694e314d61704c340a47684c556773442b33554d564c2b593953796d4b383633374967796f434764694e44362f535873613853774c4a6f3356546a717834654b70583763766c53424c0a52725278633530546d775573416873643443446c39596e5341544c6a56764a4265596c664d32746246506159776c31615238762b50576b666e4b3065666d36300a66486b69333348456e47746542504b7547713476775659706e3662594777517a2b66363333352f4132444d665a484653706a56555248506352634862434d6c610a30635578416f4942415143323565594e6b4f3437386d6f2b62426245584a6c6b6f714c6d766a417947724e466f343846396c705648365930764e75576b584a4e0a5055674c556841753652596f746a47454e71473137727a387a742f505059394f6b325033734f783874303079316d496e2f686c445a58733535464d30664f4d750a505a616973634150733748447a76794f6d4461682b667a692b5a443848324d33445332572b5945306961654a6132765a4a5332743032573042475869444933330a495a44714d794c59767777506a4f6e53684a7964457a58494434784c6c30744e6a7a4c786f3347534e41376a59716c6d627456384358496337724d534c3657560a6b7449444b4b4a636e6d706e3354634b6558364d456a615349543832704e4f5333665933506d58754c2b434d7a6677382b75373745656371373866486154694c0a50354a474d393346366d7a693139455930746d496e55424d435774514c63454e416f494241514367304b614f6b6238543336717a5072746762666f75304532440a756664704c3175676d443465644f464b51423566444651684c6e534556534a71334b5567346b57735861705164734264366b4c6478532b4b364d51724c427a720a34746630633755434631417a576b3677584d45785a386d526232526b475a595142324464796846423354506d6e71394357384a43712b366b78672f776b5534730a764d344a587a676371566f53663432514a6c2b4239776165576867304254577830316c616c34647338384876454b6d4530696b354777694462723745764444770a453655625a745163496f535449495a4467597156466652324441686f3377584a52734f58683433336c454a3858376343447a726e674662516e6c4b7270774d4c0a58676d30534955632b4e6635706f4d4d3372664c464b3737742f6f6234772b355077524b636f536e69794178724864366277796b59413856757964760a2d2d2d2d2d454e44205253412050524956415445204b45592d2d2d2d2d0a" val encodedKey = AuxBlob.encodePubKey(Algorithms.get("SHA256_RSA4096")!!, Hex.decodeHex(keyStr)) - val expectedKeyEnc = "0000100055d904add804afe3d3846c7e0d893dc28cd31255e962c9f10f5ecc1672ab447c2c654a94b5162b00bb06ef1307534cf964b9287a1b849888d867a423f9a74bdc4a0ff73a18ae54a815feb0adac35da3bad27bcafe8d32f3734d6512b6c5a27d79606af6bb880cafa30b4b185b34daaaac316341ab8e7c7faf90977ab9793eb44aecf20bcf08011db230c4771b96dd67b604787165693b7c22a9ab04c010c30d89387f0ed6e8bbe305bf6a6afdd807c455e8f91935e44feb88207ee79cabf31736258e3cdc4bcc2111da14abffe277da1f635a35ecadc572f3ef0c95d866af8af66a7edcdb8eda15fba9b851ad509ae944e3bcfcb5cc97980f7cca64aa86ad8d33111f9f602632a1a2dd11a661b1641bdbdf74dc04ae527495f7f58e3272de5c9660e52381638fb16eb533fe6fde9a25e2559d87945ff034c26a2005a8ec251a115f97bf45c819b184735d82d05e9ad0f357415a38e8bcc27da7c5de4fa04d3050bba3ab249452f47c70d413f97804d3fc1b5bb705fa737af482212452ef50f8792e28401f9120f141524ce8999eeb9c417707015eabec66c1f62b3f42d1687fb561e45abae32e45e91ed53665ebdedade612390d83c9e86b6c2da5eec45a66ae8c97d70d6c49c7f5c492318b09ee33daa937b64918f80e6045c83391ef205710be782d8326d6ca61f92fe0bf0530525a121c00a75dcc7c2ec5958ba33bf0432e5edd00db0db33799a9cd9cb743f7354421c28271ab8daab44111ec1e8dfc1482924e836a0a6b355e5de95ccc8cde39d14a5b5f63a964e00acb0bb85a7cc30be6befe8b0f7d348e026674016cca76ac7c67082f3f1aa62c60b3ffda8db8120c007fcc50a15c64a1e25f3265c99cbed60a13873c2a45470cca4282fa8965e789b48ff71ee623a5d059377992d7ce3dfde3a10bcf6c85a065f35cc64a635f6e3a3a2a8b6ab62fbbf8b24b62bc1a912566e369ca60490bf68abe3e7653c27aa8041775f1f303621b85b2b0ef8015b6d44edf71acdb2a04d4b421ba655657e8fa84a27d130eafd79a582aa381848d09a06ac1bbd9f586acbd756109e68c3d77b2ed3020e4001d97e8bfc7001b21b116e741672eec38bce51bb4062331711c49cd764a76368da3898b4a7af487c8150f3739f66d8019ef5ca866ce1b167921dfd73130c421dd345bd21a2b3e5df7eaca058eb7cb492ea0e3f4a74819109c04a7f42874c86f63202b462426191dd12c316d5a29a206a6b241cc0a27960996ac476578685198d6d8a62da0cfece274f282e397d97ed4f80b70433db17b9780d6cbd719bc630bfd4d88fe67acb8cc50b768b35bd61e25fc5f3c8db1337cb349013f71550e51ba6126faeae5b5e8aacfcd969fd6c15f5391ad05de20e751da5b9567edf4ee426570130b70141cc9e019ca5ff51d704b6c0674ecb52e77e174a1a399a0859ef1acd87e" + val expectedKeyEnc = + "0000100055d904add804afe3d3846c7e0d893dc28cd31255e962c9f10f5ecc1672ab447c2c654a94b5162b00bb06ef1307534cf964b9287a1b849888d867a423f9a74bdc4a0ff73a18ae54a815feb0adac35da3bad27bcafe8d32f3734d6512b6c5a27d79606af6bb880cafa30b4b185b34daaaac316341ab8e7c7faf90977ab9793eb44aecf20bcf08011db230c4771b96dd67b604787165693b7c22a9ab04c010c30d89387f0ed6e8bbe305bf6a6afdd807c455e8f91935e44feb88207ee79cabf31736258e3cdc4bcc2111da14abffe277da1f635a35ecadc572f3ef0c95d866af8af66a7edcdb8eda15fba9b851ad509ae944e3bcfcb5cc97980f7cca64aa86ad8d33111f9f602632a1a2dd11a661b1641bdbdf74dc04ae527495f7f58e3272de5c9660e52381638fb16eb533fe6fde9a25e2559d87945ff034c26a2005a8ec251a115f97bf45c819b184735d82d05e9ad0f357415a38e8bcc27da7c5de4fa04d3050bba3ab249452f47c70d413f97804d3fc1b5bb705fa737af482212452ef50f8792e28401f9120f141524ce8999eeb9c417707015eabec66c1f62b3f42d1687fb561e45abae32e45e91ed53665ebdedade612390d83c9e86b6c2da5eec45a66ae8c97d70d6c49c7f5c492318b09ee33daa937b64918f80e6045c83391ef205710be782d8326d6ca61f92fe0bf0530525a121c00a75dcc7c2ec5958ba33bf0432e5edd00db0db33799a9cd9cb743f7354421c28271ab8daab44111ec1e8dfc1482924e836a0a6b355e5de95ccc8cde39d14a5b5f63a964e00acb0bb85a7cc30be6befe8b0f7d348e026674016cca76ac7c67082f3f1aa62c60b3ffda8db8120c007fcc50a15c64a1e25f3265c99cbed60a13873c2a45470cca4282fa8965e789b48ff71ee623a5d059377992d7ce3dfde3a10bcf6c85a065f35cc64a635f6e3a3a2a8b6ab62fbbf8b24b62bc1a912566e369ca60490bf68abe3e7653c27aa8041775f1f303621b85b2b0ef8015b6d44edf71acdb2a04d4b421ba655657e8fa84a27d130eafd79a582aa381848d09a06ac1bbd9f586acbd756109e68c3d77b2ed3020e4001d97e8bfc7001b21b116e741672eec38bce51bb4062331711c49cd764a76368da3898b4a7af487c8150f3739f66d8019ef5ca866ce1b167921dfd73130c421dd345bd21a2b3e5df7eaca058eb7cb492ea0e3f4a74819109c04a7f42874c86f63202b462426191dd12c316d5a29a206a6b241cc0a27960996ac476578685198d6d8a62da0cfece274f282e397d97ed4f80b70433db17b9780d6cbd719bc630bfd4d88fe67acb8cc50b768b35bd61e25fc5f3c8db1337cb349013f71550e51ba6126faeae5b5e8aacfcd969fd6c15f5391ad05de20e751da5b9567edf4ee426570130b70141cc9e019ca5ff51d704b6c0674ecb52e77e174a1a399a0859ef1acd87e" assertEquals(expectedKeyEnc, Hex.encodeHexString(encodedKey)) } @Test fun testEncodeKey8192() { - val keyStr = "2d2d2d2d2d424547494e205253412050524956415445204b45592d2d2d2d2d0a4d4949534b67494241414b4342414541304433542b644953736d43486d37393777735830765666715557444a2f336d7644596f7a6c43616244686e474c6c53450a7041516266315a3854732b4f4d34705652484f4a554a4c305765624e646d5050476a737957517a367a5a4539366c515a4c3361764345587159565152363656350a3377644b2f6f68614d53526e4779454d4272716b56566246336743722b2f6972784433594b2b566f774f32574b732f3647724d647154413859354354462f4a650a707477735367354d4d6a723655614b3471446372656a33686b6742564776525633636a31736e4b3642723848755964466e7047475453306437554a6c4846676c0a74724748552f43424f393233686b48674a6157456a4330676953476a684b4b744c7a72566370445632792f6c57515039542f5434646a454149614871512b2b500a53644f535236707349475236685667536967743748436e45376e573731312f7266563555723945695670423034306d44496d4b5a6379382f2f544d6e5879644e0a314b595456642f33346664707a4d7053773569626c457262774f4c585654556d4f7a74596e706c343166654853762f6a506573487374506c666b6c494632766f0a475a456f6866397363517663754d3777454266432f615441394b33397a4d6d6b42626376535a6a4c79686d63535a574d50504f5a7949636c337a5935335168570a51432f61626d49634266493153342b72376d433469324a6e2b2b6f457675474e564772325359325a305a5a7858474c3148492f3038442f332b5463756d72636e0a34596a504b2f444d466930462b652b317834316c697075662b63782f3271524e51582f6d30325354724c59644d3665306733334b766c6e4664693262373532790a2f4f49614d777844614a76756e4d6836454d44574b4d31414862592f696f416f4b376553323648654a4c45446c6c714f342b535750333763386c4d76534557790a314769457252304863734f6a2f51775747504673656f56726f4d6941327355513049632f7467566a43546c58672b31325870556e6f754977654369384b634c2f0a6164327a4a6b6a75396842684a4c42512f32476e69764a69336c4667463447642f2f54534a36726757755846664d4b742f397a32537a33356f684558347941300a666c716c43654c496e46456f6576627a2b585439615266446536354d5a373979773354665039437256373468663152527a766544347a706933462b68635932690a4a5773483767524f5a65436d3666415835547265636433684f784a4f6641344e34727653534371364277437665625438465932355a2f564637635172485944530a696a3577366c71684d7a5848655545593930476139414b34587a6157774767657a712b52375a73303059534b7146763971594e4b645237747a33636a696a57660a39712f33523175683645514b544d5a4b6f345345436c4a6947796a4f42766d504b30396a4d465a544a763030684478616744505a426c3758704c444a352f4c6e0a31757070764c434e575759317a654a6661456c4d7971332f50714b5a4c6964463972566f41315349776b326c70645576506f7465326f466977435a6f586c775a0a4a326e636a6d5867514e7337362f38756e444a4130726a344a5071636377344d35477851376f6b62676d334634726d7a72694375763842654d53436b723272790a306d59335568706f68583477434d713047347835734555417a39465656505a4b6a786e59426d4c447a724a41522b342b4737675a736374303158444a596744640a4a5659496e465032322f63497265385672465759744862674f46644e7155695671353864653650645a472f452b7561576d455468536c527267456a54787570690a4f586667644b572f32306a317141746a4f6c714677735930393451357271554c513677507851494441514142416f4945415143686d6b6d6c68725242763432640a6659556979784b353262386174683073614a64447a36746c586d785944674a784d392f586c4f5274396f547a65446b6e6f454f356f6c752b72727834424267510a747a59696169775256585252455654575137746a7a5276614e4c2f47466b4c7439335854636370754b7779724e452f6269744c56616752627763492b485a46610a4d6b6e434f6968484d486f52746f386833464b41593934787a5341674f444d656b315747386a6867704358586d564e6e4250742b64346f44444944414741667a0a71676630334a356e6849622b38304b675a4f7a504f4b6e62764a614c36456d6c4c4862674233633432647a417737684874566d6f6659475763764c62324d49590a44564b4f3433352f73517831552f384e4448364a6a566441435a6a4c674f625848394b332f54743436445750456372504c6d443878686f633667464d2b5172300a41686b7a4b6f4259444e6b30436c6a6268644942586a6b74585536775251465a343575503265344a5a347a727a47424c722f74346c5461765a305351744c6c640a41366b4f7347682b6443574644746e736878596e6c2f7861642f79522b3361357a6d444a626f2f664a544258726c663142347266516b46744b323065744f50510a422b2b46432f726a68334d6d2f4b622f7039477a2f3275705a6441724839375a7644324c4246666a37376c466d4168714169337743526c4e2b656b755978615a0a743170425639795869673844796c64673164375838704f6e326b7972463372515544446634706137783976706e626b556c455569666f5639676e59736d646e690a71447a59427454763267364d4b7177517953586149555730594f4250624f656c6c574577784a7147595137793449665648664d306979486e65686b32745a63720a2b58617a4c6e7747652b427a347663677546684a584c7949752f2f6c414f685a74626b367231514a45557578614f4f515833777a79636545366e6b4473676d720a5035646a335a7064376653325656327679474849466e424a38384c52787265567667723651323855543237534238327a4d62376d525a545645327a65757562540a354432443158625a3077426f3657694b366552527244513248616565746b6a2f756f527936505758776e4161546d6d49727258774c71616f4a682f5531652b440a746673444c57643649784c6a66587647676c7248737274417a306f70727069785554655668675472476b394951526435727678754755596846756a56615949360a2b5155662b3333414664746e636238793943396a5a6d677838414b624a6b2b653733534c6842354a566f732b57746555376238642f4d696d356d414c6a6e4f360a5a316e2f75696d735437397353447179335853796d744b57586f2f3232556c72764743706f4575454c504d6236645346575237767772737668466e6759342f4b0a556e69746e7678626f45666c516e614951344966524c527a5a73582b73433545737177395535744874346f492b39314476334b626462634552675637334b36420a5a516743346c6b415171754658695a354149436b786a694d795a77547455394b4a37787631375875366f7977462f33417462564745545731442b336d614873440a7933444153576f6a79715a644c6a2b57477a4b5152612b737767434441594b65656b32664941584653644636337a784a3252784f4a3447696a53616f682b6d720a3448567663704461546a2b413854312b516442794d347339386775344744376b5674565147425a64576a75747948766830685776316774566d6268512f3431330a67444d4646447a48496a4c5459475965733468484c32323136396a565239735a316551787776544967334e3470443563466d307252755a5a54532b6f4a546f460a4732376142466968416f494341514479564236325a446e62785174686b2b7a49544b497a5255724a624c6f58725563414e63534866614e37696e4638374f76610a7a6537656a5439444e5345686274665a464a31473664694f596f53772b324d7a4658763067456b4c4b593064455479644b67484575366e5671356569764d67760a4434686339596b4a4d4844536c6d763246446b704c33415843416d6e5739724b702b64647474425a45436e6d6c504570484c6f6a367867427733704e613158730a49634c56666475674838364865786a366f306f4b6759666371725838555548745549322f585171674672496a386b736a6631664656574a524a46576d425871700a6e4d45735961727a4154654d316b512f6b446554315a55706f4750517430322f5871585434423541334154694574704d32752b6c343878746f675757673252790a47396c3933385374416d68556957316d37476e4b453645494676515938355776627a784f52304a5956555372374d72617346366e6e516c6859784675494a6f4a0a32682f4b4a51616f354743547647342b4774624a4a6d3463326e795a67777968697a4d7364677364636c7337396158694d6b725a5a6b616d4c56555a574f74450a3370412f6f42757a32716e4f3948776a62483148474f636371305458666d70465363455633435147594a646e6f3646793763626d7570614c34553961675134650a772b79674c31386e713548562b2b4c5374466e567267733559696a6a736b665264453947554d56446835704373643959323346796d616164344f2f32535243430a596b53737948354f7679444f4c706f79554a366736512b343548716d2f336c4734596a4e707a4655694d636e70372b33785533357143304c4b387845666565690a4d73316d54564569484e49703678482f547152645837335744372b59754b5a534c496652473764677269725536772b6d686876784435317548514b43416745410a322f316d42435235716d332f304c742b2b52516265794533746977343055657951717563472f2b567659373773534c6b492f4c78386977526c797758634c426e0a2b4134547667756b6d4164577a4373386e64674b4e7850412b67666f687642734d4f474e394b4f4231556735767667324a326b6949363476775943777a68645a0a4e5455556d4c2b474d464855715373575967366937694246635a6d7a6e72345732543362427879544d5a6b69374a53744238366533354b58727a63322f572f620a2b2f70355532484353617a444849356d4d7975436c486336476d5553564a3766374c486a4c39346a76694e716f627030566a3630337453634849536d4e725a770a544261766b765a475958736f574b767161766b376a424239517a61424c2b756e614652736c67356a5461694b6e49536a3434557331666a464b7538347869664c0a6e4a61457a6a445074375042786b6f374c5067455937774633396e4d3956706f65744937627752364e77444c535838555539374d47642b48592b4d4f315769310a7064324c61707772782f454b374f787a33333556524b344a6530615a6e61346a32547951644d4a616339667347505876345a734c66444c6a2f7744366c316a2b0a6c4c4c62427633496d64536a33324c4262687367463469434765584f384870504f2b512f68395856736e593532556d3258644e4d6e30335043476d365a76744d0a37445869532b6c50463930486a6f6c4a56485a54424e74645652724c7235337a4c7557456671543446654b72446178647469586b784c6a72422b352f565975370a6e74796b30315a513633564e664577533169726d4b6c392b715a6b54486b33484856396a4e5635527a575669776d4a493757707231597a42776d634b4342314f0a6f4755414444733851706e6b437a30786b4d56745977486a39714b5a6c716662487a72464455556346386b43676749416459765563676a662f2f6a75386d41380a3556513341635045365476796350572b6b5232447657313256634473462f73633155413764487a7a695068476e3938536d4e786c426a62387375536246505a380a5168565430574242446b6354696c774947507839617837553353366c47573256645336467151483566526d67514b5a79724356584c4f457a384267594272534a0a78752f335451415778483051746962646247486738506469353867596c574652686e394238536c6831615259484750623141684e4c4264302f6464592b3547320a397853794458646d5a67316355412b42337a41774e5371627a46786870327a552b563175587362706b344b746e595636435a4d39516c7243526a546b39694e550a645658462f716169526a667a726d3453736d4570436b4562737270374632325931626b6f6f4f52676c4d4f734e41574e716656587734774e2b7379586a31726f0a36765a3850455259724679414f52316473514d4968796d6e6d54506a4370614a34656d4b7268575479323073593731746848616b5a574a633232596f4e70625a0a453674674956734a50546c78672f342b667943434b6a3577577239326e687342314b425a50474f2f7a4668764d6c4a70765130744838573270624e3261306d490a3578394671414c6d2f716a774348665a49745377504d2b5a6f7a53687433634f6b4748646344354b58415866636673444a633453485a4b56497a71344e75734e0a353034522f6a76443147503873676c7947376f6d703735636b677a416d616b4c64784f503248685176495839746358705369724e4a36536c3262774b75754d460a77786f33722f6f2f3959393765344c6c66704559703965714d6463472b4e705239393349774b30556841575339483577646e57425355486435653478744455740a69494c4e52754f34366737522f4149687a3163535372615757516b4367674942414d6868505035433979743950496d316230655477434263746e465351494b6f0a4b734139726c6c3261622b624d4c6b396a63384d364d4c737a7930437457736f30397348663459593974696676726b4548526574684568387a736377557559750a736d326e31665469786b30756c364c5356676c35347558624d4a6179454e6e3450494b526b65773863413874536d613433343937773337686d442b4d674362310a414c7a7163636f3968666d6b676b4936666f316738436533554545434b7932594b536d5245646759634b394a46514f36315736416b46574a634478416d667a490a4a6a466b4b7773623754537737397a57694564536f4d396a6d377343504b41546436426d2f5a41416b5555547545466b666f626e39417831724a4e2f587862320a4d4b754155745176304e595930674556644736326a4974754b4c4964366e6e63483850472b7273526a504c495970577159644a704b783570556e522b34416b510a5336437352415377634634506442764444424946473658706a466f347050645168447a4c32735446386238535753424c6c4a516262374736554e7167435361750a537573434670617a7655354e66446d554d7563746f623245595661535871396a47616a366254556d447758487757696c66496b3958664c786e59665859724a360a786864497058476d4868754c517441674b324f314a744c6f50633973397150382f536b665037786a6a4736784873502f57764c37514531705073395a4d2f55490a4330314a4e484669394c4b436e386f356d625a6a4e386a556f77693766664b2b3736775a5547314c377a4d35797457514f59776f3054514266633866706d46770a2b5242524a58326b4a79444f32374578637a6f474f4b6a77714544614f444942392b397a63434b304267536f526962536d345a42766f787a57574436354b6c730a786450685a55486346475735416f494341514338694732376144386152557439344f656b363667464f4a78383451565a6568575071745a6a577956656e4475630a543864696e6b386f656a476a634b32554a755144613833617a7639306f63567145306e30726f6e5979737a74394962316a6c59432b434b3141723954594746670a5755354f57454479437a437071572f772f61473638553871684b6d304d766b4c4a522b47366576616e3954774568464556416d3369576c6c4e587339783239730a42756377794d4d4332337a73696d78596c53376441344474797656412b7a4c316f6d4c7053574862552f71747549334856314e654a7a73792b6743346d7750680a6a353274646c3636396679574c7a487a42524c65713664564f65646a6e436f2b6a6c5533644c323044456b39536157303844314350755a656b56316a56504d770a4a6f614463495268344b4c74513042595a37554a6546555473783143532f2b55717a715953504f69353761356b76723059385977526e534238644856467474580a4a5476383377545158485046534267666e484e65376c7352546649516675496b723262706955376838355551374c7371634936594861433037555263734746460a46724c5747683931717a416431646953486c6132526e59336e385050754d6e436b67754e684c557259646d794d6f6c374666574661396c77706c7375547a42710a4236796a3869616945334c4c2b512f65756c4a375336515066414932625530554a4f323359346b6f656f4969624545444d534351364b595a324e436c525252540a67613566533159666b44464563485551312f4b496b64594847424b426a6f4b4745787a69382b436769537953565359445a6c3677494f684c6a48324f5a336f6c0a6c64504e37694e41486972727867397638514f364f516c704c556b354c68702f3164536c5a36737933556a4671766178337477365a6a724c3838595035673d3d0a2d2d2d2d2d454e44205253412050524956415445204b45592d2d2d2d2d0a" + val keyStr = + "2d2d2d2d2d424547494e205253412050524956415445204b45592d2d2d2d2d0a4d4949534b67494241414b4342414541304433542b644953736d43486d37393777735830765666715557444a2f336d7644596f7a6c43616244686e474c6c53450a7041516266315a3854732b4f4d34705652484f4a554a4c305765624e646d5050476a737957517a367a5a4539366c515a4c3361764345587159565152363656350a3377644b2f6f68614d53526e4779454d4272716b56566246336743722b2f6972784433594b2b566f774f32574b732f3647724d647154413859354354462f4a650a707477735367354d4d6a723655614b3471446372656a33686b6742564776525633636a31736e4b3642723848755964466e7047475453306437554a6c4846676c0a74724748552f43424f393233686b48674a6157456a4330676953476a684b4b744c7a72566370445632792f6c57515039542f5434646a454149614871512b2b500a53644f535236707349475236685667536967743748436e45376e573731312f7266563555723945695670423034306d44496d4b5a6379382f2f544d6e5879644e0a314b595456642f33346664707a4d7053773569626c457262774f4c585654556d4f7a74596e706c343166654853762f6a506573487374506c666b6c494632766f0a475a456f6866397363517663754d3777454266432f615441394b33397a4d6d6b42626376535a6a4c79686d63535a574d50504f5a7949636c337a5935335168570a51432f61626d49634266493153342b72376d433469324a6e2b2b6f457675474e564772325359325a305a5a7858474c3148492f3038442f332b5463756d72636e0a34596a504b2f444d466930462b652b317834316c697075662b63782f3271524e51582f6d30325354724c59644d3665306733334b766c6e4664693262373532790a2f4f49614d777844614a76756e4d6836454d44574b4d31414862592f696f416f4b376553323648654a4c45446c6c714f342b535750333763386c4d76534557790a314769457252304863734f6a2f51775747504673656f56726f4d6941327355513049632f7467566a43546c58672b31325870556e6f754977654369384b634c2f0a6164327a4a6b6a75396842684a4c42512f32476e69764a69336c4667463447642f2f54534a36726757755846664d4b742f397a32537a33356f684558347941300a666c716c43654c496e46456f6576627a2b585439615266446536354d5a373979773354665039437256373468663152527a766544347a706933462b68635932690a4a5773483767524f5a65436d3666415835547265636433684f784a4f6641344e34727653534371364277437665625438465932355a2f564637635172485944530a696a3577366c71684d7a5848655545593930476139414b34587a6157774767657a712b52375a73303059534b7146763971594e4b645237747a33636a696a57660a39712f33523175683645514b544d5a4b6f345345436c4a6947796a4f42766d504b30396a4d465a544a763030684478616744505a426c3758704c444a352f4c6e0a31757070764c434e575759317a654a6661456c4d7971332f50714b5a4c6964463972566f41315349776b326c70645576506f7465326f466977435a6f586c775a0a4a326e636a6d5867514e7337362f38756e444a4130726a344a5071636377344d35477851376f6b62676d334634726d7a72694375763842654d53436b723272790a306d59335568706f68583477434d713047347835734555417a39465656505a4b6a786e59426d4c447a724a41522b342b4737675a736374303158444a596744640a4a5659496e465032322f63497265385672465759744862674f46644e7155695671353864653650645a472f452b7561576d455468536c527267456a54787570690a4f586667644b572f32306a317141746a4f6c714677735930393451357271554c513677507851494441514142416f4945415143686d6b6d6c68725242763432640a6659556979784b353262386174683073614a64447a36746c586d785944674a784d392f586c4f5274396f547a65446b6e6f454f356f6c752b72727834424267510a747a59696169775256585252455654575137746a7a5276614e4c2f47466b4c7439335854636370754b7779724e452f6269744c56616752627763492b485a46610a4d6b6e434f6968484d486f52746f386833464b41593934787a5341674f444d656b315747386a6867704358586d564e6e4250742b64346f44444944414741667a0a71676630334a356e6849622b38304b675a4f7a504f4b6e62764a614c36456d6c4c4862674233633432647a417737684874566d6f6659475763764c62324d49590a44564b4f3433352f73517831552f384e4448364a6a566441435a6a4c674f625848394b332f54743436445750456372504c6d443878686f633667464d2b5172300a41686b7a4b6f4259444e6b30436c6a6268644942586a6b74585536775251465a343575503265344a5a347a727a47424c722f74346c5461765a305351744c6c640a41366b4f7347682b6443574644746e736878596e6c2f7861642f79522b3361357a6d444a626f2f664a544258726c663142347266516b46744b323065744f50510a422b2b46432f726a68334d6d2f4b622f7039477a2f3275705a6441724839375a7644324c4246666a37376c466d4168714169337743526c4e2b656b755978615a0a743170425639795869673844796c64673164375838704f6e326b7972463372515544446634706137783976706e626b556c455569666f5639676e59736d646e690a71447a59427454763267364d4b7177517953586149555730594f4250624f656c6c574577784a7147595137793449665648664d306979486e65686b32745a63720a2b58617a4c6e7747652b427a347663677546684a584c7949752f2f6c414f685a74626b367231514a45557578614f4f515833777a79636545366e6b4473676d720a5035646a335a7064376653325656327679474849466e424a38384c52787265567667723651323855543237534238327a4d62376d525a545645327a65757562540a354432443158625a3077426f3657694b366552527244513248616565746b6a2f756f527936505758776e4161546d6d49727258774c71616f4a682f5531652b440a746673444c57643649784c6a66587647676c7248737274417a306f70727069785554655668675472476b394951526435727678754755596846756a56615949360a2b5155662b3333414664746e636238793943396a5a6d677838414b624a6b2b653733534c6842354a566f732b57746555376238642f4d696d356d414c6a6e4f360a5a316e2f75696d735437397353447179335853796d744b57586f2f3232556c72764743706f4575454c504d6236645346575237767772737668466e6759342f4b0a556e69746e7678626f45666c516e614951344966524c527a5a73582b73433545737177395535744874346f492b39314476334b626462634552675637334b36420a5a516743346c6b415171754658695a354149436b786a694d795a77547455394b4a37787631375875366f7977462f33417462564745545731442b336d614873440a7933444153576f6a79715a644c6a2b57477a4b5152612b737767434441594b65656b32664941584653644636337a784a3252784f4a3447696a53616f682b6d720a3448567663704461546a2b413854312b516442794d347339386775344744376b5674565147425a64576a75747948766830685776316774566d6268512f3431330a67444d4646447a48496a4c5459475965733468484c32323136396a565239735a316551787776544967334e3470443563466d307252755a5a54532b6f4a546f460a4732376142466968416f494341514479564236325a446e62785174686b2b7a49544b497a5255724a624c6f58725563414e63534866614e37696e4638374f76610a7a6537656a5439444e5345686274665a464a31473664694f596f53772b324d7a4658763067456b4c4b593064455479644b67484575366e5671356569764d67760a4434686339596b4a4d4844536c6d763246446b704c33415843416d6e5739724b702b64647474425a45436e6d6c504570484c6f6a367867427733704e613158730a49634c56666475674838364865786a366f306f4b6759666371725838555548745549322f585171674672496a386b736a6631664656574a524a46576d425871700a6e4d45735961727a4154654d316b512f6b446554315a55706f4750517430322f5871585434423541334154694574704d32752b6c343878746f675757673252790a47396c3933385374416d68556957316d37476e4b453645494676515938355776627a784f52304a5956555372374d72617346366e6e516c6859784675494a6f4a0a32682f4b4a51616f354743547647342b4774624a4a6d3463326e795a67777968697a4d7364677364636c7337396158694d6b725a5a6b616d4c56555a574f74450a3370412f6f42757a32716e4f3948776a62483148474f636371305458666d70465363455633435147594a646e6f3646793763626d7570614c34553961675134650a772b79674c31386e713548562b2b4c5374466e567267733559696a6a736b665264453947554d56446835704373643959323346796d616164344f2f32535243430a596b53737948354f7679444f4c706f79554a366736512b343548716d2f336c4734596a4e707a4655694d636e70372b33785533357143304c4b387845666565690a4d73316d54564569484e49703678482f547152645837335744372b59754b5a534c496652473764677269725536772b6d686876784435317548514b43416745410a322f316d42435235716d332f304c742b2b52516265794533746977343055657951717563472f2b567659373773534c6b492f4c78386977526c797758634c426e0a2b4134547667756b6d4164577a4373386e64674b4e7850412b67666f687642734d4f474e394b4f4231556735767667324a326b6949363476775943777a68645a0a4e5455556d4c2b474d464855715373575967366937694246635a6d7a6e72345732543362427879544d5a6b69374a53744238366533354b58727a63322f572f620a2b2f70355532484353617a444849356d4d7975436c486336476d5553564a3766374c486a4c39346a76694e716f627030566a3630337453634849536d4e725a770a544261766b765a475958736f574b767161766b376a424239517a61424c2b756e614652736c67356a5461694b6e49536a3434557331666a464b7538347869664c0a6e4a61457a6a445074375042786b6f374c5067455937774633396e4d3956706f65744937627752364e77444c535838555539374d47642b48592b4d4f315769310a7064324c61707772782f454b374f787a33333556524b344a6530615a6e61346a32547951644d4a616339667347505876345a734c66444c6a2f7744366c316a2b0a6c4c4c62427633496d64536a33324c4262687367463469434765584f384870504f2b512f68395856736e593532556d3258644e4d6e30335043476d365a76744d0a37445869532b6c50463930486a6f6c4a56485a54424e74645652724c7235337a4c7557456671543446654b72446178647469586b784c6a72422b352f565975370a6e74796b30315a513633564e664577533169726d4b6c392b715a6b54486b33484856396a4e5635527a575669776d4a493757707231597a42776d634b4342314f0a6f4755414444733851706e6b437a30786b4d56745977486a39714b5a6c716662487a72464455556346386b43676749416459765563676a662f2f6a75386d41380a3556513341635045365476796350572b6b5232447657313256634473462f73633155413764487a7a695068476e3938536d4e786c426a62387375536246505a380a5168565430574242446b6354696c774947507839617837553353366c47573256645336467151483566526d67514b5a79724356584c4f457a384267594272534a0a78752f335451415778483051746962646247486738506469353867596c574652686e394238536c6831615259484750623141684e4c4264302f6464592b3547320a397853794458646d5a67316355412b42337a41774e5371627a46786870327a552b563175587362706b344b746e595636435a4d39516c7243526a546b39694e550a645658462f716169526a667a726d3453736d4570436b4562737270374632325931626b6f6f4f52676c4d4f734e41574e716656587734774e2b7379586a31726f0a36765a3850455259724679414f52316473514d4968796d6e6d54506a4370614a34656d4b7268575479323073593731746848616b5a574a633232596f4e70625a0a453674674956734a50546c78672f342b667943434b6a3577577239326e687342314b425a50474f2f7a4668764d6c4a70765130744838573270624e3261306d490a3578394671414c6d2f716a774348665a49745377504d2b5a6f7a53687433634f6b4748646344354b58415866636673444a633453485a4b56497a71344e75734e0a353034522f6a76443147503873676c7947376f6d703735636b677a416d616b4c64784f503248685176495839746358705369724e4a36536c3262774b75754d460a77786f33722f6f2f3959393765344c6c66704559703965714d6463472b4e705239393349774b30556841575339483577646e57425355486435653478744455740a69494c4e52754f34366737522f4149687a3163535372615757516b4367674942414d6868505035433979743950496d316230655477434263746e465351494b6f0a4b734139726c6c3261622b624d4c6b396a63384d364d4c737a7930437457736f30397348663459593974696676726b4548526574684568387a736377557559750a736d326e31665469786b30756c364c5356676c35347558624d4a6179454e6e3450494b526b65773863413874536d613433343937773337686d442b4d674362310a414c7a7163636f3968666d6b676b4936666f316738436533554545434b7932594b536d5245646759634b394a46514f36315736416b46574a634478416d667a490a4a6a466b4b7773623754537737397a57694564536f4d396a6d377343504b41546436426d2f5a41416b5555547545466b666f626e39417831724a4e2f587862320a4d4b754155745176304e595930674556644736326a4974754b4c4964366e6e63483850472b7273526a504c495970577159644a704b783570556e522b34416b510a5336437352415377634634506442764444424946473658706a466f347050645168447a4c32735446386238535753424c6c4a516262374736554e7167435361750a537573434670617a7655354e66446d554d7563746f623245595661535871396a47616a366254556d447758487757696c66496b3958664c786e59665859724a360a786864497058476d4868754c517441674b324f314a744c6f50633973397150382f536b665037786a6a4736784873502f57764c37514531705073395a4d2f55490a4330314a4e484669394c4b436e386f356d625a6a4e386a556f77693766664b2b3736775a5547314c377a4d35797457514f59776f3054514266633866706d46770a2b5242524a58326b4a79444f32374578637a6f474f4b6a77714544614f444942392b397a63434b304267536f526962536d345a42766f787a57574436354b6c730a786450685a55486346475735416f494341514338694732376144386152557439344f656b363667464f4a78383451565a6568575071745a6a577956656e4475630a543864696e6b386f656a476a634b32554a755144613833617a7639306f63567145306e30726f6e5979737a74394962316a6c59432b434b3141723954594746670a5755354f57454479437a437071572f772f61473638553871684b6d304d766b4c4a522b47366576616e3954774568464556416d3369576c6c4e587339783239730a42756377794d4d4332337a73696d78596c53376441344474797656412b7a4c316f6d4c7053574862552f71747549334856314e654a7a73792b6743346d7750680a6a353274646c3636396679574c7a487a42524c65713664564f65646a6e436f2b6a6c5533644c323044456b39536157303844314350755a656b56316a56504d770a4a6f614463495268344b4c74513042595a37554a6546555473783143532f2b55717a715953504f69353761356b76723059385977526e534238644856467474580a4a5476383377545158485046534267666e484e65376c7352546649516675496b723262706955376838355551374c7371634936594861433037555263734746460a46724c5747683931717a416431646953486c6132526e59336e385050754d6e436b67754e684c557259646d794d6f6c374666574661396c77706c7375547a42710a4236796a3869616945334c4c2b512f65756c4a375336515066414932625530554a4f323359346b6f656f4969624545444d534351364b595a324e436c525252540a67613566533159666b44464563485551312f4b496b64594847424b426a6f4b4745787a69382b436769537953565359445a6c3677494f684c6a48324f5a336f6c0a6c64504e37694e41486972727867397638514f364f516c704c556b354c68702f3164536c5a36737933556a4671766178337477365a6a724c3838595035673d3d0a2d2d2d2d2d454e44205253412050524956415445204b45592d2d2d2d2d0a" val encodedKey = AuxBlob.encodePubKey(Algorithms.get("SHA256_RSA8192")!!, Hex.decodeHex(keyStr)) - val expectedKeyEnc = "00002000ef8168f3d03dd3f9d212b260879bbf7bc2c5f4bd57ea5160c9ff79af0d8a3394269b0e19c62e5484a4041b7f567c4ecf8e338a554473895092f459e6cd7663cf1a3b32590cfacd913dea54192f76af0845ea615411eba579df074afe885a3124671b210c06baa45556c5de00abfbf8abc43dd82be568c0ed962acffa1ab31da9303c63909317f25ea6dc2c4a0e4c323afa51a2b8a8372b7a3de19200551af455ddc8f5b272ba06bf07b987459e91864d2d1ded42651c5825b6b18753f0813bddb78641e025a5848c2d208921a384a2ad2f3ad57290d5db2fe55903fd4ff4f876310021a1ea43ef8f49d39247aa6c20647a8558128a0b7b1c29c4ee75bbd75feb7d5e54afd122569074e34983226299732f3ffd33275f274dd4a61355dff7e1f769ccca52c3989b944adbc0e2d75535263b3b589e9978d5f7874affe33deb07b2d3e57e4948176be819912885ff6c710bdcb8cef01017c2fda4c0f4adfdccc9a405b72f4998cbca199c49958c3cf399c88725df3639dd0856402fda6e621c05f2354b8fabee60b88b6267fbea04bee18d546af6498d99d196715c62f51c8ff4f03ff7f9372e9ab727e188cf2bf0cc162d05f9efb5c78d658a9b9ff9cc7fdaa44d417fe6d36493acb61d33a7b4837dcabe59c5762d9bef9db2fce21a330c43689bee9cc87a10c0d628cd401db63f8a80282bb792dba1de24b103965a8ee3e4963f7edcf2532f4845b2d46884ad1d0772c3a3fd0c1618f16c7a856ba0c880dac510d0873fb6056309395783ed765e9527a2e2307828bc29c2ff69ddb32648eef6106124b050ff61a78af262de516017819dfff4d227aae05ae5c57cc2adffdcf64b3df9a21117e320347e5aa509e2c89c51287af6f3f974fd6917c37bae4c67bf72c374df3fd0ab57be217f5451cef783e33a62dc5fa1718da2256b07ee044e65e0a6e9f017e53ade71dde13b124e7c0e0de2bbd2482aba0700af79b4fc158db967f545edc42b1d80d28a3e70ea5aa13335c7794118f7419af402b85f3696c0681eceaf91ed9b34d1848aa85bfda9834a751eedcf77238a359ff6aff7475ba1e8440a4cc64aa384840a52621b28ce06f98f2b4f6330565326fd34843c5a8033d9065ed7a4b0c9e7f2e7d6ea69bcb08d596635cde25f68494ccaadff3ea2992e2745f6b568035488c24da5a5d52f3e8b5eda8162c026685e5c192769dc8e65e040db3bebff2e9c3240d2b8f824fa9c730e0ce46c50ee891b826dc5e2b9b3ae20aebfc05e3120a4af6af2d26637521a68857e3008cab41b8c79b04500cfd15554f64a8f19d80662c3ceb24047ee3e1bb819b1cb74d570c96200dd2556089c53f6dbf708adef15ac5598b476e038574da94895ab9f1d7ba3dd646fc4fae6969844e14a546b8048d3c6ea623977e074a5bfdb48f5a80b633a5a85c2c634f78439aea50b43ac0fc51af9112e97f272e5448cc3110fce7a4081ea0613cba5637de45982ff7144d57cb6401e5186d39755af273947e526d5bb5bd4390562cfb8f28039c14be94986fb4f79a49bb97a30d2f252a8569e121993af3c57a60e98cb07dfedbdeffc887ada8d098ac4deef25fee3b33ce90be9d27ae66602da89b4b931a08ae776e7ecac8ccb30c02b72208b87f05b03b9cf83f66e4be8344fd4c4ddd08194ad7a0a3a6d6ec21058e6de8bf9c8691cb7994748e71989387340a5ecd3cd0f506b6686522673e9d2770cd13db18217cd261f706efcc0f4b3842982e4c8d333b3e0ae9348b91e15843e17371426b8294964f2e74cd1c2e08a575b66a79494d98f1db480edc741f689a3678985c379609bac92b0c192dfe5ea44fc284cf67297220888210d9ebd2d100ffc8bcb13636aad6263b2a735e3d006f309100dc391297ce7253e6df1885eefee0e7035ef318053d7177cd4acc5ec92031a1fd66def3404c4adfff0f12194a093fad509a0a6c7422011d0b0c40a6da8601fc71e48ad2544ebc652499ed591e6eb89b074fca8a920b8bbb568abfcc0af73fa4f3256cb30609cdbd11307db751d0835e09cfa1c747a58ed2919d4bd6a9a8eb2c1fb92e003bb090de173dc704b387f41b7285f95294d1ce756b269e9e3814ccb3f80efe0d7eac6d0cfe2cc51524aa4c984476d74fd34f3e4ff126cf01523a1deda0e5a0772f0e61bed8dc3615d547d8113d23d8f0bfc0097ae88258e6478cee389fbb6bf4ea68d083a938d7f781ce370c03cbd10a053e7d6a37526f610220eb684805e62204f210a790e7009cf71fb036851f5fcdb86bf640c94e0c0a412a66abf5a7f205d515b6c85d65b7da2f7e40dcf3d0567d2d851f02942a0f9a67e7f9f4427460de297d17219b940ddcfaf8310d6e906831be39c2cf1d527f2ffabd95dfe145c8f0adecfc4b167f38ae03fd8d2fe4d42bd8f2ae20f59a3688153a8b2c75ad360bd9a900d810d5ce17a5be35436cd15d6b2b881b56fd97277e4b2cd82f25df35286ec724a125280a036bcb602bd0038c5ea3026547462a06e4a45729ca0784e31d1103b7f991eaa89d7121cfd67510fb18d4d5b03068884c592d6bad56815d4eb4cffab1feb7ea27dd4e28c62db6d18f8d838b48553cd737611657463349f70cdc260ab0ad9bf163658eacc78982a274f85aadb0becf92588ecd53fc5e229bb1fe870a5f18c5c66bd154d052b2e2663004c0d6beacfcb55094ffb1898b7dbe3c9653815da4c11d53ac018b98fbb36fa61197de15258dc4614807c83c02f15420527508e63f8327b4c9862291810ff453b9badb3d7620d8c1aab8b5d50d6af59fc181161a5b1039090062f0c8995822be2df158447253b8abf913225c1bdef3e9a54a0589c1f69580e2565b28c75e9c4c8d738504ee8e08de414c64d8cee4864ecf9a60948515cc07680" + val expectedKeyEnc = + "00002000ef8168f3d03dd3f9d212b260879bbf7bc2c5f4bd57ea5160c9ff79af0d8a3394269b0e19c62e5484a4041b7f567c4ecf8e338a554473895092f459e6cd7663cf1a3b32590cfacd913dea54192f76af0845ea615411eba579df074afe885a3124671b210c06baa45556c5de00abfbf8abc43dd82be568c0ed962acffa1ab31da9303c63909317f25ea6dc2c4a0e4c323afa51a2b8a8372b7a3de19200551af455ddc8f5b272ba06bf07b987459e91864d2d1ded42651c5825b6b18753f0813bddb78641e025a5848c2d208921a384a2ad2f3ad57290d5db2fe55903fd4ff4f876310021a1ea43ef8f49d39247aa6c20647a8558128a0b7b1c29c4ee75bbd75feb7d5e54afd122569074e34983226299732f3ffd33275f274dd4a61355dff7e1f769ccca52c3989b944adbc0e2d75535263b3b589e9978d5f7874affe33deb07b2d3e57e4948176be819912885ff6c710bdcb8cef01017c2fda4c0f4adfdccc9a405b72f4998cbca199c49958c3cf399c88725df3639dd0856402fda6e621c05f2354b8fabee60b88b6267fbea04bee18d546af6498d99d196715c62f51c8ff4f03ff7f9372e9ab727e188cf2bf0cc162d05f9efb5c78d658a9b9ff9cc7fdaa44d417fe6d36493acb61d33a7b4837dcabe59c5762d9bef9db2fce21a330c43689bee9cc87a10c0d628cd401db63f8a80282bb792dba1de24b103965a8ee3e4963f7edcf2532f4845b2d46884ad1d0772c3a3fd0c1618f16c7a856ba0c880dac510d0873fb6056309395783ed765e9527a2e2307828bc29c2ff69ddb32648eef6106124b050ff61a78af262de516017819dfff4d227aae05ae5c57cc2adffdcf64b3df9a21117e320347e5aa509e2c89c51287af6f3f974fd6917c37bae4c67bf72c374df3fd0ab57be217f5451cef783e33a62dc5fa1718da2256b07ee044e65e0a6e9f017e53ade71dde13b124e7c0e0de2bbd2482aba0700af79b4fc158db967f545edc42b1d80d28a3e70ea5aa13335c7794118f7419af402b85f3696c0681eceaf91ed9b34d1848aa85bfda9834a751eedcf77238a359ff6aff7475ba1e8440a4cc64aa384840a52621b28ce06f98f2b4f6330565326fd34843c5a8033d9065ed7a4b0c9e7f2e7d6ea69bcb08d596635cde25f68494ccaadff3ea2992e2745f6b568035488c24da5a5d52f3e8b5eda8162c026685e5c192769dc8e65e040db3bebff2e9c3240d2b8f824fa9c730e0ce46c50ee891b826dc5e2b9b3ae20aebfc05e3120a4af6af2d26637521a68857e3008cab41b8c79b04500cfd15554f64a8f19d80662c3ceb24047ee3e1bb819b1cb74d570c96200dd2556089c53f6dbf708adef15ac5598b476e038574da94895ab9f1d7ba3dd646fc4fae6969844e14a546b8048d3c6ea623977e074a5bfdb48f5a80b633a5a85c2c634f78439aea50b43ac0fc51af9112e97f272e5448cc3110fce7a4081ea0613cba5637de45982ff7144d57cb6401e5186d39755af273947e526d5bb5bd4390562cfb8f28039c14be94986fb4f79a49bb97a30d2f252a8569e121993af3c57a60e98cb07dfedbdeffc887ada8d098ac4deef25fee3b33ce90be9d27ae66602da89b4b931a08ae776e7ecac8ccb30c02b72208b87f05b03b9cf83f66e4be8344fd4c4ddd08194ad7a0a3a6d6ec21058e6de8bf9c8691cb7994748e71989387340a5ecd3cd0f506b6686522673e9d2770cd13db18217cd261f706efcc0f4b3842982e4c8d333b3e0ae9348b91e15843e17371426b8294964f2e74cd1c2e08a575b66a79494d98f1db480edc741f689a3678985c379609bac92b0c192dfe5ea44fc284cf67297220888210d9ebd2d100ffc8bcb13636aad6263b2a735e3d006f309100dc391297ce7253e6df1885eefee0e7035ef318053d7177cd4acc5ec92031a1fd66def3404c4adfff0f12194a093fad509a0a6c7422011d0b0c40a6da8601fc71e48ad2544ebc652499ed591e6eb89b074fca8a920b8bbb568abfcc0af73fa4f3256cb30609cdbd11307db751d0835e09cfa1c747a58ed2919d4bd6a9a8eb2c1fb92e003bb090de173dc704b387f41b7285f95294d1ce756b269e9e3814ccb3f80efe0d7eac6d0cfe2cc51524aa4c984476d74fd34f3e4ff126cf01523a1deda0e5a0772f0e61bed8dc3615d547d8113d23d8f0bfc0097ae88258e6478cee389fbb6bf4ea68d083a938d7f781ce370c03cbd10a053e7d6a37526f610220eb684805e62204f210a790e7009cf71fb036851f5fcdb86bf640c94e0c0a412a66abf5a7f205d515b6c85d65b7da2f7e40dcf3d0567d2d851f02942a0f9a67e7f9f4427460de297d17219b940ddcfaf8310d6e906831be39c2cf1d527f2ffabd95dfe145c8f0adecfc4b167f38ae03fd8d2fe4d42bd8f2ae20f59a3688153a8b2c75ad360bd9a900d810d5ce17a5be35436cd15d6b2b881b56fd97277e4b2cd82f25df35286ec724a125280a036bcb602bd0038c5ea3026547462a06e4a45729ca0784e31d1103b7f991eaa89d7121cfd67510fb18d4d5b03068884c592d6bad56815d4eb4cffab1feb7ea27dd4e28c62db6d18f8d838b48553cd737611657463349f70cdc260ab0ad9bf163658eacc78982a274f85aadb0becf92588ecd53fc5e229bb1fe870a5f18c5c66bd154d052b2e2663004c0d6beacfcb55094ffb1898b7dbe3c9653815da4c11d53ac018b98fbb36fa61197de15258dc4614807c83c02f15420527508e63f8327b4c9862291810ff453b9badb3d7620d8c1aab8b5d50d6af59fc181161a5b1039090062f0c8995822be2df158447253b8abf913225c1bdef3e9a54a0589c1f69580e2565b28c75e9c4c8d738504ee8e08de414c64d8cee4864ecf9a60948515cc07680" assertEquals(expectedKeyEnc, Hex.encodeHexString(encodedKey)) } } diff --git a/bbootimg/src/test/kotlin/avb/FooterTest.kt b/bbootimg/src/test/kotlin/avb/FooterTest.kt index 78c280b..e884637 100644 --- a/bbootimg/src/test/kotlin/avb/FooterTest.kt +++ b/bbootimg/src/test/kotlin/avb/FooterTest.kt @@ -1,14 +1,10 @@ package avb import avb.blob.Footer -import cfig.bootimg.cpio.AndroidCpioEntry import org.apache.commons.codec.binary.Hex +import org.junit.Assert.assertEquals import org.junit.Test - -import org.junit.Assert.* import java.io.ByteArrayInputStream -import java.nio.file.Files -import java.nio.file.Paths @OptIn(ExperimentalUnsignedTypes::class) class FooterTest { diff --git a/bbootimg/src/test/kotlin/bootimg/AndroidCpioEntryTest.kt b/bbootimg/src/test/kotlin/bootimg/AndroidCpioEntryTest.kt index 9e8d153..2dbc4ff 100644 --- a/bbootimg/src/test/kotlin/bootimg/AndroidCpioEntryTest.kt +++ b/bbootimg/src/test/kotlin/bootimg/AndroidCpioEntryTest.kt @@ -3,7 +3,6 @@ package bootimg import cfig.bootimg.cpio.AndroidCpio import cfig.bootimg.cpio.AndroidCpioEntry import cfig.helper.Helper -import org.junit.Assert import org.junit.Assert.assertTrue import org.junit.Test @@ -13,8 +12,8 @@ class AndroidCpioEntryTest { run {//dir, fileMode 040755 val entry1 = AndroidCpioEntry(name = "acct", statMode = 0x41ed, data = byteArrayOf(), ino = 300000) val exp = Helper.fromHexString("3037303730313030303439336530303030303431656430303030303030303030303030303030303030303030303130303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030353030303030303030616363740000") - Assert.assertTrue(entry1.encode().contentEquals(exp)) - Assert.assertTrue(entry1.encode2().contentEquals(exp)) + assertTrue(entry1.encode().contentEquals(exp)) + assertTrue(entry1.encode2().contentEquals(exp)) } run {//dir, fileMode 040755 diff --git a/bbootimg/src/test/kotlin/bootloader_message/BootloaderMsgTest.kt b/bbootimg/src/test/kotlin/bootloader_message/BootloaderMsgTest.kt index 9aa3b74..ec2b55f 100644 --- a/bbootimg/src/test/kotlin/bootloader_message/BootloaderMsgTest.kt +++ b/bbootimg/src/test/kotlin/bootloader_message/BootloaderMsgTest.kt @@ -4,8 +4,6 @@ import cfig.bootimg.Common.Companion.deleleIfExists import cfig.bootloader_message.BootloaderMsg import org.junit.After import org.junit.Test - -import org.junit.Assert.* import org.slf4j.LoggerFactory import java.io.File diff --git a/bbootimg/src/test/resources/data b/bbootimg/src/test/resources/data new file mode 100644 index 0000000000000000000000000000000000000000..4972a582c5a88b900d6422e3bed65e1f55991f58 GIT binary patch literal 1024 zcmV+b1poX0u6pST@c{k)cN+&sFrr>Cr|kj|0EL*sG=ye2rCB!VG*X~GN5v^Db;Zl? zUoYbUlz&WpTQmv=S(U?kI-cd;T?C>cm{O4nf-Ac#L$+CRk%qLQHb65V7Ll73aVK}B zlz}o!1CyjYf{EaoP07k&(Be=ZSFHc4gq@Jhpc$Aj=TU z^#%EiN{&wwv;FG2^F#dcHGjzWI0iw<;zSxnhqacZ5uq$d z907PbblO^vgNhLzr5=H{7CTC`L*`-g89g1x0U>3_#wsm$W+!~oaZPPL6YSn7625Gj zE8zxdKSnRp5>+@T9^x2=#{Jc{yAtp3ya$yTS<{MPr&n#yv%n3<*_cUEx!v_nc+-aj zd~Y-n-#ng`_=H}$23svg`fFm#s1Y4|(>IVaL=l=4ux!zf;J+k=!i;MfMV>%`_Qo!v zvoDEbLmY3;Rw<$<2cRF?Do&e(*h$Ew_A%)2Hk>?;Sy-=(gc3+%tvnzq239B0XMCom zP4stld7O{d-;rsU%<@L!Yw9G~U;! ziZ|aT8})8%9!)+SaNbovwVy{2GMSNB7*kI$IIgOaX=!SFPIku}^Mn7sO8-Aad!Rbw z@3x#EbiLhoT`9M!r3bXW1TWcKk%IQ8;Fs9;OXyFd!zYp(nvy{5?c*hHBHQqrcL}+^ z8oCT+7-q+@y5xk%nl5kN=)8HnT2BJp%iP3OI66w^iD=_TVmH1$_XeNtaC`^z@Rp?M z!xpR{Y%-ekam^#QO2F=o=GygxKHaV&hU4tX+!-m&{}dQ5ldH}q5eV*22zWM*vwhQf z6SPQt4*_lsq5GJAI{Y7J!-p&UBY~A8WVm3=ueW*kVmUJ2k0p9;@cQRX;ee4_Nv+WBs;+EBEbN| z@%F>P+lCc~u%C7^#CdunWU0DaC)mGI-1AyeG2bt-Sf^K&LNQUrr!ay9qXGc{0)hbn0M?Tk1m4CA zB(d$sV&K`>B|bjQZ0jB3{|1bx=)9=SYtwjcrwXTR<_^0LnKfDe**XXo? z!`w>qP$CUb2nRCYfR`8UY6UY{=BAYFEVJ^2prmHVdX(5ZF$p?nH!d$^62NY4Lh)D_ z-~I!E%nZ~-+HBp!xFlE^NCC4YWD`%n-k8ZKcSzgyXKGXpfmF!5$_KgPM^!Ts#A}-O zZ{F<8j%nw}qR@_bCLokQnR0zR1pacF9hu*ot~j8w7k{H2TWbF49|8db0)hbn0FMm2 zSd@eZZOil8LF+r^ZYh5=o$?dxssvrd@O{PJN8(UP#IeNlLarW*N_QWU=dJbtwUa9MNB6mRRfiD@u-F4570O|hs88oP`H<{-WtCyW#0(F+HjcFBTNtPVs zqOAxo7-A$eO)H3r6sgRe?MH7gF5FJ$Tk3bck@E0NKQy`twmC#7`?TOyTgJ~$><(c= zegFe}?aLXyS&y+x7cyW?K{hgS`ZOu%e`OsJB7tT%e$vUP84FySkKHZd#R8E)%>sde z0Gxnk4`^q&#Rvr|X}T^DSmg_(X~iRQqj#>*`b>&xVy7{s?@%B>l*r?UT zWofQjN z+qr0%Y;#)55J7EtGjdx74aSIRNZLvuA3cfg=kcW}3-?Ohe|UTbd3%Dz{Ubm)=h@$h z^0YwLsa02~o`+_B=3mQ)WXwP_fX>WJrp<9hszYeD7Xa?hso~qjW(SiJU+Bp}E&;YH zGXjBtV=ArL8r`H~*_EbpVp|2xsYW66=~;8`kD4v(aiPJi8`ByM)}o1ZhZ|~p>uyzH zw4p3uqoir?dUseWHOKf>xwmY}&%k#`MgFNpFR|mPj0O9er&4Gc#l%UD4Z+(RrHVV$ f`+= 6.0, current is {}", gradle.gradleVersion) throw RuntimeException("ERROR: Gradle Version") @@ -74,20 +74,24 @@ tasks { pullTask.dependsOn("bbootimg:jar") //sparse image dependencies - if (localHack) { + if (bHackingMode) { + logger.info("Hacking mode!") + //C++ mkbootfs packTask.dependsOn("aosp:mkbootfs.10:mkbootfsExecutable") packTask.dependsOn("aosp:mkbootfs.11:mkbootfsExecutable") unpackTask.dependsOn("aosp:mkbootfs.10:mkbootfsExecutable") unpackTask.dependsOn("aosp:mkbootfs.11:mkbootfsExecutable") - } - if (System.getProperty("os.name").contains("Mac")) { - unpackTask.dependsOn("aosp:libsparse:simg2img:installReleaseMacos") - packTask.dependsOn("aosp:libsparse:img2simg:installReleaseMacos") - } else if (System.getProperty("os.name").contains("Linux")) { - unpackTask.dependsOn("aosp:libsparse:simg2img:installReleaseLinux") - packTask.dependsOn("aosp:libsparse:img2simg:installReleaseLinux") + if (System.getProperty("os.name").contains("Mac")) { + unpackTask.dependsOn("aosp:libsparse:simg2img:installReleaseMacos") + packTask.dependsOn("aosp:libsparse:img2simg:installReleaseMacos") + } else if (System.getProperty("os.name").contains("Linux")) { + unpackTask.dependsOn("aosp:libsparse:simg2img:installReleaseLinux") + packTask.dependsOn("aosp:libsparse:img2simg:installReleaseLinux") + } else { + logger.info("Disable C++ modules on Window$") + } } else { - logger.info("Disable C++ modules on Window$") + logger.info("Release mode") } } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 62d4c053550b91381bbd28b1afc82d634bf73a8a..e708b1c023ec8b20f512888fe07c5bd3ff77bb8f 100644 GIT binary patch delta 6656 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 Yte!%o?r4GTrVtxD61Ym!|5fq-1K$0e!T1w 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a4f0001..442d913 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.4.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index fbd7c51..4f906e0 100755 --- a/gradlew +++ b/gradlew @@ -130,7 +130,7 @@ fi if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath diff --git a/gradlew.bat b/gradlew.bat index db5e6df..ac1b06f 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -21,9 +21,6 @@ @rem @rem ########################################################################## -@rem set path for lz4 -@IF EXIST tools\bin SET PATH=%PATH%;tools\bin - @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal @@ -43,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -57,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -67,21 +64,6 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line @@ -89,7 +71,7 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell diff --git a/helper/build.gradle.kts b/helper/build.gradle.kts new file mode 100644 index 0000000..160daad --- /dev/null +++ b/helper/build.gradle.kts @@ -0,0 +1,32 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + id("org.jetbrains.kotlin.jvm") version "1.4.31" + `java-library` +} + +repositories { + mavenCentral() +} + +dependencies { + implementation(platform("org.jetbrains.kotlin:kotlin-bom")) + implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") + implementation("org.jetbrains.kotlin:kotlin-reflect") + implementation("com.google.guava:guava:18.0") + implementation("org.slf4j:slf4j-api:1.7.30") + implementation("org.slf4j:slf4j-simple:1.7.30") + implementation("org.apache.commons:commons-exec:1.3") + implementation("org.bouncycastle:bcprov-jdk15on:1.57") + implementation("org.apache.commons:commons-compress:1.20") + + testImplementation("org.jetbrains.kotlin:kotlin-test") + testImplementation("org.jetbrains.kotlin:kotlin-test-junit") + testImplementation("com.fasterxml.jackson.core:jackson-annotations:2.12.1") + testImplementation("com.fasterxml.jackson.core:jackson-databind:2.12.1") +} + +tasks.withType().all { + kotlinOptions.freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn" + kotlinOptions.jvmTarget = "1.8" +} diff --git a/helper/src/main/kotlin/cfig/helper/AndroidHelper.kt b/helper/src/main/kotlin/cfig/helper/AndroidHelper.kt new file mode 100644 index 0000000..4a3b004 --- /dev/null +++ b/helper/src/main/kotlin/cfig/helper/AndroidHelper.kt @@ -0,0 +1,26 @@ +package cfig.helper + +import org.apache.commons.exec.CommandLine +import org.apache.commons.exec.DefaultExecutor +import org.slf4j.LoggerFactory + +class AndroidHelper { + companion object { + private val log = LoggerFactory.getLogger(AndroidHelper::class.java) + + fun signFile(signer: String, + inFile: String, + outFile: String, + pemKey: String = "aosp/security/testkey.x509.pem", + pk8Key: String = "aosp/security/testkey.pk8") { + var cmd = "java -Xmx2048m -jar $signer " + cmd += " -w " + cmd += " $pemKey " + cmd += " $pk8Key " + cmd += " $inFile " + cmd += " $outFile " + log.info("signFile: $cmd") + DefaultExecutor().execute(CommandLine.parse(cmd)) + } + } +} diff --git a/bbootimg/src/main/kotlin/helper/Helper.kt b/helper/src/main/kotlin/cfig/helper/Helper.kt similarity index 95% rename from bbootimg/src/main/kotlin/helper/Helper.kt rename to helper/src/main/kotlin/cfig/helper/Helper.kt index d05b620..3cacab7 100644 --- a/bbootimg/src/main/kotlin/helper/Helper.kt +++ b/helper/src/main/kotlin/cfig/helper/Helper.kt @@ -1,30 +1,17 @@ package cfig.helper import cfig.io.Struct3 -import com.google.common.math.BigIntegerMath -import org.apache.commons.codec.binary.Hex -import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream -import org.apache.commons.compress.compressors.gzip.GzipParameters -import org.apache.commons.compress.compressors.xz.XZCompressorInputStream import org.apache.commons.exec.CommandLine import org.apache.commons.exec.DefaultExecutor import org.apache.commons.exec.ExecuteException import org.apache.commons.exec.PumpStreamHandler import org.slf4j.LoggerFactory import java.io.* -import java.math.BigInteger -import java.math.RoundingMode import java.nio.ByteBuffer import java.nio.ByteOrder -import java.nio.file.Files -import java.nio.file.Paths import java.nio.file.attribute.PosixFilePermission import java.security.MessageDigest import java.util.* -import java.util.zip.GZIPInputStream -import java.util.zip.GZIPOutputStream -import java.util.zip.ZipException -import javax.crypto.Cipher @OptIn(ExperimentalUnsignedTypes::class) class Helper { diff --git a/helper/src/main/kotlin/cfig/helper/KeyHelper.kt b/helper/src/main/kotlin/cfig/helper/KeyHelper.kt new file mode 100644 index 0000000..431f416 --- /dev/null +++ b/helper/src/main/kotlin/cfig/helper/KeyHelper.kt @@ -0,0 +1,148 @@ +package cfig.helper + +import cfig.io.Struct3 +import com.google.common.math.BigIntegerMath +import org.bouncycastle.util.io.pem.PemReader +import org.slf4j.LoggerFactory +import java.io.ByteArrayInputStream +import java.io.InputStreamReader +import java.math.BigInteger +import java.math.RoundingMode +import java.security.KeyFactory +import java.security.Security +import java.security.cert.CertificateFactory +import java.security.spec.PKCS8EncodedKeySpec +import java.security.spec.RSAPrivateKeySpec +import java.security.spec.RSAPublicKeySpec +import java.security.spec.X509EncodedKeySpec +import java.util.* + +/* +https://docs.oracle.com/javase/9/security/java-pki-programmers-guide.htm#JSSEC-GUID-650D0D53-B617-4055-AFD3-AF5C2629CBBF +https://www.baeldung.com/java-read-pem-file-keys + */ +@OptIn(ExperimentalUnsignedTypes::class) +class KeyHelper { + companion object { + private val log = LoggerFactory.getLogger(KeyHelper::class.java) + + fun getPemContent(keyText: String): ByteArray { + val publicKeyPEM = keyText + .replace("-----BEGIN PUBLIC KEY-----", "") + .replace("-----END PUBLIC KEY-----", "") + .replace("-----BEGIN RSA PRIVATE KEY-----", "") + .replace("-----END RSA PRIVATE KEY-----", "") + .replace(System.lineSeparator().toRegex(), "") + .replace("\n", "") + .replace("\r", "") + return Base64.getDecoder().decode(publicKeyPEM) + } + + /* + in: modulus, public expo + out: PublicKey + + in: modulus, private expo + out: PrivateKey + */ + fun makeKey(modulus: BigInteger, exponent: BigInteger, isPublicExpo: Boolean): Any { + return if (isPublicExpo) { + KeyFactory.getInstance("RSA").generatePublic(RSAPublicKeySpec(modulus, exponent)) + } else { + KeyFactory.getInstance("RSA").generatePrivate(RSAPrivateKeySpec(modulus, exponent)) + } + } + + fun parse(data: ByteArray): Any { + val p = PemReader(InputStreamReader(ByteArrayInputStream(data))).readPemObject() + return if (p != null) { + log.debug("parse PEM: " + p.type) + when (p.type) { + "RSA PUBLIC KEY" -> { + org.bouncycastle.asn1.pkcs.RSAPublicKey.getInstance(p.content) as org.bouncycastle.asn1.pkcs.RSAPublicKey + } + "RSA PRIVATE KEY" -> { + org.bouncycastle.asn1.pkcs.RSAPrivateKey.getInstance(p.content) as org.bouncycastle.asn1.pkcs.RSAPrivateKey + } + "PUBLIC KEY" -> { + val keySpec = X509EncodedKeySpec(p.content) + KeyFactory.getInstance("RSA").generatePublic(keySpec) as java.security.interfaces.RSAPublicKey + } + "PRIVATE KEY" -> { + val keySpec = PKCS8EncodedKeySpec(p.content) + KeyFactory.getInstance("RSA").generatePrivate(keySpec) as java.security.interfaces.RSAPrivateKey + } + "CERTIFICATE" -> { + CertificateFactory.getInstance("X.509").generateCertificate(ByteArrayInputStream(p.content)) + } + else -> throw IllegalArgumentException("unsupported type: ${p.type}") + } + } else { + try { + val spec = PKCS8EncodedKeySpec(data) + val privateKey = KeyFactory.getInstance("RSA").generatePrivate(spec) + log.debug("Parse PKCS8: Private") + privateKey + } catch (e: java.security.spec.InvalidKeySpecException) { + log.debug("Parse X509: Public") + val spec = X509EncodedKeySpec(data) + KeyFactory.getInstance("RSA").generatePublic(spec) + } + } + } + + /* + read RSA private key + assert exp == 65537 + num_bits = log2(modulus) + + @return: AvbRSAPublicKeyHeader formatted bytearray + https://android.googlesource.com/platform/external/avb/+/master/libavb/avb_crypto.h#158 + from avbtool::encode_rsa_key() + */ + fun encodeRSAkey(rsa: org.bouncycastle.asn1.pkcs.RSAPrivateKey): ByteArray { + assert(65537.toBigInteger() == rsa.publicExponent) + val numBits: Int = BigIntegerMath.log2(rsa.modulus, RoundingMode.CEILING) + assert(rsa.modulus.bitLength() == numBits) + val b = BigInteger.valueOf(2).pow(32) + val n0inv = b.minus(rsa.modulus.modInverse(b)).toLong() + val rrModn = BigInteger.valueOf(4).pow(numBits).rem(rsa.modulus) + val unsignedModulo = rsa.modulus.toByteArray().sliceArray(1..numBits / 8) //remove sign byte + return Struct3("!II${numBits / 8}b${numBits / 8}b").pack( + numBits, + n0inv, + unsignedModulo, + rrModn.toByteArray() + ) + } + + fun decodeRSAkey(key: ByteArray): java.security.interfaces.RSAPublicKey { + val ret = Struct3("!II").unpack(ByteArrayInputStream(key)) + val numBits = (ret[0] as UInt).toInt() + val n0inv = (ret[1] as UInt).toLong() + val ret2 = Struct3("!II${numBits / 8}b${numBits / 8}b").unpack(ByteArrayInputStream(key)) + val unsignedModulo = ret2[2] as ByteArray + val rrModn = BigInteger(ret2[3] as ByteArray) + log.debug("n0inv=$n0inv, unsignedModulo=${Helper.toHexString(unsignedModulo)}, rrModn=$rrModn") + val exponent = 65537L + val modulus = BigInteger(Helper.join(Struct3("x").pack(0), unsignedModulo)) + val keySpec = RSAPublicKeySpec(modulus, BigInteger.valueOf(exponent)) + return KeyFactory.getInstance("RSA").generatePublic(keySpec) as java.security.interfaces.RSAPublicKey + } + + fun listAll() { + Security.getProviders().forEach { + val sb = StringBuilder("Provider: " + it.name + "{") + it.stringPropertyNames().forEach { key -> + sb.append(" (k=" + key + ",v=" + it.getProperty(key) + "), ") + } + sb.append("}") + log.info(sb.toString()) + } + + for ((i, item) in Security.getAlgorithms("Cipher").withIndex()) { + log.info("Cipher: $i -> $item") + } + } + } +} diff --git a/bbootimg/src/main/kotlin/helper/KeyHelper2.kt b/helper/src/main/kotlin/cfig/helper/KeyHelper2.kt similarity index 58% rename from bbootimg/src/main/kotlin/helper/KeyHelper2.kt rename to helper/src/main/kotlin/cfig/helper/KeyHelper2.kt index c53fcb5..4d64f4e 100644 --- a/bbootimg/src/main/kotlin/helper/KeyHelper2.kt +++ b/helper/src/main/kotlin/cfig/helper/KeyHelper2.kt @@ -1,6 +1,5 @@ package cfig.helper -import org.apache.commons.codec.binary.Hex import org.apache.commons.exec.CommandLine import org.apache.commons.exec.DefaultExecutor import org.apache.commons.exec.ExecuteException @@ -8,12 +7,10 @@ import org.apache.commons.exec.PumpStreamHandler import org.slf4j.LoggerFactory import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream -import java.math.BigInteger -import java.security.* -import java.security.spec.PKCS8EncodedKeySpec -import java.security.spec.RSAPrivateKeySpec -import java.security.spec.RSAPublicKeySpec -import java.security.spec.X509EncodedKeySpec +import java.security.MessageDigest +import java.security.PrivateKey +import java.security.PublicKey +import java.security.Signature import java.util.* import javax.crypto.Cipher @@ -21,66 +18,6 @@ class KeyHelper2 { companion object { private val log = LoggerFactory.getLogger(KeyHelper2::class.java) - fun parseRsaPk8(inputData: ByteArray): java.security.PrivateKey { - val spec = PKCS8EncodedKeySpec(inputData) - return KeyFactory.getInstance("RSA").generatePrivate(spec) - } - - fun parseRsaKey(keyText: String): PrivateKey { - val publicKeyPEM = keyText - .replace("-----BEGIN RSA PRIVATE KEY-----", "") - .replace(System.lineSeparator().toRegex(), "") - .replace("\n", "") - .replace("\r", "") - .replace("-----END RSA PRIVATE KEY-----", "") - log.warn("trimmed key") - log.warn(publicKeyPEM) - val encoded: ByteArray = Base64.getDecoder().decode(publicKeyPEM) - val keySpec = X509EncodedKeySpec(encoded) - return KeyFactory.getInstance("RSA").generatePrivate(keySpec) - } - - fun parsePemPubkey(keyText: String): java.security.interfaces.RSAPublicKey { - val publicKeyPEM = keyText - .replace("-----BEGIN PUBLIC KEY-----", "") - .replace(System.lineSeparator().toRegex(), "") - .replace("\n", "") - .replace("\r", "") - .replace("-----END PUBLIC KEY-----", "") - val encoded: ByteArray = Base64.getDecoder().decode(publicKeyPEM) - val keySpec = X509EncodedKeySpec(encoded) - return KeyFactory.getInstance("RSA").generatePublic(keySpec) as java.security.interfaces.RSAPublicKey - } - - - fun parsePemPubCert(keyText: String) { - val publicKeyPEM = keyText - .replace("-----BEGIN CERTIFICATE-----", "") - .replace(System.lineSeparator().toRegex(), "") - .replace("\n", "") - .replace("\r", "") - .replace("-----END CERTIFICATE-----", "") - val encoded: ByteArray = Base64.getDecoder().decode(publicKeyPEM) - val keySpec = X509EncodedKeySpec(encoded) -// return KeyFactory.getInstance("RSA").generatePublic(keySpec) as java.security.interfaces.RSAPublicKey - } - - /* - in: modulus, expo - out: PublicKey - */ - fun generateRsaPublicKey(modulus: BigInteger, publicExponent: BigInteger): java.security.PublicKey { - return KeyFactory.getInstance("RSA").generatePublic(RSAPublicKeySpec(modulus, publicExponent)) - } - - /* - in: modulus, expo - out: PrivateKey - */ - fun generateRsaPrivateKey(modulus: BigInteger, privateExponent: BigInteger): java.security.PrivateKey { - return KeyFactory.getInstance("RSA").generatePrivate(RSAPrivateKeySpec(modulus, privateExponent)) - } - //inspired by // https://stackoverflow.com/questions/40242391/how-can-i-sign-a-raw-message-without-first-hashing-it-in-bouncy-castle // "specifying Cipher.ENCRYPT mode or Cipher.DECRYPT mode doesn't make a difference; @@ -93,9 +30,8 @@ class KeyHelper2 { } } - fun rawSignOpenSsl(keyPath: String, data: ByteArray): ByteArray { - log.debug("raw input: " + Hex.encodeHexString(data)) + log.debug("raw input: " + Helper.toHexString(data)) log.debug("Raw sign data size = ${data.size}, key = $keyPath") var ret = byteArrayOf() val exe = DefaultExecutor() @@ -110,7 +46,7 @@ class KeyHelper2 { } catch (e: ExecuteException) { log.error("Execute error") } finally { - log.debug("OUT: " + Hex.encodeHexString(stdout.toByteArray())) + log.debug("OUT: " + Helper.toHexString(stdout.toByteArray())) log.debug("ERR: " + String(stderr.toByteArray())) } diff --git a/bbootimg/src/main/kotlin/helper/OpenSslHelper.kt b/helper/src/main/kotlin/cfig/helper/OpenSslHelper.kt similarity index 100% rename from bbootimg/src/main/kotlin/helper/OpenSslHelper.kt rename to helper/src/main/kotlin/cfig/helper/OpenSslHelper.kt diff --git a/bbootimg/src/main/kotlin/helper/ZipHelper.kt b/helper/src/main/kotlin/cfig/helper/ZipHelper.kt similarity index 57% rename from bbootimg/src/main/kotlin/helper/ZipHelper.kt rename to helper/src/main/kotlin/cfig/helper/ZipHelper.kt index d983e56..09c6021 100644 --- a/bbootimg/src/main/kotlin/helper/ZipHelper.kt +++ b/helper/src/main/kotlin/cfig/helper/ZipHelper.kt @@ -1,28 +1,25 @@ package cfig.helper -import cfig.bootimg.cpio.AndroidCpioEntry import cfig.helper.Helper.Companion.check_call import cfig.helper.Helper.Companion.check_output import cfig.io.Struct3 -import com.fasterxml.jackson.databind.ObjectMapper -import org.apache.commons.compress.archivers.cpio.CpioArchiveInputStream -import org.apache.commons.compress.archivers.cpio.CpioConstants -import org.apache.commons.compress.archivers.zip.* +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry +import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream +import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream +import org.apache.commons.compress.archivers.zip.ZipFile +import org.apache.commons.compress.archivers.zip.ZipMethod import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream import org.apache.commons.compress.compressors.gzip.GzipParameters -import org.apache.commons.compress.compressors.lz4.FramedLZ4CompressorInputStream import org.apache.commons.compress.compressors.xz.XZCompressorInputStream -import org.apache.commons.compress.utils.IOUtils import org.apache.commons.exec.CommandLine import org.apache.commons.exec.DefaultExecutor import org.apache.commons.exec.PumpStreamHandler import org.slf4j.LoggerFactory import java.io.* -import java.lang.IllegalArgumentException +import java.lang.RuntimeException import java.net.URI import java.nio.file.FileSystems import java.nio.file.Files -import java.nio.file.Paths import java.nio.file.StandardCopyOption import java.util.zip.GZIPInputStream import java.util.zip.GZIPOutputStream @@ -36,132 +33,42 @@ class ZipHelper { companion object { private val log = LoggerFactory.getLogger("ZipHelper") - fun unZipFile2(fileName: String, outDir: String) { - val zis = ZipArchiveInputStream(BufferedInputStream(FileInputStream(fileName))) - while (true) { - val entry = zis.nextZipEntry ?: break - val entryOut = File(outDir + "/" + entry.name) - when { - entry.isDirectory -> { - log.error("Found dir : " + entry.name) - throw IllegalArgumentException("this should not happen") - } - entry.isUnixSymlink -> { - log.error("Found link: " + entry.name) - throw IllegalArgumentException("this should not happen") - } - else -> { - if (entry.name.contains("/")) { - log.debug("Createing dir: " + entryOut.parentFile.canonicalPath) - entryOut.parentFile.mkdirs() - } - log.info("Unzipping " + entry.name) - IOUtils.copy(zis, FileOutputStream(entryOut)) - } - } - } - } - /* - https://github.com/python/cpython/blob/3.8/Lib/zipfile.py - The "local file header" structure, magic number, size, and indices - (section V.A in the format document) - structFileHeader = "<4s2B4HL2L2H" - stringFileHeader = b"PK\003\004" - sizeFileHeader = struct.calcsize(structFileHeader) - */ - fun ZipArchiveEntry.getEntryOffset(): Long { - val zipFileHeaderSize = Struct3("<4s2B4HL2L2H").calcSize() - val funGetLocalHeaderOffset = ZipArchiveEntry::class.declaredFunctions.filter { funcItem -> - funcItem.name == "getLocalHeaderOffset" - }[0] - funGetLocalHeaderOffset.isAccessible = true - val headerOffset = funGetLocalHeaderOffset.call(this) as Long - val offset: Long = headerOffset + zipFileHeaderSize + this.localFileDataExtra.size + this.name.length - log.debug("headerOffset = $headerOffset") - log.debug("calcSize: $zipFileHeaderSize") - return offset - } - - fun dumpZipEntry(inFile: String, entryName: String, outFile: String) { - log.info("dumping: $inFile#$entryName -> $outFile") - val zf = ZipFile(inFile) - val entry = zf.getEntry(entryName) - FileOutputStream(outFile).use { outStream -> - zf.getInputStream(entry).copyTo(outStream) - } - zf.close() - } - - fun getEntryStream(zipFile: ZipFile, entryName: String): InputStream { - return zipFile.getInputStream(zipFile.getEntry(entryName)) - } - - fun ZipFile.dumpEntryIfExists(entryName: String, outFile: File) { - val entry = this.getEntry(entryName) - if (entry != null) { - log.info("dumping entry: $entryName -> $outFile") - FileOutputStream(outFile).use { outStream -> - this.getInputStream(entry).copyTo(outStream) + unzip(): unzip fileName to outDir + */ + fun unzip(fileName: String, outDir: String) { + log.info("unzip: $fileName --> $outDir") + if (File(outDir).exists()) { + if (!File(outDir).isDirectory) { + throw RuntimeException("$outDir exists but is not directory") } } else { - log.info("dumping entry: $entryName : entry not found, skip") - } - } - - fun ZipFile.dumpEntry(entryName: String, outFile: File) { - log.info("dumping entry: $entryName -> $outFile") - val entry = this.getEntry(entryName) - FileOutputStream(outFile).use { outStream -> - this.getInputStream(entry).copyTo(outStream) + log.info("Creating $outDir ...") + File(outDir).mkdirs() } - } - - fun ZipFile.dumpEntry(entryName: String, outFile: String) { - log.info("dumping entry: $entryName -> $outFile") - val entry = this.getEntry(entryName) - FileOutputStream(outFile).use { outStream -> - this.getInputStream(entry).copyTo(outStream) + ZipArchiveInputStream(FileInputStream(fileName)).use { zis -> + while (true) { + val entry = zis.nextZipEntry ?: break + when { + entry.isDirectory -> { + val entryOut = File(outDir + "/" + entry.name) + entryOut.mkdir() + log.debug("Unzipping[d]: ${entry.name}") + } + entry.isUnixSymlink -> { + throw IllegalArgumentException("this should not happen: Found dir ${entry.name}") + } + else -> { + val entryOut = File(outDir + "/" + entry.name) + log.debug("Unzipping[f]: ${entry.name}") + FileOutputStream(entryOut).use { + zis.copyTo(it) + } + } + } + } } - } - - fun ZipArchiveOutputStream.packFile( - inFile: File, - entryName: String, - zipMethod: ZipMethod = ZipMethod.DEFLATED - ) { - log.info("packing $entryName($zipMethod) from file $inFile (size=${inFile.length()} ...") - val entry = ZipArchiveEntry(inFile, entryName) - entry.method = zipMethod.ordinal - this.putArchiveEntry(entry) - IOUtils.copy(Files.newInputStream(inFile.toPath()), this) - this.closeArchiveEntry() - } - - fun ZipArchiveOutputStream.packEntry( - inBuf: ByteArray, - entryName: String, - zipMethod: ZipMethod = ZipMethod.DEFLATED - ) { - log.info("packing $entryName($zipMethod) from memory data (size=${inBuf.size}...") - val entry = ZipArchiveEntry(entryName) - entry.method = zipMethod.ordinal - this.putArchiveEntry(entry) - IOUtils.copy(ByteArrayInputStream(inBuf), this) - this.closeArchiveEntry() - } - - fun ZipArchiveOutputStream.packStream( - inStream: InputStream, - entryName: String, - zipMethod: ZipMethod = ZipMethod.DEFLATED - ) { - log.info("packing $entryName($zipMethod) from input stream (size=unknown...") - val entry = ZipArchiveEntry(entryName) - entry.method = zipMethod.ordinal - this.putArchiveEntry(entry) - IOUtils.copy(inStream, this) - this.closeArchiveEntry() + log.info("unzip: $fileName --> $outDir Done.") } fun zipDelete(zipFile: File, entryName: String) { @@ -181,7 +88,7 @@ class ZipHelper { while (e.hasMoreElements()) { val entry = e.nextElement() zaos.putArchiveEntry(entry) - IOUtils.copy(zf.getInputStream(entry), zaos) + zf.getInputStream(entry).copyTo(zaos) zaos.closeArchiveEntry() } zaos.finish() @@ -200,7 +107,7 @@ class ZipHelper { val entry = ZipArchiveEntry(entryRecipe.name) entry.method = entryRecipe.method.ordinal zaos.putArchiveEntry(entry) - IOUtils.copy(ByteArrayInputStream(entryRecipe.data), zaos) + ByteArrayInputStream(entryRecipe.data).copyTo(zaos) } while (e.hasMoreElements()) { @@ -208,10 +115,10 @@ class ZipHelper { zaos.putArchiveEntry(entry) if (entry.name == entryRecipe.name) { log.info("modifying existent entry [${entryRecipe.name}(${entryRecipe.method})] into [${tmpFile.canonicalPath}]") - IOUtils.copy(ByteArrayInputStream(entryRecipe.data), zaos) + ByteArrayInputStream(entryRecipe.data).copyTo(zaos) } else { log.debug("cloning entry ${entry.name} ...") - IOUtils.copy(zf.getInputStream(entry), zaos) + zf.getInputStream(entry).copyTo(zaos) } zaos.closeArchiveEntry() } @@ -224,19 +131,71 @@ class ZipHelper { log.info("renaming ${tmpFile.canonicalPath} --> $inFile done") } - fun isGZ(compressedFile: String): Boolean { - return try { - FileInputStream(compressedFile).use { fis -> - GZIPInputStream(fis).use { - } + + /* + https://github.com/python/cpython/blob/3.8/Lib/zipfile.py + The "local file header" structure, magic number, size, and indices + (section V.A in the format document) + structFileHeader = "<4s2B4HL2L2H" + stringFileHeader = b"PK\003\004" + sizeFileHeader = struct.calcsize(structFileHeader) + */ + fun ZipArchiveEntry.getEntryOffset(): Long { + val zipFileHeaderSize = Struct3("<4s2B4HL2L2H").calcSize() + val funGetLocalHeaderOffset = ZipArchiveEntry::class.declaredFunctions.filter { funcItem -> + funcItem.name == "getLocalHeaderOffset" + }[0] + funGetLocalHeaderOffset.isAccessible = true + val headerOffset = funGetLocalHeaderOffset.call(this) as Long + val offset: Long = headerOffset + zipFileHeaderSize + this.localFileDataExtra.size + this.name.length + log.debug("headerOffset = $headerOffset") + log.debug("calcSize: $zipFileHeaderSize") + return offset + } + + fun ZipFile.dumpEntry(entryName: String, outFile: File, ignoreError: Boolean = false) { + val entry = this.getEntry(entryName) + if (entry != null) { + log.info("dumping entry: $entryName -> $outFile") + FileOutputStream(outFile).use { outStream -> + this.getInputStream(entry).copyTo(outStream) + } + } else { + if (ignoreError) { + log.info("dumping entry: $entryName : entry not found, skip") + } else { + throw IllegalArgumentException("$entryName doesn't exist") } - true - } catch (e: ZipException) { - false } } - fun isXZ(compressedFile: String): Boolean { + fun ZipArchiveOutputStream.pack( + inFile: File, + entryName: String, + zipMethod: ZipMethod = ZipMethod.DEFLATED + ) { + log.info("packing $entryName($zipMethod) from file $inFile (size=${inFile.length()} ...") + val entry = ZipArchiveEntry(inFile, entryName) + entry.method = zipMethod.ordinal + this.putArchiveEntry(entry) + Files.newInputStream(inFile.toPath()).copyTo(this) + this.closeArchiveEntry() + } + + fun ZipArchiveOutputStream.pack( + inStream: InputStream, + entryName: String, + zipMethod: ZipMethod = ZipMethod.DEFLATED + ) { + log.info("packing $entryName($zipMethod) from input stream (size=unknown...") + val entry = ZipArchiveEntry(entryName) + entry.method = zipMethod.ordinal + this.putArchiveEntry(entry) + inStream.copyTo(this) + this.closeArchiveEntry() + } + + fun isXz(compressedFile: String): Boolean { return try { FileInputStream(compressedFile).use { fis -> XZCompressorInputStream(fis).use { @@ -248,7 +207,7 @@ class ZipHelper { } } - fun isLZ4(compressedFile: String): Boolean { + fun isLz4(compressedFile: String): Boolean { return try { "lz4 -t $compressedFile".check_call() true @@ -257,11 +216,11 @@ class ZipHelper { } } - fun decompressLZ4Ext(lz4File: String, outFile: String) { + fun lz4cat(lz4File: String, outFile: String) { "lz4 -d -fv $lz4File $outFile".check_call() } - fun compressLZ4(lz4File: String, inputStream: InputStream) { + fun lz4(lz4File: String, inputStream: InputStream) { FileOutputStream(File(lz4File)).use { fos -> val baosE = ByteArrayOutputStream() DefaultExecutor().let { exec -> @@ -283,51 +242,28 @@ class ZipHelper { } } - fun decompressLZ4(framedLz4: String, outFile: String) { - FramedLZ4CompressorInputStream( - Files.newInputStream(Paths.get(framedLz4)) - ).use { zIn -> - Files.newOutputStream(Paths.get(outFile)).use { out -> - log.info("decompress lz4: $framedLz4 -> $outFile") - val buffer = ByteArray(8192) - var n: Int - while (-1 != zIn.read(buffer).also { n = it }) { - out.write(buffer, 0, n) + fun isGZ(compressedFile: String): Boolean { + return try { + FileInputStream(compressedFile).use { fis -> + GZIPInputStream(fis).use { } } + true + } catch (e: ZipException) { + false } } - @Throws(IOException::class) - fun gnuZipFile(compressedFile: String, decompressedFile: String) { - val buffer = ByteArray(1024) - FileOutputStream(compressedFile).use { fos -> - GZIPOutputStream(fos).use { gos -> - FileInputStream(decompressedFile).use { fis -> - var bytesRead: Int - while (true) { - bytesRead = fis.read(buffer) - if (bytesRead <= 0) break - gos.write(buffer, 0, bytesRead) - } - gos.finish() - log.info("gzip done: $decompressedFile -> $compressedFile") - }//file-input-stream - }//gzip-output-stream - }//file-output-stream - } - - @Throws(IOException::class) - fun unGnuzipFile(compressedFile: String, decompressedFile: String) { - val buffer = ByteArray(1024) + /* + @function: zcat compressedFile > decompressedFile + */ + fun zcat(compressedFile: String, decompressedFile: String) { FileInputStream(compressedFile).use { fileIn -> - //src GZIPInputStream(fileIn).use { gZIPInputStream -> - //src FileOutputStream(decompressedFile).use { fileOutputStream -> - var bytesRead: Int + val buffer = ByteArray(1024) while (true) { - bytesRead = gZIPInputStream.read(buffer) + val bytesRead = gZIPInputStream.read(buffer) if (bytesRead <= 0) break fileOutputStream.write(buffer, 0, bytesRead) } @@ -338,49 +274,51 @@ class ZipHelper { } /* - caution: about gzip header - OS (Operating System) + @function: gzip InputStream to file, + using java.util.zip.GZIPOutputStream - According to https://docs.oracle.com/javase/8/docs/api/java/util/zip/package-summary.html and - GZIP spec RFC-1952(http://www.ietf.org/rfc/rfc1952.txt), gzip files created from java.util.zip.GZIPOutputStream - will mark the OS field with + caution: about gzip header - OS (Operating System) + According to https://docs.oracle.com/javase/8/docs/api/java/util/zip/package-summary.html + and GZIP spec RFC-1952(http://www.ietf.org/rfc/rfc1952.txt), + gzip files created from java.util.zip.GZIPOutputStream will mark the OS field with 0 - FAT filesystem (MS-DOS, OS/2, NT/Win32) But default image built from Android source code has the OS field: 3 - Unix - This MAY not be a problem, at least we didn't find it till now. */ - @Throws(IOException::class) - @Deprecated("this function misses features") - fun gnuZipFile(compressedFile: String, fis: InputStream) { - val buffer = ByteArray(1024) + fun gzip(compressedFile: String, fis: InputStream) { FileOutputStream(compressedFile).use { fos -> GZIPOutputStream(fos).use { gos -> - var bytesRead: Int + val buffer = ByteArray(1024) while (true) { - bytesRead = fis.read(buffer) + val bytesRead = fis.read(buffer) if (bytesRead <= 0) break gos.write(buffer, 0, bytesRead) } - log.info("compress(gz) done: $compressedFile") } } + log.info("compress(gz) done: $compressedFile") } - fun gnuZipFile2(compressedFile: String, fis: InputStream) { - val buffer = ByteArray(1024) - val p = GzipParameters() - p.operatingSystem = 3 + /* + @function: gzip InputStream to file like Android minigzip, + using commons.compress GzipCompressorOutputStream, + @dependency: commons.compress + */ + fun minigzip(compressedFile: String, fis: InputStream) { + val param = GzipParameters().apply { + operatingSystem = 3 //3: Unix + } FileOutputStream(compressedFile).use { fos -> - GzipCompressorOutputStream(fos, p).use { gos -> - var bytesRead: Int + GzipCompressorOutputStream(fos, param).use { gos -> + val buffer = ByteArray(1024) while (true) { - bytesRead = fis.read(buffer) + val bytesRead = fis.read(buffer) if (bytesRead <= 0) break gos.write(buffer, 0, bytesRead) } - log.info("compress(gz) done: $compressedFile") } } + log.info("compress(gz) done: $compressedFile") } - } } diff --git a/bbootimg/src/main/kotlin/cfig/io/Struct3.kt b/helper/src/main/kotlin/cfig/io/Struct3.kt similarity index 100% rename from bbootimg/src/main/kotlin/cfig/io/Struct3.kt rename to helper/src/main/kotlin/cfig/io/Struct3.kt diff --git a/helper/src/test/kotlin/cfig/helper/OpenSslHelperTest.kt b/helper/src/test/kotlin/cfig/helper/OpenSslHelperTest.kt new file mode 100644 index 0000000..4b15def --- /dev/null +++ b/helper/src/test/kotlin/cfig/helper/OpenSslHelperTest.kt @@ -0,0 +1,103 @@ +package cfig.helper + +import cfig.helper.OpenSslHelper.Companion.decodePem +import org.junit.Test +import org.slf4j.LoggerFactory +import kotlin.test.assertTrue + +class OpenSslHelperTest { + private val log = LoggerFactory.getLogger(OpenSslHelperTest::class.java) + + @Test + fun PKCS1test() { + //private RSA key + val rsa = OpenSslHelper.PK1Key.generate(4096).apply { + val fileName = "1_rsa.key" + writeTo(fileName) + } + + //Action-1: private RSA key -> RSA public key(PEM) + val rsaPubPEM = rsa.getPublicKey(OpenSslHelper.KeyFormat.PEM).apply { + writeTo("2_rsa_pub.pem.key") + } + //Action-3: RSA public key(PEM) --> RSA public key(DER) + val decodeFromPem = decodePem(String(rsaPubPEM.data)) + + //Action-2: private RSA key -> RSA public key(DER) + val rsaPubDer = rsa.getPublicKey(OpenSslHelper.KeyFormat.DER).apply { + writeTo("3_rsa_pub.der.key") + } + + //check equality: 1,3 == 2 + assertTrue(decodeFromPem.contentEquals(rsaPubDer.data)) + } + + @Test + fun PKCS8Test() { + //private RSA key + val rsa = OpenSslHelper.PK1Key.generate(4096) + + run { //check equality: 8 == 4,5 + val pk8Pub = rsa.getPk8PublicKey() + val pk8Pub2 = rsa.toPk8(OpenSslHelper.KeyFormat.PEM).getPublicKey() + assert(pk8Pub.data.contentEquals(pk8Pub2.data)) + } + + run { //check equality: 8 == 4,5 + val pk8Pub = rsa.getPk8PublicKey() + val action8_11 = decodePem(String(pk8Pub.data)) +// val pk8Pub2 = rsa.toPk8(OpenSslHelper.KeyFormat.PEM).getPublicKey() +// assert(pk8Pub.data.contentEquals(pk8Pub2.data)) + } + + //check equality: 4,9 == original RSA + rsa.toPk8(OpenSslHelper.KeyFormat.PEM).let { pk8Pem -> + val shortConversion = pk8Pem.toPk1() + assert(shortConversion.data.contentEquals(rsa.data)) + } + + //check equality: 7,10,9 == original RSA + rsa.toPk8(OpenSslHelper.KeyFormat.DER).let { pk8der -> + val longConversion = pk8der + .transform(OpenSslHelper.KeyFormat.DER, OpenSslHelper.KeyFormat.PEM) //pk8 PEM + .toPk1() //pk1 PEM + assert(longConversion.data.contentEquals(rsa.data)) + } + } + + @Test + fun CertTest() { + //private RSA key + val rsa = OpenSslHelper.PK1Key.generate(4096) + val crt = rsa.toV1Cert() + val jks = crt.toJks() + //jks.writeTo("good.jks") + val pfx = OpenSslHelper.Pfx(name = "androiddebugkey", thePassword = "somepassword") + pfx.generate(rsa, crt) + val jks2 = pfx.toJks() + } + + @Test + fun androidCertTest() { + //platform.x509.pem: Certificate, PEM + val crt = OpenSslHelper.Crt(data = this.javaClass.classLoader.getResourceAsStream("platform.x509.pem").readBytes()) + val jks = crt.toJks() + //jks.writeTo("platform.jks") + jks.check() + } + + @Test + fun androidPk8Test() { + //platform.pk8: Private Key, PKCS#8, DER encoding + val pk8rsa = OpenSslHelper.PK8RsaKey(OpenSslHelper.KeyFormat.DER, + this.javaClass.classLoader.getResourceAsStream("platform.pk8").readBytes()) + val pk1 = pk8rsa + .transform(OpenSslHelper.KeyFormat.DER, OpenSslHelper.KeyFormat.PEM) + .toPk1() + val crt = OpenSslHelper.Crt(data = this.javaClass.classLoader.getResourceAsStream("platform.x509.pem").readBytes()) + val pfx = OpenSslHelper.Pfx(name = "androiddebugkey", thePassword = "somepassword").apply { + this.generate(pk1, crt) + } + pfx.toJks().writeTo("platform.jks") + } +} diff --git a/helper/src/test/kotlin/cfig/helper/ZipHelperTest.kt b/helper/src/test/kotlin/cfig/helper/ZipHelperTest.kt new file mode 100644 index 0000000..46bf771 --- /dev/null +++ b/helper/src/test/kotlin/cfig/helper/ZipHelperTest.kt @@ -0,0 +1,38 @@ +package cfig.helper + +import cfig.helper.ZipHelper.Companion.dumpEntry +import org.apache.commons.compress.archivers.zip.ZipFile +import org.junit.After +import org.junit.Before +import org.junit.Test +import java.io.File + +class ZipHelperTest { + + @Before + fun setUp() { + File("out").let { + if (!it.exists()) it.mkdir() + } + } + + @After + fun tearDown() { + File("out").deleteRecursively() + } + + @Test + fun unzip() { + val zf = ZipHelperTest::class.java.classLoader.getResource("appcompat.zip").file + ZipHelper.unzip(File(zf).path, "out") + File("out").deleteRecursively() + } + + @Test + fun dumpEntry() { + val zf = ZipHelperTest::class.java.classLoader.getResource("appcompat.zip").file + ZipFile(zf).use { + it.dumpEntry("webview.log", File("out/webview.log")) + } + } +} \ No newline at end of file diff --git a/bbootimg/src/test/kotlin/cfig/io/Struct3Test.kt b/helper/src/test/kotlin/cfig/io/Struct3Test.kt similarity index 100% rename from bbootimg/src/test/kotlin/cfig/io/Struct3Test.kt rename to helper/src/test/kotlin/cfig/io/Struct3Test.kt diff --git a/helper/src/test/resources/appcompat.zip b/helper/src/test/resources/appcompat.zip new file mode 100644 index 0000000000000000000000000000000000000000..a06e03cfc76dd43574dae519b657075aea18b289 GIT binary patch literal 255157 zcmbTdQ+(cg_Wm6=PGdB-Z8c6B+qP}nw$a$O(bzT`J89H3=>Jal?3vy9&Aetm&%vFu z9KF|dt+lT2`p8Ovf}sEb0YL(O1nj=P-!v0}fq?Kqfq-y@D@&Xf16_loX+WK!K3lMBjc+t}sBrU`K#|{Po96zPAdQ0hT+V`U=oqk#`k@e*T=>3-ZW<~5Lre=rT=irXbsa36y+ z%d}|H;p?iJLUBaNQ(s=;Df0mA+9|auiJ(nqaRnawz&(U3r-GELUCxSuzdz>-0++JE zQ|}$|3vkd6d!A43UH*kW0j?>+3>zgJpmm8hLxz#3q>7+8tL#8*=cuP*t10G49rxYF zuN~IqxK{249wGaC*va}`E5KQjV@0!$wmLc4AK|XbP{D=rH&*R)q5UQkTgC@BdZl{} zg2jW%+s?h;Id}R>m%PVdq?(3#ECN$5rLo8~15ZxUiw^4$LGIRFw~$QiK1&VMizbYa z``N?U>_-vImptkHpv_CYK;Hu)KTZbiOC)mRZiJde*=*OAZ+poqQDsmlQ5V&GNT3$) za=CSW7fEN~tw~E~A6&-%009aE3km3IuYda@BD?NKN zYootSyVm*x18i1#_4YDI7uQrXrtmvZt6c&QK8f2b-K-L^MC6}drK?g|i^JsKIz_ug z&!=(i2t!+@A(K;Z^T*D#=$L5cHQ+NnJgZuC@8iZ1oLMxlwuvlhO=BfTw^SwMx>zR< zqQ2RF#=f%bs{aB6W%QckI$ZY9_oy1ogN8M0RLOW1q#2A**jx)4T+S}aM|*tyUa`JB zs4m|tOJtieKsQ?~IB_93X@~9L+zH3oXEEf%ZEEzOu6TMb?MzCml!TJV&CSmB8sw#V z7awBv)8Y|%Kt3|KbVS)h4QdSrfx=g6mdQdJIT zwo2bb1wJ-dFJ&=i1xR=BKJZ_<-Mr3Spn0Bu*JjwD;>{4XPR>&c#hCn}lVDav>O-i? zK37RJpO5O)2vT1izKfN4vMP(y%kO|MrrANR!T=?KOnk)IT_Cw=q4RTiKHw4jci@8* zhv4x5;D`X=AASceV5w(d@i$pJ$@4g@(Zgnq>G&~p))P;yu4}*BDhvxb<4Fx9$)@lp z;b(h&05@oMN;f3F;=Ka8_|K@Hykt`!C#!;CP&@-Cz#-#5m42|G7+r$+IXfLgHVQm- zkWB+2Mt-9)Nl-pdH#x+3Ry!R_+n?x1x5wyN&=w_3uj#}AV*lwQJpX>1Iyu+sk{MVP zBjiDtp_p1oGh>JDYgZMojV155a|WEK-b6<^^No~Nw*tz1H&@RetbOIlbg~1di7cF> z+ebovbD#ToEWxQoh7;K%R?eDo9nfPj!LbDmf!#?pg7~OfMXq5g`C{@j1@Wo04cMaH zCa(8$ID`9YzRRzMzvkZ=!_~V)-;%eVYdx-)SqHL!;l=C$k=?fKCn+0FY8F3=^m(c` zJ4mNZ^5axbrP$d2LHXi)r@njj_c?C62v{0{0bAPFwlp;JZ)E;KOdF&EohmbmRP;|} z>{Y#`Rd5T4*p3KbVG-#2l%#rQ{$N^%DTyQQ=ciMt?)2TjzhmBpYCTE-U`7LA#{M0% zpq{Z1YRgI=u|wXK$M3e+Oy?&~$IY5mzs#TpT%obD{nlXOu_Y?_%dOe@GfA zIR*Yr(qsThtHEb-MY!#mcGZ{f_=Dr=dGPxi%3mz1hud#mJyc%}A@BQ|-1MM<5+^?L z9LFl1q8}O@i&D=QkFggX!nEGzj9%y?!m8*+`)bZk3Ceal(InzTIbr#h-}<`|9xE(f zSKd~qc2}3rc;v`raY>3A(35N=r@I(g)0U3vdUNx7eb|;7Lnr_0G>L^{Wb633$4qV? z-Wddq$WT1_6NrG6^>fR4S9sA$E$>0d; zsd`daefl}WS?{;PCF-8?a#7`JrNq_);U6Pv?~CldaU)K}Xi_!jNu<|hxhh;Nd6*l$ zbck^q%y#+l{LY`w;zIPOQ!QYFs9j@qnT>ly(fMpJpag$O znMJ#csbI56?Q|$uTCu_#Jq-Srd7oCPg#TgQK>+i1c{6Y4H}j?gn70{Py5@il338p{I zTkGc#z`UV;hwU7>Qvasv|6tyt_C`j3U(`}I0Q2UN>GmIj3q8;Df(h1xtZC%9<)ue5 zfQb`U`doLgm115;qqUYl{Lm|E9&#Uw%s&t$QqysZp=EsOo@SP}X}`TLlSZDN1K`Z} z#@QEt6^weF6O`m_7cB=KCWfAd=T0gaVnkljMVf`uUZ~qiE zZ{-@tola%|r*_U$?z;}RpJpyFyiU*B44o>T%n0j*f)Vc-G9$XJi-OXh!*q8fo5N%; zm6#Wx$Ga$_Eo{py1f9U%ZGiHB{VLoV{z)|*pMUA`4^cA};f^!?&Uvq1L*>6TX&D0} zy}!?y=U?XS>5^^36b=tDyDE6^pZpi|HvfxxXWRa#d8{dL#?wHh9~GLn?*JNXq+mX( z5oKQ@;1bK-r3m{OgzrBaCSQ*L)L z6sz85F~NV$Vot79{WjxUOB07t6QW%_MF|Y4@wDQVPmF9aibl*^E;2fzt_$D5!(FrL zL_{&MvnXuU6V&&W_Swnsm`ylg4fOvq|4; z{HsaxB>dK-8UE3v4}NRX?)4CG2V$3XTfB)=l_w&qf>+l<@U{Zg9@=KY2jfoZm&D`6 zPVGmD$4K+n_uOEeI~z|j?HX6DyAR>VonPs0hW{gI-M<6c=M6N(@1WJ%7{uT7`~fhH z;ru?0$?91eIXeE`70XFpDq#-b+`Bq?MB~h#rdpja;In|6LOPksDoL|BlWX_uULJ-E z_|V%#B`yVJz5$yW2R4cB~|Hz&*W;-AtsQ!);w0e)Rqq03ln0`I+ZS3BX z<_B*FjNP1z{~EhNRWZHw0PD0gLgeQC1w+=`*llFKmD2hM7`q>T+&-HHs?g}Ulc9tWN&Nv_c{O5xoiIzyZ^CD|6>*lPyF!n>Dyn&?i^d_d2m5^TX@ zz3|K04 zG-YP-WJ~Cl>Xu>WL$Ymm-t*3CQQMgLYliw+` zZr}2gqRmC71PdOAz7^`C@KZ7$!!l9#(;8+U64K5G*I~aPAshYZB-uwV8fWx2b^nS@ zoB>mJzNdPbo-bTMstgK{Xk^o2l9FTD`rxs2pVu-qIu4aqJjZ5sh#^~t$4|3r6HoOU zjW6GnuZunQNEoRR8H*wY){K*74Y-lVHII1_S9=HKD|>L#cUlT{+jtxKY#Vsqqa>FM zvPkl)fk7>vvZsjis&BmxF8e*f{SI0H@@sP(K+&)OMPvQ0Xazm%zi-^V(SUr6=Z}1> z=&ql!=6$&`HHrHICF&o^1h?&WK_4>8;K(^6 znRPhOhzz=c4o{<%_MXYIntNKjXx&{#?IZ1(jfgk&s7-@~zdk8>Y~*Dh--ZD+T9i$5rH)eUAzN`$@6-4G70p?k+ZcMo%$w7N478;%++^M62HXi zc1Amt?&U9>>qO$T===^j@rWz$zl>oDwt5DCU(8Z5zbNbM5Q&{jPC1mn4-xNC*1rU# zplKy(fE0A))q}f%FJ*&g&>PR&`Tj_T9mz1$3~0(BghMepZ!XOEgqy4?3*~mN%hvQ5 z`c2E=04<-qY1z)tM`QXAEi?Vna!RHFOKHxZTGsoevbQAZ|Iu>C(kt7+ z<>|pq-vP}Q{MZNw^%pdw#VpAPQ8Uh#YJ`{^2-n4Mkk2zkmK?G{d?wf}C#oG*m zg?&mJ&fTCH8hm7mkg#c}M`4}{Amx8h=8Cp^i$EhfZPy*76Mas8MWADVsKm({Q~}oS zjQnZCAmG=|j}Rr!%(Yt&p;phvUXB!_Yvu|o$B!U#OTv*)y@zBe2! zh3_|hMR*vNFjOTpltd3}o}kVfbR|t~o%JGY@CYk>%Ru|>Bzhga%>A}aJ>D|VD2r78 zI!L67B|F+A&xWp-$Xd_`nBOrQAigjr1GG#6&@$fdT2|DvHZl7D6oLLl(3Af_4YMZr zCu(8hJ_1g1o>i)+P9m8c@_%!mU7z_$XK<`QzuTV9EA5!0z=nrha zmS_fYqqikG)m4gs2I0CK}159+fVGK+%BOxN$RhXSeS-`8Eb2%rwjjC7AjjOEgxhezaeOYtk0| z0nK1a_t_r_sPYTw9|@=#U;Fvcw^F4INDD~b>|tQ(qlNQ-L}Sr?o~q5J#gZwxA8e)s zr|B;@tIw@_Q=;)u=kmWI)E|;!rU!=Z$Uje{k(z%qd5gxV1STp<%1~1U7dWbVDXQP1 zv4wa3179NaodD5T;6I}=gfu`j2J|~_!T|R#-T>UaAOQOY;1;mAad9xRXZ&9uGpyu( z%SZC_n^BH*@uheS5lq9nkg3DUgjPlXTeIepS^cLyj~LGwt_IOeC?t_ppcJL z_6bpL&)2tBpnw=#0JXZjVXwp&5Mxiq#YX~S?9^P@1HuFEW^k=4e`)|kq&JA9VCob! zVKEILlG49oZ1+>_o9x|Fz@U{x@I&1L{^ztveef49QLIyI50#G(WotcH{xX2ri^)C8 zz7TZ=xyh|Hjy`Ac1>YfWDHoY;%WFDe{rP7@NGKhskK#BUs!uxEMRJ~o7>0IvH}Ra* z#H-Nz*6B*3hUBs~KoY|C#STW=$;uRvgmAn!ta@9WA{$|lU;|=WWA9d%Zl;J*|IL}J zzM8Pj02ulJB>Tot5HLks8|vBrPlob;Bp)i>{yom7e#_QX@btM9&h)WXy^BvhVv&`? z$;@70$K80SWM->h$Pzp+!#ww}_TfE1B8VFCH&pYLdd-w1m<>@Ot|v+@Nx@8EWE61Z z@r}82nz&1=&|AiA?c=&KW{PLrASJPEh0ntD~Ymy}@xNHO2?z0%{ z!Zb;&DM73YL0GZVyLHV#W?hi|o;EN?{4``>6M?2rG0dP%aU2?gjAq%DwgVo~(KaWh zp9AEER6W1*m47LAgZa1>@0F|4Z>gH)ywI{t-RdM5aRT#Uf#%K*-gs*$M7ifSYbQjc zjZbuobn#{;bZV&=iO4CREn&OB#b>v30dL*FVETTd8l~YJ9bu_NfeeP=fZnt)RK{S# zPN9%(p^pf|%B29vW8M>e(OfKsX%_W9p9fP;L{JUnA2)E*e^6ZxQ zD=J-81>7hWb^20?%o+_Vumj4wEEXmR;9nc~=Q*Tm3^Av9VbM>h>+{5-3)WqIUZUf%xoR_XCjB43ptwC; zckSZDxPUw(*&9MbpD|TM(3Xsw$2oCKs2&N6a#9)5^aSdA+%evuebVbj#4>}A$Gl2V z!c?%?L82cdafnjnK&YFU3HNh8sIDzokUpL^c9lEuDw4=?t>O4FpvoBdR1n|#N;uB3 z_uLJ0z!(lF+V}2DQXr8OULSvWdfwMgSyMv|WuhC3l`=L^_fv>lK`VBR$xpG98_$@Y z=65C}#+gMwLb)cJ6*ZW+26fyHn+_(AMu0S9y2UyUBDJCqP#+1gIR$Fu1~{gp_O)&Y zX_#-AS`<%-2xvhk)vte*j6Y#rLgNzg$FtCI?15ypFBFFiB=aGEXMpXv8PG`o!M}g^ zdO0sfbW0aH3@nN42`TeK0~Kej#RHM@Pm#T3;w8?M)ajb(@Mmi1oiB;eF|oo`^dBa< z+ZIDrZL>7!k@-!!@vzN%Ej&s{IO>$vYEwxgy!YkFceaMkZ^&0qtc0iw=h`?6qpp2K z&x)1wPfZmGOylhLZ@E%;BWxTm#xzgTdW#oI7t-!i-qF)ijGI-sn$ZNg)Vb_*fL|bp z>!@40p1Wy5dWX*H>JIis4SOq^YCW5d_wH7vUN(i9KaJgZ>|h&)$z1mYNMAmlzaR(t zlroh+xVI5r$24tn-*M)y($7-rq;Q_g(0L*8i!- z-jANZBy@}=n!xX6pr203IAvFT-Qmj}SB}tAuum{|yULASiG_}Eu^IZZRxF=yGGQS8 z&gyk*nuv>cH_7MOtN!ua?)6!5k`#?#&3C--nq@v0dfUb8{^_e=t_(qhi8sk1h#a-u8`z^as?N@#IiN6ZN4wE{a!+RHhz?PlqLG(d-CosV7T`_c6`TETFv2P_e%_z!iQ#th z&DWRlG;P1{HW1iElwQ>n(}W}T6|SW~mdV37h197&2RKL+sVZ@)EG%T^|lQ}^27V5-&r+DWK}O1@v50C~xxnDS@u`&nQ^IHe!ZA;-QXG3CwfkIWE4OzL!z^!6M@D^yI<}Uph78NE{>z*L5bbwlkI)sj#ius_c`A(}K%gB6gx9OVRqfO>GK~q-J(_ca& zrxj5`WujP&;z?}l^QF)Iz2SiYS#u}c7xmWG*pBAyEpU-8|MEE>(ej1Ng1Io?os3#v z`zefx1i&`~YSx&lz2vWhC3)oY{hL1*?lhIL1kMu9t3Asei^fM4kLcEO8;&^LGKgUA zwG{-gb#Ujk)U&rKFZq`xllxZNvpUv(PRv{j%k**Dv;SIGQ7~=Rcw_% z*wuAX&5~3^8FSYFw?wQ)X7`Y&qD3?7h6KNOK^$5}9!WHNGkp1a)WM7TG=eIM?(|4~ zH|Ng1T+JSnu~Rv*^>tEZiQg$suzh#-orAKDld<4*J+O8d2cf=F#Pr zGhkFrg#1?{h6jwKx@Evn>4Ucf@r<66Hu6jU-$8$`%xL%z7g6tkfO7EvFo9t~guZGq~fapXkKU1|FOEkT}ThQ}H1^|fR;o@&JJcIh&1 zKM*WqJvVD(KS(tt{}MZEjO;j4M1>ic&=mTKIR2OxwKkr5Gpc}|nQ@gX&Teu8vJcFx z-CG}JJ2HQyq$-k}43nk*BzK(VGibUIXR0(*5Nl#eLIJ+w$=RCkE+tfx$wG@4?d)2Q6}fz!1&#gXd#akqF@YK7`tXf@vty!b<36 z+B+w$OND>pv(I2ooam7PBGfGeJ zm7zrSh^ZVB@)5{geKO_r4ajO%q~PQ&z>?8m~r(&x`$GT0?7|Fh1<_N^BkiwpswCd4W3}2bTTV zPK%X@kPYD^7?aJ*VBsN;6^~f$dzaIq5SadM>DtaReJ67i+7cjxA{VLpxmTC<2Q@9t zvEC4Kg~q~bBk(8(M~7#c&zcmDm$@5DB6>ZJ_6bzvcjh0`>W+A>U@MFf7qkWtKoakl zlHF=}!$-^!(pJBJ`>xzlz#Sq*T{C;Z!@D_^n6}kuVqG~w_W5;l?l7YWlp0ZsBED_f z%=7z1SZ<`*&(obH!Epiah~eR5TtDmFWIEj3!l!dK%Fb@J5n)-}mAFIX(=n+iG8msD z`fa;LjARlv@-_rz`?Pmu0?+6!FJBjm$_OgeiXFGVc8l-~Tq9bK|9CvuS=s$|t<;J^ znR^YI*vis@>?F&6b?RmBEpbKqp)+ANBP-HT0vcDgSKeF{Op8a8F%_;DE9t5+0 zC5K{=awUnn6fp%g&ta}n75%;%crl({I*skov0fz*XV&~qt1~71S#=DfOv%h^yb%n7 z^#zTerm`T8W+YRM`C3h_20RYQ9J~~!N$y7`ChozD%nXt>g*cT&g#g4AbM<|>4jQ;u zNm329o*Vfd%R)_!;W7Epvk#FC`NCz{zL=ve2jfb+KdjGsf4FM@ROdbdnPRgA=BM%d zF?jX@elR`3x`8_^aSo09#e2_}V4qI4^}3hPyB4f=zE_V{UpxNGRV?ZQ=Ga_%#{RU` zg!j0h)3@jJJ7ek%CTNOrN!(sJlK8$ex)gFbVn!7g0S3Mk1tInekHBN+b#)TB$tmab zWoiNj;M*Qap+}e{&G}XqL^H*eGx=cbEEt<$Z0T^FxtbC&obbR6#v~e! z5!-YR4vjm+vC$s&Lfi=$xjU^j&kyaJee7-=`32B|s9}Dau8Bu8AepUUhW4#@(M$sQ1Ym80$7c2|>l(KT|Q2wPY11@a?s=NhQh!*eEk)p@r9r_wVmC&^PSve zIhF8Z=$-D(9F>NtN?+3AlY3WZoQ2!{y96<5O0!ILl!+# zQP(r)-Pg2AsndnpMYpIVH^3RMeFwI(dXQ6KEGQBo%ddMz)z%9}$JV^{X$`UJS{s3Jo z#mHTl&xg;&MLjX?4f}K*m~@78iT8U;$3T16FAo6(6od{01P2&4g^V051TAe0EdFOt zSJeQl#({DAeQlwQ`?d*7e+0q-EW^5K56f8xMe8O`iwbW_Z zB!4J}AYFarHl7GXaV==ASI&Y*Vn|!Wa{;&zcT3^@pkoNUk6PWQ@r@)!VXUydD1^Ym zNU0zxZV-Lg@x!sH(4X;BM!`DALh-q!##6E4#Rv-sY!U4Ae77Sh1NAUF@Q)<89mWV) zVJquR{O_0~=?WF9NJdf@7m+^S8u>^*L|~ zT2!N=rmuu01T>eBKv;t}-Fma(zuI`;^D;+F?7#)IKZv6}n%st6>{q;)6X+_~pE9gI z*!XX|70(7!-m)d4Pdf;f%GT=uvvnE)c?0eO^%0wQo*U|cgiYzaq2v8NUkeT|u^?by z=%m{k0NvZ#jgG^z7@;SIoz{Y+bDy25QmS&ff-_`a9q3ok8Np&)6*T(1qG!#0`B_ei7rlQ%2L^M z^Vh>XImwE}_v=c8wbC}-mh^q73|kaLeu;xEw}aKV28CHpxC$UkG9D6^VX>(%g7gk@ zmFihe5grbRU5O3lX2Zc!$vn$g{(p)%dR zW3~%Z!dIgk)Gt|qtRESl^aWj(l4jXm zHuSJyUHu6vJ%{zv`aSod+J}d19GaC?xQu|ZI^u75x#fgpI{R1j!|5fo2`?zN1`c_z*vgv5b&P zl;*$tv29>k2z^xSGOB?D^CkxK_%-!<0DcRK^Q&w>adX{)(+@kzg(*Zu=hJ?7c}+I8yHJ zXB%ZI0jGpD)MpCa>p&koFQ=h3I37qX@-zKyq|_zi)v3VE(hCO!J{`Y^egyeiJdA+E zn-zNHc!MYz7vGIB2c7IgeVQu*uVF+s=0)D`Gdde zGcXU+8eEq8DWdZ+*k8{XoHfQQE}y5C5#U=0LAMc8HW?=g8QJWZT1uXNP)=H|S~Y7M zQgQ8dN4L9+{~3dxjthf(-zR*&aryBexM(QMiY?SXB}S*+c3G5|C6&tEB<0+3teeBB zEG(eB%>HE}Vr2-Lztx1()XPuhqg*E1Fn%Tocv_}FAWFxQqsvxJTL-z9JpPj^rzmqa zyBkSkx8f|LYWtdb1J*5sQNzu}#WV+@K{7GE*d?O?7@F8D2_01OGgOmWy1d7dC%PutnE{gg{~6=&tN+oJvH@M`z850B#Lj&r zUe7mcJ{7bWE}a>;EyOQ5+K3jVG)@uwa_Lewg*e)5C4Tkn;GIVDaLg75_p=!8btVKG zGYFw6YzT4eH7#mhJoP#p=6-Gm6J`;&k8~>j%QFQ7bj|Z8ZDVTC(N6*smW^WZY`I?P z#H)0ak%6p<=t^(9=3Xrv0%JlmfEEfg0P4Vf?9DjEuy&{^Vi> zjM_gvg<`WvjYZ&~NDyb=w*=s`@LffV2k9|%5FYVYFzvs`2p(MF+_c9j!kea8iXV`) zI1MFRaPCC+2r(QVfI~(ML!o9@CNao@#w!PVMbA4%iFWoDvC${P80Mw|Ig0ctZk|6> z6nbSSR>yO~+jwMt#L?iWvvPENm?nBOiL|~Zq9DqCTps?!Nt6EFpVxdf^04!$QvI4T z7TOs}dP1=bqdkt}Tt1u@Lb1R2STVq^fvv0#gwBA%GIwCSMgvw*$T-f|wuU}eC%Tpn z1d}3t9AogR77j)@O0iokdgqGq@Y?nR<_n4~Y3gI^TxZ!%^MrA3%Dsl0Ss<{di=T3f z`~KE$p*hpEgiX^2#Fh6dzUGb$#h-A)vlh0wwK^N!i=Uie9tustv?K79p!fSPWg6s| z>HFskprOg`q9WC_R1%A)2S7FMHk%JU zq|)4~c*oYvwGq!Bv^%WIXxLxi3-ade&b z?z+IMk<+AGGFCnj87uh?-{pcY5v0tQCU58wm7%&0-wvTkiuOfmaO`Z{aD!IbIk_W_ z;}>ykgOh8D)O{rA=%IVZD&Vq-gt-?$3$#(W05(UIi4j4nc_rPb4in;lT}25td>jkx z0{qH}v7a*+hg@r8vVjaqEWQ6@-z2nRvfOfF`k1AeiOAVH=RREYv}M6iDdLM}9+q=v}gCQaojYKylN zhF*Obx6Fl1DtHA!=J{Gi42rj!Pt(iCGCB{w$xDD$d}WrN(KUExV)fP7E ztODwNQOGc8UK7e*(}`BKDtLSISSEnG-1`eOz+ZMwSJ!Xii zt&!Yrb=CN+rl8_BS7Ux4Q+eMuN%i^U)vA_N5EpM}a^9zU`jw`)S(`DRB83T@*-~#j zVAr99g*wNEuThou=TZWs2Mc4-6gjJv+KZH0U~!*{OjZTj1y1}F!q6vij`gtPjY&L1 zP3)WNh?mCu5cyPsC`_GYwrk|lafaxYZ{(x#^GQxl>B|WWujd)>Qpbcr6tMQ5?B`@u zFE_}g>!K#}t)#1${MQwMpP{w_7P=CW0%XEW6m}LR(gqE|Fpn&Zjmf^V?-!Ab1o#(Z zVvG*hDM^^<8rxIws!Z)BJ_dDII@2CbKt#aViW$pOKRY}J$Cz;g8|BNJRM*ud=-@FX zq4pB`oMd83bUZ7j*%0s>eyLB}M*RNryd!eCuF${Izg)Vz{JKfg>DEFIodWb2ak;rx zDb+z;Jz2tsGyF-jo`S0go9$TcXELL-9ddJ27?S=^*mw2unY`@dK~0+l>%J}@U|Wpn z0WU?$T^SPeW9c1g`Le>Q(;)XXZKC@hUNeL4OR~TzA88Ls-7hWPhdlwGR2n10DhB)* zBIw)RFy>y*-`fSMHCE)B;fzjpNWrN{Nil@edE(k*UOl7IEPs_X~Ut%>ODJiaAUOW!nuHE|=JE}#=~l67*Sfkg@DL|N8ebyXy$Cj zPvtUX(~pN&GyUt!)#_`OE!H~sk8WmhVrBK#v=-~v9W8MWfs|$BX8&(N#$WigJs{Zh zoB8zD$#{8vC74ElU&37zP{u|QLqb1XF@rG{YJz?$nAFkgAcT@`f`l|Q3HcJ{@4ItD zaWX=C{rYd`%_uyS?uCGl^s0c5^klz!yMry@(Ws!4qm7fJu$7ago}-zKwV;i?wUPbb zymXF=|8;{Ae0V~^-sD?(UQ0Q2P%nlHk0gA2*^@C3 zxd;X2?+bIc`^hlZ?w634YG8>gVR(BJ!pX- z?W=k7AgFlkRIbQ>&aVz;UZAhOND}dv)%ZXTHsMW=K zHp3=H27#wTJP2CJUwSLP7$jR7g+nHBpij9+&tD)dBDH-3ZC(Z(Q?7@J7%kUib_~(9 zpn+KLGwM-P5{HoejV1bEhq1s*esnFPWZt5ilaJn_r7rAd03$Vxj-KWyI{~~;+G>c_xGg)?zxnl);Q&iWt#U-wgx~*;Q?fM{CVdHy zN%jAn+dPDB!T;|n5VCR7|J&EGzgL0G;bT+oh;FVGw;|ozB~AshlAQf+Gu@Q)U#cMD z!k37@FAc($TjN(16o`}PHSmf>yVg}HSuf146E60QxLdc29Z)@?(LujQTGw(d0hGZj zh!1Z)0^QL|nkTpXOy*-BJdt6=T=#QV$(ao8yJHvf`NOe}*&FcWR~{VJPn5sPfco)? zx6E-VFuYjn!#mloYE_XkFIw}_g;&kLmI1~eWk5AI%hk-8`c?*@9pd1?rToPsuQG6=1l-F4o+GN#k>SB) zeFi*Sa*>Piyz&0z!o=(HtW4jH`mC4jS_>Ni{xVDkwKPFpG-ykl`gX757%ik#*>je@ zXcwXFq-B|{TkU~AOr1wr&Vp%#NPN^re<(m}s_ipw`hT7}Ohyqie+GDgG{6f;{;L;= z+5GJq2#Wu8X%{@TN8t%pI&sV0j9MW?qU*8DWsmGaYEBAoC*NcfQ#=<$Td{0l>C^qP zwvxy7l`q!zGcL9aS^^z*2VANACyYvjc%tk|izJOkfD^FT))9#^z8S$4paN)^=LO0h z%=kZQ4?me))!QSGQKmEKEb9eEIz6ZGqM*Kv?2~Wc2DNpJQ{vFoINF@rBq&BM!Dj-g zeFONwjuSFv_Px~+|8bQ*W{Goa34uzx#Kh%N*MVeD~<-t}P>qfRM zT--|!*Enbp`2gw7fBHaKkQI0c6tofT!uokrt~S_7C@Qz$SHQ)zI~_<=VzPNE;OUy0 z5q#V__eu~0T^hd6JOgw;iqJvhOORTx;r)O$@R|wodZ1f)RJJ`0zB#{%< z7P#H0K)2?!7#cX?a}X2c@mn&l1x-iM%gDsoW^mD>5hLjE zo56~u#F2~dMi8eK8%HbEu`~v-*jK_C(rwN(GTk7dE=;h@2^O9>^L1$V`l(tJE*^!1 znGWJ`M21yEe2xX>W^y#6XV2wI#%?NRuVEz~YF|l5m=D(dknts6y+bKGECs&Ib=_IW zww0^8mub6l(`Fui?*eY*YeViX%K zaqIda!HvGB=<6gsax8(ma2cMAcCfg(K{z~25@ZZ~-r*)C>lxo4;-!45V^ET5U##Y* z;Ot#Za4aliCfjH|baBLd>Mp%pAJyl;2q-*ybYd9mZ{RnpW8K2dxmda?L%~q>H#Z$o z00(q~)=0omAOaW)#7R^bTmZE|34tlwVb_}&XX0PaO65|F7 z`8xua$Rs_)!LhGTZ-rX#`wlWE+xExdoT3Vye&}D_fCu7EHxCoj98e2_db|~+mrvrw zCCGF;v}J2-*Nq+6*G6eu;>peNA14&DiTjE9fBqQQu}}M?h!+iJP~}(-nMI_m1Vi6m zo z2JyPUv(Z0Jr)c@a3m`WQIix(kZHwXicIwuCuW6r;Z9y;;sEh@>owj$o3J%QP9`_Ig zr6gr`H0hMMAnCf$ubsv^f>)*{hvgV+*c}sv#b#$_xM8)h*i31^><)<0-g5_7CpCkrhQzZmqpvUrK<`3og`oBl*4xyS2Zl0qDq z^j=g0k3U7QcWAtLNrnIw^pUHi{nB!h%+?JfpyVFvC?MqO7#hVpu;I!6rpDyh2R)aT z>jR+~HYnSy$-}(~r9tm{s=F>0LU#aeAt-Wq?02IRFHoiLKQ%lZuXVnOS>^;Hdw|^p zB@pS>f=)y+sXFh-+xWJzpWJDmGn>)GtC7RnhxQo9z_%3868KQ~J-~HH+>Z=bB}E8G~05NesHcH zo3x7qC&dw486!zqGqct4B+b1jkRB-t4211DlPZOjcc459egzIDU5c0Rjg!q~akmAJ4;;Vte8_c4*r}UaKh~hc!R3{gmfEPZ9;fj(QLp(x^c%o@u_43SJyp z*n8L6M5vuEL_hWY^qcxHjT^f*D?XJXBWaW8sLy>`{QL(Fy`b~u5Mz&%}gHBq;c=4HRYMzs{P%?&G+p2WkR_MO;;*ScaA=EiaV%t{4hF_ z^+#&PQSm|X+cM9asgra{cd-qEJE}DfS{N4w3v16PbDm+NE%JuodQKcDKo(-QGO4_n zLJ0;($^N_%12o?6SIkhbSr37~tWC{NHk}h5&-o;+*PyWIf?l9YUleH{ZOCQ7K^l)% z4APjJA$6zc8?1E;41_2P-Zc8URED#*Gt3&EO=Lg$MgMDGFz1dp*2t$$2bcjB8Z{(d zgUX!dd6-!XbxYji#!UwNLDH!4=Hk^kr}lDBY0n&-PJ^C!7Ww^5lU2rniQHC|Qz##Z z>~~G1F?AW^_8#aXqeukJg1tnPw_c1>M%QUgdpMv-ET6uokuhZD8<~7>aS zDhozhFnwI+Fivf<=uU5a&gPMK6XvE4#?Gq#;UT!!A1;~O(3mHc(6CHomH0AIjiWb4 z`I$vthy&KNk$fnV&wZM**m63N-{oA(N4uc6Q)n)V?mL*NxUMPr5r(twkvw+<7|6w~ zt?F$nZp@Pl;7gl{-I7u-)O(K`Bl6-S!_D*L?@%Ypu*o@67oTdl8&AcCl+mEOyMEGX z@<%5=a|u6sR6E06JvqU${XfR;sk^prTNiL_+s=$_+qP}n$&78=nXzr#wryMU->Uo(OMt9ms;!l)Jz(rx_(WgMWx(|b+uCR(iJz>Y!}eXd{QBI=A`ghzxO0b zHF{DNEXXPlLK@{y!Me``)7%m85RL&%X0CfC*jHkxEtEfPT72+J@uy~TuwX^Y?UoX- zXYJ>Pe$B2=-pzAEz8!dUbt#Yrql4_eT8<7atl9Clr-JsCrba5!T1wGjoMzb$%aDs1 zOOD<>j`8@t9(@H%$8OS*Da*_3IiLOeXB3Ht+a;$dJ=GI**tWjvT!|NI)2Nsc%*%T$ zVJCl@q$D+(NEuniv5+QZ(?I>_=Na7A}nKbX>2>N+94%8 zJwSBlUqZzspIb-~e!4kAq-h2w-=R!UP-GoHDbJf8tbhd0oZ~p-di(I_y|WZdvYR0n zk-@1qimNp_!UH^?P4fCcLwL@H5~^j;Y#SBcf1bZRs;nKN*H>Wr5lce_&&jT(S+OX& zlM|p3Oai*2!KFSwek5xvTRI%WU>VI~vub*0*oB=amcuP!!n9Jv6YrRar~J~QI^2%q z#qAW6Hl06nN37&Iinwb`N8B|j@0`~%0tiRMIj=SAUR5NWd+){;q8jA7F?AK9pVKQ z-y)*!z4z}`y1;wK%l*Hj=@m}2yJ=l*J^on%Zp4DJt zFEg)oT!;=n27LjOfYjpjBlf_$clzAg;(gjd*rLc9HD@d5?l@QY&=Tf$d*bV(oxXtJ z`45Li8b6U@q@)$;#51;qwJiBj({vTpB|t^um3T(YIt3Rct#cnjNya67xTP?eL^)xg zR`pZ>G3T6gZ0g;gQ0>q%qrZHad2lLa;4@N9KIre~tX23jGS<5(+OwEOjEf{8Vwh(_ zt)!t?McZ>_@}FhS%LzOekGIB*bH>y&MJcxnjtSEOh$88B-io~5Yh;rRw1 zrlDxRfS!>l#=sFbwln2wxt)4oUB0@%niazKZ}bllH0>c<_;uKIrkd_^-u!dRpgtcS z`86jUrc3n(3D06PSI;3iTLQCVaJF|R!Yi0cLR$8$T0r$Uql2_{LVM;k(4cL1e+0kN z-_H=4M@eI0gS8!s-;YUcV*qtGoi~}IDbN^?z)e;o!k`sS$P{JISVfF_vi!Yo=-{8~ zO@0qMOA1lb;MpJHi$pPZ3#f9x22s$Njm_YmvDI^Slx$5AMe1VjZ(MQ`{obO^-!Xhh zt<-boy~!jARui~3$h}iE$Fm)($X2DuUe}%)a_>%g#{@Vbdq&cxB(h66`{MZW<-Ca^ zYi3Q0Yd-K?PENii?ty>V*9JfafglI^)}r9nG@q(x#Yu*u{v!Nf%CG$c6Q96wG^H1R z;0B9B7vP39aB+W!W-AjrziD&WgQBtYkRA|x1-%Bp%?6Q=lg{f7U=LuZ#>Fj;yv}8_ zsqfI30@4M7_u;46Q1;%$e1T_ctW>mpD1@DUORowTLLk|jqEX3|t;f&uDbalQ+u}DC z*|=cp8_$l{(=-g-WE2Qz#^@r|ZG+Oel6|hsFP>ceYLzFbMgt=D%05Cl^vg$BZR?Z` z)~JTEoo0rE7?WG&IK;nvFJncbJyPxx7HC(xV(RF-Cn+Y<=_GS~r*5XZ3L`|b?C7u9 z9u@TL#rET|^O%a*^hPkm(5P((BHc8v%0{UaX!Y3yt$Bw6Ij>2lsTgx4fGo8==EGye zDg@%i+^mEll}HD=M6;u43-M%1$6l{b(mMiNml;ZZg-YKj$G@y8p=MdQZzk0ZH1aVg zAVnV^n=ZkANl18j(}Rup({Spo20tN^_Ggz*0rp<;{X(J$-b*Rpa$==n z(#70OG7&6_8`eISP4?@w;=GDtJOg&#ZIB4lczluwq-9Q*-Yt;hu?`MY z;oKt!S~V`W49e8Ap3erhTtODYc$N^+}@AR>i#+zE$?wan58j2W*1&hVAr?Mav)pTheT;?E3l| zSe!-4Bd;Ko{$x&B1RZEzU1a{2&beh^eVKWJ|4jE6vY87JS+mR zQikKd6rb-a%W{_wiCfpH2sxkcT>{E^Eq}Xjo6jTySw7CUHGyvE&JW3 zs=Qv|{_E+trWH7lVRXuH>4kZ6Ba7 z_kAz=n){69wATbpL^0-%Fdw4Ul7XPb^>sr55G>UT2capN`BS6% z^;4tzM?Mw(Nj}KhIom1yWWY_8>|7lGzcc?n|4((Y+0W->O)CVAe)bnwLRTK?_CFZr zkKobc<59Q4X%nYF(v$lsaW#kU@DJgE#yx|3EYA@lOO{cF&2E*dp;0<4(5fPLjUAdo z3o{7gh7Q!2VByWMzwI{y>h2AQC##H{v!(W&mX{~{*GPz^DOWr8Uyes=U(pFP^%qxv z2X(|5QywllXn*VV;O#7_O@A9~TKyW=`)|lY;jjLG6AwTB=}%)~t~U4w@`(Kx4VNlA z(WR3YevI}8#eIC}iY%xJXo|4kC} zdx`rEU#}S0`vZ#bu^OFWS&P&J5-~I*Xv~vvSiN6}t;u9GYOLS@h3|VE63fW8raeIQ z-GV_QG>^5$Z&RkLXj?r_D2>@xS-ac-jrWS&0L&2!bU)gXSzCjy?7CO(aJKPEjIq3A6J>kFvGm&5_n2nvN3Hwm?l)FJ)!IxFzn~6pdPs^4c0OqAggH;O@fvSVVHT3j z3x8^qBF9@9^>y!T>7my?6#)g6k|!^VKN2|jueXEAOy)%qv;xLXzmL-XB9(UpG@K$9 zhaMK~6+^KRCWy3?QHI3>T8gJ+Is_=wHX-Iwn&I7}Cy--E3MSe@7pT_b_0LvOeKB-y`(=YhXS3DE`hAuP)q zBPOU8)e#TGlt}}c&@2~Z3qIC2n#=X(F)v3AUzc5L6KS3!I2JpqMe}?zW=dq%i zl0DL=TejX(ur+~o(0jhM$W@eS$X#_=r!d~QwJi^e11SoLd{oaN)zYbNMe|b(;?8}+ zni7yKzN97hWeJS|#qyHV3qf=pM5s;>rp-M&&aI=cHn?OWtw_ZX7sDwd52`tuf*DwescQv}bW=vI{Rtfjfz97u_O=Qz-kSZJceA;cGKHJ!Ll zV|v-j%hnRst}5bdn|sbv^y6sv=GYdtx>9By@tQ-Ys)ClF7V%r_!GOsY0LEH$_VAHb zXqR?Nt*8_3$!mcDK4IRV&*{`gZu8?=Y zLvDIumO}N^bD%le5#mD(KxZcdzaDZ3-*q~VjLp5~eKatW5(|@Xf?cD8$}^W7eoL`F z7s%!>2=$~mLdyKWtbaJn9dwX$!oYGHX`H9 zJSR|LL=D32coB|X^G-kOT3`b#lhSSO0w(IWjk2Ij4<;Q_aj&tC9lcx=pP zFURE?htA&=t?B&`I@x?09)z=K9;Brq;5@sTQ->SAOn33yQ!mFhvY~ndK>VVAMZ*@d zu%QXJO(r9-X_c1Y{v#D*Ny*Z#X_RGXl+0V=Ig^iuz4)`%8ptRFCmga$%Wm6Iw;drwvxT#F~X>1#EA6R z#t8)n##BIfy?liWxb4JUZZBhN!_F4ISCvNp?HiVb(x6R^goU=xOYVzdToBhVIN*0@ zD!o^5cr!3h=tn%2(3e|yj-Og7Phg#Dg!}&1B1{v3st-HxfO8^{wfuuSmwzfZeZa(& z`-LmISc!>hH7cT5&G<>ph8#}U_D@!$klnMbZt*b>3Knejia}S7$NYXKmPs8W6HwXX~9`@qzcJj{?5` zZ&)?~p|~#2&%46$hZy+hT_OE5z+x*QBl4eG7Qsq=G3)dQJT*OrMO(n)an>AQWk`)) zVS~-3B3@M??&8`w8%?-SzB`cqq#MziaEN#_UJu6}rqM%qQb2($Ci1JC0>oV^j0(dn zb;ar$>E==6VP;g=TYmx=Yfq5~Jq=IGWyW%I2glJ$`wS|#$=a$l#k~#*y95_<-TC7) z5ft<=Dghh&zE&-0Ic`HXL`(5QK`nG4@Y zIcJox=Sihjm~(#{7vBHjeCaz?z%T=9-(mSmLt9>0Yk_+@vmO-sTRX__apf$wdKV3L zUbUVo&62_Rh1bP+!60lBLwSUHBK^gz`<;GV7 zq640NFHj(JWTT|Y#!(1}dhk*gD!^)M3znRa;10RWL1i604udB^)j$TRUa+r`+Z#1< ztlj=Hyl=Z)J+p-1@Un{6l7U|8)~zdN#Vva!KMM=$8y;H)i$Gu@b)){O|(ia1s+`E=XWW+IIU=9gctfayv7rgJaJ;Mli2mZf5 zKt&{TO&~}B0G?<80nq++!(42Q%uO7b6kIHftdyKh?ElkUyV9}xX^+i+YyX9s!tsqW z%P4O~CX3!Vi>e7%>VWn`p(B7ukiTra%HpUaaeP@D zvT>_Z*G?GYNuTqVLwmf^??>Z9+<{EL_&kgs%$>Ao?QodR8bpqT(e||`z{40M3|5<- zANeh}Irilu9T?5TO1MoxaM$_nPVg#1j07@A?&V>0DaLSjs5Oa?fClO-%cK8B6mEVx z+hP3d+MD2xl4vh_pnw2WF2TJ&6IEb>vM`kUNcFwT+X--9NXa;)#uvZ)+XxsBe9r$x zZVo3MMB>x+;9zKKY(rp=j15b;4w@c$Cx5RuAAZrOFW~)7F3^EH4Z#;--Y@uWxbMgv zptn$fo9wRF062FD_&r%RAq{Rflm5=gO~4n&uYE7OOpL4!+VOx3d&q6mTqN5a5u19G zTo5-|_rv0VZ(|m(+V|$Yp^v&q3SKuD3<=f`3m>=l0N%E9)Ax>woZ-uP;JS=&b3Dg* z&fNR7AnZfj1H-0k3nT3BG(TqHBS-$zAg+iL()^>-@L|^L?BZT30{eo!6Lwm_>Oj>D zHum2&4Z^O6JUR3H5N9yHh1&>Pb!m8SHv#!`^R%wp-T4uPvlAmu7a#P$>pSn8Vll+q z-Mo@R=_Sk4!eU*FZ4W1AWWqX4uYSuq;V=Q`Kb0Z zFNj!Jrjtc-<+g4!ghSST@oCHawpkVqNs`;`aXv#aG5Esx`5YHJ5GTDsT_u;JJA0l% z!*acZY2oGWA|E!@?IJLm(v^=w!8m}n{Ah3t#-Yr#T` z%7-?4<#_&8-@IhBxxqd#Q)xjqO@*oMrDvXHk+%fXXz`GLUz%TBh5T ztryF4g0s&RiFBKsP zpGwewLa;JDLz5{v9mDKx4{b`y%Sp>;#bEj1iQ04~BaId19TLtb!Yu4%X&r2fRkE8A z)91%N5X%c2ZOF8yCFW#rX#QSpU4At!%X;H+v$gg)=(a7>(|qNQw3VM4lxw&W>8G6p zf}t06+i}{DzCf9_)dHbxBFqBNwabgBs2k_ynIz1hWvq~+Qj!Bf>^m6!Rde_4o&}HA z9ooYar#fQr&_8n;P(F~xnVuoD!xfy5HswTTYhiNE1Vs`(xnNz9oh;^^{L0(*aM~?t z>i+)~DPN+E!_=7<69hqzIyWadP3a+@DEh8Z4l|>dp zp?-8G`mHQ`1Foj3wBeNJOX*3&L7qm2jy3v%%Q_ zoXO=rYP&+r8lv8vwKGYi;+G-!mf?%#0n$;f-i)cMuc4ha(#KHs04pK=a;LNCXv(fu z#o^FrbA3du*}5Z})5U>3_xAV{SF5%w*0dz6eyPBV2=71!T&^gvW9&VRi55bfK3Xu(^c&xYXjTD)D3hyh5!4haR+nndiYj3^ z+_5h7&>~2debcX)h6o*tLT?^oE!W+UT{9keueoNOC0?7rA?-%Uc?3*&|1bm9n+dnb z(WMuwF)kJgScbgKsmykP+i4@Wpbk=fuiYQ;l@wMWN?4Gh0F2Ib;j?aem% zitHN;{Q*r}+j1UcgaQuXKh6Qpzq(Xbv1R~gEB2*nW^1HN3s!2uAd{vc#q*%9FeCu3 zJkC8CKq2O7+NxSfo4MriUqFm)rXwm+S)PDe^RW|KpPv8n&CUTNvxN$utLQ#@EM3f! zLgqU~`lMQ^vuc?VYuPajtx3j7SAyLa4siCN?X;)A_g@;)n6&^>m;amSWSc)U&J z<$TCIDTwrb)Z^=RLq*%P>%JjS?p|19rGuH-+I&QR1qu?lnq`g?V1OWx7zE_U_)Ju| zz3`)mZ?1t^q5DxHDF}>gqSH`LAYbpWgn-$suPtk5t9pS=gkH6-P7D`fMZ~mu z;F7t$`9%+5x{;-Rtaf3$U8ZW2)}U}Cl^^_+){m$O^AqL9k?)9@FUl5NC@ANqo&_ov z5i5zhOC*hXj0W?k1?=hAl<6e6V;3cG*&gDM%>JsHY@HbTZiZ7~?;Oq0bcpVfGOfgl zrhe*``P~uS8n^ZnD-4oCRxl+1>3kO%Tah%uln1t%g|0-MJJ!=l>zYM@YQ$Qz z9(E(lKtpsY&~w(?*Br>LXombn^1@0otnYxNA%Q_i%F^n1Hq5v%X5 zT<`8&KscjHUMoKhRACW9#_LenjVFb_a>LX)3wskZq_zVRrq~fdzP_ajJ~NM?-f%c& zKaE%HZa8+Me{M9>XYSAlUW3QZD@(T$%=17}Z5dtfw-OCKpT9<6D}!DUm6-c;=BhRQ zZRKaK!NoI|$J*$cuZnHZ4jdV~=ry@i05*l)&bnmmlIbDWAycu1hLFjgrrG_iQ$CCv z$aA%9)0QLD9)c<>6}e<66IzZf>u#)MFnNwYE?`A4!cqY5s;Uw&0N=SR)=NV&b(cAT zFFHileg=dc6KgkyJyUzfqM2~4w@r_zinB~ayZ9%8K|Dzd|EhBQ3t}e;#O@quX~$`Z zi#qvdK>uu>C-{#V9P45jwVDONCyuPe%~_y-#lwU5vS1?F3cpJ6xT*DtvTxvY6?<4u zN%VJq4Q#NK8R zBXsk-Dxp?(gOK-SYR%2RbTOH3oaOS=ZH%G# z4OjW48!DPcT$}N0>P{znp9tL+mC&0iyhC@J#O}v;%?wQfL%o7kyTcb=HFE>e!ci?B z(`<>NhSz@ghr<`9%tX4Eelr%COOa0!#COfw=?UFx+E`&Y3@Z9+dKHa5X+8}+>k6Zn zk1$xY*~nq!=KU+$5hih>3ZiD zsS{Ro;V}q5x$8oI{+jQP&&5NS7$TEOY5XG;5w}lTqzhH6jxI(GVyJ# z!{@REu?4(pEwf%$y4OZ%>9l4OCrXg}}YFHmWpwW0%I*ME~k|Rv%1u2pP!+Wu#Jf zQMicL-jn{fiq^F8{d)hpXX^)+Ad2Tp4R?#ncNML4YTq%3)f*rZMLQs$>Xc?G*HlGD zTA$Ti6~rFl)+>vXG$Qqv7Eqh^qfy(?6jT%qCalh)8FAk>#7&?)&8feQ*N4pOZ<7G1 zXsKEXFADDCyCc6#E{s4`jkRUXdm@td5MZlBsHZ*TfP+{ifSdt% z-gGJDjvp~AbHbWQZ{U4exfhCmG^2qjI?GM8BM^*-++P+QgwYq%FiTRNYC&5jF+x>{ zHRA7K-r$CP&v&3WqUJ1eT5+r9h!a8*)rs}aIPH((f-2wXVNQHZ3n=s%jJ5iGZ?y6u z-ZR{WoN1M%KbcmT1@FyeW@l z10v^EY?KZ8+_6L5*Zm9}YvIK)D;nDLIleX8}=^bnw-x8~r~;g00+VMdJn zhkw>^;yl0EN{@8B^R45{$tlZLdmN>a*d*Lkt50$)QV|2WLzMd0O>Y^f*va9=pj3hO zOA}F6jz~)}bAEbxU#~P0WN#Z3B=<=f2C}^EuBsb5vqKB7K}~aA*OCqz0$G%m6~xrPMi>dMGiz z5|x@Fot-fY_%5@D=0^*zTb)(ok}N``fapTNON)_5aI(M7a&dBy=2S$gFIRF&sb@yS zN7;PTfSSqDAE_`Rehs|I^4-#{v1IlbD6t)Yi()KxwXARkjS{A=Ce<9cM>)4Eub;~b zRnH9fm>Rbv5$)feAft;`Z&|;=(RA24cfLB`e6Cpc>s7(h)7y1`op9UE`3+Arfs5nM zVjpIU*_HwizJ!OqAzwUjCB05AP9U{Aqkj-pOwC$5(DM2TD#FWY#f% zI%au-_UgPsN?Trstvqf#dR$W#uGUxx`W0-Nt3OF#7?>$@fgpA}a()q!pMBxVBdDm# z)h)pse#6gnDm$rIA#S)PsA>uD#leSKtkG^q>Z~+9Na?I%RjO2c_E}1a^boDcbv1R@ z2`EinY6uKc%?4_QOxN_sU_~-Wl17c(DQN1$?F7aq+W8C+{!yL*?;d^)D*>awU@z*} z+^Y5b)?OmBsvsjzY-_w|Q+56C>>WZFYlMMK$Hf4+$B3&FLYeS!nxSAE^}C^ym7Pc{ zb!E`HHO^U{U?`1V02>~5(?@%e67l(lNKt(wI0P5P#oF0;N_mD5_YlUL>9sl94s+lc z^9!n+KIS>ZrIqhz9_%c7n(u~?DNWkpX|;92vM1%}x>){2ziq)a5Sm17*%w#-p-&sf zcFEO5+OM*k_L+RA@tvbLur!?Al_OZD8>ug@AbI7L=bMFouO0&{ z;ExD)Tck5BogRzV8H;DlBbO^kSj_78>e(!)*+pb`M0lTtzYgu&%{2-Q!pkZ(VeK7; znGJ{;sMrB@HjItSmD@KK=BUZbO=n(B-VNBBi}xoaa9cI7HgJD=#!4moT$X9Tw{^Ov zx?5nMRF$F!wXAX{x=Z?&Tc{Q(+r<95ui-?SpW|zEYYzZ;C+xKVt@r>uE7VxrOC=`M zl#1Qv{9&rEyxeWRoBU>>YN$4-R+Q4MlMeG-!y&gkhpoqR9t~(-s2>IRYJneA5n0bn z`IFEwgT-@Tqz-wtlNKNWzZ>BhkR~`_qFny#0`t8kx$JYE8L|=xU#eBnjWw35SXw+F z*Z&o@SYP<95>8s{2>;xUdfLureBM`NP~77QwPx4r>U${C2F`6_h^9p^<5y}K%H5F5 z{@ac)JQ!D%2r9wX3$>ySk3wW}V*FO)W7X*zUUY$>sQO4}Q^^ADO0j{+?=DRPlL0v) z+>@;9`G;eD$U2hgh*j^{bEVdfae=Wh{pal((y}3M^!nGB|CDD;QkjiwnrtaO9kE4hgptT`u~! zYXcp{Gn!E&`8mr9?wB#-?fc(HoQ80ygOvo(7QOu#FNs5MF6pcJ?YWh%8I{t(RKcuK z2_-pzat@zchFKp?$_1sNtTZ@w6YkJ9~{^m+H7I7qRVYpYL=d= zPhBLfYr2o8n#-SC$?|Lab7tQ)#bRS?LoE02Dh^Tx_?A&m1j*Vv&eT_sEjPki+69)n z6&p%ULaT)tCYGAelGRVVJlw)CW_N{6F|B)Pxfr^K&o6iC&pg>ws&rA&ZZUyDk1O@f zC6UQyAah;)^ezn+E+)Cpmsp_Ll#qlDFS|>j3 zI<16jXwLX^m#aGRd8I^`Lu|{FlheK_m3>-1h$P@nbVo zs>x;s8^06Vs9g0!by&(kQ5joRh+bk^Q?A&gEZGgI)X=d>af~fpe$cigJSV-F9yvT5 zWbxj)UmY{_c*4<9LIsm4H0I6M$B^vD=IM{$hiGMUaF1ng9H~z_PuI8Qb+#*7BuHrsRf{kdwM#8UlF~QR&wnyoLrys)C z@-z4-t)42+1P{Bl2HmQviS{PF->zDRym)3Wu!HzM!|c!#?4!n6el>bCHO8Jdz*3S=6Lpdp&th_?L;<(IR3^R2CV`@RXDe|D)ycW``oGj%^X~p zJS%9|`_eAkHU8^mFx&5zd6xk(ExWzpMAO`$m)U}lMY-mdna2er?WYR3ngQs-Xr=Og z3L9i)x}wd*-RUIiw`}YIOmO{%awuxCShF2*N#Yc*#L9(vcTiAf4i_WBi z?T}?~<0ZpFBxE(fjaL#3yVD4vNin#ZX9v_|Ay2=I#0&Tyo+RjY)qdO__1#rM>6t4bWKPtyveq0DCW4Izc# zgXm6@Q*Tc=U0cZ?UXdg6;d4($l0J2iSc8nU3(yTywpj^8Rrxt>dUWS(RFUlMpXz6U z6;1orGoP05h8=B|I0+eB*Nk$V44W#1h^64d8El*u;UP}s$&fAhSIJ&k?)1sgI%fftdA|=Nsy$52 zfMvHYSRO=96M_M(@ZsVq$eprD14(cu5IVp8YEv9S`vzkGItDfJZzxux3UOa(sEA0| zFFb7^k;)JnO45iOxLdjO|y%5HX8h4>!~kG;zeVz7!5(S?d>&{gtfhb#jWLX0bk z96E8%Li8w7g@LBrY|w7XvZLOgs#dl0BW*S!v;>6Il)NSjN~xZd0lqjf zL%#UKk`bRIKwv63FvdD#-a_3!Q}^%DevqW5gbXarDW#hEyT{xsFr{Av8DZYl(9)Wf zHu|J{bmC!J$pb6Ll5}H7N*_M@_{)qSv>s zyF75eN{2{(mdTzsjbm3fC_om0Qjp%o9RKcN^={khLR`vnwPLsFx#W1uPUPnz^Ho0? ze3{Wg_l&+lE!W{Gx2rCv!qWE#EGfg}t8C$`G6J$@O2IbmRb4>IMd9Kqi$dNjFXen7 z%=Wy!2>aW)9!*xq2_tPtv z=RJBR+dH}}mZGRVbY4S|x4|Tj@RY-qQ?{b`u&dZfpFrH%Ahi83Bqc?Y7@1b+ga9bv zWG+m|%U;P7N8zZA5#b6KY?`*%{nnUbiu@uHovn}Tsv+Hr^6^6-qAxZ8Qp{37` z)(Xc1diY}nM*^4KhL`3SK&eII4b?TkGtnXm>~x}po_iav>C-BQy#_y>Fby8);9kqs zmiGsJD2y(!Ke}QrHVzXTf?9{Ii)eZ0w;OOXIZ8`paOzxQSLQXW5@J%d7!I0(@U~jG z%(xTarDEQwa)?sa{y$T(a zJfN^DD+B#A7U`6U^CVyBhi1*^H|8~|M=Ye;@DKhYE53NSIKMq#u6J)Qi;kpqr@d(o z*D{KpR3%9&)==M!pK5F$?z0#wJFHX6J}@f}9%t=FvP=dP9+W-yxwybU<0HFv4-YzY zr}R*&WwNs$LmB>(q2|4fFDl-ZU?cS-2(0uw0aMd9XBbAZj8JcS(YoU&|m!dfzmob{&=AEU$X8%Dw0Ks zNih3r{S@U0tv7(m;Q=xwMt==*4IccN@o>Ik)dN!}`+1uYGeDJCUUZ;ph>8gzI2ij1yYY|+)^Hqu&KannY;IOcW`;9(p4P06PvvukT zAVE()+oZa!&FRqF6zjWnY}CGXP%2x*VU|0d=&2m5Sm*{;m5*=vs-&xtuI8x`O`-i- z$(RaG!g>c&Ur^2psWDgRzIO?-zz9a~%j)BLpI5#^g{>>>QptRnAndk;ybIY<>fz%2 zZbz);0oEU(y<3Gb(0T2dGg(i9y?q@AkIm(l=NsO?Uz34ymrY5WMC^b$o6gLSxGKl- z!4g8|Gj1wigDwqHufZNvRFegQY=Fl&s7OV)m3d8=i8rOo_LLwo&f3?**I*=eaO(Rt z7rn!*KTT}~(^I(nan=>De)E<@tv&N+4xKFre_$pYosC&OIEUU44#>?+OO$;sZEOeA zKzi2%>uku#@VKY?|UB?$zV&+QXB>b}MFA@5ZDr zxgqLf2-NSTs?@4aB@0wX+96kH3i`Umauj#!ykHbc!aw^YhO`OCxpidJCih@PJ% z;Q|QEVZb-qAutamMeOwC&3YwDB7-&H$Zk}=j@kL8huwkb(Z>W70hICN27I2@ z8cQ3hc zV5EdPov)UCselfUDe6e7nUj$(SlLp@_RPA})8uWjF}J5FqiUng(n=)o_m3v)U^1+s z*294v5LXqA48wDCn@>2O-s&#?vP}59%)p+)#~B^H1Z``3wD&~l5FPi71MA|k$cr@;;wd; z_#_3@pH9sb!e6xv)aW8vR-N4U4!qFXeGO_i9#U42JLBPWT%9&+DI?CvNFzt@2o}7~ z`y3n7X>wIWKfBvBoeksHH(0RyMDho*9Cq87d;x){a@f5^vZs1C5lWi$&%%Zc<&4=? zZxFMJ6PRgQR3y-heD_J=x)wd|afK0dQB$6s$plqOsJTl(IO&*qoqMjj0xaNDhFP}z zL6%=E8HUrPXooY?i(i~tD(=AVrC;0YRvP)K7X99bpog=1;;}L+13g)?taNs6WZ-4u zqss9<2OmI!SyM9ldW-K+JqB|<{53taUFB>9%?~a&PXXVMZ+*UkPRzy<>fKRqFsP>j zi+4pNtk2@KgOW^MC?6QF`U8?}p?RZm;)UKK^geahN4;Eh+3k$*Z?>mZFyQ>{KcJG` zvikkqyEqiV)4=vUgZlc8Fw_afPOkJ%j;;aFioEE7N2By1c1QZAw+YamF9{}#R$mQ1 zjxzl_5=;+5S8DE@j^k`TYd<*u`k4#3SKgb{-VMwo)BSC67yvWahllu%b)OiG1^^ES zM}9R0OF7X8giQ@(CfIZ@o{J5P?f}U#3O@nR;r#<&JQ#V(f5^|h%LEu6M}XVuzDEmW zu8IB|oXqTbLI2?IzpaCph3KNB`e7E|asJEywJ~vWGBC5S{f~<#j{Y(IIT3!_{{C;% zU*ha2PS#A&9Lz~@55e5*eO}=*x{ye!ngsZ)hL37O0>{u$kb{Q}FM!5EZKt}iBlnOA zOLq<mIU8V=#iZ~id%VK%7D7MBSv%k$Ie+|6tv?I}83jw?l0sRg z=m)b*lP_Z`AL17>A~{kYi+%bpf=OCP7|1dLD8(}A zLN7Fgppx)(c_AW+AZ8F-!buneYlU=rYJZ!6ZsBx>&{_J%>2c;1lQdoP5^bpj`l>3j z>#!@)cVIiGEKeLFYESG-?F*Arcg{{d0-HMkTl*u5!#LjF(nb7w4MCW$(UD;p8q@@w zX;`ybz>P#nbp>ZZdvK>3p+BTQX95mx+mStW2I5>t+|PQ&X1V45IXg@zvHPsJ4*rq^z0yR1$F)1xtp~=0c*Fp0hS31wTICb%U*GdfpGwU z7VbRlS72F#{>{!Ag zM`yo>m_e-?r+{3$@@tIeOCS$m9?eXDg|22hC^fKCz2DC=ZY4EoExRh)1x^ev4?{ge zfgS;DsgGR0tKuazb9*qhqQe; zMA}-28|dV0uf4#~=XJ6$vBlEttHK)kAJ&ou`w@v`%lij8rEnjGIj|Rn{6=sdG?2m5 z4bn;=P?C8Rqi0jpp?PHJDwwwVtwAZwBo8f{LD=y4v(=ohIdCrTxe!+HFO^f7f{lMw zEH;Ufm1@y;sWzEwlG$U1Kj`~Cncw(hxI;jgs{DG^@_K~;MU$`JU=I2q5xYLeL`{u{ z?D*Ao)&0c1s_T1a#G7P1J2O<5LOCOQIe$W^32q%Zw*N?42@4Rat)Xx-tSv?P+6b#6 z-9f3Y#66Onhgc(h_?d0SvU(t+nWQ1jLNH4jy_TJ+$spyf`1$2zD)l`Ox|PcyaS1#y z=g@)y!L7N)eOJgEt8fgH4PTHqwG@|iGrLq}hY&rJ%Jw?Pii_=(GKy~X0d8A_+^dqk zJ9p-DI;L!V8%eH1+hO!?af0pI(VUK|0;x#@&tRCA^HX6=@p;&*d4|bcjP}r8Kn*D! zigcvVm}|x;lvqvTIA?W_1*VlVdEh5`Wc9%^rP> zibM0@jwt(0AOXft_Y4o5(y?w-3+BKYW{-JLX}U#Ls6qYkT3pMN zORIwaUgO+J(QFB-5 z892tTB(3#i$ijsPTV=cJ^nQP-nrl*R{m@b@wLyIqd$Ocqc)p!FrY=RuSgWr1lpjXP z_*}Pke18VfwMVI7y9B)PL!A>9(Be3Z)O zC5BDaid5(*q>4~)118=hTIHbWSwOP&REsK^IW0W7TtezBXR+cQ=!MSUQuH^MZfT*! zi`Sm<73xIK1T5W!EuQKY0poObfDFV1Z~)dMM_1ie^V&rR)rVzy(h6dmcdOa6ti1g7 zD86Ry8`-N<9D`S66f(K^Aq&W8ONWb^v0Ei=3~LFLF?{4uScqC%cfbfbI04uCw7J== zTUxcv%-GHZT6!%xkU+Z`AWUd8|OyRR|tk!uGCHr*35d%dFsneBGsT?P_bu?bS4&hL#`|y@QQD|C^fl`2gM1v0UR$X6iRwbsy3U7PVv=PA!ss-dl;R`)z;ABZp^l=vf14F& z144;){fUxo{>+Ob{Y>)8*crQ6o5+|r8yFin8~mp!UK_;@M{EX|%7GgG^vTm}WxW%k zU{gb};13vKK{uQ`RG`OIUwrulWDN&MeK&s{$Jpl}Xn}rlrd1p<>1xxP;WQm+6p7jV zJP+B)7s7N&6+o&5%!ihK#p|S-am0x+jNme}EtdOr5vjyA?l13e-ht3~GyOYH zRjC+CcF+7csUi~MOAzW`rOJ+|54Ah~c;f_AP^~Z&(6dxOJ0{o5{@F1JIHkcc^0UnQ z{SxOP{@^W_6KooR$7$v;hBbqxa+_nm@};BZv&wA?Mhk*BdlZoNlw~>E)wrsS<{~=i zt^TT}QP~r^{Z11vpnE~)ix-cm8}6;a^sVx3gZso5vpqOyFZzom-PZDs4unCi-6d!l zsiFclO-M=Gwy&%jb_x-P1w0^OEz%KHDXxQ{kN#DiQlrM{3u*%5_}`WZermsM+5eni z<g|?eH!<7CpXfP?H;d#$rmlxtM)3CX$IKdOZA=b8 zQ`(u6JU*D{GEUAWlaNhgq)O;9<#JjB6VH*)GGzzk&27YqAq<;xa1}g{E2KYT)_A_$ zKAC$1qfE8#It8R+s5o8nqon_bvUgw)E!fsIW81dvtk_OgY$q$WZQHi(WW}~^+qOG< zpT76>-hKPor~klw=A7fJQB|XAyq`imA{-DJvJzEmcq<&WegDlV`|Xm%_44ZIbLhgzpYp&1^$%SY2s$UGo;wf`Bi zfvo=y*|m!rRVV1@twy%L&R+2s&wqz(p8N3sD`dE-ivK%gng6Gd@q94(zy4dx(=_Wj z!9N&d!ar?K#6KbXt?z7R@=waBpuYXj2sC0AbaHgGvHqVT=Kd8f=4ahZ$`1}~wnymk zUpDN8;R~!^&xfl&;iP1`+vn*Lv;W_;QMdY3&&l5P*g*3>)7Jq(MQFC&j$w17O5u01 z_=MMVuLyLOKoA#nno#G5n@|S~Il%@wxbeyf@=nO8`bvDS*L)1RMebdI9g_PEu49j(BVR#P6vh;Ap+Y}Zf6RtMyx!R`Q zuUnoS)o8>FYf(0%ArT=f<=s(e7?X;!v zU_ZRkf1<@kSPB1$789nP@t`_F7^TIU{%^Dx=#i1p4_a)s2jd4cxn%tw$49IF|KN?j zNix5Yw8HMg2EEp*PjM@8{@kpGeU^v!K>ntxA@@{2ZjL{!I&itqL?5qJnpH$2egxZm)(1Oth83JFD=maEK(Bri zwDfQbAUv*#Nq!pAg6&xerYoJSBJC24d)l=>D>{N$>2UA90&F=gnCDd1gs!R7 zV`8J2;}EF#>dNojhQ#5JkcIMTc~_@zeJr4yIV5gM)oE;3alCT8(xy5s{g9oGw2XblqmCr63(wy?0sBxOr4y4o_lcYnqh837eD*+O-NNH=V{E0^EG6UE6TuL zi8BmJFGts2hb=AwNvpEZquC^_zZ*b4af17!tcER_{}!y~_dlGIp;Wwn(5*2w?fC%t zSCwFs0237as6^yPB_#g?mHel?AEfZF9`BvBNPE z`8;p?Jl!T9F<+s?0z+wkcigTRLdF;!8L1Z|%MuzWCTX29Wr3HhNoG|TTWfGM+V}~L zTiO8xs4*9LviCxQhfRfdbO4&X4C7P zZWnGF$xAN-W&)~@H48CqIU$$(1+!WEWjuvDkz7i#a_PJuXK&9s?R+11mKFBfJHkoT z9j2%LE;ceZYjb-3F@67glaB%_TySdr57T$@AJg}-wca0UMzCa1MO*tP+(ek~?@|N| zCh8gF*J6<5GFppFGf-!_ejKD%kpt$T&H>@q{%8q|BZ_*OOM10qHikijk*lWd&J=hl zHcNeA$|GXX9>ju6FC)w>s%E>kJlkuw@uFeL<3GqXyRjF4*>7v^+=oh7yOU{ZNW0s` zbZGhwelC{L+_t3+E?~%lF#lt6-%3cWKyArW$8Sc7TrNR_fcp#X--onVyQC|Hr(j#Y`kGsRzu28GAV4Fg3$Pe{epn730!=cnb|So(0Yuph z<`exR&uJb}iqie=R37Y4j(dSMxS%!rQ|&d+Uh#LpJSU_<*Q7B>2C3D{0!o^41dp?` zT7Ru3TXHz+;*_>UJjZ;Gy_<+p9OtlId!v}=UbaUyRHB~ zOKM6wH=`@3!h}(NA#5e8yL68dQ$_oBb?*k`NhlPr&=}N%pqDaGgslt~SsO4HP{pd) z*|GC9>y?#EtSYDICB8nS$B< zwHW(VvNi4uaW~!_X{(UOfFHr0FzyNqD~7hj7Ar4QQfS^TGqlViJEAO4vN1uj2E#>8 zM}b!jz&%eZ79GM3qBR{vtRPh9a00%ZXLz$3OF|c|ZwPXd?=gOOYZj%;sDW=J(-$-c ziVw)MYrGYU2GpWe_)Ra7*iXv1wt%bGfPI4IUT-lUYY{f38#DZl*OW=p?-17i@W7h zz*>URh*BgfB04mz`%@XlB7$o9r-GcMS)u|xCSncBHUjZcH2=G(J5FN4PaR z#`j#VwtC(EbI6?KQyvrV>DPJgVs)koq=)Y5i+HXA2>~Ddn`iH{&ZMi~k1+0jwgmrZ&y=+` zQZlnLlCU;&{PC?ZbN|oIHC76Y@#_pf8#~opX=9qvrZ#E?Q?e9?U0&dX+CWATCX$oZ z@pIsz-+NL@NGpQ|=-j!TJJJZYMTnMK9x!xb&R#Gi9Z2A4qSJg78OJB(-THpO+?%lk zX^HPhC#5f^fZwDV53zE|-@B(|T42&;FxUr_C;~nu!vGjkZ_ZEUn~Q?0vt?7n15^Qe z*%HBtPCV58^b_k>#UN;g+MLX%>iKfE8J2!C5 zXQ&Ro-yb}h!(VS-S`RMMS)U1@T3`=A5r&WG4pT=T9lPm{OlK$ zwJNtxwazPue_6nRP@;A2H|ZlKv&H6~yUL`|Sm=HaZUp@MVv%BHn>6=lloP@I*Dl@8 z(B90_%E83Z$=ce;@;^=bhpL)38XO4T(LO<>Pk@CzkXFwM3d;Ue3NgaTH2UvzAtNjO zy@SKfo`g5oF46=D1XjNjLKf-habk||UK@D!TMayipmNibX7V-?tJX(QzV^Xg6q33i z+WnMG)!=Ys z753lN@J|0&!{9ua?mfvD!k3Yd^@N)2H83xcb`0-wk%gR8a=bgFZRQs<6U zOe3dX%I4Px)9_)^;EcE1l^X7r+V?PKVWOj#UZ$?z2nH{DH*DU;P| zXb5^7MNetH$<7(L_5EhX$8KVh^U^(M3vjrQx>`gpN=@0|J-$6nr5 z(U{DWu~`D7MB+uUh+s|p0y235eH>YF973QYUO9~2X>_+58x2g@)Xb;n2>}|8Gv5yG zX7a`CO})`o@TGgW;tm1a$su-nphF|LymnmRx_KhxtV+mI)>$FQpxUGLnG_oF)&}H6 ze{d>ZTav0VduM^F!N4~@YENCx=VbKFmv+~Tf8zpcO~;|d6je5(k3lw|@mDjnIzR~h zxINiTwmAP?QH!_I0@pkVl8-|V@Qiw;+eSYIwJR8Je+XQ}J^K%_oL-42eT^*$o%qek zY4qfdC?;>a1S+mB{NvD+H;m;PVR3o!<$i{}TD=2q?n>>qSP>^EG#s^KRsrYHGApFSMskMZWA{_n)19a{Le#>Rs=;&> zFK5WCwDFNrgG z$peh;)6{@L+dT|9`L$w2!>(^;0nv8?AX$+*z=t$vTzhX83T0#7qpzk8b&+(EXZpaS>E^Y$;Cg?iaE#V3+f^oAG_hDwcSU#+=wo3+1ZzoLIT;rLcONa9PRuP9Sj zD65Chd`P;SG8TP}T29x(%@1Oro=C5?P%ECtmctyaKkpv{ZvEVLBhoRcoc&4W>`{uIm9DUxEJvL~Dcx5X zQ2iHDX3%e9OKG^$KLxuc{3rbJlHfK#X9UlVSYVvl^Jw<)k;K;M`GB9jzXhM=L?g&$ zi;k?o_IUqiRY%rs*P)4?JDAR7oaP@>M55rL7bj-gg%cYPW)pYmz$JxQC2WS0a_;Kh zvKrV$#7rl6kgy2!MJjTAvtW?*svJeK^QP)+gNvSzfAgCO>cGJ>`3bJlkJ0HrO0NIK zOfb^7H#8Nras5xRom7&M#b!j{+1F)6!a<_UC}Js*BScgx6EMs3f9lIicQxrG(^-E3 zCjIVefJ{V?gBKCpOyJw{>|oz=3A6VL?=g@vjIGAaukxQ?yrHvb4Gk1vb7)4<)lQlO z17GVq1p}o-81}lZRkgSXtYaph^&MX52z-<2Rm*>_+knhmOP%2kTwB<;G49Hh{>#-VDs%G?Y&U7cgpK=cMCIsnEWmv`2UzU(Ol6xsdz^ z_(pS81tmA%gK4Vy&pbjgB#8#ZfwuVGgFV!SY2bpM|CpZ>q^SfGIS?=8D%s{7fZCtv zGT70=G!t~SMvQ5U)n(CEgRKoUpBh|%AfZjy!1Ad)@z@}=w?7=|0)t>I3rgFWJME&K= zdU)dtTH$j?uA`K-a2pId?IwP@)eXDN$l<8?3#mO}^U8sf^E|zsHunY&xzL`rA+0vO zh4_oo0pbtoAa4Usr{AIR=6QFEmr1;jg-9qOOIvv;&z1d{j8mtwAqL>Iy8vpg;AAwL zuMk_{PQCfxFP%E}vyEGM%sQ79tK;BLJBx2u?Zy_G4U3SkrhYEFOU`D$DIS`1)nc zbBMivvp@9nqJbIsA&=pq0svtANLJCv@dqhm;viw|Xk=+=_75oje@sf7YTJtIzYx5u ze~2H6A%BVoNSEz-P8`Vsjc;%paq=#ubveU3NjU$ECLQpbtW$3C}gmt(NTUIKiwxs~qTLu-z{+0oT8;;{VW%!p~5)TT6G0ui+%rk>qk zZk5<-=3p|FKS9#XBU&{5a>xuZlS>63h&>g{Gf&SD*;N-K;mJ;PI~i*70O{q|iGEEn zLf;G!|71`oNG%#l%Fab5F_J0s)uC6*K!vc#Bp4@3m%Y(zwwP;LQ**gse;?hTx@~h& z{Nc>rUQ!^(V6Oq;@Tcx1q*OVyLaOem!B2!2@9WcW>#meEs_b5H~I;=Q~1 z>c#@{Zx>>#%?!uEhMCWKyltzVLYSoEH5B5m>Kk(4x5`Y&fDAWfHSXj{juR1;uSm?J z^Xl?BcC=M5K4Lx4=ljWdM$F|*LVc@%bMZ9LEfM>`m28lXE-Suo7YKR|`C2IcjR1^p zgT5up5fSSakTd=G*Z{N1xgR`Y6gdfV;h`J0(K6_3sX0$*_2;6+l9G;v6BV@(JaYD3 z!Rqup*o77E5Xm{kZ3P7;23bg|O&MyH3lxUvMy^6(*-$lgyeL(&o8WOqa09ui9NUCY zNHrxLE$hrtO$3dKcBl&n6=gpcv|!%IwF>a$Ae6`aGMXQ| zc1`pa_tEbmsLkT+9ewIdt4y;mLt|6-N;UR?u_78w%lRxGqS8_A8|?1O6wLsl3g>g| z5TXimXDG~FoH8FS=J4_QdA}zPQLH5V!xI81z+eTQB8W+&8Z)xa5+_ywPnN=W@hoCI zUG$Ig;>Qis?TpuXo%|HN>n11fPSfyqZ8k&+!SKf^VuBm~c;Kga!b9DHi95z;<^|~B zfa(j>l)xU#8-s~%yWV(a z>hcoi?=x0W*Y8liIX{Z&7r`b|Ez$0WP=t(e#LyMFx)-^8us_bGNa$tpeg!@KSo z(ys2rt7gufNaB}*@MHbAf&h70vAn#}{1JIWWqCp3C&jdP*j@R{bq31x{j^ii7>0I@ z&G$9^Yg_h`yj#SXnY@7<+GAn|a}}F%l*)IMcOUxbCg1JOFdv76e32|YoL%x>5j z_P|1an{&RWd1sK>>^<@_$X-iF_5xL3+wM$9gnm`|kP z#X*Lx1k&^VWzg1%@kmqRhT>DIddgUiW~2ZxzjBUPr6xm9LCqV%^kFmlT+&kNlk?p@ z-97#4!{LZef9n-qBeSc}=dy+SRqW6gs7=$w*tZM635*k&Wdj5Nu1G9de-<7p+5>8m zX8$y!__PT=COgZiNkcn;_)8$B1S+E^rYyYOBm?1iRV1x{9O`TFj?k0nF9a~pnd3FQU*hGb}1;DH!iwRKUoU_~2$yuNU*@sErwpq6XJ*(uT1I8<6e=fB9rlP=mj_t(iVypLEv z(;yd)HZcsh>Fo8!izpo%^~c^tBA-LYJ?--VR}H0JA<@d&hrC&0Me3cDLo z^E221JUv4G!lMFS&lme%oGGA>2cR%D2HIQqr+NC-(l^UAP5oz!ZUQId7NMs`R1YTI zuW2|LZ+clM*#=X2j)!p!_xW?Tx{h5aR6bwXdl-G&`JF$A#R1Qq2V?=NN zYw@iM8FGhWD_OoSb1Gq-Mlxpngtu)d(3mWXgzA&Vm$!|yP^M&?@S50)=eKm8QY9|St}!a0aO%Qi{t{n(Vs9MDHe{>bJIE& zCdGRckvO1kuw-uSI0tf`e6d@8SK(h!fk+e98lX;in~J;T@DkLHn1Gb|))ihG)ttYKt4`6R@x6LdIX2mfx7_x;CMt}VT6*$snfezU}NV za_SAX*h<+c4vAY6J$ZHsg{CoD(eKmTYN`smJncHW6-$qt-M{Zp{k3&u>dpdfih#Dq zA0HY&-$?>Ig1(?tpZLC&Y46_?>L*C6c1$t#Z*C8_U0I&ABk7nvQW1>$JsH`-E$6n1 zwm96G6SRvQ$bFm&B$Jm%VfP^v?Q^#FD&87ylnnf6yE~~6^1-3=~9q0pS`6dulOdki38e!F?Rht#>5w%O;W3Gir|H${W_(Eun6O zUU(KYz0h23zu8EESZ|7AC`8CApLM*{ifQNpK?=H=l!BUu;##p@G7=8wG?t6W$Hg_8 zh-L~{XOVI#{tJXd5mHhCcSA%1DnEM>gedx(OAs`GP9TXnd!O(Zc`KU(QHoa&%(ZJL z6^q^sZ5^z#GRTQ$;(}gq5Kf*ZZD(`iL;O_7fCnc%yP||e4KdmM_Q4@lIlUa(zOFL| zuQaV!5mcaE)3dw!V$8X|jY8Ah!Oz zzj{|%A|(=uxg4v_ub}q%a1|M%U7&f4gEs;0Dh-3}qx3PJ91#(!J=(+vq%_EZZHwrWpaY6o-=U|&pyYiIp2)?x* zMeUODLltUpkk&F>A(rmi&fut~!$_!I>a|S2*rj>LZ|rH2UIDgtwzLLW38Bxd+EE=x z8h1o7-Mdt0u1o1c9GuM?ZuqUNl&AH7y zI7K}1b$xBTmR(!sws$Y|c#%z%fv>LfMx{Nwrr;Vk6cW@0P7@&cGTk(s`yj^*b+SAf zf~T7d3K=+P#2$*+Yi8+=emP_#UaC;)koUR#^7Yxj+DDuE5J}tUeaa*6gdM!*TOQ_y z?5}(7K00+@#E88e#0DG12-P}#!OA4}86yHTaYB*1dlG9C4tEv1N3x0mh7g2P#$InK zhR$ctEA>73*g%t5VxAFzP>|0=U(`<<5I%YF(bM`&@jEu%&*BVV$1lYl1||yS&ApLM zhe%H&VptomziFKLG-UBin}8U*Fce$E@6I;NN%tsG+LRyRbP1bO=8ps*iVC z2_M_peUJMLx~9NlSnfo{3@BF{;KGwvGN-raeh3x;3I`*WmW9S|RWEp8(=gQWz|f~H z+sNDrW2X^DR%!~MA**J@_I9lsV_B0TZ}n;AXIw2HCcFh5j|p_c z@h5mr?P zY0P^yn6CXj2jQGqW(Qz6x{MxMvO9%bU0Ig|iC9y4zil`*q%cHx7g$m>UBHFnQ!D_? z9Ux=G+^3LVbO*S}t>(PLIpx;7if8!Ikk%t2(dZMJg5fg~5k5Ki%&g9OCqP@j9^BKT zq6%@ZjA30YB~0ww-xVQ=q*pN(=8xi_uoFs($h z*CVTSAU$u-vGcq+ZS|TuUAgUSCem&}wYDhHThvieh_JBygay7SI5l#LsDjGjpSD^;$_L?2n5EdKMDD3Uv7X$&XbYr_q~iY6rlScD7z7X z{!qNmZAmc2>OS2yrUJWl^q+#LTu=iL0Kpuk=8O!oT%98EP&r+SaerU{LUZSXK{EZ7 z{jJw&y0+v>^v7PcxR{Ni6!MpFPH{rd?tRdTray^v9LRO9BzVIi*$v15}Nq!vFRcDZwSh2238XL@)ZKRcZAs2MVqsm+pZhDkuLaJmztZ# zByQc>-~uWoY$noYP>7gzAe(m*7f6gBmo&N`2qc7^1@ECF!cNCtMIsglqv~Cr>ESh+ z(1aiBCkg$aRv+jB8jNhb+u^xU-vh&?UnWW*Fu+kB<>JYUYUyE4J_00 ziIBRze*gn=J_@(y+`5La1Q)aTXKaDVUsTAPkk@8#b>8ND{6n6KKrD_If33A9>E-Rk zz0d_;@@HW(za2c+;tr?+8!uAzzC=Z%RnEzGCg6p&KbeMw@NeJb{NZR{@3?1OJxNV# zEq;08SWO`@o}h_zy6u+$w{iuD5{l1N?IP6QP2Z~M0Wv7nB!Az!XlG(30_n|FYSu1V znk6DFhh*eHebQgXt{ytOR`#yut`M5Y9OJnG@xNhUr46d`3+K+;;Toe`F3d(lMZGZ- zVQlT|_wQPD4LNTcs-==j${LV>z2+~)Y^~g}_DA9tJ{xVg#}DQNZ7at@v6I3zSGLEL zN<>l-q@|&}CS)hFq8B;G|Gphlpw@_DN`_Es&D|($L^qXuYaWRhWKk`>rz0^*GB&sw zdIZ6DP|0+0eJh|9sqGvP=wMLU-0EUb84u>XndeDYE~-^!YJREOdXXPQ7H?#7FMMYRf0_Poz9gr{WUK z!h@;RepBV2ko=WXJ>Q6!kXe<{FGUBqA<)MakO70%+kE2J;*44RRssv8{I85p^k#disGvq%An*F$Z3*b zR;wg-GY8=WWPQ9GDsYES}P(wj-W1G8oN&ua@n>wWnmF}EsbK=O6{RjQ`38>&6<)rq-KCkNfJD8HR#Nc zuuefC@lLeUlXim`NQp+7HDE!Lbadm#n;?nEt`jla7~iqH&ELy{^GAP?X|FT3`1Mmj znKYJH6Mx{lq52GU?%@ygOv{4B4kLBv+?EMAwbJat<<>eeK}ra}~DVl3h@ zUu3=X>OnA-p$*RXqiL@g%R2vZCOexY03}!5ZNoQr`sxJh^uz26I;BjslOD(1d6iIs7p$G5DpRj?1Y-GW^q9QNmOA4T7DP;zMbIHVUEBxZ>SPhr;T0!C$ga6kyOc1GGL~v>Jyr{*x`@ z&PPi>CMLa0WrGM2UoL92;Vqyg%@JS^47UBuFhD);uWGKE$&YzvNN~tp5KRGcdj)#R?tT(1EHS~|W0!YRc>!Y3I5W?$<~^4N^OEA8-nHY?Kfx?XE@ z!A#vDdyZ^M(JP&%Hi|=}hxch}-praGC=plimAm{~Gm|d5s6BRC9GDib zA*BYOJg`9Xp(kz=kPu)}b*Rf*)W$!xl3g629b;@F<~sGodBjZrs-{?_^a0cCLIhIr z2Mh`+El}eU)7zQfKr`T)3e=@P#cLI3e{eV6jhow4GzO)Y1s=GhDN%6;KU~@%Vr0G4 zStL`Y3Gr3H-bt}m5v&#@_ z5c$!gB~itfM)c+1Ub5s_Mw5+g!llR4!L7|^mYv&BEI)+8vB zC*(;ujykzW^=PIv*^`#;%GHF5b%SD1iUAZ7!7lGZ*-a@n$S2}HR0jkQ_bc`Y*?fwD zmGPj|me9#cj!C?;#h_DtFKWU`PtT;`1woD}Z!Q`hUlX&IRKJ-yq^)Zhc#a>*jGVq! zkjpeu8)=8b=~|}N_>oKhO7-|MpQnP5x?y!#WVpQm{RP6INoD<`iUs;aqpurvOFxs%@CV?cq%naR70}6226EtGoadP7{)r7p(Xk!%Csi9Do?aO z;TxzW4mqHt=XrN@x-Ald9kS0HBW&?YRs&XXc>V7spXb-am6{x+i&Y{VdmzZFSzZ2b zADa`|B+-iVU+Fs;Ex{dQuGuN|%iebr_33--Fn%_qLy_d=ygtQuu%>6Vre$_IWX%%6 zK^3Tl3vqb70xW(K;ww?Xc&^G4B)qiDB$=`*x8dFvHE4?&iTZ}R;Y9RHau>GI!xF6> z(0pZN)6bOyd-Nyu7buj>ydN2QL^LlVX$OaPk-fimAeb?JgY%);i_fA(6Xt|M=oapo zoRG|E&z{NYpW<&Oh`IP{&UwAiY(eK+c;<0DMse~6f*!8t2O0zJ{!N(*LjS1DMqS9X z_)Tztx>Bwoew;)Js z1|72g)>i=piO;9{?#O+MuPRb-5;i1*I1)6pcmcw$ZOT+*kGL~iDSE4y|P>C()*2i<$r^lwUG( zSgKcPA6}SnD2p62$IB;5edxk9^>iN)=HVfQKOV7tss#@-m>_cz;KUocVv38@Z16(r zCFgtk{OhP{TrGNd!M?f)RC(6vv;m+S+jz4@N6(utQBxOY4Gyo#rOy0a0ABL>>L_l)WPkk!R!dNn-c^HkxpUGS{m4L}f@q z<>U;OZ)vYnz4bsOo5(GJt8ImFM=?gQ$c_7tTVj~f!hm^O$_77?b=l^B>j0iZUA(_C zXsP&uXGBT4v)z|)hl`j8z`E4en8h05o7!hfT56=9l}bsK`HX1tBjt@ z;BM^iIXL(Ba|DZ(9q7nS6NPuHNtQx$scaZAQaLE5ohgu4j=2!f13s7+A2Sp^f>&J0 zsK28KnF!l_sg|<-N<^KU0T|i1<*@E-E6tVv5zlU|nhp$bJh)%hky};u0AH^SUKQi0 z>WB6kg1>T|zc94NG(;OG{f9Ko*`gnrtgMY4fCr!UrY{f5J$ySBekzbRRBSMieai*% z2Dmp>G%#xRh4;<8;X>lCR^mhJoS&5#(8ii@a+c1^F@6q{nFxj2d=)4%Md>|24E9P zNV$+5n9GG58wkmBvX<(x+H@qKNLO`C2-hh5SQT0v$8!t*UXM8M>9(^;`LQz#aLd^H z3(gqH6MgcB_O=+Rk41F<`n+q_s0#N}wYd@3F4H$pkHW$PHgQLJA~g{g!6VUSm{0p$ zFzCSsIF)6{+YeqwZ@3e9B~5Cbs7o`QBj82B9=tX3X>?LSOj?LX7Dz@pP+-9crd!nX zj870sMmcm~Nl!`Z6j?`n7^Oadcj&;KXIZ3AKPtGgLJD+iPk$v>Bddi{0wAy(FdBGw zz&=hvfIPa}f*Q9rowR#(E(K3(n|-QDgHpEGXHE||bC+_h7mDcHhH)o$z(>8PL&1-B z(06BULUn8LrJp0Ks7Z)rG~XWZbNIZ*K6NGO-#7IkRArl8;;6i^!UV?06K!rB@EDvt zmnfFGj=n3~hQt?XCKQGCEbd(oHyUh~1Z+2k-VpEw;e&ei6o2cnquOYx|87W&I8#_P z-ke)P-^Y1g6+h$>VKH!LOM?Kug*4vJDb>*%&5b6^q3d2KNy4fmIhYdBQ8-S*6_36O zBD-pL8Dz#nU^tB|SM-z|bI!Ez2D330Hjl-~%AX0A`jYa=;kh=NYq zGk7{325R3PHfK^}je7<`eK<%)#^+f#G?t(UjqEVp`e8t-OLrLy89OG6G6G`DT^h@wj} z48eU=P_~ccMdxascQEZx{xjY@ICu{NVPx1tY!~w7DApJU;xR{I{Q@k^cT;e_;yhx; zM?nWONQq|%{0k3_8|71BqOT4gbuIV&^_(BM(saX2XIhSD(7gRl?@BT>{~f?*cRSV) zT&2>Pg~kY{M(WP|rRN(h7#UgE%$_zz7!{I@BLT-$ov(EzmaQYiD56Vc;CbYD52%LX zD_K4oqNeh2x(ALIi8p-;S8xlPaXp9m0R^_egc*1R2?P=W5DtTEgx1?+Ea^r46n7M;gmE{lgeCSL<6S+nm!(Uh9Tf;2I)V409%B$(UraaY~DLJEsKM~G!V&Y z(awf5$uZU?Wj4Sb=DY|VHWwCzh29ACN!1=@r6dHLcT|q{OPR7MELy3Q{iRPeXK$&( zTeKW;)EY)}Wzwh4P^8JKk}Ax~-aTJYE{~wE5xc{XBl8HIzL24(SA!hIi9(X^kgTVy z0`La#N!VhcEu2zyu1mK!HS@^WMKY1jJrgi3Z4ia#a<0Yn4+O4)XhL0U!Ok*E=XPo) z!=>*NP#4Xx(}KiOz#EvDrsKBYuS4sD&YIpWuM61^HB=-O@3?zaA((zLesj9`c4VkR z9`el>NmEr8z=l#$oJxTk*@u2otMxc&#?g=j_K=Q_0?Uo)rBDZPVR9pNDv}HS%Z-@7;*ek^+)AH-#j(7y0w@{1HO;G2g@PxKd?)W1IHobr zvj)5EjjmE&!<6MC$cG5Ri*VR&32JhuX$<6H7}Lc@*ci$r+Is&Elax~G&l#ocl#_DX zOgiTIUWRtjJWuR&tp(Awm_T3KCv$DU8Bk1mR`OC?e6kfvMP}kIH|ZzR95W zM(~pQ%>e%dU|{bbRATQ}2f~C1c@fnVQ@r-VolR2CE3 zhO*s! z5LG6W{%)$6WuhBlX*;>!PP85p41QTepp}zY&_oTlOzdLO4Jq$V!Xo^JD?&N8CyrZi zTsQF$418Z^U}=R_i8&WUAh^;)HT#>@(2blVQn%y{ijLCPajv%|MXJ} zm#8E4L{nks6!aFhkX3C3F;Uu0pGV3k9#^b|Z24SLzm`XgK*>C4kkBz_gJj<3B?rxa zx^#%-UBGE%|6{ACph!HxxRiK{BgQ?J65HirWrZTsXX-rQEF{-A$0WqduA=a`)m!PeU@;vs3FM~Mun%Voar&q*a*KZaT z1xT9~VfPGlL6{hVa8km2l!78kI{|C3mZl1NOx_v9jqbhcT;%kh&aOW&-Dxg7x(vmz z`{_bvJ09K*PJvg7o;7!$Ln0S(qSnum#~{wF(alB789-#yPn^BX!4)&k11D7nv#sOy zD|{l#UM*dn!ZWjxt!sJTp$^Y+1o~op6}cz4hImqks!7o}(bmKiJFmBU`Rx>&utRHM zN#YeOXSRjM7lPY7OK)k)rrp?LHeZP*&9T2jo6#$nUDJ_wm%PJH1=;?dkE@UejMW#_wx#VeDpR2 zG_MJ^xER^@ZFv(DN4lti4qNBo<*m-Wal5u-LKjmo)IIPg!ne|LZmmHO6Z5zsS0$za z>~Kq}d1)o(iy<5Jic04w*}DiZ<}20-Uj^WP_-wgjdH7^T2nq0zk3+*;#RAYtOO04Z zdAJA2%0LwDBFzqyD*$r3O#3UMbVNN-u#>>I@5?fEL=}dR*@?sW{l9n#oe{|8cwVg_ zL<6td05Q>SZ7WLhT+1ahhxB`Skzu|~j3t+fL}D=7%Z?alIpE1 zY@C;ycZq()*|1hc>dN>7cCO(oeT*_R!RaW7z?c(W1``bmMFXJ|Pei<(&om!s8*U%q zDpvP`R=KGqhLG9XB+WE2Pi|9Lmi7G-^J%iLmT)}YQHej0NmJVZtTHHir$38b*_!FL zhY*m2`}`YqiHyBYwh53t645g-waQ5N&k~0kxEq=21r9}B)4|_Q6XHO5(#kt|`z+tD zo^W98T>GSjCdM{7PDd(vhldMayi~egbK-le{|jY6n!iQ)%l&5~7)|jykfo=|1C`rR z-r5cXA(7m#bb|m)!=2L%MM;P|Z_*F!@`onn@H<(8VR=9pv^HoNV2`m##3MRf$s8K1 zy#H(j%UV)V^Bu49rPPA9nVdxtyvVBrb_-2svZ^ornRrasgf-_rj_PP~kS0;p^bQ8q ziTn^^@FT7=eMTsz3KLLN)r}#*ij1jB_v$Pw*7&BamwAjKJls%W(UqV2m&K1J6k zol!F_Bt)p|2JSy|Ea7IxR8aKsCOXd!vJK@z!KK_Dz?uNm7%4b|!~j8!8k!YYVo7q* z7Rq7*jR$);i||%2k5Uxzk|}gAuhSSrW_;yVq$FDnTb}fK>Nh7SnwRili>8X-aQGQ5 zMi9W0O4$65P%sdndnEF}^AUvnq{1j6%oky0xs1)yPaH-49nfBYv3-A+I`sbY5#)Qh zaw;#3*cF9`+^Cjne?lNLy+%nH?5;=BtpF%9Pci77M+Q=cB)yANMIsf2k+DW|>t4OHW+Ez{3udSx+hq9mVyB2FQ>26%)JHhN=^QiT= zeb?elT=Y7lX-puY6GQb+h;v7GD80(hl1zwt85-PU3#tL&UFFF>@c011Ay7p+bYJ$r zHX2mg_|4uUMfjuM4!>`&XR1TAin63m{zOOeY6Yy2oO9$J1q1NA8c+N1-$k^|8~?^- z#b)3CI1CK83|_=OoHi+dMvu2*1wWD2PA%YSTo=>XA^9)wZa1&j*KmVWZAOK-9<#$F z1MB9m_Msd}h4%wA)}=q?Xb)5Y7(CGK0kreH)U{u!JWA=ZK`EeIUu_(Sw(_BlATwht zA6|&=nq_xMm0;E6cccu8%mNx-nI~nIa{A>V)|HK62Obm9m<+f|T*-2k-`=K3BE383 zGfof#8_NqA364|L*@&8bVAez z2BWoZ(=DIJ-EY8$Um|-oEa%msXND(qsTOHafYC#p*#}>v7mi*d(?UUsij4NsAd8_q zL)&8Ce?{K*!qL5?Ta;x~$%2owxgkt|Vw7ndF|^;HLohesYRw|nVVN)_eIsUEx6~8e zKVwMXVEgJ-_YvYFbvpeEh4;#DF_{OEMSnTlR?Taw9^6qy99@Y6Iw>4cZgi?>(`2Ry z?>SrDLzQR%Hq7|&zUlhY9#LO#&HGd}JOOy1rq+zx+HHD_Al&DtGm(VON-(xpmc35% z>**o>r|sNv^0P?F4dnKpRn7%a#2W(k5%dM(!-7o>7{mk~zy}siN2ep1+%pq9=_GJ# zvbFbL*o(y~u!VYlPXtGA;69-KnIaH_R+o0`{k7#u^~46TeOP)MP1PB5lx47isc8AE?$Wvc((X~zEf8k+pp+n(d!&u1Fc-x5B*niSbPKs+KAJH9(xZr{3VRm4L<(#L zTNxjm63P?dky3)05}ID-slcJ6JhL`7>MJ!_U^We}JL#AL%f>ed1+t!={6vd2l!O+( zzG3}+L9D9QD+nzJ2^r&&u*c{oTBnd*MpBO#>Joa87w+K2b;nc=c_T~VQH9j96z~mO z11<6Yok{)5t`^mp)y1eL1<6Sn#AEj1J@1=|3BIP~RofEUdmn9G0;O?PL%4Di3;~Qq z%DL*zZ1C;gY-Se(`EUS?emGK0cE&`xS9V3lM8%4t+|pprlTgm0_#+^dT`hqj|I9O) zT;K5n!^VTJh0W)50L+u>#`fKneBcHPAzi16?ht?M1~a9hU2|}uVQH z7srH?8WM|XUb19{roqazUQXlub~d69O2Z&23?#X^ffQ>Q@jX_G#LfjxM#V*$uZnsi z4}v9ee5r6^I3}F0p|A+P^JsMBoQh+hW-+(R`SrE8wFTo%uDP@1wuHXQc#Ev?f3KqI z2bdS~Sq8TETP&YtvD8lXD;`M_+@Yj45nNwc8%$6{W?w1}|Ddo;-Dn{dxmV<;(jz*W zAShM?WAUWyLmv5t#56?Vd|gA5zlvci+ii48G>~#GE#S=;Kc_d$SwvoGJV!knL|_^v zY#Ee+@8(XZ0@80y47T(FT8u=hr1mmRPZmh#8L`PP?Cr(u5U@Q&E{0 zki%q7gbNaC)v;e)p;ZCpso&!zP!U`l+`WXbFu~Dgks?5g0@2hdp*xt6881IY`L$iA z@qkNayGmpwLN~NYgZ5T%Cck6=Gzi1qmSh*} z)Pxj{CA?hefoV=<%b|ps9Ii2MbaV=E`oKOQYb~97QXUXLq?t`NxITLCKCroy7*%oe zkr^ot6`VdVLBnkp<@vUTT~Si^W$B|l_H$hVkX_c_d>}kw((cB#P7`xdEy)8`J8<&M z=9jTg)(&0L_DSH21xdFVwF+bH z)2Fp{Jm^E#!y2<^S&7pUA>AASdN-TrYo4w}!<>sPS`xGEnPwB=`cy*t5b zfvYn7*oG~@BiP$-9Mjtb(`1K|kOfl|vn-;SJbf}c`^ZR-h#J*PR8FtRe^`>xMEdlt z!~i)@O^~$ZwXrZ+JlHq#SBu?slEuyASu6w>*_#hE&KWoKn`thR#SgiBiyZlF2_1c7 zvq0#vC5cq5861~%s-{<>Z=h&1L1Qo}*6sMsw^gqiB}c?fk=3IExtHSlkxHIbrH%n` zl{rZBacS7lwK7g4u|!gHiiHJLk_67`56)~+uMpYxAy4C`u+$qj5AaCDbxt0%QP)z) z=#5*tnI0?1{Bp+1nX^5jJ;MSFELGOt7$yAcbdBmfub0z9{@1~NT)c0Z-_ia(Q3|HC zg`gWLen^egLHPoT(LNj>tm7o#a&1`Kz1{)_WML%@>E`;7+%8#_Gy*A4mvkTzzs!tk zi+*WP_V>zcd1Z`xf_`N-i~SP}TqRLcY$|T2t1DT3vTA%_AG0H%nnU!Uq1T>aXVOS)af5DQ_YDA$wyXp0 zakwFqLtiwp-|6E5lFsUO7yR*faDb|9G5Sd}%j|7+ZTAxa-koS%K<#*VSO`AO3b82H}Wo$|NR)+|)xR>&hfldZT&%PM5M@(Hs*rNi{$~dQizMcxLJ^ z=;7^%Fct{k8cmc&fspV5*w1S>#%$%wbgX{|x$)mawAlTvy>njG3vPKJ-lYn%d8@FS zyBzJLk~MH2KmwAeAE%)6DDLv17aD8=qhG;&69}&Goo$0hu?8btu|{WyehGG?lW+I7 zeQb7x5j8njSz}#3=2@ho?d8M(C{LT!#YsfV6Q9AKJgt^|U`ftVnnHO`o?3d`Y{ec? z6mll4twV<`+X6QtR(rt1Ry7j4&`+hF^dC?JddoqgtIdo>PT>^-hZL0Pe#~h-X#SCn zCG-=c<+k9Z4nuqAZITeF_+_2Mc%)XJ%&X}|gtu=B-?#@p+4&VO(9D4+!rnV?rKDdDuI=g!vrjYL>_fr_q_nzSN4M*A#HIVpTQyRT_R)W>E@=u$8@VCGS`=jtl@ty-J^bGJY7s|iR8{1X}(6J8x~Mi2lk%GHc~zk>+b|$!Oarqb2kVy973OO52s#A@)l?i{c?OLUb5$7z zXDh;N`!K@d3k&8|XH)?`Mzq1x(QQDi7~t}^IzNWfCJ0WuRTuWDG5ySCpMp&zLn*ny zA7+<|5d4MrsDS2U-l860y6sS3(?x%W!h?%4$xG-~yURW5xdTjQytdf1!SyCq#D#(T6UYI_+$t}rgyiZ8{`U!a21@(7LBv?yUOcU{`1yB~?}J47ZhJF%d#RM0sS<*S zqaq@{>jX(|-O;z#D5}`MLC7;%W?wHz8_g79`laAr!M}Cy!Q3B_4bcf5IU>V*xShM> z@p2x|2RqM!Ouqh`KJ)veUM$6+$iO%mkLZi`rw!RzcmW(Y=*GU-NKg2WvR4Q^#th^lPm{&QNlXtB4?o-#bY4*d+*Zc4Vlw=qS55~}FrS-ShdGeA z3L|k?+~gQ&D_q$xp8G0bZB%!Ee}@K|_fC-3ZexNPZPP~gfrkX8mlX)jMNfh4cE*k}D zkBS}dFFfNeHkLF^(2m+SccIb}bEjKr7@Dd*w6E$r^`DEpME`{LLpOQ3lAB0lAd86B z_>F3o<~5-@RyXWixP0fRe&6{R5{u3zzhID2AesXA6Z)9~(@iLb>mOyKW*Yj_8QOY=>(IH+jJeEyqgvB=k1T|qu9 z{Gsl<nYJXkzxLdkt4KDx&>pxz>BD4 zwR@{Gl&w3Jo8ghw2yK}LzjumITs2lny!;DC=| z-)PUA+n`6wJg@lA^${+3(U*{klpttE!(Jx|2dakAzHLlf6!A28iJ(D1UN+J(Daj$s zd6f&`V9|ncm=_8+jQ<`|@D{%d;cq@P&c*)1=r^)1B#kKxT0teppyQDac%z6+N|gPT zR~d1p#(4-OLZO(m=r(IwrgKPz9(5$pZLuy9*0M-oyFnLF2})zaQuSf+Zll_n@+!Z* zP0@UT_k1Qz-)?iMVc)kTi}QQwO+7)VapHxKmM*L;S4Y`5=ht|d?^NpG_vQ)a7}0f9 zp=swgVfEu8%oT5vG$ofm{Bcabgoao2^=AAQTD+-$*?Zw$&SM%=&ol-(%}dBAQc^z8 z4(d8uEDgl|>QzRhnU{ISzb%s*9Y!fAZ`vAFb5`EQ55puY*7XYE%PXEar+=cXiEjOlGMUCLh7&f6YEiA*)t4qc0JjNP z-`@ISkfDb6f(|q|G%x$NV%v=k;>93qOl8yBzB_XxH{D}$M9cQ^_oy*hVjfR!AU zWP_>3ktyA&v@O{VDB){o`6)*5;0yLD|A8_glm>748T1=-HBnA)@qWfPK0YbY;>U0F z!z_!bvOpSxk@-GFn|xhgL}j$9IyNYNWz+h9;){ZH()K1HhRWOdpEZW5>zh#!gk3Yi za@wb8oh_D9SwBu=&4nqfIuUYI{fzm6H@h%R2z}1KqB6PJ>~(0#zV8a#q|iK%wTjT>_GbfoDWn>@Cnvsa$z5sf0Iro@|9mW78jauiuL@xx@5io=^4yzpF_T zND_L>d6v5Wqv@u07cglBT|(pyM5`4=r8$B@8_>R%Ti8G@yS};OZy1ru{LL-lyTc?j zzhSO3hg!%+`_(1>VV!4)hEnUOIukR_u=s`*Of1M|wkAbdE#l-3M6z{?1TiRzV|G-8Fm+yYn8v^04VHo=ip2_kh(E1puOZ~^~* z%&%2|0Rwb73986%*QptK0uQ18M2!_`!ZEL!-p@m4yDPH&>DMCTqDouQ{1dv3790Fk zI6v(Uo>T|f=2O1-fdy5{#SO>Ge{lR^=%Dxb(k!9^m3UihppLZi&S@V*v`~ub@EK_o z1BzDDWB8Y|T=963FZTK--Xp0+x^))m9MY?jokn^+z2~(!=|^EgV7u%cB6}IL@B1QG zH!`KGPV!#}K`r#f-jzZnSxXE}|7fd(VMS;M4NeLW3NP1Lmat5riE#Dx5whBT98Rn> zbp?gpqLgY|On!;tRgz74MSA=<+yz#v;82fON(A+*oT>4&^1juprzxvTuE4hNIw#tU zSu1p5ScV;>3%7#(>~7*F`*oZsS;<~Om z*F+nd2BBqXs<4}k_C#R{Ry-RR%|}NW9LwhjEFrju1(mISlVyxQke!R=H1`TqJop&P zel-1>6z9mxDQ{;%KFfa1tLR#ceuX=_kx^8*l7a~@jT!DLoKAk$Wu%XoNQG!-NBfeq z8a6^f3l${yczW HaTk(00kR>H}vx&rA< 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

vNYt}6z_nTW@e(wm&5Y>9h5>4h4&4S8TT|-}h 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 P{se%pEz&o@`#j|TfdlX9 literal 0 HcmV?d00001 diff --git a/helper/src/test/resources/general.cfg b/helper/src/test/resources/general.cfg new file mode 100644 index 0000000..e69de29 diff --git a/helper/src/test/resources/platform.pk8 b/helper/src/test/resources/platform.pk8 new file mode 100644 index 0000000000000000000000000000000000000000..e27a3933e82ee93d4faa03ed06467bfecf81bf80 GIT binary patch literal 1216 zcmV;x1V8&Qf&{z*0RS)!1_>&LNQUrrZ9p8q5=T`0)hbn0GxOQlB^9~ zI2_)pW$ehN0B$x&3~h1;u^n%{9o*76`CfXB^Ed)p=?JBom8CbLTu zbt9ybXd+1j+yO~Gdh~&0EeWy&v4>s~ zteC;7cRgqTx$6DpZCJk8=-L+fqhJY~H>fnG-|e@yv`Pe?2cl{G&n#4y^3OKbP5BBt zjgK^=x~oj}GjXdYahp4(hg7W$Q~VU++eOtLBTu{OJe#EL`OZ`(6Hx3^RtLXnqW?;u zeYN-MAPoto!L*(sKre~y5s-;Gt6GtO@lxn7g``(g&tJiiamDV)CjtQj0)hbmXix*U z9bP^qXq0i8NQJ}zNqL1`o=gQGzzfthuF=Qrc<8GU>Pv)=OciWZ+KAp#k{NA%2LMPJ z%-px5Z5Uyi!G;4pRxs33vEOE{g`-ar0#ZOAX$ts^ELH2B9voUC&by28`W!GG26nB> zuapdP5P=*|ennN$M^o-d<xX;JnQoNPm9p-SYQM4# zVRJ*i(v&d>pk0OlG^Hsj``%F~3Mc5Xd{g{k?{<&Lsrldj*QmHzuGYJo0)c@5$R~Hg z?l7?sF8|84X|na>^?Wnles)*kBpG)f)o@X}2lylQRTMobi5g+k@HxLB&scnds{7ys zn-cu~ixUUTjs#taYUvfKp>|Yq?Ja?{ z4Z$WokggqDfdQ)Zr~>(grr#5{7x_v0m`d4U=oIQv`fjl84I{_${{@4kBtN)^T;61o zp)3>=qK8b?nJsX!m=;8{G?$bjYk5yw1g<`4r_nL@x!HY-FbcVJ8qu0Gg-Rs*0)c@5 zg>R)Sp35M$bgG9Vo6Mu_PEyT2{`rsVZDvnuj!NMtTBU7H<6_fs1`(ExO3^A7iaPzQ zas5C85)7!RvJ9`?w0EZH(l{V#*YsZD4FLu6*`kL0++;~x>qsB#t(p+DAhe1;F@hKT zQxv~?`qtv_AwA~ZPB}4?R!o+8(U%5;0)c@5g=)`bdL*JlPgwg+@;ye{M@9~D!1;}# z^K+}sUVy|Y3m(2b0ISDNZ~^ZNNz5ve?xN&)^Bc%A zHCABO#0G6v)>>x`wWPcwb=sAH2Vo4G@gcF51Nd^%fH#Qt9l13)a12|{9ee~BLjha` e)`?Ej7eZFsUzB0T-7pi1g}8>P$D#^4VDU$4aXRP# literal 0 HcmV?d00001 diff --git a/helper/src/test/resources/platform.x509.pem b/helper/src/test/resources/platform.x509.pem new file mode 100644 index 0000000..087f02e --- /dev/null +++ b/helper/src/test/resources/platform.x509.pem @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIIEqDCCA5CgAwIBAgIJALOZgIbQVs/6MA0GCSqGSIb3DQEBBAUAMIGUMQswCQYD +VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4g +VmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UE +AxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAe +Fw0wODA0MTUyMjQwNTBaFw0zNTA5MDEyMjQwNTBaMIGUMQswCQYDVQQGEwJVUzET +MBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4G +A1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9p +ZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCASAwDQYJKoZI +hvcNAQEBBQADggENADCCAQgCggEBAJx4BZKsDV04HN6qZezIpgBuNkgMbXIHsSAR +vlCGOqvitV0Amt9xRtbyICKAx81Ne9smJDuKgGwms0sTdSOkkmgiSQTcAUk+fArP +GgXIdPabA3tgMJ2QdNJCgOFrrSqHNDYZUer3KkgtCbIEsYdeEqyYwap3PWgAuer9 +5W1Yvtjo2hb5o2AJnDeoNKbf7be2tEoEngeiafzPLFSW8s821k35CjuNjzSjuqtM +9TNxqydxmzulh1StDFP8FOHbRdUeI0+76TybpO35zlQmE1DsU1YHv2mi/0qgfbX3 +6iANCabBtJ4hQC+J7RGQiTqrWpGA8VLoL4WkV1PPX8GQccXuyCcCAQOjgfwwgfkw +HQYDVR0OBBYEFE/koLPdnLop9x1yh8Tnw48ghsKZMIHJBgNVHSMEgcEwgb6AFE/k +oLPdnLop9x1yh8Tnw48ghsKZoYGapIGXMIGUMQswCQYDVQQGEwJVUzETMBEGA1UE +CBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMH +QW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAG +CSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbYIJALOZgIbQVs/6MAwGA1Ud +EwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADggEBAFclUbjZOh9z3g9tRp+G2tZwFAAp +PIigzXzXeLc9r8wZf6t25iEuVsHHYc/EL9cz3lLFCuCIFM78CjtaGkNGBU2Cnx2C +tCsgSL+ItdFJKe+F9g7dEtctVWV+IuPoXQTIMdYT0Zk4u4mCJH+jISVroS0dao+S +6h2xw3Mxe6DAN/DRr/ZFrvIkl5+6bnoUvAJccbmBOM7z3fwFlhfPJIRc97QNY4L3 +J17XOElatuWTG5QhdlxJG3L7aOCA29tYwgKdNHyLMozkPvaosVUz7fvpib1qSN1L +IC7alMarjdW4OZID2q4u1EYjLk/pvZYTlMYwDlE448/Shebk5INTjLixs1c= +-----END CERTIFICATE----- diff --git a/helper/src/test/resources/testkey.pk8 b/helper/src/test/resources/testkey.pk8 new file mode 100644 index 0000000000000000000000000000000000000000..586c1bd5cf96f9358f36b37ea98fef93f4d0a8e3 GIT binary patch literal 1217 zcmV;y1U~yPf&{$+0RS)!1_>&LNQUrr!ay9qXGc{0)hbn0M?Tk1m4CA zB(d$sV&K`>B|bjQZ0jB3{|1bx=)9=SYtwjcrwXTR<_^0LnKfDe**XXo? z!`w>qP$CUb2nRCYfR`8UY6UY{=BAYFEVJ^2prmHVdX(5ZF$p?nH!d$^62NY4Lh)D_ z-~I!E%nZ~-+HBp!xFlE^NCC4YWD`%n-k8ZKcSzgyXKGXpfmF!5$_KgPM^!Ts#A}-O zZ{F<8j%nw}qR@_bCLokQnR0zR1pacF9hu*ot~j8w7k{H2TWbF49|8db0)hbn0FMm2 zSd@eZZOil8LF+r^ZYh5=o$?dxssvrd@O{PJN8(UP#IeNlLarW*N_QWU=dJbtwUa9MNB6mRRfiD@u-F4570O|hs88oP`H<{-WtCyW#0(F+HjcFBTNtPVs zqOAxo7-A$eO)H3r6sgRe?MH7gF5FJ$Tk3bck@E0NKQy`twmC#7`?TOyTgJ~$><(c= zegFe}?aLXyS&y+x7cyW?K{hgS`ZOu%e`OsJB7tT%e$vUP84FySkKHZd#R8E)%>sde z0Gxnk4`^q&#Rvr|X}T^DSmg_(X~iRQqj#>*`b>&xVy7{s?@%B>l*r?UT zWofQjN z+qr0%Y;#)55J7EtGjdx74aSIRNZLvuA3cfg=kcW}3-?Ohe|UTbd3%Dz{Ubm)=h@$h z^0YwLsa02~o`+_B=3mQ)WXwP_fX>WJrp<9hszYeD7Xa?hso~qjW(SiJU+Bp}E&;YH zGXjBtV=ArL8r`H~*_EbpVp|2xsYW66=~;8`kD4v(aiPJi8`ByM)}o1ZhZ|~p>uyzH zw4p3uqoir?dUseWHOKf>xwmY}&%k#`MgFNpFR|mPj0O9er&4Gc#l%UD4Z+(RrHVV$ f`+