diff --git a/.jcheck/conf b/.jcheck/conf index fd9a62ff0a58..d592833b176c 100644 --- a/.jcheck/conf +++ b/.jcheck/conf @@ -1,7 +1,7 @@ [general] project=jdk-updates jbs=JDK -version=21.0.12 +version=21.0.13 [checks] error=author,committer,reviewers,merge,issues,executable,symlink,message,hg-tag,whitespace,problemlists diff --git a/doc/testing.html b/doc/testing.html index b9720dd31a89..eeb67854a53c 100644 --- a/doc/testing.html +++ b/doc/testing.html @@ -509,6 +509,8 @@

REPEAT_COUNT

REPORT

Use this report style when reporting test results (sent to JTReg as -report). Defaults to files.

+

MANUAL

+

Set to true to execute manual tests only.

Gtest keywords

REPEAT

The number of times to repeat the tests diff --git a/doc/testing.md b/doc/testing.md index 9faf3d9b0f45..6e605d0db9d0 100644 --- a/doc/testing.md +++ b/doc/testing.md @@ -498,6 +498,10 @@ Defaults to 0. Use this report style when reporting test results (sent to JTReg as `-report`). Defaults to `files`. +#### MANUAL + +Set to `true` to execute manual tests only. + ### Gtest keywords #### REPEAT diff --git a/make/RunTests.gmk b/make/RunTests.gmk index f61125f53315..859eb68031ac 100644 --- a/make/RunTests.gmk +++ b/make/RunTests.gmk @@ -205,7 +205,8 @@ $(eval $(call SetTestOpt,REPORT,JTREG)) $(eval $(call ParseKeywordVariable, JTREG, \ SINGLE_KEYWORDS := JOBS TIMEOUT_FACTOR FAILURE_HANDLER_TIMEOUT \ TEST_MODE ASSERT VERBOSE RETAIN TEST_THREAD_FACTORY MAX_MEM RUN_PROBLEM_LISTS \ - RETRY_COUNT REPEAT_COUNT MAX_OUTPUT REPORT $(CUSTOM_JTREG_SINGLE_KEYWORDS), \ + RETRY_COUNT REPEAT_COUNT MAX_OUTPUT REPORT MANUAL \ + $(CUSTOM_JTREG_SINGLE_KEYWORDS), \ STRING_KEYWORDS := OPTIONS JAVA_OPTIONS VM_OPTIONS KEYWORDS \ EXTRA_PROBLEM_LISTS LAUNCHER_OPTIONS \ $(CUSTOM_JTREG_STRING_KEYWORDS), \ @@ -793,7 +794,13 @@ define SetupRunJtregTestBody -vmoption:-Dtest.boot.jdk="$$(BOOT_JDK)" \ -vmoption:-Djava.io.tmpdir="$$($1_TEST_TMP_DIR)" - $1_JTREG_BASIC_OPTIONS += -automatic -ignore:quiet + $1_JTREG_BASIC_OPTIONS += -ignore:quiet + + ifeq ($$(JTREG_MANUAL), true) + $1_JTREG_BASIC_OPTIONS += -manual + else + $1_JTREG_BASIC_OPTIONS += -automatic + endif # Make it possible to specify the JIB_DATA_DIR for tests using the # JIB Artifact resolver diff --git a/make/autoconf/flags-ldflags.m4 b/make/autoconf/flags-ldflags.m4 index e5c345fdef16..a1f50ffdaf3e 100644 --- a/make/autoconf/flags-ldflags.m4 +++ b/make/autoconf/flags-ldflags.m4 @@ -101,6 +101,9 @@ AC_DEFUN([FLAGS_SETUP_LDFLAGS_HELPER], # Setup OS-dependent LDFLAGS if test "x$OPENJDK_TARGET_OS" = xmacosx && test "x$TOOLCHAIN_TYPE" = xclang; then + if test x$DEBUG_LEVEL = xrelease; then + BASIC_LDFLAGS_JDK_ONLY="$BASIC_LDFLAGS_JDK_ONLY -Wl,-dead_strip" + fi # FIXME: We should really generalize SET_SHARED_LIBRARY_ORIGIN instead. OS_LDFLAGS_JVM_ONLY="-Wl,-rpath,@loader_path/. -Wl,-rpath,@loader_path/.." OS_LDFLAGS="-mmacosx-version-min=$MACOSX_VERSION_MIN" diff --git a/make/autoconf/lib-tests.m4 b/make/autoconf/lib-tests.m4 index 9c674721e39b..288f41b58a2c 100644 --- a/make/autoconf/lib-tests.m4 +++ b/make/autoconf/lib-tests.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ ################################################################################ # Minimum supported versions -JTREG_MINIMUM_VERSION=7.5.2 +JTREG_MINIMUM_VERSION=8.2.1 GTEST_MINIMUM_VERSION=1.14.0 ############################################################################### diff --git a/make/conf/github-actions.conf b/make/conf/github-actions.conf index b35533eb1ce6..e1001dd6c4fe 100644 --- a/make/conf/github-actions.conf +++ b/make/conf/github-actions.conf @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ # Versions and download locations for dependencies used by GitHub Actions (GHA) GTEST_VERSION=1.14.0 -JTREG_VERSION=7.5.2+1 +JTREG_VERSION=8.2.1+1 LINUX_X64_BOOT_JDK_EXT=tar.gz LINUX_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.11%2B10/OpenJDK21U-jdk_x64_linux_hotspot_21.0.11_10.tar.gz diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index 1aa445d88e9b..eabfc859a202 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1200,9 +1200,9 @@ var getJibProfilesDependencies = function (input, common) { jtreg: { server: "jpg", product: "jtreg", - version: "7.5.2", + version: "8.2.1", build_number: "1", - file: "bundles/jtreg-7.5.2+1.zip", + file: "bundles/jtreg-8.2.1+1.zip", environment_name: "JT_HOME", environment_path: input.get("jtreg", "home_path") + "/bin", configure_args: "--with-jtreg=" + input.get("jtreg", "home_path"), @@ -1532,7 +1532,7 @@ var getVersionNumbers = function () { var isWsl = function (input) { return ( input.build_osenv == "wsl" || (input.build_os == "linux" - && java.lang.System.getProperty("os.version").contains("Microsoft"))); + && java.lang.System.getProperty("os.version").toLowerCase().contains("microsoft"))); } var error = function (s) { diff --git a/make/conf/version-numbers.conf b/make/conf/version-numbers.conf index acb2393671cb..906c95217b49 100644 --- a/make/conf/version-numbers.conf +++ b/make/conf/version-numbers.conf @@ -28,15 +28,15 @@ DEFAULT_VERSION_FEATURE=21 DEFAULT_VERSION_INTERIM=0 -DEFAULT_VERSION_UPDATE=12 +DEFAULT_VERSION_UPDATE=13 DEFAULT_VERSION_PATCH=0 DEFAULT_VERSION_EXTRA1=0 DEFAULT_VERSION_EXTRA2=0 DEFAULT_VERSION_EXTRA3=0 -DEFAULT_VERSION_DATE=2026-07-21 +DEFAULT_VERSION_DATE=2026-10-20 DEFAULT_VERSION_CLASSFILE_MAJOR=65 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`" DEFAULT_VERSION_CLASSFILE_MINOR=0 DEFAULT_VERSION_DOCS_API_SINCE=11 DEFAULT_ACCEPTABLE_BOOT_VERSIONS="20 21" DEFAULT_JDK_SOURCE_TARGET_VERSION=21 -DEFAULT_PROMOTED_VERSION_PRE= +DEFAULT_PROMOTED_VERSION_PRE=ea diff --git a/make/data/hotspot-symbols/symbols-unix b/make/data/hotspot-symbols/symbols-unix index 5cf6662cba84..be5528b12261 100644 --- a/make/data/hotspot-symbols/symbols-unix +++ b/make/data/hotspot-symbols/symbols-unix @@ -188,6 +188,7 @@ JVM_RawMonitorDestroy JVM_RawMonitorEnter JVM_RawMonitorExit JVM_ReferenceClear +JVM_ReferenceGet JVM_ReferenceRefersTo JVM_RegisterContinuationMethods JVM_RegisterLambdaProxyClassForArchiving diff --git a/make/hotspot/lib/JvmOverrideFiles.gmk b/make/hotspot/lib/JvmOverrideFiles.gmk index b50d6f8bb36d..f64c538cd231 100644 --- a/make/hotspot/lib/JvmOverrideFiles.gmk +++ b/make/hotspot/lib/JvmOverrideFiles.gmk @@ -37,6 +37,10 @@ ifeq ($(TOOLCHAIN_TYPE), gcc) # Need extra inlining to collapse shared marking code into the hot marking loop BUILD_LIBJVM_shenandoahMark.cpp_CXXFLAGS := --param inline-unit-growth=1000 endif + # disable lto in g1ParScanThreadState because of special inlining/flattening used there + ifeq ($(call check-jvm-feature, link-time-opt), true) + BUILD_LIBJVM_g1ParScanThreadState.cpp_CXXFLAGS := -fno-lto + endif endif LIBJVM_FDLIBM_COPY_OPT_FLAG := $(CXX_O_FLAG_NONE) diff --git a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp index 5d3ca441b410..9ab80e91639f 100644 --- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2024, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -2571,6 +2571,11 @@ template ldst_sstr(T, index, a, op1, op2, Vt, Vt2, Vt3, Vt4); \ } + INSN1(ld1, 0b001101010, 0b0000); + INSN2(ld2, 0b001101011, 0b0000); + INSN3(ld3, 0b001101010, 0b0010); + INSN4(ld4, 0b001101011, 0b0010); + INSN1(st1, 0b001101000, 0b0000); INSN2(st2, 0b001101001, 0b0000); INSN3(st3, 0b001101000, 0b0010); @@ -2605,6 +2610,7 @@ template void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm) { \ guarantee(T != T1Q && T != T1D, "incorrect arrangement"); \ if (!acceptT2D) guarantee(T != T2D, "incorrect arrangement"); \ + if (opc2 == 0b101101) guarantee(T != T8B && T != T16B, "incorrect arrangement"); \ starti; \ f(0, 31), f((int)T & 1, 30), f(opc, 29), f(0b01110, 28, 24); \ f((int)T >> 1, 23, 22), f(1, 21), rf(Vm, 16), f(opc2, 15, 10); \ @@ -2628,6 +2634,8 @@ template INSN(minv, 0, 0b011011, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S INSN(smaxp, 0, 0b101001, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S INSN(sminp, 0, 0b101011, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S + INSN(sqdmulh,0, 0b101101, false); // accepted arrangements: T4H, T8H, T2S, T4S + INSN(shsubv, 0, 0b001001, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S #undef INSN diff --git a/src/hotspot/cpu/aarch64/register_aarch64.cpp b/src/hotspot/cpu/aarch64/register_aarch64.cpp index 3a46e38a72a7..b61627f6b91e 100644 --- a/src/hotspot/cpu/aarch64/register_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/register_aarch64.cpp @@ -59,3 +59,23 @@ const char* PRegister::PRegisterImpl::name() const { }; return is_valid() ? names[encoding()] : "pnoreg"; } + +// convenience methods for splitting 8-way vector register sequences +// in half -- needed because vector operations can normally only be +// benefit from 4-way instruction parallelism + +VSeq<4> vs_front(const VSeq<8>& v) { + return VSeq<4>(v.base(), v.delta()); +} + +VSeq<4> vs_back(const VSeq<8>& v) { + return VSeq<4>(v.base() + 4 * v.delta(), v.delta()); +} + +VSeq<4> vs_even(const VSeq<8>& v) { + return VSeq<4>(v.base(), v.delta() * 2); +} + +VSeq<4> vs_odd(const VSeq<8>& v) { + return VSeq<4>(v.base() + 1, v.delta() * 2); +} diff --git a/src/hotspot/cpu/aarch64/register_aarch64.hpp b/src/hotspot/cpu/aarch64/register_aarch64.hpp index eef4182efe91..45351bb39451 100644 --- a/src/hotspot/cpu/aarch64/register_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/register_aarch64.hpp @@ -408,4 +408,72 @@ inline Register as_Register(FloatRegister reg) { return as_Register(reg->encoding()); } +// AArch64 Vector Register Sequence management support +// +// VSeq implements an indexable (by operator[]) vector register +// sequence starting from a fixed base register and with a fixed delta +// (defaulted to 1, but sometimes 0 or 2) e.g. VSeq<4>(16) will return +// registers v16, ... v19 for indices 0, ... 3. +// +// Generator methods may iterate across sets of VSeq<4> to schedule an +// operation 4 times using distinct input and output registers, +// profiting from 4-way instruction parallelism. +// +// A VSeq<2> can be used to specify registers loaded with special +// constants e.g. --> . +// +// A VSeq with base n and delta 0 can be used to generate code that +// combines values in another VSeq with the constant in register vn. +// +// A VSeq with base n and delta 2 can be used to select an odd or even +// indexed set of registers. +// +// Methods which accept arguments of type VSeq<8>, may split their +// inputs into front and back halves or odd and even halves (see +// convenience methods below). + +template class VSeq { + static_assert(N >= 2, "vector sequence length must be greater than 1"); + static_assert(N <= 8, "vector sequence length must not exceed 8"); + static_assert((N & (N - 1)) == 0, "vector sequence length must be power of two"); +private: + int _base; // index of first register in sequence + int _delta; // increment to derive successive indices +public: + VSeq(FloatRegister base_reg, int delta = 1) : VSeq(base_reg->encoding(), delta) { } + VSeq(int base, int delta = 1) : _base(base), _delta(delta) { + assert (_base >= 0, "invalid base register"); + assert (_delta >= 0, "invalid register delta"); + assert ((_base + (N - 1) * _delta) < 32, "range exceeded"); + } + // indexed access to sequence + FloatRegister operator [](int i) const { + assert (0 <= i && i < N, "index out of bounds"); + return as_FloatRegister(_base + i * _delta); + } + int mask() const { + int m = 0; + int bit = 1 << _base; + for (int i = 0; i < N; i++) { + m |= bit << (i * _delta); + } + return m; + } + int base() const { return _base; } + int delta() const { return _delta; } +}; + +// declare convenience methods for splitting vector register sequences + +VSeq<4> vs_front(const VSeq<8>& v); +VSeq<4> vs_back(const VSeq<8>& v); +VSeq<4> vs_even(const VSeq<8>& v); +VSeq<4> vs_odd(const VSeq<8>& v); + +// methods for use in asserts to check VSeq inputs and oupts are +// either disjoint or equal + +template bool vs_disjoint(const VSeq& n, const VSeq& m) { return (n.mask() & m.mask()) == 0; } +template bool vs_same(const VSeq& n, const VSeq& m) { return n.mask() == m.mask(); } + #endif // CPU_AARCH64_REGISTER_AARCH64_HPP diff --git a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp index 2bfc49d05dd6..77cea7998832 100644 --- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp @@ -3983,6 +3983,95 @@ class StubGenerator: public StubCodeGenerator { return start; } + // Execute one round of keccak of two computations in parallel. + // One of the states should be loaded into the lower halves of + // the vector registers v0-v24, the other should be loaded into + // the upper halves of those registers. The ld1r instruction loads + // the round constant into both halves of register v31. + // Intermediate results c0...c5 and d0...d5 are computed + // in registers v25...v30. + // All vector instructions that are used operate on both register + // halves in parallel. + // If only a single computation is needed, one can only load the lower halves. + void keccak_round(Register rscratch1) { + __ eor3(v29, __ T16B, v4, v9, v14); // c4 = a4 ^ a9 ^ a14 + __ eor3(v26, __ T16B, v1, v6, v11); // c1 = a1 ^ a16 ^ a11 + __ eor3(v28, __ T16B, v3, v8, v13); // c3 = a3 ^ a8 ^a13 + __ eor3(v25, __ T16B, v0, v5, v10); // c0 = a0 ^ a5 ^ a10 + __ eor3(v27, __ T16B, v2, v7, v12); // c2 = a2 ^ a7 ^ a12 + __ eor3(v29, __ T16B, v29, v19, v24); // c4 ^= a19 ^ a24 + __ eor3(v26, __ T16B, v26, v16, v21); // c1 ^= a16 ^ a21 + __ eor3(v28, __ T16B, v28, v18, v23); // c3 ^= a18 ^ a23 + __ eor3(v25, __ T16B, v25, v15, v20); // c0 ^= a15 ^ a20 + __ eor3(v27, __ T16B, v27, v17, v22); // c2 ^= a17 ^ a22 + + __ rax1(v30, __ T2D, v29, v26); // d0 = c4 ^ rol(c1, 1) + __ rax1(v26, __ T2D, v26, v28); // d2 = c1 ^ rol(c3, 1) + __ rax1(v28, __ T2D, v28, v25); // d4 = c3 ^ rol(c0, 1) + __ rax1(v25, __ T2D, v25, v27); // d1 = c0 ^ rol(c2, 1) + __ rax1(v27, __ T2D, v27, v29); // d3 = c2 ^ rol(c4, 1) + + __ eor(v0, __ T16B, v0, v30); // a0 = a0 ^ d0 + __ xar(v29, __ T2D, v1, v25, (64 - 1)); // a10' = rol((a1^d1), 1) + __ xar(v1, __ T2D, v6, v25, (64 - 44)); // a1 = rol(a6^d1), 44) + __ xar(v6, __ T2D, v9, v28, (64 - 20)); // a6 = rol((a9^d4), 20) + __ xar(v9, __ T2D, v22, v26, (64 - 61)); // a9 = rol((a22^d2), 61) + __ xar(v22, __ T2D, v14, v28, (64 - 39)); // a22 = rol((a14^d4), 39) + __ xar(v14, __ T2D, v20, v30, (64 - 18)); // a14 = rol((a20^d0), 18) + __ xar(v31, __ T2D, v2, v26, (64 - 62)); // a20' = rol((a2^d2), 62) + __ xar(v2, __ T2D, v12, v26, (64 - 43)); // a2 = rol((a12^d2), 43) + __ xar(v12, __ T2D, v13, v27, (64 - 25)); // a12 = rol((a13^d3), 25) + __ xar(v13, __ T2D, v19, v28, (64 - 8)); // a13 = rol((a19^d4), 8) + __ xar(v19, __ T2D, v23, v27, (64 - 56)); // a19 = rol((a23^d3), 56) + __ xar(v23, __ T2D, v15, v30, (64 - 41)); // a23 = rol((a15^d0), 41) + __ xar(v15, __ T2D, v4, v28, (64 - 27)); // a15 = rol((a4^d4), 27) + __ xar(v28, __ T2D, v24, v28, (64 - 14)); // a4' = rol((a24^d4), 14) + __ xar(v24, __ T2D, v21, v25, (64 - 2)); // a24 = rol((a21^d1), 2) + __ xar(v8, __ T2D, v8, v27, (64 - 55)); // a21' = rol((a8^d3), 55) + __ xar(v4, __ T2D, v16, v25, (64 - 45)); // a8' = rol((a16^d1), 45) + __ xar(v16, __ T2D, v5, v30, (64 - 36)); // a16 = rol((a5^d0), 36) + __ xar(v5, __ T2D, v3, v27, (64 - 28)); // a5 = rol((a3^d3), 28) + __ xar(v27, __ T2D, v18, v27, (64 - 21)); // a3' = rol((a18^d3), 21) + __ xar(v3, __ T2D, v17, v26, (64 - 15)); // a18' = rol((a17^d2), 15) + __ xar(v25, __ T2D, v11, v25, (64 - 10)); // a17' = rol((a11^d1), 10) + __ xar(v26, __ T2D, v7, v26, (64 - 6)); // a11' = rol((a7^d2), 6) + __ xar(v30, __ T2D, v10, v30, (64 - 3)); // a7' = rol((a10^d0), 3) + + __ bcax(v20, __ T16B, v31, v22, v8); // a20 = a20' ^ (~a21 & a22') + __ bcax(v21, __ T16B, v8, v23, v22); // a21 = a21' ^ (~a22 & a23) + __ bcax(v22, __ T16B, v22, v24, v23); // a22 = a22 ^ (~a23 & a24) + __ bcax(v23, __ T16B, v23, v31, v24); // a23 = a23 ^ (~a24 & a20') + __ bcax(v24, __ T16B, v24, v8, v31); // a24 = a24 ^ (~a20' & a21') + + __ ld1r(v31, __ T2D, __ post(rscratch1, 8)); // rc = round_constants[i] + + __ bcax(v17, __ T16B, v25, v19, v3); // a17 = a17' ^ (~a18' & a19) + __ bcax(v18, __ T16B, v3, v15, v19); // a18 = a18' ^ (~a19 & a15') + __ bcax(v19, __ T16B, v19, v16, v15); // a19 = a19 ^ (~a15 & a16) + __ bcax(v15, __ T16B, v15, v25, v16); // a15 = a15 ^ (~a16 & a17') + __ bcax(v16, __ T16B, v16, v3, v25); // a16 = a16 ^ (~a17' & a18') + + __ bcax(v10, __ T16B, v29, v12, v26); // a10 = a10' ^ (~a11' & a12) + __ bcax(v11, __ T16B, v26, v13, v12); // a11 = a11' ^ (~a12 & a13) + __ bcax(v12, __ T16B, v12, v14, v13); // a12 = a12 ^ (~a13 & a14) + __ bcax(v13, __ T16B, v13, v29, v14); // a13 = a13 ^ (~a14 & a10') + __ bcax(v14, __ T16B, v14, v26, v29); // a14 = a14 ^ (~a10' & a11') + + __ bcax(v7, __ T16B, v30, v9, v4); // a7 = a7' ^ (~a8' & a9) + __ bcax(v8, __ T16B, v4, v5, v9); // a8 = a8' ^ (~a9 & a5) + __ bcax(v9, __ T16B, v9, v6, v5); // a9 = a9 ^ (~a5 & a6) + __ bcax(v5, __ T16B, v5, v30, v6); // a5 = a5 ^ (~a6 & a7) + __ bcax(v6, __ T16B, v6, v4, v30); // a6 = a6 ^ (~a7 & a8') + + __ bcax(v3, __ T16B, v27, v0, v28); // a3 = a3' ^ (~a4' & a0) + __ bcax(v4, __ T16B, v28, v1, v0); // a4 = a4' ^ (~a0 & a1) + __ bcax(v0, __ T16B, v0, v2, v1); // a0 = a0 ^ (~a1 & a2) + __ bcax(v1, __ T16B, v1, v27, v2); // a1 = a1 ^ (~a2 & a3) + __ bcax(v2, __ T16B, v2, v28, v27); // a2 = a2 ^ (~a3 & a4') + + __ eor(v0, __ T16B, v0, v31); // a0 = a0 ^ rc + } + // Arguments: // // Inputs: @@ -4074,7 +4163,7 @@ class StubGenerator: public StubCodeGenerator { __ cbzw(c_rarg5, rounds24_loop); __ tbnz(block_size, 5, shake128); - // block_size == 144, bit5 == 0, SHA3-244 + // block_size == 144, bit5 == 0, SHA3-224 __ ldrd(v28, __ post(buf, 8)); __ eor(v17, __ T8B, v17, v28); __ b(rounds24_loop); @@ -4103,82 +4192,7 @@ class StubGenerator: public StubCodeGenerator { __ BIND(rounds24_loop); __ subw(rscratch2, rscratch2, 1); - __ eor3(v29, __ T16B, v4, v9, v14); - __ eor3(v26, __ T16B, v1, v6, v11); - __ eor3(v28, __ T16B, v3, v8, v13); - __ eor3(v25, __ T16B, v0, v5, v10); - __ eor3(v27, __ T16B, v2, v7, v12); - __ eor3(v29, __ T16B, v29, v19, v24); - __ eor3(v26, __ T16B, v26, v16, v21); - __ eor3(v28, __ T16B, v28, v18, v23); - __ eor3(v25, __ T16B, v25, v15, v20); - __ eor3(v27, __ T16B, v27, v17, v22); - - __ rax1(v30, __ T2D, v29, v26); - __ rax1(v26, __ T2D, v26, v28); - __ rax1(v28, __ T2D, v28, v25); - __ rax1(v25, __ T2D, v25, v27); - __ rax1(v27, __ T2D, v27, v29); - - __ eor(v0, __ T16B, v0, v30); - __ xar(v29, __ T2D, v1, v25, (64 - 1)); - __ xar(v1, __ T2D, v6, v25, (64 - 44)); - __ xar(v6, __ T2D, v9, v28, (64 - 20)); - __ xar(v9, __ T2D, v22, v26, (64 - 61)); - __ xar(v22, __ T2D, v14, v28, (64 - 39)); - __ xar(v14, __ T2D, v20, v30, (64 - 18)); - __ xar(v31, __ T2D, v2, v26, (64 - 62)); - __ xar(v2, __ T2D, v12, v26, (64 - 43)); - __ xar(v12, __ T2D, v13, v27, (64 - 25)); - __ xar(v13, __ T2D, v19, v28, (64 - 8)); - __ xar(v19, __ T2D, v23, v27, (64 - 56)); - __ xar(v23, __ T2D, v15, v30, (64 - 41)); - __ xar(v15, __ T2D, v4, v28, (64 - 27)); - __ xar(v28, __ T2D, v24, v28, (64 - 14)); - __ xar(v24, __ T2D, v21, v25, (64 - 2)); - __ xar(v8, __ T2D, v8, v27, (64 - 55)); - __ xar(v4, __ T2D, v16, v25, (64 - 45)); - __ xar(v16, __ T2D, v5, v30, (64 - 36)); - __ xar(v5, __ T2D, v3, v27, (64 - 28)); - __ xar(v27, __ T2D, v18, v27, (64 - 21)); - __ xar(v3, __ T2D, v17, v26, (64 - 15)); - __ xar(v25, __ T2D, v11, v25, (64 - 10)); - __ xar(v26, __ T2D, v7, v26, (64 - 6)); - __ xar(v30, __ T2D, v10, v30, (64 - 3)); - - __ bcax(v20, __ T16B, v31, v22, v8); - __ bcax(v21, __ T16B, v8, v23, v22); - __ bcax(v22, __ T16B, v22, v24, v23); - __ bcax(v23, __ T16B, v23, v31, v24); - __ bcax(v24, __ T16B, v24, v8, v31); - - __ ld1r(v31, __ T2D, __ post(rscratch1, 8)); - - __ bcax(v17, __ T16B, v25, v19, v3); - __ bcax(v18, __ T16B, v3, v15, v19); - __ bcax(v19, __ T16B, v19, v16, v15); - __ bcax(v15, __ T16B, v15, v25, v16); - __ bcax(v16, __ T16B, v16, v3, v25); - - __ bcax(v10, __ T16B, v29, v12, v26); - __ bcax(v11, __ T16B, v26, v13, v12); - __ bcax(v12, __ T16B, v12, v14, v13); - __ bcax(v13, __ T16B, v13, v29, v14); - __ bcax(v14, __ T16B, v14, v26, v29); - - __ bcax(v7, __ T16B, v30, v9, v4); - __ bcax(v8, __ T16B, v4, v5, v9); - __ bcax(v9, __ T16B, v9, v6, v5); - __ bcax(v5, __ T16B, v5, v30, v6); - __ bcax(v6, __ T16B, v6, v4, v30); - - __ bcax(v3, __ T16B, v27, v0, v28); - __ bcax(v4, __ T16B, v28, v1, v0); - __ bcax(v0, __ T16B, v0, v2, v1); - __ bcax(v1, __ T16B, v1, v27, v2); - __ bcax(v2, __ T16B, v2, v28, v27); - - __ eor(v0, __ T16B, v0, v31); + keccak_round(rscratch1); __ cbnzw(rscratch2, rounds24_loop); @@ -4197,6 +4211,7 @@ class StubGenerator: public StubCodeGenerator { __ st1(v20, v21, v22, v23, __ T1D, __ post(state, 32)); __ st1(v24, __ T1D, state); + // restore callee-saved registers __ ldpd(v14, v15, Address(sp, 48)); __ ldpd(v12, v13, Address(sp, 32)); __ ldpd(v10, v11, Address(sp, 16)); @@ -4207,6 +4222,96 @@ class StubGenerator: public StubCodeGenerator { return start; } + // Inputs: + // c_rarg0 - long[] state0 + // c_rarg1 - long[] state1 + address generate_double_keccak() { + static const uint64_t round_consts[24] = { + 0x0000000000000001L, 0x0000000000008082L, 0x800000000000808AL, + 0x8000000080008000L, 0x000000000000808BL, 0x0000000080000001L, + 0x8000000080008081L, 0x8000000000008009L, 0x000000000000008AL, + 0x0000000000000088L, 0x0000000080008009L, 0x000000008000000AL, + 0x000000008000808BL, 0x800000000000008BL, 0x8000000000008089L, + 0x8000000000008003L, 0x8000000000008002L, 0x8000000000000080L, + 0x000000000000800AL, 0x800000008000000AL, 0x8000000080008081L, + 0x8000000000008080L, 0x0000000080000001L, 0x8000000080008008L + }; + + // Implements the double_keccak() method of the + // sun.secyrity.provider.SHA3Parallel class + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", "double_keccak"); + address start = __ pc(); + __ enter(); + + Register state0 = c_rarg0; + Register state1 = c_rarg1; + + Label rounds24_loop; + + // save callee-saved registers + __ stpd(v8, v9, __ pre(sp, -64)); + __ stpd(v10, v11, Address(sp, 16)); + __ stpd(v12, v13, Address(sp, 32)); + __ stpd(v14, v15, Address(sp, 48)); + + // load states + __ add(rscratch1, state0, 32); + __ ld4(v0, v1, v2, v3, __ D, 0, state0); + __ ld4(v4, v5, v6, v7, __ D, 0, __ post(rscratch1, 32)); + __ ld4(v8, v9, v10, v11, __ D, 0, __ post(rscratch1, 32)); + __ ld4(v12, v13, v14, v15, __ D, 0, __ post(rscratch1, 32)); + __ ld4(v16, v17, v18, v19, __ D, 0, __ post(rscratch1, 32)); + __ ld4(v20, v21, v22, v23, __ D, 0, __ post(rscratch1, 32)); + __ ld1(v24, __ D, 0, rscratch1); + __ add(rscratch1, state1, 32); + __ ld4(v0, v1, v2, v3, __ D, 1, state1); + __ ld4(v4, v5, v6, v7, __ D, 1, __ post(rscratch1, 32)); + __ ld4(v8, v9, v10, v11, __ D, 1, __ post(rscratch1, 32)); + __ ld4(v12, v13, v14, v15, __ D, 1, __ post(rscratch1, 32)); + __ ld4(v16, v17, v18, v19, __ D, 1, __ post(rscratch1, 32)); + __ ld4(v20, v21, v22, v23, __ D, 1, __ post(rscratch1, 32)); + __ ld1(v24, __ D, 1, rscratch1); + + // 24 keccak rounds + __ movw(rscratch2, 24); + + // load round_constants base + __ lea(rscratch1, ExternalAddress((address) round_consts)); + + __ BIND(rounds24_loop); + __ subw(rscratch2, rscratch2, 1); + keccak_round(rscratch1); + __ cbnzw(rscratch2, rounds24_loop); + + __ st4(v0, v1, v2, v3, __ D, 0, __ post(state0, 32)); + __ st4(v4, v5, v6, v7, __ D, 0, __ post(state0, 32)); + __ st4(v8, v9, v10, v11, __ D, 0, __ post(state0, 32)); + __ st4(v12, v13, v14, v15, __ D, 0, __ post(state0, 32)); + __ st4(v16, v17, v18, v19, __ D, 0, __ post(state0, 32)); + __ st4(v20, v21, v22, v23, __ D, 0, __ post(state0, 32)); + __ st1(v24, __ D, 0, state0); + __ st4(v0, v1, v2, v3, __ D, 1, __ post(state1, 32)); + __ st4(v4, v5, v6, v7, __ D, 1, __ post(state1, 32)); + __ st4(v8, v9, v10, v11, __ D, 1, __ post(state1, 32)); + __ st4(v12, v13, v14, v15, __ D, 1, __ post(state1, 32)); + __ st4(v16, v17, v18, v19, __ D, 1, __ post(state1, 32)); + __ st4(v20, v21, v22, v23, __ D, 1, __ post(state1, 32)); + __ st1(v24, __ D, 1, state1); + + // restore callee-saved vector registers + __ ldpd(v14, v15, Address(sp, 48)); + __ ldpd(v12, v13, Address(sp, 32)); + __ ldpd(v10, v11, Address(sp, 16)); + __ ldpd(v8, v9, __ post(sp, 64)); + + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ mov(r0, zr); // return 0 + __ ret(lr); + + return start; + } + /** * Arguments: * @@ -4373,6 +4478,963 @@ class StubGenerator: public StubCodeGenerator { return start; } + // Helpers to schedule parallel operation bundles across vector + // register sequences of size 2, 4 or 8. + + // Implement various primitive computations across vector sequences + + template + void vs_addv(const VSeq& v, Assembler::SIMD_Arrangement T, + const VSeq& v1, const VSeq& v2) { + for (int i = 0; i < N; i++) { + __ addv(v[i], T, v1[i], v2[i]); + } + } + + template + void vs_subv(const VSeq& v, Assembler::SIMD_Arrangement T, + const VSeq& v1, const VSeq& v2) { + for (int i = 0; i < N; i++) { + __ subv(v[i], T, v1[i], v2[i]); + } + } + + template + void vs_mulv(const VSeq& v, Assembler::SIMD_Arrangement T, + const VSeq& v1, const VSeq& v2) { + for (int i = 0; i < N; i++) { + __ mulv(v[i], T, v1[i], v2[i]); + } + } + + template + void vs_negr(const VSeq& v, Assembler::SIMD_Arrangement T, const VSeq& v1) { + for (int i = 0; i < N; i++) { + __ negr(v[i], T, v1[i]); + } + } + + template + void vs_sshr(const VSeq& v, Assembler::SIMD_Arrangement T, + const VSeq& v1, int shift) { + for (int i = 0; i < N; i++) { + __ sshr(v[i], T, v1[i], shift); + } + } + + template + void vs_andr(const VSeq& v, const VSeq& v1, const VSeq& v2) { + for (int i = 0; i < N; i++) { + __ andr(v[i], __ T16B, v1[i], v2[i]); + } + } + + template + void vs_orr(const VSeq& v, const VSeq& v1, const VSeq& v2) { + for (int i = 0; i < N; i++) { + __ orr(v[i], __ T16B, v1[i], v2[i]); + } + } + + template + void vs_notr(const VSeq& v, const VSeq& v1) { + for (int i = 0; i < N; i++) { + __ notr(v[i], __ T16B, v1[i]); + } + } + + // load N/2 successive pairs of quadword values from memory in order + // into N successive vector registers of the sequence via the + // address supplied in base. + template + void vs_ldpq(const VSeq& v, Register base) { + for (int i = 0; i < N; i += 2) { + __ ldpq(v[i], v[i+1], Address(base, 32 * i)); + } + } + + // load N/2 successive pairs of quadword values from memory in order + // into N vector registers of the sequence via the address supplied + // in base using post-increment addressing + template + void vs_ldpq_post(const VSeq& v, Register base) { + for (int i = 0; i < N; i += 2) { + __ ldpq(v[i], v[i+1], __ post(base, 32)); + } + } + + // store N successive vector registers of the sequence into N/2 + // successive pairs of quadword memory locations via the address + // supplied in base using post-increment addressing + template + void vs_stpq_post(const VSeq& v, Register base) { + for (int i = 0; i < N; i += 2) { + __ stpq(v[i], v[i+1], __ post(base, 32)); + } + } + + // load N/2 pairs of quadword values from memory into N vector + // registers via the address supplied in base with each pair indexed + // using the the start offset plus the corresponding entry in the + // offsets array + template + void vs_ldpq_indexed(const VSeq& v, Register base, int start, int (&offsets)[N/2]) { + for (int i = 0; i < N/2; i++) { + __ ldpq(v[2*i], v[2*i+1], Address(base, start + offsets[i])); + } + } + + // store N vector registers into N/2 pairs of quadword memory + // locations via the address supplied in base with each pair indexed + // using the the start offset plus the corresponding entry in the + // offsets array + template + void vs_stpq_indexed(const VSeq& v, Register base, int start, int offsets[N/2]) { + for (int i = 0; i < N/2; i++) { + __ stpq(v[2*i], v[2*i+1], Address(base, start + offsets[i])); + } + } + + // load N single quadword values from memory into N vector registers + // via the address supplied in base with each value indexed using + // the the start offset plus the corresponding entry in the offsets + // array + template + void vs_ldr_indexed(const VSeq& v, Assembler::SIMD_RegVariant T, Register base, + int start, int (&offsets)[N]) { + for (int i = 0; i < N; i++) { + __ ldr(v[i], T, Address(base, start + offsets[i])); + } + } + + // store N vector registers into N single quadword memory locations + // via the address supplied in base with each value indexed using + // the the start offset plus the corresponding entry in the offsets + // array + template + void vs_str_indexed(const VSeq& v, Assembler::SIMD_RegVariant T, Register base, + int start, int (&offsets)[N]) { + for (int i = 0; i < N; i++) { + __ str(v[i], T, Address(base, start + offsets[i])); + } + } + + // load N/2 pairs of quadword values from memory de-interleaved into + // N vector registers 2 at a time via the address supplied in base + // with each pair indexed using the the start offset plus the + // corresponding entry in the offsets array + template + void vs_ld2_indexed(const VSeq& v, Assembler::SIMD_Arrangement T, Register base, + Register tmp, int start, int (&offsets)[N/2]) { + for (int i = 0; i < N/2; i++) { + __ add(tmp, base, start + offsets[i]); + __ ld2(v[2*i], v[2*i+1], T, tmp); + } + } + + // store N vector registers 2 at a time interleaved into N/2 pairs + // of quadword memory locations via the address supplied in base + // with each pair indexed using the the start offset plus the + // corresponding entry in the offsets array + template + void vs_st2_indexed(const VSeq& v, Assembler::SIMD_Arrangement T, Register base, + Register tmp, int start, int (&offsets)[N/2]) { + for (int i = 0; i < N/2; i++) { + __ add(tmp, base, start + offsets[i]); + __ st2(v[2*i], v[2*i+1], T, tmp); + } + } + + // Helper routines for various flavours of dilithium montgomery + // multiply + + // Perform 16 32-bit Montgomery multiplications in parallel + // See the montMul() method of the sun.security.provider.ML_DSA class. + // + // Computes 4x4S results + // a = b * c * 2^-32 mod MONT_Q + // Inputs: vb, vc - 4x4S vector register sequences + // vq - 2x4S constants + // Temps: vtmp - 4x4S vector sequence trashed after call + // Outputs: va - 4x4S vector register sequences + // vb, vc, vtmp and vq must all be disjoint + // va must be disjoint from all other inputs/temps or must equal vc + // n.b. MONT_R_BITS is 32, so the right shift by it is implicit. + void dilithium_montmul16(const VSeq<4>& va, const VSeq<4>& vb, const VSeq<4>& vc, + const VSeq<4>& vtmp, const VSeq<2>& vq) { + assert(vs_disjoint(vb, vc), "vb and vc overlap"); + assert(vs_disjoint(vb, vq), "vb and vq overlap"); + assert(vs_disjoint(vb, vtmp), "vb and vtmp overlap"); + + assert(vs_disjoint(vc, vq), "vc and vq overlap"); + assert(vs_disjoint(vc, vtmp), "vc and vtmp overlap"); + + assert(vs_disjoint(vq, vtmp), "vq and vtmp overlap"); + + assert(vs_disjoint(va, vc) || vs_same(va, vc), "va and vc neither disjoint nor equal"); + assert(vs_disjoint(va, vb), "va and vb overlap"); + assert(vs_disjoint(va, vq), "va and vq overlap"); + assert(vs_disjoint(va, vtmp), "va and vtmp overlap"); + + // schedule 4 streams of instructions across the vector sequences + for (int i = 0; i < 4; i++) { + __ sqdmulh(vtmp[i], __ T4S, vb[i], vc[i]); // aHigh = hi32(2 * b * c) + __ mulv(va[i], __ T4S, vb[i], vc[i]); // aLow = lo32(b * c) + } + + for (int i = 0; i < 4; i++) { + __ mulv(va[i], __ T4S, va[i], vq[0]); // m = aLow * qinv + } + + for (int i = 0; i < 4; i++) { + __ sqdmulh(va[i], __ T4S, va[i], vq[1]); // n = hi32(2 * m * q) + } + + for (int i = 0; i < 4; i++) { + __ shsubv(va[i], __ T4S, vtmp[i], va[i]); // a = (aHigh - n) / 2 + } + } + + // Perform 2x16 32-bit Montgomery multiplications in parallel + // See the montMul() method of the sun.security.provider.ML_DSA class. + // + // Computes 8x4S results + // a = b * c * 2^-32 mod MONT_Q + // Inputs: vb, vc - 8x4S vector register sequences + // vq - 2x4S constants + // Temps: vtmp - 4x4S vector sequence trashed after call + // Outputs: va - 8x4S vector register sequences + // vb, vc, vtmp and vq must all be disjoint + // va must be disjoint from all other inputs/temps or must equal vc + // n.b. MONT_R_BITS is 32, so the right shift by it is implicit. + void vs_montmul32(const VSeq<8>& va, const VSeq<8>& vb, const VSeq<8>& vc, + const VSeq<4>& vtmp, const VSeq<2>& vq) { + // vb, vc, vtmp and vq must be disjoint. va must either be + // disjoint from all other registers or equal vc + + assert(vs_disjoint(vb, vc), "vb and vc overlap"); + assert(vs_disjoint(vb, vq), "vb and vq overlap"); + assert(vs_disjoint(vb, vtmp), "vb and vtmp overlap"); + + assert(vs_disjoint(vc, vq), "vc and vq overlap"); + assert(vs_disjoint(vc, vtmp), "vc and vtmp overlap"); + + assert(vs_disjoint(vq, vtmp), "vq and vtmp overlap"); + + assert(vs_disjoint(va, vc) || vs_same(va, vc), "va and vc neither disjoint nor equal"); + assert(vs_disjoint(va, vb), "va and vb overlap"); + assert(vs_disjoint(va, vq), "va and vq overlap"); + assert(vs_disjoint(va, vtmp), "va and vtmp overlap"); + + // we need to multiply the front and back halves of each sequence + // 4x4S at a time because + // + // 1) we are currently only able to get 4-way instruction + // parallelism at best + // + // 2) we need registers for the constants in vq and temporary + // scratch registers to hold intermediate results so vtmp can only + // be a VSeq<4> which means we only have 4 scratch slots + + dilithium_montmul16(vs_front(va), vs_front(vb), vs_front(vc), vtmp, vq); + dilithium_montmul16(vs_back(va), vs_back(vb), vs_back(vc), vtmp, vq); + } + + // perform combined montmul then add/sub on 4x4S vectors + + void dilithium_montmul16_sub_add(const VSeq<4>& va0, const VSeq<4>& va1, const VSeq<4>& vc, + const VSeq<4>& vtmp, const VSeq<2>& vq) { + // compute a = montmul(a1, c) + dilithium_montmul16(vc, va1, vc, vtmp, vq); + // ouptut a1 = a0 - a + vs_subv(va1, __ T4S, va0, vc); + // and a0 = a0 + a + vs_addv(va0, __ T4S, va0, vc); + } + + // perform combined add/sub then montul on 4x4S vectors + + void dilithium_sub_add_montmul16(const VSeq<4>& va0, const VSeq<4>& va1, const VSeq<4>& vb, + const VSeq<4>& vtmp1, const VSeq<4>& vtmp2, const VSeq<2>& vq) { + // compute c = a0 - a1 + vs_subv(vtmp1, __ T4S, va0, va1); + // output a0 = a0 + a1 + vs_addv(va0, __ T4S, va0, va1); + // output a1 = b montmul c + dilithium_montmul16(va1, vtmp1, vb, vtmp2, vq); + } + + // At these levels, the indices that correspond to the 'j's (and 'j+l's) + // in the Java implementation come in sequences of at least 8, so we + // can use ldpq to collect the corresponding data into pairs of vector + // registers. + // We collect the coefficients corresponding to the 'j+l' indexes into + // the vector registers v0-v7, the zetas into the vector registers v16-v23 + // then we do the (Montgomery) multiplications by the zetas in parallel + // into v16-v23, load the coeffs corresponding to the 'j' indexes into + // v0-v7, then do the additions into v24-v31 and the subtractions into + // v0-v7 and finally save the results back to the coeffs array. + void dilithiumNttLevel0_4(const Register dilithiumConsts, + const Register coeffs, const Register zetas) { + int c1 = 0; + int c2 = 512; + int startIncr; + // don't use callee save registers v8 - v15 + VSeq<8> vs1(0), vs2(16), vs3(24); // 3 sets of 8x4s inputs/outputs + VSeq<4> vtmp = vs_front(vs3); // n.b. tmp registers overlap vs3 + VSeq<2> vq(30); // n.b. constants overlap vs3 + int offsets[4] = { 0, 32, 64, 96 }; + + for (int level = 0; level < 5; level++) { + int c1Start = c1; + int c2Start = c2; + if (level == 3) { + offsets[1] = 32; + offsets[2] = 128; + offsets[3] = 160; + } else if (level == 4) { + offsets[1] = 64; + offsets[2] = 128; + offsets[3] = 192; + } + + // for levels 1 - 4 we simply load 2 x 4 adjacent values at a + // time at 4 different offsets and multiply them in order by the + // next set of input values. So we employ indexed load and store + // pair instructions with arrangement 4S + for (int i = 0; i < 4; i++) { + // reload q and qinv + vs_ldpq(vq, dilithiumConsts); // qInv, q + // load 8x4S coefficients via second start pos == c2 + vs_ldpq_indexed(vs1, coeffs, c2Start, offsets); + // load next 8x4S inputs == b + vs_ldpq_post(vs2, zetas); + // compute a == c2 * b mod MONT_Q + vs_montmul32(vs2, vs1, vs2, vtmp, vq); + // load 8x4s coefficients via first start pos == c1 + vs_ldpq_indexed(vs1, coeffs, c1Start, offsets); + // compute a1 = c1 + a + vs_addv(vs3, __ T4S, vs1, vs2); + // compute a2 = c1 - a + vs_subv(vs1, __ T4S, vs1, vs2); + // output a1 and a2 + vs_stpq_indexed(vs3, coeffs, c1Start, offsets); + vs_stpq_indexed(vs1, coeffs, c2Start, offsets); + + int k = 4 * level + i; + + if (k > 7) { + startIncr = 256; + } else if (k == 5) { + startIncr = 384; + } else { + startIncr = 128; + } + + c1Start += startIncr; + c2Start += startIncr; + } + + c2 /= 2; + } + } + + // Dilithium NTT function except for the final "normalization" to |coeff| < Q. + // Implements the method + // static int implDilithiumAlmostNtt(int[] coeffs, int zetas[]) {} + // of the Java class sun.security.provider + // + // coeffs (int[256]) = c_rarg0 + // zetas (int[256]) = c_rarg1 + address generate_dilithiumAlmostNtt() { + + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", "dilithiumAlmostNtt"); + address start = __ pc(); + __ enter(); + + const Register coeffs = c_rarg0; + const Register zetas = c_rarg1; + + const Register tmpAddr = r9; + const Register dilithiumConsts = r10; + const Register result = r11; + // don't use callee save registers v8 - v15 + VSeq<8> vs1(0), vs2(16), vs3(24); // 3 sets of 8x4s inputs/outputs + VSeq<4> vtmp = vs_front(vs3); // n.b. tmp registers overlap vs3 + VSeq<2> vq(30); // n.b. constants overlap vs3 + int offsets[4] = {0, 32, 64, 96}; + int offsets1[8] = {16, 48, 80, 112, 144, 176, 208, 240 }; + int offsets2[8] = { 0, 32, 64, 96, 128, 160, 192, 224 }; + __ add(result, coeffs, 0); + __ lea(dilithiumConsts, ExternalAddress((address) StubRoutines::aarch64::_dilithiumConsts)); + + // Each level represents one iteration of the outer for loop of the Java version + + // level 0-4 + dilithiumNttLevel0_4(dilithiumConsts, coeffs, zetas); + + // level 5 + + // at level 5 the coefficients we need to combine with the zetas + // are grouped in memory in blocks of size 4. So, for both sets of + // coefficients we load 4 adjacent values at 8 different offsets + // using an indexed ldr with register variant Q and multiply them + // in sequence order by the next set of inputs. Likewise we store + // the resuls using an indexed str with register variant Q. + for (int i = 0; i < 1024; i += 256) { + // reload constants q, qinv each iteration as they get clobbered later + vs_ldpq(vq, dilithiumConsts); // qInv, q + // load 32 (8x4S) coefficients via first offsets = c1 + vs_ldr_indexed(vs1, __ Q, coeffs, i, offsets1); + // load next 32 (8x4S) inputs = b + vs_ldpq_post(vs2, zetas); + // a = b montul c1 + vs_montmul32(vs2, vs1, vs2, vtmp, vq); + // load 32 (8x4S) coefficients via second offsets = c2 + vs_ldr_indexed(vs1, __ Q, coeffs, i, offsets2); + // add/sub with result of multiply + vs_addv(vs3, __ T4S, vs1, vs2); // a1 = a - c2 + vs_subv(vs1, __ T4S, vs1, vs2); // a0 = a + c1 + // write back new coefficients using same offsets + vs_str_indexed(vs3, __ Q, coeffs, i, offsets2); + vs_str_indexed(vs1, __ Q, coeffs, i, offsets1); + } + + // level 6 + // at level 6 the coefficients we need to combine with the zetas + // are grouped in memory in pairs, the first two being montmul + // inputs and the second add/sub inputs. We can still implement + // the montmul+sub+add using 4-way parallelism but only if we + // combine the coefficients with the zetas 16 at a time. We load 8 + // adjacent values at 4 different offsets using an ld2 load with + // arrangement 2D. That interleaves the lower and upper halves of + // each pair of quadwords into successive vector registers. We + // then need to montmul the 4 even elements of the coefficients + // register sequence by the zetas in order and then add/sub the 4 + // odd elements of the coefficients register sequence. We use an + // equivalent st2 operation to store the results back into memory + // de-interleaved. + for (int i = 0; i < 1024; i += 128) { + // reload constants q, qinv each iteration as they get clobbered later + vs_ldpq(vq, dilithiumConsts); // qInv, q + // load interleaved 16 (4x2D) coefficients via offsets + vs_ld2_indexed(vs1, __ T2D, coeffs, tmpAddr, i, offsets); + // load next 16 (4x4S) inputs + vs_ldpq_post(vs_front(vs2), zetas); + // mont multiply odd elements of vs1 by vs2 and add/sub into odds/evens + dilithium_montmul16_sub_add(vs_even(vs1), vs_odd(vs1), + vs_front(vs2), vtmp, vq); + // store interleaved 16 (4x2D) coefficients via offsets + vs_st2_indexed(vs1, __ T2D, coeffs, tmpAddr, i, offsets); + } + + // level 7 + // at level 7 the coefficients we need to combine with the zetas + // occur singly with montmul inputs alterating with add/sub + // inputs. Once again we can use 4-way parallelism to combine 16 + // zetas at a time. However, we have to load 8 adjacent values at + // 4 different offsets using an ld2 load with arrangement 4S. That + // interleaves the the odd words of each pair into one + // coefficients vector register and the even words of the pair + // into the next register. We then need to montmul the 4 even + // elements of the coefficients register sequence by the zetas in + // order and then add/sub the 4 odd elements of the coefficients + // register sequence. We use an equivalent st2 operation to store + // the results back into memory de-interleaved. + + for (int i = 0; i < 1024; i += 128) { + // reload constants q, qinv each iteration as they get clobbered later + vs_ldpq(vq, dilithiumConsts); // qInv, q + // load interleaved 16 (4x4S) coefficients via offsets + vs_ld2_indexed(vs1, __ T4S, coeffs, tmpAddr, i, offsets); + // load next 16 (4x4S) inputs + vs_ldpq_post(vs_front(vs2), zetas); + // mont multiply odd elements of vs1 by vs2 and add/sub into odds/evens + dilithium_montmul16_sub_add(vs_even(vs1), vs_odd(vs1), + vs_front(vs2), vtmp, vq); + // store interleaved 16 (4x4S) coefficients via offsets + vs_st2_indexed(vs1, __ T4S, coeffs, tmpAddr, i, offsets); + } + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ mov(r0, zr); // return 0 + __ ret(lr); + + return start; + } + + // At these levels, the indices that correspond to the 'j's (and 'j+l's) + // in the Java implementation come in sequences of at least 8, so we + // can use ldpq to collect the corresponding data into pairs of vector + // registers + // We collect the coefficients that correspond to the 'j's into vs1 + // the coefficiets that correspond to the 'j+l's into vs2 then + // do the additions into vs3 and the subtractions into vs1 then + // save the result of the additions, load the zetas into vs2 + // do the (Montgomery) multiplications by zeta in parallel into vs2 + // finally save the results back to the coeffs array + void dilithiumInverseNttLevel3_7(const Register dilithiumConsts, + const Register coeffs, const Register zetas) { + int c1 = 0; + int c2 = 32; + int startIncr; + int offsets[4]; + VSeq<8> vs1(0), vs2(16), vs3(24); // 3 sets of 8x4s inputs/outputs + VSeq<4> vtmp = vs_front(vs3); // n.b. tmp registers overlap vs3 + VSeq<2> vq(30); // n.b. constants overlap vs3 + + offsets[0] = 0; + + for (int level = 3; level < 8; level++) { + int c1Start = c1; + int c2Start = c2; + if (level == 3) { + offsets[1] = 64; + offsets[2] = 128; + offsets[3] = 192; + } else if (level == 4) { + offsets[1] = 32; + offsets[2] = 128; + offsets[3] = 160; + } else { + offsets[1] = 32; + offsets[2] = 64; + offsets[3] = 96; + } + + // for levels 3 - 7 we simply load 2 x 4 adjacent values at a + // time at 4 different offsets and multiply them in order by the + // next set of input values. So we employ indexed load and store + // pair instructions with arrangement 4S + for (int i = 0; i < 4; i++) { + // load v1 32 (8x4S) coefficients relative to first start index + vs_ldpq_indexed(vs1, coeffs, c1Start, offsets); + // load v2 32 (8x4S) coefficients relative to second start index + vs_ldpq_indexed(vs2, coeffs, c2Start, offsets); + // a0 = v1 + v2 -- n.b. clobbers vqs + vs_addv(vs3, __ T4S, vs1, vs2); + // a1 = v1 - v2 + vs_subv(vs1, __ T4S, vs1, vs2); + // save a1 relative to first start index + vs_stpq_indexed(vs3, coeffs, c1Start, offsets); + // load constants q, qinv each iteration as they get clobbered above + vs_ldpq(vq, dilithiumConsts); // qInv, q + // load b next 32 (8x4S) inputs + vs_ldpq_post(vs2, zetas); + // a = a1 montmul b + vs_montmul32(vs2, vs1, vs2, vtmp, vq); + // save a relative to second start index + vs_stpq_indexed(vs2, coeffs, c2Start, offsets); + + int k = 4 * level + i; + + if (k < 24) { + startIncr = 256; + } else if (k == 25) { + startIncr = 384; + } else { + startIncr = 128; + } + + c1Start += startIncr; + c2Start += startIncr; + } + + c2 *= 2; + } + } + + // Dilithium Inverse NTT function except the final mod Q division by 2^256. + // Implements the method + // static int implDilithiumAlmostInverseNtt(int[] coeffs, int[] zetas) {} of + // the sun.security.provider.ML_DSA class. + // + // coeffs (int[256]) = c_rarg0 + // zetas (int[256]) = c_rarg1 + address generate_dilithiumAlmostInverseNtt() { + + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", "dilithiumAlmostInverseNtt"); + address start = __ pc(); + __ enter(); + + const Register coeffs = c_rarg0; + const Register zetas = c_rarg1; + + const Register tmpAddr = r9; + const Register dilithiumConsts = r10; + const Register result = r11; + VSeq<8> vs1(0), vs2(16), vs3(24); // 3 sets of 8x4s inputs/outputs + VSeq<4> vtmp = vs_front(vs3); // n.b. tmp registers overlap vs3 + VSeq<2> vq(30); // n.b. constants overlap vs3 + int offsets[4] = { 0, 32, 64, 96 }; + int offsets1[8] = { 0, 32, 64, 96, 128, 160, 192, 224 }; + int offsets2[8] = { 16, 48, 80, 112, 144, 176, 208, 240 }; + + __ add(result, coeffs, 0); + __ lea(dilithiumConsts, ExternalAddress((address) StubRoutines::aarch64::_dilithiumConsts)); + + // Each level represents one iteration of the outer for loop of the Java version + // level0 + + // level 0 + // At level 0 we need to interleave adjacent quartets of + // coefficients before we multiply and add/sub by the next 16 + // zetas just as we did for level 7 in the multiply code. So we + // load and store the values using an ld2/st2 with arrangement 4S + for (int i = 0; i < 1024; i += 128) { + // load constants q, qinv + // n.b. this can be moved out of the loop as they do not get + // clobbered by first two loops + vs_ldpq(vq, dilithiumConsts); // qInv, q + // a0/a1 load interleaved 32 (8x4S) coefficients + vs_ld2_indexed(vs1, __ T4S, coeffs, tmpAddr, i, offsets); + // b load next 32 (8x4S) inputs + vs_ldpq_post(vs_front(vs2), zetas); + // compute in parallel (a0, a1) = (a0 + a1, (a0 - a1) montmul b) + // n.b. second half of vs2 provides temporary register storage + dilithium_sub_add_montmul16(vs_even(vs1), vs_odd(vs1), + vs_front(vs2), vs_back(vs2), vtmp, vq); + // a0/a1 store interleaved 32 (8x4S) coefficients + vs_st2_indexed(vs1, __ T4S, coeffs, tmpAddr, i, offsets); + } + + // level 1 + // At level 1 we need to interleave pairs of adjacent pairs of + // coefficients before we multiply by the next 16 zetas just as we + // did for level 6 in the multiply code. So we load and store the + // values an ld2/st2 with arrangement 2D + for (int i = 0; i < 1024; i += 128) { + // a0/a1 load interleaved 32 (8x2D) coefficients + vs_ld2_indexed(vs1, __ T2D, coeffs, tmpAddr, i, offsets); + // b load next 16 (4x4S) inputs + vs_ldpq_post(vs_front(vs2), zetas); + // compute in parallel (a0, a1) = (a0 + a1, (a0 - a1) montmul b) + // n.b. second half of vs2 provides temporary register storage + dilithium_sub_add_montmul16(vs_even(vs1), vs_odd(vs1), + vs_front(vs2), vs_back(vs2), vtmp, vq); + // a0/a1 store interleaved 32 (8x2D) coefficients + vs_st2_indexed(vs1, __ T2D, coeffs, tmpAddr, i, offsets); + } + + // level 2 + // At level 2 coefficients come in blocks of 4. So, we load 4 + // adjacent coefficients at 8 distinct offsets for both the first + // and second coefficient sequences, using an ldr with register + // variant Q then combine them with next set of 32 zetas. Likewise + // we store the results using an str with register variant Q. + for (int i = 0; i < 1024; i += 256) { + // c0 load 32 (8x4S) coefficients via first offsets + vs_ldr_indexed(vs1, __ Q, coeffs, i, offsets1); + // c1 load 32 (8x4S) coefficients via second offsets + vs_ldr_indexed(vs2, __ Q,coeffs, i, offsets2); + // a0 = c0 + c1 n.b. clobbers vq which overlaps vs3 + vs_addv(vs3, __ T4S, vs1, vs2); + // c = c0 - c1 + vs_subv(vs1, __ T4S, vs1, vs2); + // store a0 32 (8x4S) coefficients via first offsets + vs_str_indexed(vs3, __ Q, coeffs, i, offsets1); + // b load 32 (8x4S) next inputs + vs_ldpq_post(vs2, zetas); + // reload constants q, qinv -- they were clobbered earlier + vs_ldpq(vq, dilithiumConsts); // qInv, q + // compute a1 = b montmul c + vs_montmul32(vs2, vs1, vs2, vtmp, vq); + // store a1 32 (8x4S) coefficients via second offsets + vs_str_indexed(vs2, __ Q, coeffs, i, offsets2); + } + + // level 3-7 + dilithiumInverseNttLevel3_7(dilithiumConsts, coeffs, zetas); + + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ mov(r0, zr); // return 0 + __ ret(lr); + + return start; + + } + + // Dilithium multiply polynomials in the NTT domain. + // Straightforward implementation of the method + // static int implDilithiumNttMult( + // int[] result, int[] ntta, int[] nttb {} of + // the sun.security.provider.ML_DSA class. + // + // result (int[256]) = c_rarg0 + // poly1 (int[256]) = c_rarg1 + // poly2 (int[256]) = c_rarg2 + address generate_dilithiumNttMult() { + + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", "dilithiumNttMult"); + address start = __ pc(); + __ enter(); + + Label L_loop; + + const Register result = c_rarg0; + const Register poly1 = c_rarg1; + const Register poly2 = c_rarg2; + + const Register dilithiumConsts = r10; + const Register len = r11; + + VSeq<8> vs1(0), vs2(16), vs3(24); // 3 sets of 8x4s inputs/outputs + VSeq<4> vtmp = vs_front(vs3); // n.b. tmp registers overlap vs3 + VSeq<2> vq(30); // n.b. constants overlap vs3 + VSeq<8> vrsquare(29, 0); // for montmul by constant RSQUARE + + __ lea(dilithiumConsts, ExternalAddress((address) StubRoutines::aarch64::_dilithiumConsts)); + + // load constants q, qinv + vs_ldpq(vq, dilithiumConsts); // qInv, q + // load constant rSquare into v29 + __ ldr(v29, __ Q, Address(dilithiumConsts, 48)); // rSquare + + __ mov(len, zr); + __ add(len, len, 1024); + + __ BIND(L_loop); + + // b load 32 (8x4S) next inputs from poly1 + vs_ldpq_post(vs1, poly1); + // c load 32 (8x4S) next inputs from poly2 + vs_ldpq_post(vs2, poly2); + // compute a = b montmul c + vs_montmul32(vs2, vs1, vs2, vtmp, vq); + // compute a = rsquare montmul a + vs_montmul32(vs2, vrsquare, vs2, vtmp, vq); + // save a 32 (8x4S) results + vs_stpq_post(vs2, result); + + __ sub(len, len, 128); + __ cmp(len, (u1)128); + __ br(Assembler::GE, L_loop); + + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ mov(r0, zr); // return 0 + __ ret(lr); + + return start; + + } + + // Dilithium Motgomery multiply an array by a constant. + // A straightforward implementation of the method + // static int implDilithiumMontMulByConstant(int[] coeffs, int constant) {} + // of the sun.security.provider.MLDSA class + // + // coeffs (int[256]) = c_rarg0 + // constant (int) = c_rarg1 + address generate_dilithiumMontMulByConstant() { + + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", "dilithiumMontMulByConstant"); + address start = __ pc(); + __ enter(); + + Label L_loop; + + const Register coeffs = c_rarg0; + const Register constant = c_rarg1; + + const Register dilithiumConsts = r10; + const Register result = r11; + const Register len = r12; + + VSeq<8> vs1(0), vs2(16), vs3(24); // 3 sets of 8x4s inputs/outputs + VSeq<4> vtmp = vs_front(vs3); // n.b. tmp registers overlap vs3 + VSeq<2> vq(30); // n.b. constants overlap vs3 + VSeq<8> vconst(29, 0); // for montmul by constant + + // results track inputs + __ add(result, coeffs, 0); + __ lea(dilithiumConsts, ExternalAddress((address) StubRoutines::aarch64::_dilithiumConsts)); + + // load constants q, qinv -- they do not get clobbered by first two loops + vs_ldpq(vq, dilithiumConsts); // qInv, q + // copy caller supplied constant across vconst + __ dup(vconst[0], __ T4S, constant); + __ mov(len, zr); + __ add(len, len, 1024); + + __ BIND(L_loop); + + // load next 32 inputs + vs_ldpq_post(vs2, coeffs); + // mont mul by constant + vs_montmul32(vs2, vconst, vs2, vtmp, vq); + // write next 32 results + vs_stpq_post(vs2, result); + + __ sub(len, len, 128); + __ cmp(len, (u1)128); + __ br(Assembler::GE, L_loop); + + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ mov(r0, zr); // return 0 + __ ret(lr); + + return start; + + } + + // Dilithium decompose poly. + // Implements the method + // static int implDilithiumDecomposePoly(int[] coeffs, int constant) {} + // of the sun.security.provider.ML_DSA class + // + // input (int[256]) = c_rarg0 + // lowPart (int[256]) = c_rarg1 + // highPart (int[256]) = c_rarg2 + // twoGamma2 (int) = c_rarg3 + // multiplier (int) = c_rarg4 + address generate_dilithiumDecomposePoly() { + + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", "dilithiumDecomposePoly"); + address start = __ pc(); + Label L_loop; + + const Register input = c_rarg0; + const Register lowPart = c_rarg1; + const Register highPart = c_rarg2; + const Register twoGamma2 = c_rarg3; + const Register multiplier = c_rarg4; + + const Register len = r9; + const Register dilithiumConsts = r10; + const Register tmp = r11; + + VSeq<4> vs1(0), vs2(4), vs3(8); // 6 independent sets of 4x4s values + VSeq<4> vs4(12), vs5(16), vtmp(20); + VSeq<4> one(25, 0); // 7 constants for cross-multiplying + VSeq<4> qminus1(26, 0); + VSeq<4> g2(27, 0); + VSeq<4> twog2(28, 0); + VSeq<4> mult(29, 0); + VSeq<4> q(30, 0); + VSeq<4> qadd(31, 0); + + __ enter(); + + __ lea(dilithiumConsts, ExternalAddress((address) StubRoutines::aarch64::_dilithiumConsts)); + + // save callee-saved registers + __ stpd(v8, v9, __ pre(sp, -64)); + __ stpd(v10, v11, Address(sp, 16)); + __ stpd(v12, v13, Address(sp, 32)); + __ stpd(v14, v15, Address(sp, 48)); + + // populate constant registers + __ mov(tmp, zr); + __ add(tmp, tmp, 1); + __ dup(one[0], __ T4S, tmp); // 1 + __ ldr(q[0], __ Q, Address(dilithiumConsts, 16)); // q + __ ldr(qadd[0], __ Q, Address(dilithiumConsts, 64)); // addend for mod q reduce + __ dup(twog2[0], __ T4S, twoGamma2); // 2 * gamma2 + __ dup(mult[0], __ T4S, multiplier); // multiplier for mod 2 * gamma reduce + __ subv(qminus1[0], __ T4S, v30, v25); // q - 1 + __ sshr(g2[0], __ T4S, v28, 1); // gamma2 + + __ mov(len, zr); + __ add(len, len, 1024); + + __ BIND(L_loop); + + // load next 4x4S inputs interleaved: rplus --> vs1 + __ ld4(vs1[0], vs1[1], vs1[2], vs1[3], __ T4S, __ post(input, 64)); + + // rplus = rplus - ((rplus + qadd) >> 23) * q + vs_addv(vtmp, __ T4S, vs1, qadd); + vs_sshr(vtmp, __ T4S, vtmp, 23); + vs_mulv(vtmp, __ T4S, vtmp, q); + vs_subv(vs1, __ T4S, vs1, vtmp); + + // rplus = rplus + ((rplus >> 31) & dilithium_q); + vs_sshr(vtmp, __ T4S, vs1, 31); + vs_andr(vtmp, vtmp, q); + vs_addv(vs1, __ T4S, vs1, vtmp); + + // quotient --> vs2 + // int quotient = (rplus * multiplier) >> 22; + vs_mulv(vtmp, __ T4S, vs1, mult); + vs_sshr(vs2, __ T4S, vtmp, 22); + + // r0 --> vs3 + // int r0 = rplus - quotient * twoGamma2; + vs_mulv(vtmp, __ T4S, vs2, twog2); + vs_subv(vs3, __ T4S, vs1, vtmp); + + // mask --> vs4 + // int mask = (twoGamma2 - r0) >> 22; + vs_subv(vtmp, __ T4S, twog2, vs3); + vs_sshr(vs4, __ T4S, vtmp, 22); + + // r0 -= (mask & twoGamma2); + vs_andr(vtmp, vs4, twog2); + vs_subv(vs3, __ T4S, vs3, vtmp); + + // quotient += (mask & 1); + vs_andr(vtmp, vs4, one); + vs_addv(vs2, __ T4S, vs2, vtmp); + + // mask = (twoGamma2 / 2 - r0) >> 31; + vs_subv(vtmp, __ T4S, g2, vs3); + vs_sshr(vs4, __ T4S, vtmp, 31); + + // r0 -= (mask & twoGamma2); + vs_andr(vtmp, vs4, twog2); + vs_subv(vs3, __ T4S, vs3, vtmp); + + // quotient += (mask & 1); + vs_andr(vtmp, vs4, one); + vs_addv(vs2, __ T4S, vs2, vtmp); + + // r1 --> vs5 + // int r1 = rplus - r0 - (dilithium_q - 1); + vs_subv(vtmp, __ T4S, vs1, vs3); + vs_subv(vs5, __ T4S, vtmp, qminus1); + + // r1 --> vs1 (overwriting rplus) + // r1 = (r1 | (-r1)) >> 31; // 0 if rplus - r0 == (dilithium_q - 1), -1 otherwise + vs_negr(vtmp, __ T4S, vs5); + vs_orr(vtmp, vs5, vtmp); + vs_sshr(vs1, __ T4S, vtmp, 31); + + // r0 += ~r1; + vs_notr(vtmp, vs1); + vs_addv(vs3, __ T4S, vs3, vtmp); + + // r1 = r1 & quotient; + vs_andr(vs1, vs2, vs1); + + // store results inteleaved + // lowPart[m] = r0; + // highPart[m] = r1; + __ st4(vs3[0], vs3[1], vs3[2], vs3[3], __ T4S, __ post(lowPart, 64)); + __ st4(vs1[0], vs1[1], vs1[2], vs1[3], __ T4S, __ post(highPart, 64)); + + + __ sub(len, len, 64); + __ cmp(len, (u1)64); + __ br(Assembler::GE, L_loop); + + // restore callee-saved vector registers + __ ldpd(v14, v15, Address(sp, 48)); + __ ldpd(v12, v13, Address(sp, 32)); + __ ldpd(v10, v11, Address(sp, 16)); + __ ldpd(v8, v9, __ post(sp, 64)); + + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ mov(r0, zr); // return 0 + __ ret(lr); + + return start; + + } + /** * Arguments: * @@ -8822,6 +9884,14 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_chacha20Block = generate_chacha20Block_blockpar(); } + if (UseDilithiumIntrinsics) { + StubRoutines::_dilithiumAlmostNtt = generate_dilithiumAlmostNtt(); + StubRoutines::_dilithiumAlmostInverseNtt = generate_dilithiumAlmostInverseNtt(); + StubRoutines::_dilithiumNttMult = generate_dilithiumNttMult(); + StubRoutines::_dilithiumMontMulByConstant = generate_dilithiumMontMulByConstant(); + StubRoutines::_dilithiumDecomposePoly = generate_dilithiumDecomposePoly(); + } + if (UseBASE64Intrinsics) { StubRoutines::_base64_encodeBlock = generate_base64_encodeBlock(); StubRoutines::_base64_decodeBlock = generate_base64_decodeBlock(); @@ -8864,6 +9934,7 @@ class StubGenerator: public StubCodeGenerator { } if (UseSHA3Intrinsics) { StubRoutines::_sha3_implCompress = generate_sha3_implCompress(false, "sha3_implCompress"); + StubRoutines::_double_keccak = generate_double_keccak(); StubRoutines::_sha3_implCompressMB = generate_sha3_implCompress(true, "sha3_implCompressMB"); } diff --git a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp index c107e614b574..f7f836cab9f6 100644 --- a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp @@ -68,6 +68,15 @@ address StubRoutines::aarch64::_spin_wait = CAST_FROM_FN_PTR(address, empty_spin bool StubRoutines::aarch64::_completed = false; +ATTRIBUTE_ALIGNED(64) uint32_t StubRoutines::aarch64::_dilithiumConsts[] = +{ + 58728449, 58728449, 58728449, 58728449, // montQInvModR + 8380417, 8380417, 8380417, 8380417, // dilithium_q + 16382, 16382, 16382, 16382, // toMont((dilithium_n)^-1 (mod dilithium_q)) + 2365951, 2365951, 2365951, 2365951, // montRSquareModQ + 5373807, 5373807, 5373807, 5373807 // addend for modular reduce +}; + /** * crc_table[] from jdk/src/share/native/java/util/zip/zlib-1.2.5/crc32.h */ diff --git a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp index dcc2604ed214..d4e206d1b38d 100644 --- a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -38,7 +38,7 @@ enum platform_dependent_constants { // simply increase sizes if too small (assembler will crash if too small) _initial_stubs_code_size = 10000, _continuation_stubs_code_size = 2000, - _compiler_stubs_code_size = 30000 ZGC_ONLY(+10000), + _compiler_stubs_code_size = 55000 ZGC_ONLY(+10000), _final_stubs_code_size = 20000 ZGC_ONLY(+100000) }; @@ -220,6 +220,7 @@ class aarch64 { } private: + static uint32_t _dilithiumConsts[]; static juint _crc_table[]; static jubyte _adler_table[]; // begin trigonometric tables block. See comments in .cpp file diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index 6c95dc9c8ff9..50ea4b3d2c47 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -411,6 +411,17 @@ void VM_Version::initialize() { FLAG_SET_DEFAULT(UseChaCha20Intrinsics, false); } + if (_features & CPU_ASIMD) { + if (FLAG_IS_DEFAULT(UseDilithiumIntrinsics)) { + UseDilithiumIntrinsics = true; + } + } else if (UseDilithiumIntrinsics) { + if (!FLAG_IS_DEFAULT(UseDilithiumIntrinsics)) { + warning("Dilithium intrinsic requires ASIMD instructions"); + } + FLAG_SET_DEFAULT(UseDilithiumIntrinsics, false); + } + if (FLAG_IS_DEFAULT(UseBASE64Intrinsics)) { UseBASE64Intrinsics = true; } diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp index 7daf7589fb09..a018eaf7b576 100644 --- a/src/hotspot/cpu/x86/assembler_x86.cpp +++ b/src/hotspot/cpu/x86/assembler_x86.cpp @@ -3260,6 +3260,23 @@ void Assembler::evmovdqub(Address dst, KRegister mask, XMMRegister src, bool mer emit_operand(src, dst, 0); } +void Assembler::evmovdquw(XMMRegister dst, XMMRegister src, int vector_len) { + // Unmasked instruction + evmovdquw(dst, k0, src, /*merge*/ false, vector_len); +} + +void Assembler::evmovdquw(XMMRegister dst, KRegister mask, XMMRegister src, bool merge, int vector_len) { + assert(vector_len <= AVX_256bit ? VM_Version::supports_avx512vlbw() : VM_Version::supports_avx512bw(), ""); + InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); + attributes.set_embedded_opmask_register_specifier(mask); + attributes.set_is_evex_instruction(); + if (merge) { + attributes.reset_is_clear_context(); + } + int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F, &attributes); + emit_int16(0x6F, (0xC0 | encode)); +} + void Assembler::evmovdquw(XMMRegister dst, Address src, int vector_len) { // Unmasked instruction evmovdquw(dst, k0, src, /*merge*/ false, vector_len); @@ -7483,6 +7500,15 @@ void Assembler::vpmuludq(XMMRegister dst, XMMRegister nds, XMMRegister src, int emit_int16((unsigned char)0xF4, (0xC0 | encode)); } +void Assembler::vpmuldq(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(vector_len == AVX_128bit ? VM_Version::supports_avx() : + (vector_len == AVX_256bit ? VM_Version::supports_avx2() : VM_Version::supports_evex()), ""); + InstructionAttr attributes(vector_len, /* vex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_rex_vex_w_reverted(); + int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int16(0x28, (0xC0 | encode)); +} + void Assembler::vpmullw(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { assert(UseAVX > 0, "requires some form of AVX"); InstructionMark im(this); @@ -9438,6 +9464,18 @@ void Assembler::evpmullq(XMMRegister dst, KRegister mask, XMMRegister nds, Addre emit_operand(dst, src, 0); } +void Assembler::evpmulhw(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int vector_len) { + assert(VM_Version::supports_avx512bw() && (vector_len == AVX_512bit || VM_Version::supports_avx512vl()), ""); + InstructionAttr attributes(vector_len, /* vex_w */ false,/* legacy_mode */ false, /* no_mask_reg */ false,/* uses_vl */ true); + attributes.set_is_evex_instruction(); + attributes.set_embedded_opmask_register_specifier(mask); + if (merge) { + attributes.reset_is_clear_context(); + } + int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F, &attributes); + emit_int16((unsigned char)0xE5, (0xC0 | encode)); +} + void Assembler::evmulps(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int vector_len) { assert(VM_Version::supports_evex(), ""); assert(vector_len == AVX_512bit || VM_Version::supports_avx512vl(), ""); @@ -14067,3 +14105,28 @@ void InstructionAttr::set_address_attributes(int tuple_type, int input_size_in_b _input_size_in_bits = input_size_in_bits; } } + +void Assembler::evpermt2w(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(vector_len <= AVX_256bit ? VM_Version::supports_avx512vlbw() : VM_Version::supports_avx512bw(), ""); + InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int16(0x7D, (0xC0 | encode)); +} + +void Assembler::evpermt2d(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(VM_Version::supports_evex() && (vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl()), ""); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int16(0x7E, (0xC0 | encode)); +} + +void Assembler::evpermt2q(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(VM_Version::supports_evex() && (vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl()), ""); + InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int16(0x7E, (0xC0 | encode)); +} + diff --git a/src/hotspot/cpu/x86/assembler_x86.hpp b/src/hotspot/cpu/x86/assembler_x86.hpp index 8b17abd3fe6e..fe7e1b20e8be 100644 --- a/src/hotspot/cpu/x86/assembler_x86.hpp +++ b/src/hotspot/cpu/x86/assembler_x86.hpp @@ -1597,6 +1597,7 @@ class Assembler : public AbstractAssembler { void evmovdqub(XMMRegister dst, KRegister mask, Address src, bool merge, int vector_len); void evmovdqub(Address dst, KRegister mask, XMMRegister src, bool merge, int vector_len); + void evmovdquw(XMMRegister dst, XMMRegister src, int vector_len); void evmovdquw(XMMRegister dst, Address src, int vector_len); void evmovdquw(Address dst, XMMRegister src, int vector_len); void evmovdquw(XMMRegister dst, KRegister mask, XMMRegister src, bool merge, int vector_len); @@ -1777,6 +1778,9 @@ class Assembler : public AbstractAssembler { void vpermpd(XMMRegister dst, XMMRegister src, int imm8, int vector_len); void evpermi2q(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); void evpermt2b(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); + void evpermt2w(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); + void evpermt2d(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); + void evpermt2q(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); void evpmultishiftqb(XMMRegister dst, XMMRegister ctl, XMMRegister src, int vector_len); void pause(); @@ -2420,6 +2424,7 @@ class Assembler : public AbstractAssembler { void evsubps(XMMRegister dst, KRegister mask, XMMRegister nds, Address src, bool merge, int vector_len); void evsubpd(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int vector_len); void evsubpd(XMMRegister dst, KRegister mask, XMMRegister nds, Address src, bool merge, int vector_len); + void evpmulhw(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int vector_len); void evpmullw(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int vector_len); void evpmullw(XMMRegister dst, KRegister mask, XMMRegister nds, Address src, bool merge, int vector_len); void evpmulld(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int vector_len); @@ -2556,6 +2561,7 @@ class Assembler : public AbstractAssembler { void vpmulld(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); void evpmullq(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); void vpmuludq(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); + void vpmuldq(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); void vpmullw(XMMRegister dst, XMMRegister nds, Address src, int vector_len); void vpmulld(XMMRegister dst, XMMRegister nds, Address src, int vector_len); void evpmullq(XMMRegister dst, XMMRegister nds, Address src, int vector_len); diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp index 7d07519c1c76..407e3bfd2cd8 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp @@ -1220,6 +1220,7 @@ class MacroAssembler: public Assembler { void evmovdqub(XMMRegister dst, KRegister mask, Address src, bool merge, int vector_len) { Assembler::evmovdqub(dst, mask, src, merge, vector_len); } void evmovdqub(XMMRegister dst, KRegister mask, AddressLiteral src, bool merge, int vector_len, Register rscratch = noreg); + void evmovdquw(XMMRegister dst, XMMRegister src, int vector_len) { Assembler::evmovdquw(dst, src, vector_len); } void evmovdquw(Address dst, XMMRegister src, int vector_len) { Assembler::evmovdquw(dst, src, vector_len); } void evmovdquw(XMMRegister dst, Address src, int vector_len) { Assembler::evmovdquw(dst, src, vector_len); } @@ -1428,6 +1429,8 @@ class MacroAssembler: public Assembler { void vpmulld(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { Assembler::vpmulld(dst, nds, src, vector_len); } void vpmulld(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len, Register rscratch = noreg); + void vpmuldq(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { Assembler::vpmuldq(dst, nds, src, vector_len); } + void vpsubb(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); void vpsubb(XMMRegister dst, XMMRegister nds, Address src, int vector_len); @@ -1437,9 +1440,13 @@ class MacroAssembler: public Assembler { void vpsraw(XMMRegister dst, XMMRegister nds, XMMRegister shift, int vector_len); void vpsraw(XMMRegister dst, XMMRegister nds, int shift, int vector_len); + void evpsrad(XMMRegister dst, XMMRegister nds, XMMRegister shift, int vector_len); + void evpsrad(XMMRegister dst, XMMRegister nds, int shift, int vector_len); + void evpsraq(XMMRegister dst, XMMRegister nds, XMMRegister shift, int vector_len); void evpsraq(XMMRegister dst, XMMRegister nds, int shift, int vector_len); + using Assembler::evpsllw; void evpsllw(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int vector_len, bool is_varshift) { if (!is_varshift) { Assembler::evpsllw(dst, mask, nds, src, merge, vector_len); @@ -1482,6 +1489,7 @@ class MacroAssembler: public Assembler { Assembler::evpsrlvq(dst, mask, nds, src, merge, vector_len); } } + using Assembler::evpsraw; void evpsraw(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int vector_len, bool is_varshift) { if (!is_varshift) { Assembler::evpsraw(dst, mask, nds, src, merge, vector_len); @@ -1489,6 +1497,7 @@ class MacroAssembler: public Assembler { Assembler::evpsravw(dst, mask, nds, src, merge, vector_len); } } + using Assembler::evpsrad; void evpsrad(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int vector_len, bool is_varshift) { if (!is_varshift) { Assembler::evpsrad(dst, mask, nds, src, merge, vector_len); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp index 15e9ba59c9ce..957ec4139aff 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp @@ -4206,6 +4206,8 @@ void StubGenerator::generate_compiler_stubs() { StubRoutines::_base64_decodeBlock = generate_base64_decodeBlock(); } + generate_sha3_stubs(); + #ifdef COMPILER2 if (UseMultiplyToLenIntrinsic) { StubRoutines::_multiplyToLen = generate_multiplyToLen(); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp index 0e813681fcf2..5a3d6fe917cc 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp @@ -423,6 +423,10 @@ class StubGenerator: public StubCodeGenerator { const XMMRegister L0, const XMMRegister L1, const XMMRegister L2, bool padMSG, const XMMRegister TMP, const Register rscratch); + // SHA3 stubs + void generate_sha3_stubs(); + address generate_sha3_implCompress(bool multiBlock, const char *name); + // BASE64 stubs address base64_shuffle_addr(); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_sha3.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_sha3.cpp new file mode 100644 index 000000000000..49c39226708e --- /dev/null +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_sha3.cpp @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "asm/assembler.hpp" +#include "asm/assembler.inline.hpp" +#include "runtime/stubRoutines.hpp" +#include "macroAssembler_x86.hpp" +#include "stubGenerator_x86_64.hpp" + +#define __ _masm-> + +#ifdef PRODUCT +#define BLOCK_COMMENT(str) /* nothing */ +#else +#define BLOCK_COMMENT(str) __ block_comment(str) +#endif // PRODUCT + +#define BIND(label) bind(label); BLOCK_COMMENT(#label ":") + +// Constants +ATTRIBUTE_ALIGNED(64) static const uint64_t round_consts_arr[24] = { + 0x0000000000000001L, 0x0000000000008082L, 0x800000000000808AL, + 0x8000000080008000L, 0x000000000000808BL, 0x0000000080000001L, + 0x8000000080008081L, 0x8000000000008009L, 0x000000000000008AL, + 0x0000000000000088L, 0x0000000080008009L, 0x000000008000000AL, + 0x000000008000808BL, 0x800000000000008BL, 0x8000000000008089L, + 0x8000000000008003L, 0x8000000000008002L, 0x8000000000000080L, + 0x000000000000800AL, 0x800000008000000AL, 0x8000000080008081L, + 0x8000000000008080L, 0x0000000080000001L, 0x8000000080008008L + }; + +ATTRIBUTE_ALIGNED(64) static const uint64_t permsAndRots[] = { + // permutation in combined rho and pi + 9, 2, 11, 0, 1, 2, 3, 4, // step 1 and 3 + 8, 1, 9, 2, 11, 4, 12, 0, // step 2 + 9, 2, 10, 3, 11, 4, 12, 0, // step 4 + 8, 9, 2, 3, 4, 5, 6, 7, // step 5 + 0, 8, 9, 10, 15, 0, 0, 0, // step 6 + 4, 5, 8, 9, 6, 7, 10, 11, // step 7 and 8 + 0, 1, 2, 3, 13, 0, 0, 0, // step 9 + 2, 3, 0, 1, 11, 0, 0, 0, // step 10 + 4, 5, 6, 7, 14, 0, 0, 0, // step 11 + 14, 15, 12, 13, 4, 0, 0, 0, // step 12 + // size of rotations (after step 5) + 1, 6, 62, 55, 28, 20, 27, 36, + 3, 45, 10, 15, 25, 8, 39, 41, + 44, 43, 21, 18, 2, 61, 56, 14, + // rotation of row elements + 12, 8, 9, 10, 11, 5, 6, 7, + 9, 10, 11, 12, 8, 5, 6, 7 +}; + +static address round_constsAddr() { + return (address) round_consts_arr; +} + +static address permsAndRotsAddr() { + return (address) permsAndRots; +} + +void StubGenerator::generate_sha3_stubs() { + if (UseSHA3Intrinsics) { + StubRoutines::_sha3_implCompress = generate_sha3_implCompress(false,"sha3_implCompress"); + StubRoutines::_sha3_implCompressMB = generate_sha3_implCompress(true, "sha3_implCompressMB"); + } +} + +// Arguments: +// +// Inputs: +// c_rarg0 - byte[] source+offset +// c_rarg1 - long[] SHA3.state +// c_rarg2 - int block_size +// c_rarg3 - int offset +// c_rarg4 - int limit +// +address StubGenerator::generate_sha3_implCompress(bool multiBlock, const char *name) { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", name); + address start = __ pc(); + + const Register buf = c_rarg0; + const Register state = c_rarg1; + const Register block_size = c_rarg2; + const Register ofs = c_rarg3; +#ifndef _WIN64 + const Register limit = c_rarg4; +#else + const Address limit_mem(rbp, 6 * wordSize); + const Register limit = r12; +#endif + + const Register permsAndRots = r10; + const Register round_consts = r11; + const Register constant2use = r13; + const Register roundsLeft = r14; + + Label sha3_loop; + Label rounds24_loop, block104, block136, block144, block168; + + __ enter(); + + __ push(r12); + __ push(r13); + __ push(r14); + +#ifdef _WIN64 + // on win64, fill limit from stack position + __ movptr(limit, limit_mem); +#endif + + __ lea(permsAndRots, ExternalAddress(permsAndRotsAddr())); + __ lea(round_consts, ExternalAddress(round_constsAddr())); + + // set up the masks + __ movl(rax, 0x1F); + __ kmovwl(k5, rax); + __ kshiftrwl(k4, k5, 1); + __ kshiftrwl(k3, k5, 2); + __ kshiftrwl(k2, k5, 3); + __ kshiftrwl(k1, k5, 4); + + // load the state + __ evmovdquq(xmm0, k5, Address(state, 0), false, Assembler::AVX_512bit); + __ evmovdquq(xmm1, k5, Address(state, 40), false, Assembler::AVX_512bit); + __ evmovdquq(xmm2, k5, Address(state, 80), false, Assembler::AVX_512bit); + __ evmovdquq(xmm3, k5, Address(state, 120), false, Assembler::AVX_512bit); + __ evmovdquq(xmm4, k5, Address(state, 160), false, Assembler::AVX_512bit); + + // load the permutation and rotation constants + __ evmovdquq(xmm17, Address(permsAndRots, 0), Assembler::AVX_512bit); + __ evmovdquq(xmm18, Address(permsAndRots, 64), Assembler::AVX_512bit); + __ evmovdquq(xmm19, Address(permsAndRots, 128), Assembler::AVX_512bit); + __ evmovdquq(xmm20, Address(permsAndRots, 192), Assembler::AVX_512bit); + __ evmovdquq(xmm21, Address(permsAndRots, 256), Assembler::AVX_512bit); + __ evmovdquq(xmm22, Address(permsAndRots, 320), Assembler::AVX_512bit); + __ evmovdquq(xmm23, Address(permsAndRots, 384), Assembler::AVX_512bit); + __ evmovdquq(xmm24, Address(permsAndRots, 448), Assembler::AVX_512bit); + __ evmovdquq(xmm25, Address(permsAndRots, 512), Assembler::AVX_512bit); + __ evmovdquq(xmm26, Address(permsAndRots, 576), Assembler::AVX_512bit); + __ evmovdquq(xmm27, Address(permsAndRots, 640), Assembler::AVX_512bit); + __ evmovdquq(xmm28, Address(permsAndRots, 704), Assembler::AVX_512bit); + __ evmovdquq(xmm29, Address(permsAndRots, 768), Assembler::AVX_512bit); + __ evmovdquq(xmm30, Address(permsAndRots, 832), Assembler::AVX_512bit); + __ evmovdquq(xmm31, Address(permsAndRots, 896), Assembler::AVX_512bit); + + __ BIND(sha3_loop); + + // there will be 24 keccak rounds + __ movl(roundsLeft, 24); + // load round_constants base + __ movptr(constant2use, round_consts); + + // load input: 72, 104, 136, 144 or 168 bytes + // i.e. 5+4, 2*5+3, 3*5+2, 3*5+3 or 4*5+1 longs + __ evpxorq(xmm0, k5, xmm0, Address(buf, 0), true, Assembler::AVX_512bit); + + // if(blockSize == 72) SHA3-512 + __ cmpl(block_size, 72); + __ jcc(Assembler::notEqual, block104); + __ evpxorq(xmm1, k4, xmm1, Address(buf, 40), true, Assembler::AVX_512bit); + __ jmp(rounds24_loop); + + // if(blockSize == 104) SHA3-384 + __ BIND(block104); + __ cmpl(block_size, 104); + __ jcc(Assembler::notEqual, block136); + __ evpxorq(xmm1, k5, xmm1, Address(buf, 40), true, Assembler::AVX_512bit); + __ evpxorq(xmm2, k3, xmm2, Address(buf, 80), true, Assembler::AVX_512bit); + __ jmp(rounds24_loop); + + // if(blockSize == 136) SHA3-256 and SHAKE256 + __ BIND(block136); + __ cmpl(block_size, 136); + __ jcc(Assembler::notEqual, block144); + __ evpxorq(xmm1, k5, xmm1, Address(buf, 40), true, Assembler::AVX_512bit); + __ evpxorq(xmm2, k5, xmm2, Address(buf, 80), true, Assembler::AVX_512bit); + __ evpxorq(xmm3, k2, xmm3, Address(buf, 120), true, Assembler::AVX_512bit); + __ jmp(rounds24_loop); + + // if(blockSize == 144) SHA3-224 + __ BIND(block144); + __ cmpl(block_size, 144); + __ jcc(Assembler::notEqual, block168); + __ evpxorq(xmm1, k5, xmm1, Address(buf, 40), true, Assembler::AVX_512bit); + __ evpxorq(xmm2, k5, xmm2, Address(buf, 80), true, Assembler::AVX_512bit); + __ evpxorq(xmm3, k3, xmm3, Address(buf, 120), true, Assembler::AVX_512bit); + __ jmp(rounds24_loop); + + // if(blockSize == 168) SHAKE128 + __ BIND(block168); + __ evpxorq(xmm1, k5, xmm1, Address(buf, 40), true, Assembler::AVX_512bit); + __ evpxorq(xmm2, k5, xmm2, Address(buf, 80), true, Assembler::AVX_512bit); + __ evpxorq(xmm3, k5, xmm3, Address(buf, 120), true, Assembler::AVX_512bit); + __ evpxorq(xmm4, k1, xmm4, Address(buf, 160), true, Assembler::AVX_512bit); + + // The 24 rounds of the keccak transformation. + // The implementation closely follows the Java version, with the state + // array "rows" in the lowest 5 64-bit slots of zmm0 - zmm4, i.e. + // each row of the SHA3 specification is located in one zmm register. + __ BIND(rounds24_loop); + __ subl(roundsLeft, 1); + + __ evmovdquw(xmm5, xmm0, Assembler::AVX_512bit); + // vpternlogq(x, 150, y, z) does x = x ^ y ^ z + __ vpternlogq(xmm5, 150, xmm1, xmm2, Assembler::AVX_512bit); + __ vpternlogq(xmm5, 150, xmm3, xmm4, Assembler::AVX_512bit); + // Now the "c row", i.e. c0-c4 are in zmm5. + // Rotate each element of the c row by one bit to zmm6, call the + // rotated version c'. + __ evprolq(xmm6, xmm5, 1, Assembler::AVX_512bit); + // Rotate elementwise the c row so that c4 becomes c0, + // c0 becomes c1, etc. + __ evpermt2q(xmm5, xmm30, xmm5, Assembler::AVX_512bit); + // rotate elementwise the c' row so that c'0 becomes c'4, + // c'1 becomes c'0, etc. + __ evpermt2q(xmm6, xmm31, xmm6, Assembler::AVX_512bit); + __ vpternlogq(xmm0, 150, xmm5, xmm6, Assembler::AVX_512bit); + __ vpternlogq(xmm1, 150, xmm5, xmm6, Assembler::AVX_512bit); + __ vpternlogq(xmm2, 150, xmm5, xmm6, Assembler::AVX_512bit); + __ vpternlogq(xmm3, 150, xmm5, xmm6, Assembler::AVX_512bit); + __ vpternlogq(xmm4, 150, xmm5, xmm6, Assembler::AVX_512bit); + // Now the theta mapping has been finished. + + // Do the cyclical permutation of the 24 moving state elements + // and the required rotations within each element (the combined + // rho and sigma steps). + __ evpermt2q(xmm4, xmm17, xmm3, Assembler::AVX_512bit); + __ evpermt2q(xmm3, xmm18, xmm2, Assembler::AVX_512bit); + __ evpermt2q(xmm2, xmm17, xmm1, Assembler::AVX_512bit); + __ evpermt2q(xmm1, xmm19, xmm0, Assembler::AVX_512bit); + __ evpermt2q(xmm4, xmm20, xmm2, Assembler::AVX_512bit); + // The 24 moving elements are now in zmm1, zmm3 and zmm4, + // do the rotations now. + __ evprolvq(xmm1, xmm1, xmm27, Assembler::AVX_512bit); + __ evprolvq(xmm3, xmm3, xmm28, Assembler::AVX_512bit); + __ evprolvq(xmm4, xmm4, xmm29, Assembler::AVX_512bit); + __ evmovdquw(xmm2, xmm1, Assembler::AVX_512bit); + __ evmovdquw(xmm5, xmm3, Assembler::AVX_512bit); + __ evpermt2q(xmm0, xmm21, xmm4, Assembler::AVX_512bit); + __ evpermt2q(xmm1, xmm22, xmm3, Assembler::AVX_512bit); + __ evpermt2q(xmm5, xmm22, xmm2, Assembler::AVX_512bit); + __ evmovdquw(xmm3, xmm1, Assembler::AVX_512bit); + __ evmovdquw(xmm2, xmm5, Assembler::AVX_512bit); + __ evpermt2q(xmm1, xmm23, xmm4, Assembler::AVX_512bit); + __ evpermt2q(xmm2, xmm24, xmm4, Assembler::AVX_512bit); + __ evpermt2q(xmm3, xmm25, xmm4, Assembler::AVX_512bit); + __ evpermt2q(xmm4, xmm26, xmm5, Assembler::AVX_512bit); + // The combined rho and sigma steps are done. + + // Do the chi step (the same operation on all 5 rows). + // vpternlogq(x, 180, y, z) does x = x ^ (y & ~z). + __ evpermt2q(xmm5, xmm31, xmm0, Assembler::AVX_512bit); + __ evpermt2q(xmm6, xmm31, xmm5, Assembler::AVX_512bit); + __ vpternlogq(xmm0, 180, xmm6, xmm5, Assembler::AVX_512bit); + + __ evpermt2q(xmm5, xmm31, xmm1, Assembler::AVX_512bit); + __ evpermt2q(xmm6, xmm31, xmm5, Assembler::AVX_512bit); + __ vpternlogq(xmm1, 180, xmm6, xmm5, Assembler::AVX_512bit); + + // xor the round constant into a0 (the lowest 64 bits of zmm0 + __ evpxorq(xmm0, k1, xmm0, Address(constant2use, 0), true, Assembler::AVX_512bit); + __ addptr(constant2use, 8); + + __ evpermt2q(xmm5, xmm31, xmm2, Assembler::AVX_512bit); + __ evpermt2q(xmm6, xmm31, xmm5, Assembler::AVX_512bit); + __ vpternlogq(xmm2, 180, xmm6, xmm5, Assembler::AVX_512bit); + + __ evpermt2q(xmm5, xmm31, xmm3, Assembler::AVX_512bit); + __ evpermt2q(xmm6, xmm31, xmm5, Assembler::AVX_512bit); + __ vpternlogq(xmm3, 180, xmm6, xmm5, Assembler::AVX_512bit); + + __ evpermt2q(xmm5, xmm31, xmm4, Assembler::AVX_512bit); + __ evpermt2q(xmm6, xmm31, xmm5, Assembler::AVX_512bit); + __ vpternlogq(xmm4, 180, xmm6, xmm5, Assembler::AVX_512bit); + __ cmpl(roundsLeft, 0); + __ jcc(Assembler::notEqual, rounds24_loop); + + if (multiBlock) { + __ addptr(buf, block_size); + __ addl(ofs, block_size); + __ cmpl(ofs, limit); + __ jcc(Assembler::lessEqual, sha3_loop); + __ movq(rax, ofs); // return ofs + } else { + __ xorq(rax, rax); // return 0 + } + + // store the state + __ evmovdquq(Address(state, 0), k5, xmm0, true, Assembler::AVX_512bit); + __ evmovdquq(Address(state, 40), k5, xmm1, true, Assembler::AVX_512bit); + __ evmovdquq(Address(state, 80), k5, xmm2, true, Assembler::AVX_512bit); + __ evmovdquq(Address(state, 120), k5, xmm3, true, Assembler::AVX_512bit); + __ evmovdquq(Address(state, 160), k5, xmm4, true, Assembler::AVX_512bit); + + __ pop(r14); + __ pop(r13); + __ pop(r12); + + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ ret(0); + + return start; +} diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index b7f5a2bc9127..c28afa1e44f5 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -1212,9 +1212,16 @@ void VM_Version::get_processor_features() { FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); } - if (UseSHA3Intrinsics) { - warning("Intrinsics for SHA3-224, SHA3-256, SHA3-384 and SHA3-512 crypto hash functions not available on this CPU."); - FLAG_SET_DEFAULT(UseSHA3Intrinsics, false); +#ifdef _LP64 + if (supports_evex() && supports_avx512bw()) { + if (FLAG_IS_DEFAULT(UseSHA3Intrinsics)) { + UseSHA3Intrinsics = true; + } + } else +#endif + if (UseSHA3Intrinsics) { + warning("Intrinsics for SHA3-224, SHA3-256, SHA3-384 and SHA3-512 crypto hash functions not available on this CPU."); + FLAG_SET_DEFAULT(UseSHA3Intrinsics, false); } if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) { diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index a163b864808a..5ae41609b597 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -2058,6 +2058,10 @@ void os::print_os_info(outputStream* st) { st->cr(); } + if (os::Linux::print_numa_info(st)) { + st->cr(); + } + VM_Version::print_platform_virtualization_info(st); os::Linux::print_steal_info(st); @@ -2427,6 +2431,97 @@ bool os::Linux::print_container_info(outputStream* st) { return true; } +#define SYS_DEVICES_NODE "/sys/devices/system/node" + +static size_t read_sysfs_file(const char* path, char* buf, size_t sz) { + FILE* f = os::fopen(path, "r"); + if (f == nullptr) return 0; + size_t n = fread(buf, 1, sz - 1, f); + fclose(f); + buf[n] = '\0'; + while (n > 0 && (buf[n-1] == '\n' || buf[n-1] == '\r')) buf[--n] = '\0'; + return n; +} + +static void print_numa_memory_info(outputStream* st, int node) { + char path[256]; + char line[256]; + long long mem_total = -1; + long long mem_free = -1; + os::snprintf_checked(path, sizeof(path), SYS_DEVICES_NODE "/node%d/meminfo", node); + FILE* f = os::fopen(path, "r"); + if (f == nullptr) { + return; + } + + while (fgets(line, sizeof(line), f) != nullptr) { + long long mval; + if (sscanf(line, "Node %*d MemTotal: %lld kB", &mval) == 1) mem_total = mval; + if (sscanf(line, "Node %*d MemFree: %lld kB", &mval) == 1) mem_free = mval; + } + fclose(f); + + if (mem_total >= 0) { st->print_cr("mem size: %lld kB", mem_total); } + if (mem_free >= 0) { st->print_cr("mem free: %lld kB", mem_free); } +} + +static void print_numa_cpu_list(outputStream* st, int node) { + char path[256]; + char buf[1024]; + os::snprintf_checked(path, sizeof(path), SYS_DEVICES_NODE "/node%d/cpulist", node); + if (read_sysfs_file(path, buf, sizeof(buf)) > 0) { + st->print_cr("cpus: %s", buf); + } else { + st->print_cr("cpus: (unavailable)"); + } +} + +bool os::Linux::print_numa_info(outputStream* st) { + if (!UseNUMA) { + // If NUMA optimizations are not enabled we don't print anything + return false; + } + + char buf[1024]; + if (read_sysfs_file("/sys/devices/system/node/online", buf, sizeof(buf)) > 0) { + st->print_cr("NUMA nodes online: %s", buf); + } else { + return false; + } + + bool first = true; + int node_count = 0; + + if (nindex_to_node() == nullptr) { + return false; + } + + for (int node: *nindex_to_node()) { + char nodepath[256]; + os::snprintf_checked(nodepath, sizeof(nodepath), SYS_DEVICES_NODE "/node%d", node); + DIR* currd = os::opendir(nodepath); + if (currd == nullptr) continue; + if (first) { + st->cr(); + first = false; + } + os::closedir(currd); + + st->print_cr("NUMA node %d", node); + streamIndentor si(st); + print_numa_cpu_list(st, node); + print_numa_memory_info(st, node); + node_count++; + } + + if (node_count == 0) { + return false; + } + + st->print_cr("Total NUMA node count: %d", node_count); + return true; +} + void os::Linux::print_steal_info(outputStream* st) { if (has_initial_tick_info) { CPUPerfTicks pticks; diff --git a/src/hotspot/os/linux/os_linux.hpp b/src/hotspot/os/linux/os_linux.hpp index ed6c52aade44..799d98d9a155 100644 --- a/src/hotspot/os/linux/os_linux.hpp +++ b/src/hotspot/os/linux/os_linux.hpp @@ -96,6 +96,7 @@ class os::Linux { static void print_proc_sys_info(outputStream* st); static bool print_ld_preload_file(outputStream* st); static void print_uptime_info(outputStream* st); + static bool print_numa_info(outputStream* st); public: struct CPUPerfTicks { diff --git a/src/hotspot/os/windows/os_perf_windows.cpp b/src/hotspot/os/windows/os_perf_windows.cpp index 57dcd2710c87..227564b066d0 100644 --- a/src/hotspot/os/windows/os_perf_windows.cpp +++ b/src/hotspot/os/windows/os_perf_windows.cpp @@ -780,6 +780,114 @@ static OSReturn allocate_pdh_constants() { return OS_OK; } +// Look up the PDH index by reading the English (locale 009) counter name +// registry. See KB Q287159: Using PDH APIs Correctly in a Localized Language +// for details. +static OSReturn lookup_perf_index_by_english_name(const char* english_name, + DWORD* result) { + ResourceMark rm; + + DWORD type = 0; + DWORD size = 0; + + // Determine the required buffer size + if (RegQueryValueEx(HKEY_PERFORMANCE_DATA, "Counter 009", + nullptr, &type, nullptr, &size) != ERROR_SUCCESS) { + return OS_ERR; + } + + // Since registry entries in `HKEY_PERFORMANCE_DATA` are generated on the fly, + // they could change between calls, so we can't rely just on the size returned + // by the first call. Instead, Microsoft's documentation suggests running + // these calls in a loop until the return code is no longer `ERROR_MORE_DATA`. + + char* buffer; + do { + if (size == 0) { + return OS_ERR; + } + + // When `RegQueryValueEx()` returns `ERROR_MORE_DATA`, the value in the + // callback argument is undefined, so we need to create a new variable whose + // address is passed as the callback size argument. + buffer = NEW_RESOURCE_ARRAY(char, size); + + DWORD cb_size = size; + LSTATUS status = RegQueryValueEx(HKEY_PERFORMANCE_DATA, "Counter 009", + nullptr, &type, (LPBYTE)buffer, + &cb_size); + if (status == ERROR_MORE_DATA) { + // We need to increase the buffer size. Since we don't know _how much_ to + // increase it by, we use an estimate (4096) for the increment. + DWORD increment = 4096; + if (size > MAXDWORD - increment) { + return OS_ERR; + } + size += increment; + } else if (status == ERROR_SUCCESS) { + break; + } else { + // If there was some other problem fetching this registry entry, tell the + // caller that we couldn't lookup the index. + return OS_ERR; + } + } while (true); + + if (type != REG_MULTI_SZ) { + return OS_ERR; + } + + // The buffer contains indices and names in the form (\0\0)*, so + // iterate character by character to parse the name and if it matches the + // English name, then we return the integer value of the index. + for (const char* p = buffer; *p != '\0'; ) { + const char* idx_str = p; + p += strlen(p) + 1; + if (*p == '\0') { + break; + } + + const char* name = p; + p += strlen(p) + 1; + if (strcmp(name, english_name) == 0) { + errno = 0; + char* end = nullptr; + unsigned long value = strtoul(idx_str, &end, 10); + if (errno == 0 && end != idx_str && value <= MAXDWORD) { + *result = (DWORD)value; + return OS_OK; + } + } + } + + return OS_ERR; +} + +// Return the counter index of the 'Processor Information' counter, if +// available, or else the 'Processor' counter. The former is aware of the +// possibility of multiple processor groups and thus provides a more accurate +// processor count whereas the latter serves as fallback. +static DWORD get_proc_counter() { + static DWORD pdh_idx = 0; + if (pdh_idx != 0) { + return pdh_idx; + } + + // Some APIs accept English counter names whereas others accept counter names + // in the specific user's locale. We determine the locale-specific name using + // the counter index, but to find the counter index, we use the English name + // of the counter and look for it in a specific registry key. + DWORD info_idx; + if (lookup_perf_index_by_english_name("Processor Information", + &info_idx) != OS_OK) { + info_idx = PDH_PROCESSOR_IDX; + } + + // Assign to the static variable so that the value persists across calls. + pdh_idx = info_idx; + return pdh_idx; +} + /* * Enuerate the Processor PDH object and returns a buffer containing the enumerated instances. * Caller needs ResourceMark; @@ -787,8 +895,11 @@ static OSReturn allocate_pdh_constants() { * @return buffer if successful, null on failure. */ static const char* enumerate_cpu_instances() { - char* processor; //'Processor' == PDH_PROCESSOR_IDX - if (lookup_name_by_index(PDH_PROCESSOR_IDX, &processor) != OS_OK) { + // The `PdhEnumObjectItems()` function accepts a localized name of the perf + // counter. To obtain the name that is specific to the user's locale, we + // perform a reverse lookup from counter index to counter name. + char* processor; + if (lookup_name_by_index(get_proc_counter(), &processor) != OS_OK) { return nullptr; } DWORD c_size = 0; @@ -822,13 +933,17 @@ static const char* enumerate_cpu_instances() { static int count_logical_cpus(const char* instances) { assert(instances != nullptr, "invariant"); - // count logical instances. - DWORD count; - char* tmp; - for (count = 0, tmp = const_cast(instances); *tmp != '\0'; tmp = &tmp[strlen(tmp) + 1], count++); - // PDH reports an instance for each logical processor plus an instance for the total (_Total) - assert(count == os::processor_count() + 1, "invalid enumeration!"); - return count - 1; + DWORD count = 0; + for (const char* tmp = instances; *tmp != '\0'; tmp += strlen(tmp) + 1) { + // In both the 'Processor' counter and the 'Processor Information' counter, + // the output contains totals for the processor group(s). We filter those + // out by looking for the `_Total` substring. + if (strstr(tmp, "_Total") == nullptr) { + count++; + } + } + assert(count >= 1, "invalid enumeration!"); + return count; } static int number_of_logical_cpus() { @@ -848,7 +963,16 @@ static double cpu_factor() { static double cpuFactor = .0; if (numCpus == 0) { numCpus = number_of_logical_cpus(); - assert(os::processor_count() <= (int)numCpus, "invariant"); + + // If we are using the legacy 'Processor' counter, which counts processors + // only in the first processor group, then `numCpus` can undercount, in + // which case, `numCpus` will be likely smaller than `os_processor_count`. + // However, when we use the 'Processor Information' counter, we expect both + // `numCpus` and `os::processorCount` to be identical. In both cases, we + // expect to see at least one CPU. + assert(numCpus >= 1 && numCpus <= (DWORD)os::processor_count(), + "unexpected cpu count"); + cpuFactor = numCpus * 100; } return cpuFactor; @@ -862,8 +986,8 @@ static void log_error_message_on_no_PDH_artifact(const char* counter_path) { static int initialize_cpu_query_counters(MultiCounterQueryP query, DWORD pdh_counter_idx) { assert(query != nullptr, "invariant"); assert(query->counters != nullptr, "invariant"); - char* processor; //'Processor' == PDH_PROCESSOR_IDX - if (lookup_name_by_index(PDH_PROCESSOR_IDX, &processor) != OS_OK) { + char* processor; + if (lookup_name_by_index(get_proc_counter(), &processor) != OS_OK) { return OS_ERR; } char* counter_name = nullptr; @@ -881,7 +1005,11 @@ static int initialize_cpu_query_counters(MultiCounterQueryP query, DWORD pdh_cou counter_len += OBJECT_WITH_INSTANCES_COUNTER_FMT_LEN; // "\\%s(%s)\\%s" const char* instances = enumerate_cpu_instances(); DWORD index = 0; - for (char* tmp = const_cast(instances); *tmp != '\0'; tmp = &tmp[strlen(tmp) + 1], index++) { + for (char* tmp = const_cast(instances); *tmp != '\0'; tmp = &tmp[strlen(tmp) + 1]) { + // Skip totals for each processor group. + if (strstr(tmp, ",_Total") != nullptr) { + continue; + } const size_t tmp_len = strlen(tmp); char* counter_path = NEW_RESOURCE_ARRAY(char, counter_len + tmp_len + 1); const size_t jio_snprintf_result = jio_snprintf(counter_path, @@ -897,6 +1025,7 @@ static int initialize_cpu_query_counters(MultiCounterQueryP query, DWORD pdh_cou // return OS_OK to have the system continue to run without the missing counter return OS_OK; } + index++; } // Query once to initialize the counters which require at least two samples // (like the % CPU usage) to calculate correctly. diff --git a/src/hotspot/share/c1/c1_Compiler.cpp b/src/hotspot/share/c1/c1_Compiler.cpp index 22299b4051b6..bac3a74e99e3 100644 --- a/src/hotspot/share/c1/c1_Compiler.cpp +++ b/src/hotspot/share/c1/c1_Compiler.cpp @@ -138,7 +138,7 @@ bool Compiler::is_intrinsic_supported(const methodHandle& method) { case vmIntrinsics::_arraycopy: case vmIntrinsics::_currentTimeMillis: case vmIntrinsics::_nanoTime: - case vmIntrinsics::_Reference_get: + case vmIntrinsics::_Reference_get0: // Use the intrinsic version of Reference.get() so that the value in // the referent field can be registered by the G1 pre-barrier code. // Also to prevent commoning reads from this field across safepoint diff --git a/src/hotspot/share/c1/c1_GraphBuilder.cpp b/src/hotspot/share/c1/c1_GraphBuilder.cpp index f58e69d9cfa0..517fd07d64a6 100644 --- a/src/hotspot/share/c1/c1_GraphBuilder.cpp +++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp @@ -3377,7 +3377,7 @@ GraphBuilder::GraphBuilder(Compilation* compilation, IRScope* scope) break; } - case vmIntrinsics::_Reference_get: + case vmIntrinsics::_Reference_get0: { { // With java.lang.ref.reference.get() we must go through the diff --git a/src/hotspot/share/c1/c1_LIRGenerator.cpp b/src/hotspot/share/c1/c1_LIRGenerator.cpp index dda69ef237c0..2699d840dde6 100644 --- a/src/hotspot/share/c1/c1_LIRGenerator.cpp +++ b/src/hotspot/share/c1/c1_LIRGenerator.cpp @@ -1203,7 +1203,7 @@ void LIRGenerator::do_Return(Return* x) { // Example: ref.get() // Combination of LoadField and g1 pre-write barrier -void LIRGenerator::do_Reference_get(Intrinsic* x) { +void LIRGenerator::do_Reference_get0(Intrinsic* x) { const int referent_offset = java_lang_ref_Reference::referent_offset(); @@ -3016,8 +3016,8 @@ void LIRGenerator::do_Intrinsic(Intrinsic* x) { case vmIntrinsics::_onSpinWait: __ on_spin_wait(); break; - case vmIntrinsics::_Reference_get: - do_Reference_get(x); + case vmIntrinsics::_Reference_get0: + do_Reference_get0(x); break; case vmIntrinsics::_updateCRC32: diff --git a/src/hotspot/share/c1/c1_LIRGenerator.hpp b/src/hotspot/share/c1/c1_LIRGenerator.hpp index 20101fd02dd5..6ce708ce6e6b 100644 --- a/src/hotspot/share/c1/c1_LIRGenerator.hpp +++ b/src/hotspot/share/c1/c1_LIRGenerator.hpp @@ -267,7 +267,7 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure { void do_CompareAndSwap(Intrinsic* x, ValueType* type); void do_PreconditionsCheckIndex(Intrinsic* x, BasicType type); void do_FPIntrinsics(Intrinsic* x); - void do_Reference_get(Intrinsic* x); + void do_Reference_get0(Intrinsic* x); void do_update_CRC32(Intrinsic* x); void do_update_CRC32C(Intrinsic* x); void do_vectorizedMismatch(Intrinsic* x); diff --git a/src/hotspot/share/classfile/classLoader.cpp b/src/hotspot/share/classfile/classLoader.cpp index ec340d08e9a1..78445bc0f94e 100644 --- a/src/hotspot/share/classfile/classLoader.cpp +++ b/src/hotspot/share/classfile/classLoader.cpp @@ -1463,6 +1463,10 @@ char* ClassLoader::lookup_vm_options() { jio_snprintf(modules_path, JVM_MAXPATHLEN, "%s%slib%smodules", Arguments::get_java_home(), fileSep, fileSep); JImage_file =(*JImageOpen)(modules_path, &error); if (JImage_file == nullptr) { + if (Arguments::has_jimage()) { + // The modules file exists but is unreadable or corrupt + vm_exit_during_initialization(err_msg("Unable to load %s", modules_path)); + } return nullptr; } diff --git a/src/hotspot/share/classfile/stringTable.cpp b/src/hotspot/share/classfile/stringTable.cpp index 19ac5cc7709d..679edd396713 100644 --- a/src/hotspot/share/classfile/stringTable.cpp +++ b/src/hotspot/share/classfile/stringTable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -455,6 +455,10 @@ struct StringTableDeleteCheck : StackObj { }; void StringTable::clean_dead_entries(JavaThread* jt) { + // BulkDeleteTask::prepare() may take ConcurrentHashTableResize_lock (nosafepoint-2). + // When NativeHeapTrimmer is enabled, SuspendMark may take NativeHeapTrimmer::_lock (nosafepoint). + // Take SuspendMark first to keep lock order and avoid deadlock. + NativeHeapTrimmer::SuspendMark sm("stringtable"); StringTableHash::BulkDeleteTask bdt(_local_table); if (!bdt.prepare(jt)) { return; @@ -462,7 +466,6 @@ void StringTable::clean_dead_entries(JavaThread* jt) { StringTableDeleteCheck stdc; StringTableDoDelete stdd; - NativeHeapTrimmer::SuspendMark sm("stringtable"); { TraceTime timer("Clean", TRACETIME_LOG(Debug, stringtable, perf)); while(bdt.do_task(jt, stdc, stdd)) { diff --git a/src/hotspot/share/classfile/symbolTable.cpp b/src/hotspot/share/classfile/symbolTable.cpp index 0b0377a2bb55..3e8ade0022b3 100644 --- a/src/hotspot/share/classfile/symbolTable.cpp +++ b/src/hotspot/share/classfile/symbolTable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -755,6 +755,10 @@ struct SymbolTableDeleteCheck : StackObj { }; void SymbolTable::clean_dead_entries(JavaThread* jt) { + // BulkDeleteTask::prepare() may take ConcurrentHashTableResize_lock (nosafepoint-2). + // When NativeHeapTrimmer is enabled, SuspendMark may take NativeHeapTrimmer::_lock (nosafepoint). + // Take SuspendMark first to keep lock order and avoid deadlock. + NativeHeapTrimmer::SuspendMark sm("symboltable"); SymbolTableHash::BulkDeleteTask bdt(_local_table); if (!bdt.prepare(jt)) { return; @@ -762,7 +766,6 @@ void SymbolTable::clean_dead_entries(JavaThread* jt) { SymbolTableDeleteCheck stdc; SymbolTableDoDelete stdd; - NativeHeapTrimmer::SuspendMark sm("symboltable"); { TraceTime timer("Clean", TRACETIME_LOG(Debug, symboltable, perf)); while (bdt.do_task(jt, stdc, stdd)) { diff --git a/src/hotspot/share/classfile/vmIntrinsics.cpp b/src/hotspot/share/classfile/vmIntrinsics.cpp index 578b171a5528..63cc1fa8baf8 100644 --- a/src/hotspot/share/classfile/vmIntrinsics.cpp +++ b/src/hotspot/share/classfile/vmIntrinsics.cpp @@ -94,7 +94,7 @@ bool vmIntrinsics::preserves_state(vmIntrinsics::ID id) { case vmIntrinsics::_dpow: case vmIntrinsics::_Preconditions_checkIndex: case vmIntrinsics::_Preconditions_checkLongIndex: - case vmIntrinsics::_Reference_get: + case vmIntrinsics::_Reference_get0: case vmIntrinsics::_Continuation_doYield: case vmIntrinsics::_updateCRC32: case vmIntrinsics::_updateBytesCRC32: @@ -238,7 +238,7 @@ bool vmIntrinsics::disabled_by_jvm_flags(vmIntrinsics::ID id) { case vmIntrinsics::_storeFence: case vmIntrinsics::_fullFence: case vmIntrinsics::_countPositives: - case vmIntrinsics::_Reference_get: + case vmIntrinsics::_Reference_get0: case vmIntrinsics::_Continuation_doYield: case vmIntrinsics::_Continuation_enterSpecial: break; @@ -472,6 +472,7 @@ bool vmIntrinsics::disabled_by_jvm_flags(vmIntrinsics::ID id) { case vmIntrinsics::_sha5_implCompress: if (!UseSHA512Intrinsics) return true; break; + case vmIntrinsics::_double_keccak: case vmIntrinsics::_sha3_implCompress: if (!UseSHA3Intrinsics) return true; break; @@ -484,6 +485,13 @@ bool vmIntrinsics::disabled_by_jvm_flags(vmIntrinsics::ID id) { case vmIntrinsics::_chacha20Block: if (!UseChaCha20Intrinsics) return true; break; + case vmIntrinsics::_dilithiumAlmostNtt: + case vmIntrinsics::_dilithiumAlmostInverseNtt: + case vmIntrinsics::_dilithiumNttMult: + case vmIntrinsics::_dilithiumMontMulByConstant: + case vmIntrinsics::_dilithiumDecomposePoly: + if (!UseDilithiumIntrinsics) return true; + break; case vmIntrinsics::_base64_encodeBlock: case vmIntrinsics::_base64_decodeBlock: if (!UseBASE64Intrinsics) return true; diff --git a/src/hotspot/share/classfile/vmIntrinsics.hpp b/src/hotspot/share/classfile/vmIntrinsics.hpp index 15ad554d8ec5..2c4b9da5bc2d 100644 --- a/src/hotspot/share/classfile/vmIntrinsics.hpp +++ b/src/hotspot/share/classfile/vmIntrinsics.hpp @@ -458,7 +458,7 @@ class methodHandle; do_signature(vectorizedMismatch_signature, "(Ljava/lang/Object;JLjava/lang/Object;JII)I") \ \ /* java/lang/ref/Reference */ \ - do_intrinsic(_Reference_get, java_lang_ref_Reference, get_name, void_object_signature, F_R) \ + do_intrinsic(_Reference_get0, java_lang_ref_Reference, get0_name, void_object_signature, F_RN) \ do_intrinsic(_Reference_refersTo0, java_lang_ref_Reference, refersTo0_name, object_boolean_signature, F_RN) \ do_intrinsic(_PhantomReference_refersTo0, java_lang_ref_PhantomReference, refersTo0_name, object_boolean_signature, F_RN) \ \ @@ -514,6 +514,12 @@ class methodHandle; do_class(sun_security_provider_sha3, "sun/security/provider/SHA3") \ do_intrinsic(_sha3_implCompress, sun_security_provider_sha3, implCompress_name, implCompress_signature, F_R) \ \ + /* support for sun.security.provider.SHAKE128Parallel */ \ + do_class(sun_security_provider_sha3_parallel, "sun/security/provider/SHA3Parallel") \ + do_intrinsic(_double_keccak, sun_security_provider_sha3_parallel, double_keccak_name, double_keccak_signature, F_S) \ + do_name( double_keccak_name, "doubleKeccak") \ + do_signature(double_keccak_signature, "([J[J)I") \ + \ /* support for sun.security.provider.DigestBase */ \ do_class(sun_security_provider_digestbase, "sun/security/provider/DigestBase") \ do_intrinsic(_digestBase_implCompressMB, sun_security_provider_digestbase, implCompressMB_name, countPositives_signature, F_R) \ @@ -548,6 +554,26 @@ class methodHandle; do_name(chacha20Block_name, "implChaCha20Block") \ do_signature(chacha20Block_signature, "([I[B)I") \ \ + /* support for sun.security.provider.ML_DSA */ \ + do_class(sun_security_provider_ML_DSA, "sun/security/provider/ML_DSA") \ + do_signature(IaII_signature, "([II)I") \ + do_signature(IaIaI_signature, "([I[I)I") \ + do_signature(IaIaIaI_signature, "([I[I[I)I") \ + do_signature(IaIaIaIII_signature, "([I[I[III)I") \ + do_intrinsic(_dilithiumAlmostNtt, sun_security_provider_ML_DSA, dilithiumAlmostNtt_name, IaIaI_signature, F_S) \ + do_name(dilithiumAlmostNtt_name, "implDilithiumAlmostNtt") \ + do_intrinsic(_dilithiumAlmostInverseNtt, sun_security_provider_ML_DSA, \ + dilithiumAlmostInverseNtt_name, IaIaI_signature, F_S) \ + do_name(dilithiumAlmostInverseNtt_name, "implDilithiumAlmostInverseNtt") \ + do_intrinsic(_dilithiumNttMult, sun_security_provider_ML_DSA, dilithiumNttMult_name, IaIaIaI_signature, F_S) \ + do_name(dilithiumNttMult_name, "implDilithiumNttMult") \ + do_intrinsic(_dilithiumMontMulByConstant, sun_security_provider_ML_DSA, \ + dilithiumMontMulByConstant_name, IaII_signature, F_S) \ + do_name(dilithiumMontMulByConstant_name, "implDilithiumMontMulByConstant") \ + do_intrinsic(_dilithiumDecomposePoly, sun_security_provider_ML_DSA, \ + dilithiumDecomposePoly_name, IaIaIaIII_signature, F_S) \ + do_name(dilithiumDecomposePoly_name, "implDilithiumDecomposePoly") \ + \ /* support for java.util.zip */ \ do_class(java_util_zip_CRC32, "java/util/zip/CRC32") \ do_intrinsic(_updateCRC32, java_util_zip_CRC32, update_name, int2_int_signature, F_SN) \ diff --git a/src/hotspot/share/classfile/vmSymbols.hpp b/src/hotspot/share/classfile/vmSymbols.hpp index ba4dd72408be..82a79effb2c6 100644 --- a/src/hotspot/share/classfile/vmSymbols.hpp +++ b/src/hotspot/share/classfile/vmSymbols.hpp @@ -441,7 +441,7 @@ template(cs_name, "cs") \ template(refStack_name, "refStack") \ template(refSP_name, "refSP") \ - template(get_name, "get") \ + template(get0_name, "get0") \ template(refersTo0_name, "refersTo0") \ template(put_name, "put") \ template(type_name, "type") \ diff --git a/src/hotspot/share/include/jvm.h b/src/hotspot/share/include/jvm.h index 73e29bcf2006..ae554f2091c0 100644 --- a/src/hotspot/share/include/jvm.h +++ b/src/hotspot/share/include/jvm.h @@ -357,6 +357,9 @@ JVM_HasReferencePendingList(JNIEnv *env); JNIEXPORT void JNICALL JVM_WaitForReferencePendingList(JNIEnv *env); +JNIEXPORT jobject JNICALL +JVM_ReferenceGet(JNIEnv *env, jobject ref); + JNIEXPORT jboolean JNICALL JVM_ReferenceRefersTo(JNIEnv *env, jobject ref, jobject o); diff --git a/src/hotspot/share/interpreter/abstractInterpreter.cpp b/src/hotspot/share/interpreter/abstractInterpreter.cpp index 2883630c37de..939e6afc0839 100644 --- a/src/hotspot/share/interpreter/abstractInterpreter.cpp +++ b/src/hotspot/share/interpreter/abstractInterpreter.cpp @@ -147,7 +147,7 @@ AbstractInterpreter::MethodKind AbstractInterpreter::method_kind(const methodHan case vmIntrinsics::_fmaF: return java_lang_math_fmaF; case vmIntrinsics::_dsqrt: return java_lang_math_sqrt; case vmIntrinsics::_dsqrt_strict: return java_lang_math_sqrt_strict; - case vmIntrinsics::_Reference_get: return java_lang_ref_reference_get; + case vmIntrinsics::_Reference_get0: return java_lang_ref_reference_get0; case vmIntrinsics::_Object_init: if (RegisterFinalizersAtInit && m->code_size() == 1) { // We need to execute the special return bytecode to check for @@ -207,7 +207,7 @@ vmIntrinsics::ID AbstractInterpreter::method_intrinsic(MethodKind kind) { case java_lang_math_exp : return vmIntrinsics::_dexp; case java_lang_math_fmaD : return vmIntrinsics::_fmaD; case java_lang_math_fmaF : return vmIntrinsics::_fmaF; - case java_lang_ref_reference_get: return vmIntrinsics::_Reference_get; + case java_lang_ref_reference_get0: return vmIntrinsics::_Reference_get0; case java_util_zip_CRC32_update : return vmIntrinsics::_updateCRC32; case java_util_zip_CRC32_updateBytes : return vmIntrinsics::_updateBytesCRC32; @@ -323,7 +323,7 @@ void AbstractInterpreter::print_method_kind(MethodKind kind) { case java_util_zip_CRC32_updateByteBuffer : tty->print("java_util_zip_CRC32_updateByteBuffer"); break; case java_util_zip_CRC32C_updateBytes : tty->print("java_util_zip_CRC32C_updateBytes"); break; case java_util_zip_CRC32C_updateDirectByteBuffer: tty->print("java_util_zip_CRC32C_updateDirectByteByffer"); break; - case java_lang_ref_reference_get : tty->print("java_lang_ref_reference_get"); break; + case java_lang_ref_reference_get0 : tty->print("java_lang_ref_reference_get0"); break; case java_lang_Thread_currentThread : tty->print("java_lang_Thread_currentThread"); break; case java_lang_Float_intBitsToFloat : tty->print("java_lang_Float_intBitsToFloat"); break; case java_lang_Float_floatToRawIntBits : tty->print("java_lang_Float_floatToRawIntBits"); break; diff --git a/src/hotspot/share/interpreter/abstractInterpreter.hpp b/src/hotspot/share/interpreter/abstractInterpreter.hpp index e487b152b76e..6805bfe25f69 100644 --- a/src/hotspot/share/interpreter/abstractInterpreter.hpp +++ b/src/hotspot/share/interpreter/abstractInterpreter.hpp @@ -81,7 +81,7 @@ class AbstractInterpreter: AllStatic { java_lang_math_exp, // implementation of java.lang.Math.exp (x) java_lang_math_fmaF, // implementation of java.lang.Math.fma (x, y, z) java_lang_math_fmaD, // implementation of java.lang.Math.fma (x, y, z) - java_lang_ref_reference_get, // implementation of java.lang.ref.Reference.get() + java_lang_ref_reference_get0, // implementation of java.lang.ref.Reference.get() java_util_zip_CRC32_update, // implementation of java.util.zip.CRC32.update() java_util_zip_CRC32_updateBytes, // implementation of java.util.zip.CRC32.updateBytes() java_util_zip_CRC32_updateByteBuffer, // implementation of java.util.zip.CRC32.updateByteBuffer() diff --git a/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp b/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp index 9cd6f5ceffbe..372e89ecb334 100644 --- a/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp +++ b/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp @@ -201,7 +201,7 @@ void TemplateInterpreterGenerator::generate_all() { method_entry(java_lang_math_pow ) method_entry(java_lang_math_fmaF ) method_entry(java_lang_math_fmaD ) - method_entry(java_lang_ref_reference_get) + method_entry(java_lang_ref_reference_get0) AbstractInterpreter::initialize_method_handle_entries(); method_entry(java_util_zip_CRC32C_updateBytes) @@ -225,6 +225,7 @@ void TemplateInterpreterGenerator::generate_all() { // entries for `native` methods to use the same address in case // intrinsic is disabled. native_method_entry(java_lang_Thread_currentThread) + native_method_entry(java_lang_ref_reference_get0) native_method_entry(java_util_zip_CRC32_update) native_method_entry(java_util_zip_CRC32_updateBytes) @@ -467,7 +468,7 @@ address TemplateInterpreterGenerator::generate_intrinsic_entry(AbstractInterpret case Interpreter::java_lang_math_fmaF : entry_point = generate_math_entry(kind); break; case Interpreter::java_lang_math_sqrt_strict : entry_point = generate_math_entry(Interpreter::java_lang_math_sqrt); break; - case Interpreter::java_lang_ref_reference_get + case Interpreter::java_lang_ref_reference_get0 : entry_point = generate_Reference_get_entry(); break; case Interpreter::java_util_zip_CRC32_update : entry_point = generate_CRC32_update_entry(); break; diff --git a/src/hotspot/share/interpreter/zero/zeroInterpreterGenerator.cpp b/src/hotspot/share/interpreter/zero/zeroInterpreterGenerator.cpp index e08d9553c3e0..56cdf4505c8c 100644 --- a/src/hotspot/share/interpreter/zero/zeroInterpreterGenerator.cpp +++ b/src/hotspot/share/interpreter/zero/zeroInterpreterGenerator.cpp @@ -63,7 +63,7 @@ void ZeroInterpreterGenerator::generate_all() { method_entry(java_lang_math_exp ); method_entry(java_lang_math_fmaD ); method_entry(java_lang_math_fmaF ); - method_entry(java_lang_ref_reference_get); + method_entry(java_lang_ref_reference_get0); AbstractInterpreter::initialize_method_handle_entries(); @@ -104,7 +104,7 @@ address ZeroInterpreterGenerator::generate_method_entry( case Interpreter::java_lang_math_exp : // fall thru case Interpreter::java_lang_math_fmaD : // fall thru case Interpreter::java_lang_math_fmaF : entry_point = generate_math_entry(kind); break; - case Interpreter::java_lang_ref_reference_get + case Interpreter::java_lang_ref_reference_get0 : entry_point = generate_Reference_get_entry(); break; default: fatal("unexpected method kind: %d", kind); diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index a4195a04f186..b058f31fec9b 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -350,7 +350,13 @@ static_field(StubRoutines, _sha512_implCompress, address) \ static_field(StubRoutines, _sha512_implCompressMB, address) \ static_field(StubRoutines, _sha3_implCompress, address) \ + static_field(StubRoutines, _double_keccak, address) \ static_field(StubRoutines, _sha3_implCompressMB, address) \ + static_field(StubRoutines, _dilithiumAlmostNtt, address) \ + static_field(StubRoutines, _dilithiumAlmostInverseNtt, address) \ + static_field(StubRoutines, _dilithiumNttMult, address) \ + static_field(StubRoutines, _dilithiumMontMulByConstant, address) \ + static_field(StubRoutines, _dilithiumDecomposePoly, address) \ static_field(StubRoutines, _updateBytesCRC32, address) \ static_field(StubRoutines, _crc_table_adr, address) \ static_field(StubRoutines, _crc32c_table_addr, address) \ diff --git a/src/hotspot/share/opto/c2compiler.cpp b/src/hotspot/share/opto/c2compiler.cpp index 9e27ff17d9e1..eb9cd8e95402 100644 --- a/src/hotspot/share/opto/c2compiler.cpp +++ b/src/hotspot/share/opto/c2compiler.cpp @@ -706,7 +706,7 @@ bool C2Compiler::is_intrinsic_supported(const methodHandle& method) { case vmIntrinsics::_doubleToRawLongBits: case vmIntrinsics::_doubleToLongBits: case vmIntrinsics::_longBitsToDouble: - case vmIntrinsics::_Reference_get: + case vmIntrinsics::_Reference_get0: case vmIntrinsics::_Reference_refersTo0: case vmIntrinsics::_PhantomReference_refersTo0: case vmIntrinsics::_Class_cast: @@ -723,6 +723,7 @@ bool C2Compiler::is_intrinsic_supported(const methodHandle& method) { case vmIntrinsics::_sha2_implCompress: case vmIntrinsics::_sha5_implCompress: case vmIntrinsics::_sha3_implCompress: + case vmIntrinsics::_double_keccak: case vmIntrinsics::_digestBase_implCompressMB: case vmIntrinsics::_multiplyToLen: case vmIntrinsics::_squareToLen: @@ -734,6 +735,11 @@ bool C2Compiler::is_intrinsic_supported(const methodHandle& method) { case vmIntrinsics::_vectorizedMismatch: case vmIntrinsics::_ghash_processBlocks: case vmIntrinsics::_chacha20Block: + case vmIntrinsics::_dilithiumAlmostNtt: + case vmIntrinsics::_dilithiumAlmostInverseNtt: + case vmIntrinsics::_dilithiumNttMult: + case vmIntrinsics::_dilithiumMontMulByConstant: + case vmIntrinsics::_dilithiumDecomposePoly: case vmIntrinsics::_base64_encodeBlock: case vmIntrinsics::_base64_decodeBlock: case vmIntrinsics::_poly1305_processBlocks: diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index b83464783d12..e47a4daf833c 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -748,19 +748,9 @@ Compile::Compile( ciEnv* ci_env, ciMethod* target, int osr_bci, StartNode* s = new StartNode(root(), tf()->domain()); initial_gvn()->set_type_bottom(s); init_start(s); - if (method()->intrinsic_id() == vmIntrinsics::_Reference_get) { - // With java.lang.ref.reference.get() we must go through the - // intrinsic - even when get() is the root - // method of the compile - so that, if necessary, the value in - // the referent field of the reference object gets recorded by - // the pre-barrier code. - cg = find_intrinsic(method(), false); - } - if (cg == nullptr) { - float past_uses = method()->interpreter_invocation_count(); - float expected_uses = past_uses; - cg = CallGenerator::for_inline(method(), expected_uses); - } + float past_uses = method()->interpreter_invocation_count(); + float expected_uses = past_uses; + cg = CallGenerator::for_inline(method(), expected_uses); } if (failing()) return; if (cg == nullptr) { diff --git a/src/hotspot/share/opto/escape.cpp b/src/hotspot/share/opto/escape.cpp index 190b3ae75510..f71b43ed1525 100644 --- a/src/hotspot/share/opto/escape.cpp +++ b/src/hotspot/share/opto/escape.cpp @@ -1172,6 +1172,11 @@ void ConnectionGraph::process_call_arguments(CallNode *call) { strcmp(call->as_CallLeaf()->_name, "poly1305_processBlocks") == 0 || strcmp(call->as_CallLeaf()->_name, "ghash_processBlocks") == 0 || strcmp(call->as_CallLeaf()->_name, "chacha20Block") == 0 || + strcmp(call->as_CallLeaf()->_name, "dilithiumAlmostNtt") == 0 || + strcmp(call->as_CallLeaf()->_name, "dilithiumAlmostInverseNtt") == 0 || + strcmp(call->as_CallLeaf()->_name, "dilithiumNttMult") == 0 || + strcmp(call->as_CallLeaf()->_name, "dilithiumMontMulByConstant") == 0 || + strcmp(call->as_CallLeaf()->_name, "dilithiumDecomposePoly") == 0 || strcmp(call->as_CallLeaf()->_name, "encodeBlock") == 0 || strcmp(call->as_CallLeaf()->_name, "decodeBlock") == 0 || strcmp(call->as_CallLeaf()->_name, "md5_implCompress") == 0 || @@ -1183,6 +1188,7 @@ void ConnectionGraph::process_call_arguments(CallNode *call) { strcmp(call->as_CallLeaf()->_name, "sha512_implCompress") == 0 || strcmp(call->as_CallLeaf()->_name, "sha512_implCompressMB") == 0 || strcmp(call->as_CallLeaf()->_name, "sha3_implCompress") == 0 || + strcmp(call->as_CallLeaf()->_name, "double_keccak") == 0 || strcmp(call->as_CallLeaf()->_name, "sha3_implCompressMB") == 0 || strcmp(call->as_CallLeaf()->_name, "multiplyToLen") == 0 || strcmp(call->as_CallLeaf()->_name, "squareToLen") == 0 || diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index 8c892c3acb26..a2f341826ce9 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -568,7 +568,7 @@ bool LibraryCallKit::try_to_inline(int predicate) { case vmIntrinsics::_getCallerClass: return inline_native_Reflection_getCallerClass(); - case vmIntrinsics::_Reference_get: return inline_reference_get(); + case vmIntrinsics::_Reference_get0: return inline_reference_get0(); case vmIntrinsics::_Reference_refersTo0: return inline_reference_refersTo0(false); case vmIntrinsics::_PhantomReference_refersTo0: return inline_reference_refersTo0(true); @@ -597,6 +597,8 @@ bool LibraryCallKit::try_to_inline(int predicate) { case vmIntrinsics::_sha5_implCompress: case vmIntrinsics::_sha3_implCompress: return inline_digestBase_implCompress(intrinsic_id()); + case vmIntrinsics::_double_keccak: + return inline_double_keccak(); case vmIntrinsics::_digestBase_implCompressMB: return inline_digestBase_implCompressMB(predicate); @@ -627,6 +629,16 @@ bool LibraryCallKit::try_to_inline(int predicate) { return inline_ghash_processBlocks(); case vmIntrinsics::_chacha20Block: return inline_chacha20Block(); + case vmIntrinsics::_dilithiumAlmostNtt: + return inline_dilithiumAlmostNtt(); + case vmIntrinsics::_dilithiumAlmostInverseNtt: + return inline_dilithiumAlmostInverseNtt(); + case vmIntrinsics::_dilithiumNttMult: + return inline_dilithiumNttMult(); + case vmIntrinsics::_dilithiumMontMulByConstant: + return inline_dilithiumMontMulByConstant(); + case vmIntrinsics::_dilithiumDecomposePoly: + return inline_dilithiumDecomposePoly(); case vmIntrinsics::_base64_encodeBlock: return inline_base64_encodeBlock(); case vmIntrinsics::_base64_decodeBlock: @@ -6554,9 +6566,9 @@ bool LibraryCallKit::inline_updateByteBufferAdler32() { return true; } -//----------------------------inline_reference_get---------------------------- +//----------------------------inline_reference_get0---------------------------- // public T java.lang.ref.Reference.get(); -bool LibraryCallKit::inline_reference_get() { +bool LibraryCallKit::inline_reference_get0() { const int referent_offset = java_lang_ref_Reference::referent_offset(); // Get the argument: @@ -7258,6 +7270,176 @@ bool LibraryCallKit::inline_chacha20Block() { return true; } +//------------------------------inline_dilithiumAlmostNtt +bool LibraryCallKit::inline_dilithiumAlmostNtt() { + address stubAddr; + const char *stubName; + assert(UseDilithiumIntrinsics, "need Dilithium intrinsics support"); + assert(callee()->signature()->size() == 2, "dilithiumAlmostNtt has 2 parameters"); + + stubAddr = StubRoutines::dilithiumAlmostNtt(); + stubName = "dilithiumAlmostNtt"; + if (!stubAddr) return false; + + Node* coeffs = argument(0); + Node* ntt_zetas = argument(1); + + coeffs = must_be_not_null(coeffs, true); + ntt_zetas = must_be_not_null(ntt_zetas, true); + + Node* coeffs_start = array_element_address(coeffs, intcon(0), T_INT); + assert(coeffs_start, "coeffs is null"); + Node* ntt_zetas_start = array_element_address(ntt_zetas, intcon(0), T_INT); + assert(ntt_zetas_start, "ntt_zetas is null"); + Node* dilithiumAlmostNtt = make_runtime_call(RC_LEAF|RC_NO_FP, + OptoRuntime::dilithiumAlmostNtt_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + coeffs_start, ntt_zetas_start); + // return an int + Node* retvalue = _gvn.transform(new ProjNode(dilithiumAlmostNtt, TypeFunc::Parms)); + set_result(retvalue); + return true; +} + +//------------------------------inline_dilithiumAlmostInverseNtt +bool LibraryCallKit::inline_dilithiumAlmostInverseNtt() { + address stubAddr; + const char *stubName; + assert(UseDilithiumIntrinsics, "need Dilithium intrinsics support"); + assert(callee()->signature()->size() == 2, "dilithiumAlmostInverseNtt has 2 parameters"); + + stubAddr = StubRoutines::dilithiumAlmostInverseNtt(); + stubName = "dilithiumAlmostInverseNtt"; + if (!stubAddr) return false; + + Node* coeffs = argument(0); + Node* zetas = argument(1); + + coeffs = must_be_not_null(coeffs, true); + zetas = must_be_not_null(zetas, true); + + Node* coeffs_start = array_element_address(coeffs, intcon(0), T_INT); + assert(coeffs_start, "coeffs is null"); + Node* zetas_start = array_element_address(zetas, intcon(0), T_INT); + assert(zetas_start, "inverseNtt_zetas is null"); + Node* dilithiumAlmostInverseNtt = make_runtime_call(RC_LEAF|RC_NO_FP, + OptoRuntime::dilithiumAlmostInverseNtt_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + coeffs_start, zetas_start); + + // return an int + Node* retvalue = _gvn.transform(new ProjNode(dilithiumAlmostInverseNtt, TypeFunc::Parms)); + set_result(retvalue); + return true; +} + +//------------------------------inline_dilithiumNttMult +bool LibraryCallKit::inline_dilithiumNttMult() { + address stubAddr; + const char *stubName; + assert(UseDilithiumIntrinsics, "need Dilithium intrinsics support"); + assert(callee()->signature()->size() == 3, "dilithiumNttMult has 3 parameters"); + + stubAddr = StubRoutines::dilithiumNttMult(); + stubName = "dilithiumNttMult"; + if (!stubAddr) return false; + + Node* result = argument(0); + Node* ntta = argument(1); + Node* nttb = argument(2); + + result = must_be_not_null(result, true); + ntta = must_be_not_null(ntta, true); + nttb = must_be_not_null(nttb, true); + + Node* result_start = array_element_address(result, intcon(0), T_INT); + assert(result_start, "result is null"); + Node* ntta_start = array_element_address(ntta, intcon(0), T_INT); + assert(ntta_start, "ntta is null"); + Node* nttb_start = array_element_address(nttb, intcon(0), T_INT); + assert(nttb_start, "nttb is null"); + Node* dilithiumNttMult = make_runtime_call(RC_LEAF|RC_NO_FP, + OptoRuntime::dilithiumNttMult_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + result_start, ntta_start, nttb_start); + + // return an int + Node* retvalue = _gvn.transform(new ProjNode(dilithiumNttMult, TypeFunc::Parms)); + set_result(retvalue); + + return true; +} + +//------------------------------inline_dilithiumMontMulByConstant +bool LibraryCallKit::inline_dilithiumMontMulByConstant() { + address stubAddr; + const char *stubName; + assert(UseDilithiumIntrinsics, "need Dilithium intrinsics support"); + assert(callee()->signature()->size() == 2, "dilithiumMontMulByConstant has 2 parameters"); + + stubAddr = StubRoutines::dilithiumMontMulByConstant(); + stubName = "dilithiumMontMulByConstant"; + if (!stubAddr) return false; + + Node* coeffs = argument(0); + Node* constant = argument(1); + + coeffs = must_be_not_null(coeffs, true); + + Node* coeffs_start = array_element_address(coeffs, intcon(0), T_INT); + assert(coeffs_start, "coeffs is null"); + Node* dilithiumMontMulByConstant = make_runtime_call(RC_LEAF|RC_NO_FP, + OptoRuntime::dilithiumMontMulByConstant_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + coeffs_start, constant); + + // return an int + Node* retvalue = _gvn.transform(new ProjNode(dilithiumMontMulByConstant, TypeFunc::Parms)); + set_result(retvalue); + return true; +} + + +//------------------------------inline_dilithiumDecomposePoly +bool LibraryCallKit::inline_dilithiumDecomposePoly() { + address stubAddr; + const char *stubName; + assert(UseDilithiumIntrinsics, "need Dilithium intrinsics support"); + assert(callee()->signature()->size() == 5, "dilithiumDecomposePoly has 5 parameters"); + + stubAddr = StubRoutines::dilithiumDecomposePoly(); + stubName = "dilithiumDecomposePoly"; + if (!stubAddr) return false; + + Node* input = argument(0); + Node* lowPart = argument(1); + Node* highPart = argument(2); + Node* twoGamma2 = argument(3); + Node* multiplier = argument(4); + + input = must_be_not_null(input, true); + lowPart = must_be_not_null(lowPart, true); + highPart = must_be_not_null(highPart, true); + + Node* input_start = array_element_address(input, intcon(0), T_INT); + assert(input_start, "input is null"); + Node* lowPart_start = array_element_address(lowPart, intcon(0), T_INT); + assert(lowPart_start, "lowPart is null"); + Node* highPart_start = array_element_address(highPart, intcon(0), T_INT); + assert(highPart_start, "highPart is null"); + + Node* dilithiumDecomposePoly = make_runtime_call(RC_LEAF|RC_NO_FP, + OptoRuntime::dilithiumDecomposePoly_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + input_start, lowPart_start, highPart_start, + twoGamma2, multiplier); + + // return an int + Node* retvalue = _gvn.transform(new ProjNode(dilithiumDecomposePoly, TypeFunc::Parms)); + set_result(retvalue); + return true; +} + bool LibraryCallKit::inline_base64_encodeBlock() { address stubAddr; const char *stubName; @@ -7430,7 +7612,7 @@ bool LibraryCallKit::inline_digestBase_implCompress(vmIntrinsics::ID id) { break; case vmIntrinsics::_sha3_implCompress: assert(UseSHA3Intrinsics, "need SHA3 instruction support"); - state = get_state_from_digest_object(digestBase_obj, T_BYTE); + state = get_state_from_digest_object(digestBase_obj, T_LONG); stubAddr = StubRoutines::sha3_implCompress(); stubName = "sha3_implCompress"; block_size = get_block_size_from_digest_object(digestBase_obj); @@ -7460,6 +7642,38 @@ bool LibraryCallKit::inline_digestBase_implCompress(vmIntrinsics::ID id) { return true; } +//------------------------------inline_double_keccak +bool LibraryCallKit::inline_double_keccak() { + address stubAddr; + const char *stubName; + assert(UseSHA3Intrinsics, "need SHA3 intrinsics support"); + assert(callee()->signature()->size() == 2, "double_keccak has 2 parameters"); + + stubAddr = StubRoutines::double_keccak(); + stubName = "double_keccak"; + if (!stubAddr) return false; + + Node* status0 = argument(0); + Node* status1 = argument(1); + + status0 = must_be_not_null(status0, true); + status1 = must_be_not_null(status1, true); + + Node* status0_start = array_element_address(status0, intcon(0), T_LONG); + assert(status0_start, "status0 is null"); + Node* status1_start = array_element_address(status1, intcon(0), T_LONG); + assert(status1_start, "status1 is null"); + Node* double_keccak = make_runtime_call(RC_LEAF|RC_NO_FP, + OptoRuntime::double_keccak_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + status0_start, status1_start); + // return an int + Node* retvalue = _gvn.transform(new ProjNode(double_keccak, TypeFunc::Parms)); + set_result(retvalue); + return true; +} + + //------------------------------inline_digestBase_implCompressMB----------------------- // // Calculate MD5/SHA/SHA2/SHA5/SHA3 for multi-block byte[] array. @@ -7530,7 +7744,7 @@ bool LibraryCallKit::inline_digestBase_implCompressMB(int predicate) { klass_digestBase_name = "sun/security/provider/SHA3"; stub_name = "sha3_implCompressMB"; stub_addr = StubRoutines::sha3_implCompressMB(); - elem_type = T_BYTE; + elem_type = T_LONG; } break; default: diff --git a/src/hotspot/share/opto/library_call.hpp b/src/hotspot/share/opto/library_call.hpp index f714625a4df4..5449d2f6d590 100644 --- a/src/hotspot/share/opto/library_call.hpp +++ b/src/hotspot/share/opto/library_call.hpp @@ -288,7 +288,7 @@ class LibraryCallKit : public GraphKit { bool inline_bitshuffle_methods(vmIntrinsics::ID id); bool inline_compare_unsigned(vmIntrinsics::ID id); bool inline_divmod_methods(vmIntrinsics::ID id); - bool inline_reference_get(); + bool inline_reference_get0(); bool inline_reference_refersTo0(bool is_phantom); bool inline_Class_cast(); bool inline_aescrypt_Block(vmIntrinsics::ID id); @@ -301,10 +301,16 @@ class LibraryCallKit : public GraphKit { Node* get_key_start_from_aescrypt_object(Node* aescrypt_object); bool inline_ghash_processBlocks(); bool inline_chacha20Block(); + bool inline_dilithiumAlmostNtt(); + bool inline_dilithiumAlmostInverseNtt(); + bool inline_dilithiumNttMult(); + bool inline_dilithiumMontMulByConstant(); + bool inline_dilithiumDecomposePoly(); bool inline_base64_encodeBlock(); bool inline_base64_decodeBlock(); bool inline_poly1305_processBlocks(); bool inline_digestBase_implCompress(vmIntrinsics::ID id); + bool inline_double_keccak(); bool inline_digestBase_implCompressMB(int predicate); bool inline_digestBase_implCompressMB(Node* digestBaseObj, ciInstanceKlass* instklass, BasicType elem_type, address stubAddr, const char *stubName, diff --git a/src/hotspot/share/opto/runtime.cpp b/src/hotspot/share/opto/runtime.cpp index bb79da326224..66e7e28db99c 100644 --- a/src/hotspot/share/opto/runtime.cpp +++ b/src/hotspot/share/opto/runtime.cpp @@ -1081,6 +1081,25 @@ const TypeFunc* OptoRuntime::digestBase_implCompressMB_Type(bool is_sha3) { return TypeFunc::make(domain, range); } +// SHAKE128Parallel doubleKeccak function +const TypeFunc* OptoRuntime::double_keccak_Type() { + int argcnt = 2; + + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypePtr::NOTNULL; // status0 + fields[argp++] = TypePtr::NOTNULL; // status1 + + assert(argp == TypeFunc::Parms + argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms + argcnt, fields); + + // result type needed + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms + 0] = TypeInt::INT; + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms + 1, fields); + return TypeFunc::make(domain, range); +} + const TypeFunc* OptoRuntime::multiplyToLen_Type() { // create input type (domain) int num_args = 6; @@ -1270,6 +1289,105 @@ const TypeFunc* OptoRuntime::chacha20Block_Type() { return TypeFunc::make(domain, range); } +// Dilithium NTT function except for the final "normalization" to |coeff| < Q +const TypeFunc* OptoRuntime::dilithiumAlmostNtt_Type() { + int argcnt = 2; + + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypePtr::NOTNULL; // coeffs + fields[argp++] = TypePtr::NOTNULL; // NTT zetas + + assert(argp == TypeFunc::Parms + argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms + argcnt, fields); + + // result type needed + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms + 0] = TypeInt::INT; + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms + 1, fields); + return TypeFunc::make(domain, range); +} + +// Dilithium inverse NTT function except the final mod Q division by 2^256 +const TypeFunc* OptoRuntime::dilithiumAlmostInverseNtt_Type() { + int argcnt = 2; + + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypePtr::NOTNULL; // coeffs + fields[argp++] = TypePtr::NOTNULL; // inverse NTT zetas + + assert(argp == TypeFunc::Parms + argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms + argcnt, fields); + + // result type needed + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms + 0] = TypeInt::INT; + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms + 1, fields); + return TypeFunc::make(domain, range); +} + +// Dilithium NTT multiply function +const TypeFunc* OptoRuntime::dilithiumNttMult_Type() { + int argcnt = 3; + + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypePtr::NOTNULL; // result + fields[argp++] = TypePtr::NOTNULL; // ntta + fields[argp++] = TypePtr::NOTNULL; // nttb + + assert(argp == TypeFunc::Parms + argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms + argcnt, fields); + + // result type needed + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms + 0] = TypeInt::INT; + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms + 1, fields); + return TypeFunc::make(domain, range); +} + +// Dilithium Montgomery multiply a polynome coefficient array by a constant +const TypeFunc* OptoRuntime::dilithiumMontMulByConstant_Type() { + int argcnt = 2; + + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypePtr::NOTNULL; // coeffs + fields[argp++] = TypeInt::INT; // constant multiplier + + assert(argp == TypeFunc::Parms + argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms + argcnt, fields); + + // result type needed + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms + 0] = TypeInt::INT; + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms + 1, fields); + return TypeFunc::make(domain, range); +} + +// Dilithium decompose polynomial +const TypeFunc* OptoRuntime::dilithiumDecomposePoly_Type() { + int argcnt = 5; + + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypePtr::NOTNULL; // input + fields[argp++] = TypePtr::NOTNULL; // lowPart + fields[argp++] = TypePtr::NOTNULL; // highPart + fields[argp++] = TypeInt::INT; // 2 * gamma2 + fields[argp++] = TypeInt::INT; // multiplier + + assert(argp == TypeFunc::Parms + argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms + argcnt, fields); + + // result type needed + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms + 0] = TypeInt::INT; + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms + 1, fields); + return TypeFunc::make(domain, range); +} + // Base64 encode function const TypeFunc* OptoRuntime::base64_encodeBlock_Type() { int argcnt = 6; @@ -1291,6 +1409,7 @@ const TypeFunc* OptoRuntime::base64_encodeBlock_Type() { const TypeTuple* range = TypeTuple::make(TypeFunc::Parms, fields); return TypeFunc::make(domain, range); } + // Base64 decode function const TypeFunc* OptoRuntime::base64_decodeBlock_Type() { int argcnt = 7; diff --git a/src/hotspot/share/opto/runtime.hpp b/src/hotspot/share/opto/runtime.hpp index cd13c14148d7..c00f9228716b 100644 --- a/src/hotspot/share/opto/runtime.hpp +++ b/src/hotspot/share/opto/runtime.hpp @@ -275,6 +275,7 @@ class OptoRuntime : public AllStatic { static const TypeFunc* galoisCounterMode_aescrypt_Type(); static const TypeFunc* digestBase_implCompress_Type(bool is_sha3); + static const TypeFunc* double_keccak_Type(); static const TypeFunc* digestBase_implCompressMB_Type(bool is_sha3); static const TypeFunc* multiplyToLen_Type(); @@ -291,6 +292,11 @@ class OptoRuntime : public AllStatic { static const TypeFunc* ghash_processBlocks_Type(); static const TypeFunc* chacha20Block_Type(); + static const TypeFunc* dilithiumAlmostNtt_Type(); + static const TypeFunc* dilithiumAlmostInverseNtt_Type(); + static const TypeFunc* dilithiumNttMult_Type(); + static const TypeFunc* dilithiumMontMulByConstant_Type(); + static const TypeFunc* dilithiumDecomposePoly_Type(); static const TypeFunc* base64_encodeBlock_Type(); static const TypeFunc* base64_decodeBlock_Type(); static const TypeFunc* poly1305_processBlocks_Type(); diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp index 7f0eddbda271..cb293051166d 100644 --- a/src/hotspot/share/prims/jvm.cpp +++ b/src/hotspot/share/prims/jvm.cpp @@ -3257,9 +3257,17 @@ JVM_ENTRY(void, JVM_WaitForReferencePendingList(JNIEnv* env)) } JVM_END +JVM_ENTRY(jobject, JVM_ReferenceGet(JNIEnv* env, jobject ref)) + oop ref_oop = JNIHandles::resolve_non_null(ref); + // PhantomReference has its own implementation of get(). + assert(!java_lang_ref_Reference::is_phantom(ref_oop), "precondition"); + oop referent = java_lang_ref_Reference::weak_referent(ref_oop); + return JNIHandles::make_local(THREAD, referent); +JVM_END + JVM_ENTRY(jboolean, JVM_ReferenceRefersTo(JNIEnv* env, jobject ref, jobject o)) oop ref_oop = JNIHandles::resolve_non_null(ref); - // PhantomReference has it's own implementation of refersTo(). + // PhantomReference has its own implementation of refersTo(). // See: JVM_PhantomReferenceRefersTo assert(!java_lang_ref_Reference::is_phantom(ref_oop), "precondition"); oop referent = java_lang_ref_Reference::weak_referent_no_keepalive(ref_oop); diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index bcd6d0291d54..a56d12b6c79b 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -332,6 +332,9 @@ const int ObjectAlignmentInBytes = 8; product(bool, UseChaCha20Intrinsics, false, DIAGNOSTIC, \ "Use intrinsics for the vectorized version of ChaCha20") \ \ + product(bool, UseDilithiumIntrinsics, false, DIAGNOSTIC, \ + "Use intrinsics for the vectorized version of Dilithium") \ + \ product(bool, UseMD5Intrinsics, false, DIAGNOSTIC, \ "Use intrinsics for MD5 crypto hash function") \ \ diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index 77f6ef463bf3..2a64bc6fdd28 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -198,9 +198,9 @@ char* os::iso8601_time(jlong milliseconds_since_19700101, char* buffer, size_t b abs_local_to_UTC = -(abs_local_to_UTC); } // Convert time zone offset seconds to hours and minutes. - const time_t zone_hours = (abs_local_to_UTC / seconds_per_hour); - const time_t zone_min = - ((abs_local_to_UTC % seconds_per_hour) / seconds_per_minute); + const int zone_hours = static_cast(abs_local_to_UTC / seconds_per_hour); + const int zone_min = + static_cast((abs_local_to_UTC % seconds_per_hour) / seconds_per_minute); // Print an ISO 8601 date and time stamp into the buffer const int year = 1900 + time_struct.tm_year; diff --git a/src/hotspot/share/runtime/stubRoutines.cpp b/src/hotspot/share/runtime/stubRoutines.cpp index c5ef1c771949..4b80a34d3f4b 100644 --- a/src/hotspot/share/runtime/stubRoutines.cpp +++ b/src/hotspot/share/runtime/stubRoutines.cpp @@ -127,6 +127,11 @@ address StubRoutines::_counterMode_AESCrypt = nullptr; address StubRoutines::_galoisCounterMode_AESCrypt = nullptr; address StubRoutines::_ghash_processBlocks = nullptr; address StubRoutines::_chacha20Block = nullptr; +address StubRoutines::_dilithiumAlmostNtt = nullptr; +address StubRoutines::_dilithiumAlmostInverseNtt = nullptr; +address StubRoutines::_dilithiumNttMult = nullptr; +address StubRoutines::_dilithiumMontMulByConstant = nullptr; +address StubRoutines::_dilithiumDecomposePoly = nullptr; address StubRoutines::_base64_encodeBlock = nullptr; address StubRoutines::_base64_decodeBlock = nullptr; address StubRoutines::_poly1305_processBlocks = nullptr; @@ -140,6 +145,7 @@ address StubRoutines::_sha256_implCompressMB = nullptr; address StubRoutines::_sha512_implCompress = nullptr; address StubRoutines::_sha512_implCompressMB = nullptr; address StubRoutines::_sha3_implCompress = nullptr; +address StubRoutines::_double_keccak = nullptr; address StubRoutines::_sha3_implCompressMB = nullptr; address StubRoutines::_updateBytesCRC32 = nullptr; diff --git a/src/hotspot/share/runtime/stubRoutines.hpp b/src/hotspot/share/runtime/stubRoutines.hpp index 96946643c087..014aba74fbb4 100644 --- a/src/hotspot/share/runtime/stubRoutines.hpp +++ b/src/hotspot/share/runtime/stubRoutines.hpp @@ -207,6 +207,11 @@ class StubRoutines: AllStatic { static address _galoisCounterMode_AESCrypt; static address _ghash_processBlocks; static address _chacha20Block; + static address _dilithiumAlmostNtt; + static address _dilithiumAlmostInverseNtt; + static address _dilithiumNttMult; + static address _dilithiumMontMulByConstant; + static address _dilithiumDecomposePoly; static address _base64_encodeBlock; static address _base64_decodeBlock; static address _poly1305_processBlocks; @@ -220,6 +225,7 @@ class StubRoutines: AllStatic { static address _sha512_implCompress; static address _sha512_implCompressMB; static address _sha3_implCompress; + static address _double_keccak; static address _sha3_implCompressMB; static address _updateBytesCRC32; @@ -396,6 +402,11 @@ class StubRoutines: AllStatic { static address counterMode_AESCrypt() { return _counterMode_AESCrypt; } static address ghash_processBlocks() { return _ghash_processBlocks; } static address chacha20Block() { return _chacha20Block; } + static address dilithiumAlmostNtt() { return _dilithiumAlmostNtt; } + static address dilithiumAlmostInverseNtt() { return _dilithiumAlmostInverseNtt; } + static address dilithiumNttMult() { return _dilithiumNttMult; } + static address dilithiumMontMulByConstant() { return _dilithiumMontMulByConstant; } + static address dilithiumDecomposePoly() { return _dilithiumDecomposePoly; } static address base64_encodeBlock() { return _base64_encodeBlock; } static address base64_decodeBlock() { return _base64_decodeBlock; } static address md5_implCompress() { return _md5_implCompress; } @@ -407,6 +418,7 @@ class StubRoutines: AllStatic { static address sha512_implCompress() { return _sha512_implCompress; } static address sha512_implCompressMB() { return _sha512_implCompressMB; } static address sha3_implCompress() { return _sha3_implCompress; } + static address double_keccak() { return _double_keccak; } static address sha3_implCompressMB() { return _sha3_implCompressMB; } static address updateBytesCRC32() { return _updateBytesCRC32; } diff --git a/src/hotspot/share/runtime/threads.cpp b/src/hotspot/share/runtime/threads.cpp index 90514b737bcc..1fbe6683f719 100644 --- a/src/hotspot/share/runtime/threads.cpp +++ b/src/hotspot/share/runtime/threads.cpp @@ -1306,10 +1306,24 @@ void Threads::print_on(outputStream* st, bool print_stacks, char buf[32]; st->print_raw_cr(os::local_time_string(buf, sizeof(buf))); - st->print_cr("Full thread dump %s (%s %s):", + st->print_cr("Full thread dump %s (%s %s)", VM_Version::vm_name(), VM_Version::vm_release(), VM_Version::vm_info_string()); + JDK_Version::current().to_string(buf, sizeof(buf)); + const char* runtime_name = JDK_Version::runtime_name() != nullptr ? + JDK_Version::runtime_name() : ""; + const char* runtime_version = JDK_Version::runtime_version() != nullptr ? + JDK_Version::runtime_version() : ""; + const char* vendor_version = JDK_Version::runtime_vendor_version() != nullptr ? + JDK_Version::runtime_vendor_version() : ""; + const char* jdk_debug_level = VM_Version::printable_jdk_debug_level() != nullptr ? + VM_Version::printable_jdk_debug_level() : ""; + + st->print_cr(" JDK version: %s%s%s (%s) (%sbuild %s)", runtime_name, + (*vendor_version != '\0') ? " " : "", vendor_version, + buf, jdk_debug_level, runtime_version); + st->cr(); #if INCLUDE_SERVICES diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index 6c57c7998e7f..9d8034561647 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -540,6 +540,11 @@ static_field(StubRoutines, _galoisCounterMode_AESCrypt, address) \ static_field(StubRoutines, _ghash_processBlocks, address) \ static_field(StubRoutines, _chacha20Block, address) \ + static_field(StubRoutines, _dilithiumAlmostNtt, address) \ + static_field(StubRoutines, _dilithiumAlmostInverseNtt, address) \ + static_field(StubRoutines, _dilithiumNttMult, address) \ + static_field(StubRoutines, _dilithiumMontMulByConstant, address) \ + static_field(StubRoutines, _dilithiumDecomposePoly, address) \ static_field(StubRoutines, _base64_encodeBlock, address) \ static_field(StubRoutines, _base64_decodeBlock, address) \ static_field(StubRoutines, _poly1305_processBlocks, address) \ @@ -548,6 +553,7 @@ static_field(StubRoutines, _crc32c_table_addr, address) \ static_field(StubRoutines, _updateBytesCRC32C, address) \ static_field(StubRoutines, _updateBytesAdler32, address) \ + static_field(StubRoutines, _double_keccak, address) \ static_field(StubRoutines, _multiplyToLen, address) \ static_field(StubRoutines, _squareToLen, address) \ static_field(StubRoutines, _bigIntegerRightShiftWorker, address) \ diff --git a/src/java.base/linux/native/libnio/ch/FileDispatcherImpl.c b/src/java.base/linux/native/libnio/ch/FileDispatcherImpl.c index 207e61431dc9..7c3761a613c3 100644 --- a/src/java.base/linux/native/libnio/ch/FileDispatcherImpl.c +++ b/src/java.base/linux/native/libnio/ch/FileDispatcherImpl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,7 +63,7 @@ Java_sun_nio_ch_FileDispatcherImpl_transferFrom0(JNIEnv *env, jobject this, if (n < 0) { if (errno == EAGAIN) return IOS_UNAVAILABLE; - if (errno == ENOSYS) + if (errno == ENOSYS || errno == EOPNOTSUPP) return IOS_UNSUPPORTED_CASE; if ((errno == EBADF || errno == EINVAL || errno == EXDEV) && ((ssize_t)count >= 0)) @@ -103,6 +103,7 @@ Java_sun_nio_ch_FileDispatcherImpl_transferTo0(JNIEnv *env, jobject this, case EINVAL: case ENOSYS: case EXDEV: + case EOPNOTSUPP: // ignore and try sendfile() break; default: diff --git a/src/java.base/linux/native/libnio/fs/LinuxNativeDispatcher.c b/src/java.base/linux/native/libnio/fs/LinuxNativeDispatcher.c index cf8592e1ced5..5f14896ad24c 100644 --- a/src/java.base/linux/native/libnio/fs/LinuxNativeDispatcher.c +++ b/src/java.base/linux/native/libnio/fs/LinuxNativeDispatcher.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -199,6 +199,7 @@ Java_sun_nio_fs_LinuxNativeDispatcher_directCopy0 case EINVAL: case ENOSYS: case EXDEV: + case EOPNOTSUPP: // ignore and try sendfile() break; default: diff --git a/src/java.base/share/classes/com/sun/crypto/provider/ML_KEM.java b/src/java.base/share/classes/com/sun/crypto/provider/ML_KEM.java new file mode 100644 index 000000000000..9808a0133032 --- /dev/null +++ b/src/java.base/share/classes/com/sun/crypto/provider/ML_KEM.java @@ -0,0 +1,1183 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.crypto.provider; + +import java.security.*; +import java.util.Arrays; +import javax.crypto.DecapsulateException; + +import sun.security.provider.SHA3.SHAKE256; +import sun.security.provider.SHA3Parallel.Shake128Parallel; + +public final class ML_KEM { + + public static final int SECRET_SIZE = 32; + private static final String HASH_H_NAME = "SHA3-256"; + private static final String HASH_G_NAME = "SHA3-512"; + + private static final int ML_KEM_Q = 3329; + private static final int ML_KEM_N = 256; + + private static final int XOF_BLOCK_LEN = 168; // the block length for SHAKE128 + private static final int XOF_PAD = 24; + private static final int MONT_R_BITS = 20; + private static final int MONT_Q = 3329; + private static final int MONT_R_SQUARE_MOD_Q = 152; + private static final int MONT_Q_INV_MOD_R = 586497; + + // toMont((ML_KEM_N / 2)^-1 mod ML_KEM_Q) using R = 2^MONT_R_BITS + private static final int MONT_DIM_HALF_INVERSE = 1534; + private static final int BARRETT_MULTIPLIER = 20159; + private static final int BARRETT_SHIFT = 26; + private static final int[] MONT_ZETAS_FOR_NTT = new int[]{ + 1188, 914, -969, 585, -551, 1263, -97, 593, + -35, -1400, -417, -1253, 742, -281, 185, -819, + -1226, 895, -530, 52, 25, 1000, 1249, -909, + -373, -1604, -259, -1369, -82, 49, 1496, -406, + 445, 1155, -405, -714, 553, -1183, -1401, 1598, + -128, 1538, -669, 744, 1382, -1313, 201, -332, + -1440, -1007, -36, -1617, 567, -623, 1429, 290, + -1269, -825, -1613, 510, -395, 845, -426, -1003, + 222, -1107, 172, -42, 620, 1497, -1649, 94, + -595, -497, -431, -1327, -702, -1448, -184, -607, + -868, -1430, 977, 884, 425, 355, 1259, 1192, + 317, -636, -1074, 30, -1394, 833, -1200, -244, + 907, -339, -227, 1178, -586, -137, -514, 534, + 1153, -486, -1386, -668, 191, 982, 88, 1014, + -1177, -474, -612, -857, -348, -604, 990, 1601, + -1599, -709, -789, -1317, -57, 1049, -584 + }; + + private static final int[] MONT_ZETAS_FOR_NTT_MULT = new int[]{ + -1003, 1003, 222, -222, -1107, 1107, 172, -172, + -42, 42, 620, -620, 1497, -1497, -1649, 1649, + 94, -94, -595, 595, -497, 497, -431, 431, + -1327, 1327, -702, 702, -1448, 1448, -184, 184, + -607, 607, -868, 868, -1430, 1430, 977, -977, + 884, -884, 425, -425, 355, -355, 1259, -1259, + 1192, -1192, 317, -317, -636, 636, -1074, 1074, + 30, -30, -1394, 1394, 833, -833, -1200, 1200, + -244, 244, 907, -907, -339, 339, -227, 227, + 1178, -1178, -586, 586, -137, 137, -514, 514, + 534, -534, 1153, -1153, -486, 486, -1386, 1386, + -668, 668, 191, -191, 982, -982, 88, -88, + 1014, -1014, -1177, 1177, -474, 474, -612, 612, + -857, 857, -348, 348, -604, 604, 990, -990, + 1601, -1601, -1599, 1599, -709, 709, -789, 789, + -1317, 1317, -57, 57, 1049, -1049, -584, 584 + }; + + private final int mlKem_k; + private final int mlKem_eta1; + private final int mlKem_eta2; + + private final int mlKem_du; + private final int mlKem_dv; + private final int encapsulationSize; + + public ML_KEM(String name) { + switch (name) { + case "ML-KEM-512" -> { + mlKem_k = 2; + mlKem_eta1 = 3; + mlKem_eta2 = 2; + mlKem_du = 10; + mlKem_dv = 4; + } + case "ML-KEM-768" -> { + mlKem_k = 3; + mlKem_eta1 = 2; + mlKem_eta2 = 2; + mlKem_du = 10; + mlKem_dv = 4; + } + case "ML-KEM-1024" -> { + mlKem_k = 4; + mlKem_eta1 = 2; + mlKem_eta2 = 2; + mlKem_du = 11; + mlKem_dv = 5; + } + default -> throw new IllegalArgumentException( + // This should never happen. + "Invalid algorithm name (" + name + ")."); + } + encapsulationSize = (mlKem_k * mlKem_du + mlKem_dv) * 32; + } + + /* + Classes for the internal K_PKE scheme + */ + private record K_PKE_EncryptionKey(byte[] keyBytes) {} + + private record K_PKE_DecryptionKey(byte[] keyBytes) {} + + private record K_PKE_KeyPair( + K_PKE_EncryptionKey publicKey, K_PKE_DecryptionKey privateKey) { + } + + protected record K_PKE_CipherText(byte[] encryptedBytes) { + } + + private boolean isValidCipherText(K_PKE_CipherText cipherText) { + return (cipherText.encryptedBytes.length == encapsulationSize); + } + + /* + Classes for internal KEM scheme + */ + protected record ML_KEM_EncapsulationKey(byte[] keyBytes) { + } + + protected record ML_KEM_DecapsulationKey(byte[] keyBytes) { + } + + protected record ML_KEM_KeyPair( + ML_KEM_EncapsulationKey encapsulationKey, + ML_KEM_DecapsulationKey decapsulationKey) { + } + + protected record ML_KEM_EncapsulateResult( + K_PKE_CipherText cipherText, byte[] sharedSecret) { + } + + protected int getEncapsulationSize() { + return encapsulationSize; + } + + // Encapsulation key checks from section 7.2 of spec + protected Object checkPublicKey(byte[] pk) throws InvalidKeyException { + //Encapsulation key type check + if (pk.length != mlKem_k * 384 + 32) { + throw new InvalidKeyException("Public key is not the correct size"); + } + + //Encapsulation key modulus check + int x, y, z, a, b; + for (int i = 0; i < mlKem_k * 384; i += 3) { + x = pk[i] & 0xFF; + y = pk[i + 1] & 0xFF; + z = pk[i + 2] & 0xFF; + a = x + ((y & 0xF) << 8); + b = (y >> 4) + (z << 4); + if ((a >= ML_KEM_Q) || (b >= ML_KEM_Q)) { + throw new InvalidKeyException( + "Coefficients in public key not in specified range"); + } + } + return null; + } + + // Decapsulation key checks from Section 7.3 of spec + protected Object checkPrivateKey(byte[] sk) throws InvalidKeyException { + MessageDigest mlKemH; + try { + mlKemH = MessageDigest.getInstance(HASH_H_NAME); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + + //Decapsulation key type check + if (sk.length != mlKem_k * 768 + 96) { + throw new InvalidKeyException("Private key is not the correct size"); + } + + //Decapsulation hash check + mlKemH.update(sk, mlKem_k * 384, mlKem_k * 384 + 32); + byte[] check = Arrays.copyOfRange(sk, mlKem_k * 768 + 32, mlKem_k * 768 + 64); + if (!MessageDigest.isEqual(mlKemH.digest(), check)) { + throw new InvalidKeyException("Private key hash check failed"); + } + return null; + } + + /* + Main internal algorithms from Section 6 of specification + */ + protected ML_KEM_KeyPair generateKemKeyPair(byte[] kem_d, byte[] kem_z) { + MessageDigest mlKemH; + try { + mlKemH = MessageDigest.getInstance(HASH_H_NAME); + } catch (NoSuchAlgorithmException e) { + // This should never happen. + throw new RuntimeException(e); + } + + //Generate K-PKE keys + var kPkeKeyPair = generateK_PkeKeyPair(kem_d); + //encaps key = kPke encryption key + byte[] encapsKey = kPkeKeyPair.publicKey.keyBytes; + + //Derive decapsulation key = kPkePrivatKey || encapsKey || H(encapsKey) || kem_Z + byte[] kPkePrivateKey = kPkeKeyPair.privateKey.keyBytes; + byte[] decapsKey = new byte[encapsKey.length + kPkePrivateKey.length + 64]; + System.arraycopy(kPkePrivateKey, 0, decapsKey, 0, kPkePrivateKey.length); + Arrays.fill(kPkePrivateKey, (byte)0); + System.arraycopy(encapsKey, 0, decapsKey, + kPkePrivateKey.length, encapsKey.length); + + mlKemH.update(encapsKey); + try { + mlKemH.digest(decapsKey, kPkePrivateKey.length + encapsKey.length, 32); + } catch (DigestException e) { + // This should never happen. + throw new RuntimeException(e); + } + System.arraycopy(kem_z, 0, decapsKey, + kPkePrivateKey.length + encapsKey.length + 32, 32); + + return new ML_KEM_KeyPair( + new ML_KEM_EncapsulationKey(encapsKey), + new ML_KEM_DecapsulationKey(decapsKey)); + } + + protected ML_KEM_EncapsulateResult encapsulate( + ML_KEM_EncapsulationKey encapsulationKey, byte[] randomMessage) { + MessageDigest mlKemH; + MessageDigest mlKemG; + try { + mlKemH = MessageDigest.getInstance(HASH_H_NAME); + mlKemG = MessageDigest.getInstance(HASH_G_NAME); + } catch (NoSuchAlgorithmException e){ + // This should never happen. + throw new RuntimeException(e); + } + + mlKemH.update(encapsulationKey.keyBytes); + mlKemG.update(randomMessage); + mlKemG.update(mlKemH.digest()); + var kHatAndRandomCoins = mlKemG.digest(); + var randomCoins = Arrays.copyOfRange(kHatAndRandomCoins, 32, 64); + var cipherText = kPkeEncrypt(new K_PKE_EncryptionKey(encapsulationKey.keyBytes), + randomMessage, randomCoins); + Arrays.fill(randomCoins, (byte) 0); + byte[] sharedSecret = Arrays.copyOfRange(kHatAndRandomCoins, 0, 32); + Arrays.fill(kHatAndRandomCoins, (byte) 0); + + return new ML_KEM_EncapsulateResult(cipherText, sharedSecret); + } + + protected byte[] decapsulate(ML_KEM_DecapsulationKey decapsulationKey, + K_PKE_CipherText cipherText) + throws DecapsulateException { + + //Check ciphertext validity + if (!isValidCipherText(cipherText)) { + throw new DecapsulateException("Invalid ciphertext"); + } + + int encode12PolyLen = 12 * ML_KEM_N / 8; + var decapsKeyBytes = decapsulationKey.keyBytes; + MessageDigest mlKemG; + SHAKE256 mlKemJ; + try { + mlKemG = MessageDigest.getInstance(HASH_G_NAME); + mlKemJ = new SHAKE256(32); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + + byte[] kPkePrivateKeyBytes = new byte[mlKem_k * encode12PolyLen]; + System.arraycopy(decapsKeyBytes, 0, kPkePrivateKeyBytes, 0, + kPkePrivateKeyBytes.length); + + byte[] encapsKeyBytes = new byte[mlKem_k * encode12PolyLen + 32]; + System.arraycopy(decapsKeyBytes, mlKem_k * encode12PolyLen, + encapsKeyBytes, 0, encapsKeyBytes.length); + var mCandidate = kPkeDecrypt( + new K_PKE_DecryptionKey(kPkePrivateKeyBytes), cipherText); + mlKemG.update(mCandidate); + mlKemG.update(decapsKeyBytes, decapsKeyBytes.length - 64, 32); + var kAndCoins = mlKemG.digest(); + var realResult = Arrays.copyOfRange(kAndCoins, 0, 32); + var coins = Arrays.copyOfRange(kAndCoins, 32, 64); + + // Zero out unused byte arrays containing sensitive data + Arrays.fill(kPkePrivateKeyBytes, (byte) 0); + Arrays.fill(kAndCoins, (byte) 0); + + mlKemJ.update(decapsKeyBytes, decapsKeyBytes.length - 32, 32); + mlKemJ.update(cipherText.encryptedBytes); + var fakeResult = mlKemJ.digest(); + var computedCipherText = kPkeEncrypt( + new K_PKE_EncryptionKey(encapsKeyBytes), mCandidate, coins); + + // The rest of this method implements the following in constant time + // + // if (Arrays.equals(cipherText.encryptedBytes, + // computedCipherText.encryptedBytes)) { + // return realResult; + // } else { + // return fakeResult; + // } + + int mask = 0; + byte[] origCiphertestBytes = cipherText.encryptedBytes; + byte[] compCipherTextBytes = computedCipherText.encryptedBytes; + for (int i = 0; i < cipherText.encryptedBytes.length; i++) { + mask |= (origCiphertestBytes[i] ^ compCipherTextBytes[i]); + } + mask = - (mask & 0xff); // sets mask to negative or 0 + mask >>= 31; // sets mask to all 1-bits or all 0-bits + int notMask = ~mask; + + byte[] result = realResult; + for (int i = 0; i < realResult.length; i ++) { + result[i] = (byte)((notMask & realResult[i]) | (mask & fakeResult[i])); + } + + return result; + } + + /* + K-PKE subroutines defined in Section 5 of spec + */ + private K_PKE_KeyPair generateK_PkeKeyPair(byte[] seed) { + + MessageDigest mlKemG; + SHAKE256 mlKemJ; + try { + mlKemG = MessageDigest.getInstance(HASH_G_NAME); + mlKemJ = new SHAKE256(64 * mlKem_eta1); + } catch (NoSuchAlgorithmException e) { + // This should never happen. + throw new RuntimeException(e); + } + + mlKemG.update(seed); + mlKemG.update((byte)mlKem_k); + + var rhoSigma = mlKemG.digest(); + var rho = Arrays.copyOfRange(rhoSigma, 0, 32); + var sigma = Arrays.copyOfRange(rhoSigma, 32, 64); + Arrays.fill(rhoSigma, (byte)0); + + var keyGenA = generateA(rho, false); + + int keyGenN = 0; + byte[] prfSeed = new byte[sigma.length + 1]; + System.arraycopy(sigma, 0, prfSeed, 0, sigma.length); + byte[] cbdInput; + short[][] keyGenS = new short[mlKem_k][]; + short[][] keyGenE = new short[mlKem_k][]; + for (int i = 0; i < mlKem_k; i++) { + prfSeed[sigma.length] = (byte) (keyGenN++); + mlKemJ.update(prfSeed); + cbdInput = mlKemJ.digest(); + keyGenS[i] = centeredBinomialDistribution(mlKem_eta1, cbdInput); + } + for (int i = 0; i < mlKem_k; i++) { + prfSeed[sigma.length] = (byte) (keyGenN++); + mlKemJ.update(prfSeed); + cbdInput = mlKemJ.digest(); + keyGenE[i] = centeredBinomialDistribution(mlKem_eta1, cbdInput); + } + Arrays.fill(sigma, (byte)0); + + short[][] keyGenSHat = mlKemVectorNTT(keyGenS); + mlKemVectorReduce(keyGenSHat); + short[][] keyGenEHat = mlKemVectorNTT(keyGenE); + + short[][] keyGenTHat = + mlKemMatrixVectorMuladd(keyGenA, keyGenSHat, keyGenEHat); + + byte[] pkEncoded = new byte[(mlKem_k * ML_KEM_N * 12) / 8 + rho.length]; + byte[] skEncoded = new byte[(mlKem_k * ML_KEM_N * 12) / 8]; + for (int i = 0; i < mlKem_k; i++) { + encodePoly12(keyGenTHat[i], pkEncoded, i * ((ML_KEM_N * 12) / 8)); + encodePoly12(keyGenSHat[i], skEncoded, i * ((ML_KEM_N * 12) / 8)); + Arrays.fill(keyGenEHat[i], (short) 0); + Arrays.fill(keyGenSHat[i], (short) 0); + } + System.arraycopy(rho, 0, + pkEncoded, (mlKem_k * ML_KEM_N * 12) / 8, rho.length); + + return new K_PKE_KeyPair( + new K_PKE_EncryptionKey(pkEncoded), + new K_PKE_DecryptionKey(skEncoded)); + } + + private K_PKE_CipherText kPkeEncrypt( + K_PKE_EncryptionKey publicKey, byte[] message, byte[] sigma) { + short[][] zeroes = new short[mlKem_k][ML_KEM_N]; + byte[] pkBytes = publicKey.keyBytes; + byte[] rho = Arrays.copyOfRange(pkBytes, + pkBytes.length - 32, pkBytes.length); + byte[] tHatBytes = Arrays.copyOfRange(pkBytes, + 0, pkBytes.length - 32); + var encryptTHat = decodeVector(12, tHatBytes); + var encryptA = generateA(rho, true); + short[][] encryptR = new short[mlKem_k][]; + short[][] encryptE1 = new short[mlKem_k][]; + int encryptN = 0; + byte[] prfSeed = new byte[sigma.length + 1]; + System.arraycopy(sigma, 0, prfSeed, 0, sigma.length); + + var kPkePRFeta1 = new SHAKE256(64 * mlKem_eta1); + var kPkePRFeta2 = new SHAKE256(64 * mlKem_eta2); + for (int i = 0; i < mlKem_k; i++) { + prfSeed[sigma.length] = (byte) (encryptN++); + kPkePRFeta1.update(prfSeed); + byte[] cbdInput = kPkePRFeta1.digest(); + encryptR[i] = centeredBinomialDistribution(mlKem_eta1, cbdInput); + } + for (int i = 0; i < mlKem_k; i++) { + prfSeed[sigma.length] = (byte) (encryptN++); + kPkePRFeta2.update(prfSeed); + byte[] cbdInput = kPkePRFeta2.digest(); + encryptE1[i] = centeredBinomialDistribution(mlKem_eta2, cbdInput); + } + prfSeed[sigma.length] = (byte) encryptN; + kPkePRFeta2.reset(); + kPkePRFeta2.update(prfSeed); + byte[] cbdInput = kPkePRFeta2.digest(); + var encryptE2 = centeredBinomialDistribution(mlKem_eta2, cbdInput); + + var encryptRHat = mlKemVectorNTT(encryptR); + var encryptUHat = mlKemMatrixVectorMuladd(encryptA, encryptRHat, zeroes); + var encryptU = mlKemVectorInverseNTT(encryptUHat); + encryptU = mlKemAddVec(encryptU, encryptE1); + var encryptVHat = mlKemVectorScalarMult(encryptTHat, encryptRHat); + var encryptV = mlKemInverseNTT(encryptVHat); + encryptV = mlKemAddPoly(encryptV, encryptE2, decompressDecode(message)); + var encryptC1 = encodeVector(mlKem_du, compressVector10_11(encryptU, mlKem_du)); + var encryptC2 = encodePoly(mlKem_dv, compressPoly4_5(encryptV, mlKem_dv)); + + byte[] result = new byte[encryptC1.length + encryptC2.length]; + System.arraycopy(encryptC1, 0, + result, 0, encryptC1.length); + System.arraycopy(encryptC2, 0, + result, encryptC1.length, encryptC2.length); + + return new K_PKE_CipherText(result); + } + + private byte[] kPkeDecrypt(K_PKE_DecryptionKey privateKey, + K_PKE_CipherText cipherText) { + int uBytesLen = mlKem_k * mlKem_du * ML_KEM_N / 8; + byte[] uBytes = Arrays.copyOfRange(cipherText.encryptedBytes, + 0, uBytesLen); + byte[] vBytes = Arrays.copyOfRange(cipherText.encryptedBytes, + uBytesLen, cipherText.encryptedBytes.length); + var decryptU = decompressVector(decodeVector(mlKem_du, uBytes), mlKem_du); + var decryptV = decompressPoly( + decodePoly(mlKem_dv, vBytes, 0), mlKem_dv); + var decryptSHat = decodeVector(12, privateKey.keyBytes); + var decryptSU = mlKemInverseNTT( + mlKemVectorScalarMult(decryptSHat, mlKemVectorNTT(decryptU))); + for (int i = 0; i < mlKem_k; i++) { + Arrays.fill(decryptSHat[i], (short) 0); + } + decryptV = mlKemSubtractPoly(decryptV, decryptSU); + Arrays.fill(decryptSU, (short) 0); + + return encodeCompress(decryptV); + } + + /* + Sampling algorithms from Section 4.2.2 of the spec + */ + + //Combination of SampleNTT and KeyGen/Encrypt generation of A + private short[][][] generateA(byte[] rho, Boolean transposed) { + short[][][] a = new short[mlKem_k][mlKem_k][]; + + int nrPar = 2; + int rhoLen = rho.length; + byte[] seedBuf = new byte[XOF_BLOCK_LEN]; + System.arraycopy(rho, 0, seedBuf, 0, rho.length); + seedBuf[rhoLen + 2] = 0x1F; + seedBuf[XOF_BLOCK_LEN - 1] = (byte)0x80; + byte[][] xofBufArr = new byte[nrPar][XOF_BLOCK_LEN + XOF_PAD]; + int[] iIndex = new int[nrPar]; + int[] jIndex = new int[nrPar]; + + short[] parsedBuf = new short[(xofBufArr[0].length / 3) * 2]; + + int parInd = 0; + boolean allDone; + int[] ofs = new int[nrPar]; + Arrays.fill(ofs, 0); + short[][] aij = new short[nrPar][]; + try { + Shake128Parallel parXof = new Shake128Parallel(xofBufArr); + + for (int i = 0; i < mlKem_k; i++) { + for (int j = 0; j < mlKem_k; j++) { + xofBufArr[parInd] = seedBuf.clone(); + if (transposed) { + xofBufArr[parInd][rhoLen] = (byte) i; + xofBufArr[parInd][rhoLen + 1] = (byte) j; + } else { + xofBufArr[parInd][rhoLen] = (byte) j; + xofBufArr[parInd][rhoLen + 1] = (byte) i; + } + iIndex[parInd] = i; + jIndex[parInd] = j; + ofs[parInd] = 0; + aij[parInd] = new short[ML_KEM_N]; + parInd++; + + if ((parInd == nrPar) || + ((i == mlKem_k - 1) && (j == mlKem_k - 1))) { + parXof.reset(xofBufArr); + + allDone = false; + while (!allDone) { + allDone = true; + parXof.squeezeBlock(); + for (int k = 0; k < parInd; k++) { + int parsedOfs = 0; + int tmp; + if (ofs[k] < ML_KEM_N) { + twelve2Sixteen(xofBufArr[k], 0, + parsedBuf, (XOF_BLOCK_LEN / 3) * 2); + } + while ((ofs[k] < ML_KEM_N) && + (parsedOfs < (XOF_BLOCK_LEN / 3) * 2)) { + tmp = parsedBuf[parsedOfs++] & 0xFFFF; + if (tmp < ML_KEM_Q) { + aij[k][ofs[k]] = (short) tmp; + ofs[k]++; + } + tmp = parsedBuf[parsedOfs++] & 0xFFFF; + if ((ofs[k] < ML_KEM_N) && (tmp < ML_KEM_Q)) { + aij[k][ofs[k]] = (short) tmp; + ofs[k]++; + } + } + if (ofs[k] < ML_KEM_N) { + allDone = false; + } + } + } + + for (int k = 0; k < parInd; k++) { + a[iIndex[k]][jIndex[k]] = aij[k]; + } + parInd = 0; + } + } + } + } catch (InvalidAlgorithmParameterException e) { + // This should never happen since xofBufArr is of the correct size + throw new RuntimeException("Internal error."); + } + + return a; + } + + private short[] centeredBinomialDistribution(int eta, byte[] input) { + if (eta == 2) return centeredBinomialDistribution2(input); + if (eta == 3) return centeredBinomialDistribution3(input); + // Below for arbitrary eta, not used in ML-KEM + short[] result = new short[ML_KEM_N]; + int index = 0; + int shift = 8; + int currentByte = input[0]; + for (int m = 0; m < ML_KEM_N; m++) { + int a = 0; + int b = 0; + for (int j = 0; j < eta; j++) { + if (shift == 8) { + currentByte = input[index++]; + shift = 0; + } + a += (currentByte >> shift) & 1; + shift++; + } + for (int j = 0; j < eta; j++) { + if (shift == 8) { + currentByte = input[index++]; + shift = 0; + } + b += (currentByte >> shift) & 1; + shift++; + } + result[m] = (short) (a - b); + } + return result; + } + + private short[] centeredBinomialDistribution2(byte[] input) { + short[] result = new short[ML_KEM_N]; + // A 64-bit number divided into 16 4-bits, representing all 4-bit + // patterns of input with values are CBD samples in [-2, 2]. + long bits = 0x0112f001f001eff0L; + int j = 0; + + for (int i = 0; i < input.length; i++) { + // One byte has 2 4-bit sequences, each producing a sample + int a = input[i]; + int shift1 = (a << 2) & 0x3c; + int shift2 = (a >> 2) & 0x3c; + result[j++] = (short) ((bits << shift1) >> 60); + result[j++] = (short) ((bits << shift2) >> 60); + } + + return result; + } + + private short[] centeredBinomialDistribution3(byte[] input) { + short[] result = new short[ML_KEM_N]; + // A 32-bit number divided into 8 4-bits, representing all 3-bits + // patterns (one half of a 6-bit input) with values in [0, 3]. + int bits = 0x01121223; + int j = 0; + + for (int i = 0; i < input.length; i += 3) { + // Every 3 bytes has 24 bits that produce 4 6-bit sequences. + // We calculate values for both halves of each sequence and + // do the subtraction to get the sample + int a1 = input[i]; + int a2 = input[i + 1]; + int a3 = input[i + 2]; + int shift1 = (a1 << 2) & 0x1c; + int shift2 = (a1 >> 1) & 0x1c; + int shift3 = ((a1 >> 4) & 0x0c) | ((a2 << 4) & 0x10); + int shift4 = (a2 << 1) & 0x1c; + int shift5 = (a2 >> 2) & 0x1c; + int shift6 = ((a2 >> 5) & 0x04) | ((a3 << 3) & 0x18); + int shift7 = a3 & 0x1c; + int shift8 = (a3 >> 3) & 0x1c; + result[j++] = (short) + (((bits << shift1) >> 28) - ((bits << shift2) >> 28)); + result[j++] = (short) + (((bits << shift3) >> 28) - ((bits << shift4) >> 28)); + result[j++] = (short) + (((bits << shift5) >> 28) - ((bits << shift6) >> 28)); + result[j++] = (short) + (((bits << shift7) >> 28) - ((bits << shift8) >> 28)); + } + + return result; + } + + /* + NTT algorithms from Section 4.3 of the specification + */ + + // Works in place, it returns its (modified) input so that it can be used in + // expressions + private short[][] mlKemVectorNTT(short[][] vector) { + for (int i = 0; i < mlKem_k; i++) { + mlKemNTT(vector[i]); + } + return vector; + } + + // Works in place, it returns its (modified) input so that it can be used in + // expressions + private short[][] mlKemVectorReduce(short[][] vector) { + for (int i = 0; i < mlKem_k; i++) { + mlKemBarrettReduce(vector[i]); + } + return vector; + } + + // Works in place, it returns its (modified) input so that it can be used in + // expressions + private short[][] mlKemVectorInverseNTT(short[][] vector) { + for (int i = 0; i < mlKem_k; i++) { + vector[i] = mlKemInverseNTT(vector[i]); + } + return vector; + } + + // The elements of poly should be in the range [-ML_KEM_Q, ML_KEM_Q] + // The elements of poly at return will be in the range of [0, ML_KEM_Q] + private void mlKemNTT(short[] poly) { + int[] coeffs = new int[ML_KEM_N]; + for (int m = 0; m < ML_KEM_N; m++) { + coeffs[m] = poly[m]; + } + seilerNTT(coeffs); + for (int m = 0; m < ML_KEM_N; m++) { + poly[m] = (short) coeffs[m]; + } + mlKemBarrettReduce(poly); + } + + // Works in place, but also returns its (modified) input so that it can + // be used in expressions + private short[] mlKemInverseNTT(short[] poly) { + int[] coeffs = new int[ML_KEM_N]; + for (int m = 0; m < ML_KEM_N; m++) { + coeffs[m] = poly[m]; + } + seilerInverseNTT(coeffs); + for (int m = 0; m < ML_KEM_N; m++) { + poly[m] = (short) coeffs[m]; + } + return poly; + } + + // Implements the ML_KEM NTT algorithm similarly to that described + // in https://eprint.iacr.org/2018/039.pdf . + // It works in place, replaces the elements of the input coeffs array + // by the transformed representation. + // The input elements should be in the range [-MONT_Q, MONT_Q]. + // The result elements will fit into the range of short + // (i.e. [-32768, 32767]). + private static void seilerNTT(int[] coeffs) { + int dimension = ML_KEM_N; + int zetaIndex = 0; + for (int l = dimension / 2; l > 1; l /= 2) { + for (int s = 0; s < dimension; s += 2 * l) { + for (int j = s; j < s + l; j++) { + int tmp = montMul(MONT_ZETAS_FOR_NTT[zetaIndex], coeffs[j + l]); + coeffs[j + l] = coeffs[j] - tmp; + coeffs[j] = coeffs[j] + tmp; + } + zetaIndex++; + } + } + } + + // Implements the ML_KEM inverse NTT algorithm similarly to that described + // in https://eprint.iacr.org/2018/039.pdf . + // It works in place, replaces the elements of the input coeffs array + // by the transformed representation. + // The input elements should be in the range [-MONT_Q, MONT_Q). + // The output elements will be in the range (-MONT_Q, MONT_Q). + private static void seilerInverseNTT(int[] coeffs) { + int dimension = ML_KEM_N; + int zetaIndex = MONT_ZETAS_FOR_NTT.length - 1; + for (int l = 2; l < dimension; l *= 2) { + for (int s = 0; s < dimension; s += 2 * l) { + for (int j = s; j < s + l; j++) { + int tmp = coeffs[j]; + coeffs[j] = (tmp + coeffs[j + l]); + coeffs[j + l] = montMul( + tmp - coeffs[j + l], + -MONT_ZETAS_FOR_NTT[zetaIndex]); + } + zetaIndex--; + } + } + + for (int i = 0; i < dimension; i++) { + int r = montMul(coeffs[i], MONT_DIM_HALF_INVERSE); + coeffs[i] = r; + } + } + + // Performs A o b + c where + // A is a mlKem_k by mlKem_k matrix, + // b and c are mlKem_k long vectors of degree ML_KEM_N - 1 + // polynomials in the NTT domain representation. + // The coefficients in the result are in the range [0, ML_KEM_Q). + private short[][] mlKemMatrixVectorMuladd( + short[][][] a, short[][] b, short[][] c) { + short[] product = new short[ML_KEM_N]; + + for (int i = 0; i < mlKem_k; i++) { + for (int j = 0; j < mlKem_k; j++) { + nttMult(product, a[i][j], b[j]); + mlKemAddPoly(c[i], product); + } + mlKemBarrettReduce(c[i]); + } + return c; + } + + // Performs a^T o b where a and b are mlKem_k long vectors + // of degree ML_KEM_N - 1 polynomials in the NTT representation, + // with coefficients in the range [-ML_KEM_Q, ML_KEM_Q]. + // The coefficients in the result are in the range [0, ML_KEM_Q). + private short[] mlKemVectorScalarMult(short[][] a, short[][] b) { + short[] result = new short[ML_KEM_N]; + short[] product = new short[ML_KEM_N]; + + int j; + for (j = 0; j < mlKem_k; j++) { + nttMult(product, a[j], b[j]); + mlKemAddPoly(result, product); + } + mlKemBarrettReduce(result); + + return result; + } + + // Multiplies two polynomials represented in the NTT domain. + // The result is a representation of the product still in the NTT domain. + // The coefficients in the result are in the range (-ML_KEM_Q, ML_KEM_Q). + private void nttMult(short[] result, short[] ntta, short[] nttb) { + for (int m = 0; m < ML_KEM_N / 2; m++) { + int a0 = ntta[2 * m]; + int a1 = ntta[2 * m + 1]; + int b0 = nttb[2 * m]; + int b1 = nttb[2 * m + 1]; + int r = montMul(a0, b0) + + montMul(montMul(a1, b1), MONT_ZETAS_FOR_NTT_MULT[m]); + result[2 * m] = (short) montMul(r, MONT_R_SQUARE_MOD_Q); + result[2 * m + 1] = (short) montMul( + (montMul(a0, b1) + montMul(a1, b0)), MONT_R_SQUARE_MOD_Q); + } + } + + // Adds the vector of polynomials b to a in place, i.e. a will hold + // the result. It also returns (the modified) a so that it can be used + // in an expression. + // The coefficients in all polynomials of both vectors are supposed to be + // greater than -ML_KEM_Q and less than ML_KEM_Q. + // The coefficients in the result are nonnegative and less than ML_KEM_Q. + private short[][] mlKemAddVec(short[][] a, short[][] b) { + for (int i = 0; i < mlKem_k; i++) { + mlKemAddPoly(a[i], b[i]); + mlKemBarrettReduce(a[i]); + } + return a; + } + + // Adds the polynomial b to a in place, i.e. (the modified) a will hold + // the result. + // The coefficients are supposed be greater than -ML_KEM_Q in a and + // greater than -ML_KEM_Q and less than ML_KEM_Q in b. + // The coefficients in the result are greater than -ML_KEM_Q. + private void mlKemAddPoly(short[] a, short[] b) { + for (int m = 0; m < ML_KEM_N; m++) { + int r = a[m] + b[m] + ML_KEM_Q; // This makes r > -ML_KEM_Q + a[m] = (short) r; + } + } + + // Adds the polynomials b and c to a in place, i.e. 'a' will hold the sum. + // 'a' is also returned so that this function can be used in an expression. + // The coefficients in all three polynomials are supposed to be + // greater than -ML_KEM_Q and less than ML_KEM_Q. + // The coefficients in the result are nonnegative and less than ML_KEM_Q. + private short[] mlKemAddPoly(short[] a, short[] b, short[] c) { + for (int m = 0; m < ML_KEM_N; m++) { + int r = a[m] + b[m] + c[m] + 2 * ML_KEM_Q; // This makes r > - ML_KEM_Q + a[m] = (short) r; + } + mlKemBarrettReduce(a); + return a; + } + + // Subtracts the polynomial b from a in place, i.e. the result is + // stored in a. It also returns (the modified) a, so that it can be used + // in an expression. + // The coefficiens in both are assumed to be greater than -ML_KEM_Q + // and less than ML_KEM_Q. + // The coefficients in the result are nonnegative and less than ML_KEM_Q. + private short[] mlKemSubtractPoly(short[] a, short[] b) { + for (int m = 0; m < ML_KEM_N; m++) { + int r = a[m] - b[m] + ML_KEM_Q; // This makes r > -ML_KEM_Q + a[m] = (short) r; + } + mlKemBarrettReduce(a); + return a; + } + + private byte[] encodeVector(int l, short[][] vector) { + return encodeVector(l, vector, mlKem_k); + } + + private static byte[] encodeVector(int l, short[][] vector, int k) { + int encodedPolyLength = ML_KEM_N * l / 8; + byte[] result = new byte[k * encodedPolyLength]; + + for (int i = 0; i < k; i++) { + byte[] resultBytes = encodePoly(l, vector[i]); + System.arraycopy(resultBytes, 0, + result, i * encodedPolyLength, encodedPolyLength); + } + return result; + } + + private static void encodePoly12(short[] poly, byte[] result, int resultOffs) { + int low; + int high; + for (int m = 0; m < ML_KEM_N / 2; m++) { + low = poly[2 * m]; + low += ((low >> 31) & ML_KEM_Q); + low = low & 0xfff; + high = poly[2 * m + 1]; + high += ((high >> 31) & ML_KEM_Q); + high = high & 0xfff; + + result[resultOffs++] = (byte) low; + result[resultOffs++] = (byte) ((high << 4) + (low >> 8)); + result[resultOffs++] = (byte) (high >> 4); + } + } + + private static void encodePoly4(short[] poly, byte[] result) { + for (int m = 0; m < ML_KEM_N / 2; m++) { + result[m] = (byte) ((poly[2 * m] & 0xf) + (poly[2 * m + 1] << 4)); + } + } + + // Computes the byte array containing the packed l-bit representation + // of a polynomial. The coefficients in poly should be either nonnegative + // or elements of Z_(ML_KEM_Q) represented by a 16-bit value + // between -ML_KEM_Q and ML_KEM_Q. + private static byte[] encodePoly(int l, short[] poly) { + byte[] result = new byte[ML_KEM_N / 8 * l]; + if (l == 4) { + encodePoly4(poly, result); + } else { + int mask = (1 << l) - 1; + int shift = 0; + int index = 0; + int current = 0; + for (int m = 0; m < ML_KEM_N; m++) { + int currentShort = poly[m]; + currentShort += (currentShort >> 31) & ML_KEM_Q; + current += ((currentShort & mask) << shift); + shift += l; + while (shift >= 8) { + result[index++] = (byte) current; + current >>>= 8; + shift -= 8; + } + } + } + + return result; + } + + private static byte[] encodeCompress(short[] poly) { + byte[] result = new byte[ML_KEM_N / 8]; + int xx; + int currentByte; + for (int i = 0; i < ML_KEM_N / 8; i++) { + currentByte = 0; + xx = poly[i * 8]; + currentByte |= (((832 - xx) & (xx - 2497)) >>> 31); + xx = poly[i * 8 + 1]; + currentByte |= ((((832 - xx) & (xx - 2497)) >>> 30) & 2); + xx = poly[i * 8 + 2]; + currentByte |= ((((832 - xx) & (xx - 2497)) >>> 29) & 4); + xx = poly[i * 8 + 3]; + currentByte |= ((((832 - xx) & (xx - 2497)) >>> 28) & 8); + xx = poly[i * 8 + 4]; + currentByte |= ((((832 - xx) & (xx - 2497)) >>> 27) & 16); + xx = poly[i * 8 + 5]; + currentByte |= ((((832 - xx) & (xx - 2497)) >>> 26) & 32); + xx = poly[i * 8 + 6]; + currentByte |= ((((832 - xx) & (xx - 2497)) >>> 25) & 64); + xx = poly[i * 8 + 7]; + currentByte |= ((((832 - xx) & (xx - 2497)) >>> 24) & 128); + result[i] = (byte) currentByte; + } + return result; + } + + private short[][] decodeVector(int l, byte[] encodedVector) { + short[][] result = new short[mlKem_k][]; + for (int i = 0; i < mlKem_k; i++) { + result[i] = decodePoly(l, encodedVector, (i * ML_KEM_N * l) / 8); + } + return result; + } + + // The intrinsic implementations assume that the input and output buffers + // are such that condensed can be read in 192-byte chunks and + // parsed can be written in 128 shorts chunks. In other words, + // if (i - 1) * 128 < parsedLengths <= i * 128 then + // parsed.size should be at least i * 128 and + // condensed.size should be at least index + i * 192 + private void twelve2Sixteen(byte[] condensed, int index, + short[] parsed, int parsedLength) { + + for (int i = 0; i < parsedLength * 3 / 2; i += 3) { + parsed[(i / 3) * 2] = (short) ((condensed[i + index] & 0xff) + + 256 * (condensed[i + index + 1] & 0xf)); + parsed[(i / 3) * 2 + 1] = (short) (((condensed[i + index + 1] >>> 4) & 0xf) + + 16 * (condensed[i + index + 2] & 0xff)); + } + } + + private static void decodePoly5(byte[] condensed, int index, short[] parsed) { + int j = index; + for (int i = 0; i < ML_KEM_N; i += 8) { + parsed[i] = (short) (condensed[j] & 0x1f); + parsed[i + 1] = (short) ((((condensed[j] & 0xff) >>> 5) + + (condensed[j + 1] << 3) & 0x1f)); + parsed[i + 2] = (short) ((condensed[j + 1] & 0x7f) >>> 2); + parsed[i + 3] = (short) ((((condensed[j + 1] & 0xff) >>> 7) + + (condensed[j + 2] << 1)) & 0x1f); + parsed[i + 4] = (short) ((((condensed[j + 2] & 0xff) >>> 4) + + (condensed[j + 3] << 4)) & 0x1f); + parsed[i + 5] = (short) ((condensed[j + 3] & 0x3f) >>> 1); + parsed[i + 6] = (short) ((((condensed[j + 3] & 0xff) >>> 6) + + (condensed[j + 4] << 2)) & 0x1f); + parsed[i + 7] = (short) ((condensed[j + 4] & 0xff) >>> 3); + j += 5; + } + } + + private static void decodePoly4(byte[] condensed, int index, short[] parsed) { + for (int i = 0; i < ML_KEM_N / 2; i++) { + parsed[i * 2] = (short) (condensed[i + index] & 0xf); + parsed[i * 2 + 1] = (short) ((condensed[i + index] >>> 4) & 0xf); + } + } + + // Recovers the 16-bit coefficients of a polynomial from a byte array + // containing a packed l-bit representation. + // The recovered coefficients will be in the range 0 <= coeff < 2^l . + private short[] decodePoly(int l, byte[] input, int index) { + short[] poly = new short[ML_KEM_N]; + if (l == 12) { + twelve2Sixteen(input, index, poly, ML_KEM_N); + } else if (l == 4) { + decodePoly4(input, index, poly); + } else if (l == 5) { + decodePoly5(input, index, poly); + } else { + int mask = (1 << l) - 1; + int top = 0; + int shift = 0; + int acc = 0; + for (int m = 0; m < ML_KEM_N; m++) { + while (top - shift < l) { + acc += ((input[index++] & 0xff) << top); + top += 8; + } + poly[m] = (short) ((acc >> shift) & mask); + shift += l; + while (shift >= 8) { + top -= 8; + shift -= 8; + acc >>>= 8; + } + } + } + + return poly; + } + + // Prerequisite: d == 10 or d == 11 + // Compresses a vector in place, i.e. it modifies the coefficients of the + // polynomials of its input vector. It returns its (modified) input so that + // the function can be used in an expression. + private short[][] compressVector10_11(short[][] vector, int d) { + for (int i = 0; i < mlKem_k; i++) { + vector[i] = compressPoly10_11(vector[i], d); + } + return vector; + } + + // Prerequisite: for all m, 0 <= poly[m] < ML_KEM_Q, d == 4 or d == 5 + // Replaces poly[m] with round(2^d * poly[m] / ML_KEM_Q) mod 2^d for all m, + // where round(z) is the integer closest to z, i.e. + // compresses a polynomial in place. + private static short[] compressPoly4_5(short[] poly, int d) { + int xx; + for (int m = 0; m < ML_KEM_N; m++) { + xx = (poly[m] << d) + ML_KEM_Q / 2; + poly[m] = (short)((xx * 315) >> 20); + } + return poly; + } + + // Prerequisite: for all m, 0 <= poly[m] < ML_KEM_Q, d == 10 or d == 11 + // Replaces poly[m] with round(2^d * poly[m] / ML_KEM_Q) mod 2^d for all m, + // where round(z) is the integer closest to z, i.e. + // compresses a polynomial in place. + private static short[] compressPoly10_11(short[] poly, int d) { + long xx; + for (int m = 0; m < ML_KEM_N; m++) { + xx = (poly[m] << d) + ML_KEM_Q / 2; + poly[m] = (short)((xx * 161271L) >> 29); + } + return poly; + } + + // Decompresses a vector in place, i.e. it modifies the coefficients of the + // polynomials of its input vector. It returns its (modified) input so that + // the function can be used in an expression. + private short[][] decompressVector(short[][] vector, int d) { + for (int i = 0; i < mlKem_k; i++) { + vector[i] = decompressPoly(vector[i], d); + } + return vector; + } + + // Decompresses a polynomial in place, i.e. it modifies the coefficients + // in its input. It returns its (modified) input so that the function can + // be used in an expression. + // Prerequisite: 0 <= x[i] < 2^d < ML_KEM_Q . + // Computes Round(ML_KEM_Q * x[i] / 2^d), + // where Round(z) is the integer closest to z, + // for each coefficient of a polynomial + private static short[] decompressPoly(short[] poly, int d) { + for (int m = 0; m < ML_KEM_N; m++) { + int qx = ML_KEM_Q * poly[m]; + poly[m] = (short) ((qx >> d) + ((qx >> (d - 1)) & 1)); + } + return poly; + } + + private static short[] decompressDecode(byte[] input) { + short[] result = new short[256]; + for (int i = 0; i < 32; i++) { + int currentByte = input[i] & 0xFF; + result [i * 8] = (short)(((currentByte << 31 ) >> 31) & 1665); + result [i * 8 + 1] = (short)(((currentByte << 30 ) >> 31) & 1665); + result [i * 8 + 2] = (short)(((currentByte << 29 ) >> 31) & 1665); + result [i * 8 + 3] = (short)(((currentByte << 28 ) >> 31) & 1665); + result [i * 8 + 4] = (short)(((currentByte << 27 ) >> 31) & 1665); + result [i * 8 + 5] = (short)(((currentByte << 26 ) >> 31) & 1665); + result [i * 8 + 6] = (short)(((currentByte << 25 ) >> 31) & 1665); + result [i * 8 + 7] = (short)(((currentByte << 24 ) >> 31) & 1665); + } + return result; + } + + // The input elements can have any short value. + // Modifies poly such that upon return poly[i] will be + // in the range [0, ML_KEM_Q] and will be congruent with the original + // poly[i] modulo ML_KEM_Q, for all i in [0, ML_KEM_N). + // At return, poly[i] == ML_KEM_Q if and only if the original poly[i] was + // a negative integer multiple of ML_KEM_Q. + // That means that if the original poly[i] > -ML_KEM_Q then at return it + // will be in the range [0, ML_KEM_Q), i.e. it will be the canonical + // representative of its residue class. + private void mlKemBarrettReduce(short[] poly) { + for (int m = 0; m < ML_KEM_N; m++) { + int tmp = ((int) poly[m] * BARRETT_MULTIPLIER) >> BARRETT_SHIFT; + poly[m] = (short) (poly[m] - tmp * ML_KEM_Q); + } + } + + // Precondition: -(2^MONT_R_BITS -1) * MONT_Q <= b * c < (2^MONT_R_BITS - 1) * MONT_Q + // Computes b * c * 2^-MONT_R_BITS mod MONT_Q + // The result is between -MONT_Q and MONT_Q + private static int montMul(int b, int c) { + int a = b * c; + int aHigh = a >> MONT_R_BITS; + int aLow = a & ((1 << MONT_R_BITS) - 1); + // signed low product + int m = ((MONT_Q_INV_MOD_R * aLow) << (32 - MONT_R_BITS)) >> (32 - MONT_R_BITS); + + return (aHigh - ((m * MONT_Q) >> MONT_R_BITS)); // subtract signed high product + } +} diff --git a/src/java.base/share/classes/com/sun/crypto/provider/ML_KEM_Impls.java b/src/java.base/share/classes/com/sun/crypto/provider/ML_KEM_Impls.java new file mode 100644 index 000000000000..2ce5b3324e76 --- /dev/null +++ b/src/java.base/share/classes/com/sun/crypto/provider/ML_KEM_Impls.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.crypto.provider; + +import sun.security.jca.JCAUtil; +import sun.security.provider.NamedKEM; +import sun.security.provider.NamedKeyFactory; +import sun.security.provider.NamedKeyPairGenerator; + +import java.security.*; +import java.util.Arrays; + +import javax.crypto.DecapsulateException; + +public final class ML_KEM_Impls { + + public sealed static class KPG + extends NamedKeyPairGenerator permits KPG2, KPG3, KPG5 { + + public KPG() { + // ML-KEM-768 is the default + super("ML-KEM", "ML-KEM-768", "ML-KEM-512", "ML-KEM-1024"); + } + + protected KPG(String pname) { + super("ML-KEM", pname); + } + + @Override + protected byte[][] implGenerateKeyPair(String name, SecureRandom random) { + byte[] seed = new byte[32]; + var r = random != null ? random : JCAUtil.getDefSecureRandom(); + r.nextBytes(seed); + byte[] z = new byte[32]; + r.nextBytes(z); + + ML_KEM mlKem = new ML_KEM(name); + ML_KEM.ML_KEM_KeyPair kp; + try { + kp = mlKem.generateKemKeyPair(seed, z); + } finally { + Arrays.fill(seed, (byte)0); + Arrays.fill(z, (byte)0); + } + return new byte[][] { + kp.encapsulationKey().keyBytes(), + kp.decapsulationKey().keyBytes() + }; + } + } + + public final static class KPG2 extends KPG { + public KPG2() { + super("ML-KEM-512"); + } + } + + public final static class KPG3 extends KPG { + public KPG3() { + super("ML-KEM-768"); + } + } + + public final static class KPG5 extends KPG { + public KPG5() { + super("ML-KEM-1024"); + } + } + + public sealed static class KF extends NamedKeyFactory permits KF2, KF3, KF5 { + public KF() { + super("ML-KEM", "ML-KEM-512", "ML-KEM-768", "ML-KEM-1024"); + } + public KF(String name) { + super("ML-KEM", name); + } + } + + public final static class KF2 extends KF { + public KF2() { + super("ML-KEM-512"); + } + } + + public final static class KF3 extends KF { + public KF3() { + super("ML-KEM-768"); + } + } + + public final static class KF5 extends KF { + public KF5() { + super("ML-KEM-1024"); + } + } + + public sealed static class K extends NamedKEM permits K2, K3, K5 { + private static final int SEED_SIZE = 32; + + @Override + protected byte[][] implEncapsulate(String name, byte[] encapsulationKey, + Object ek, SecureRandom secureRandom) { + + byte[] randomBytes = new byte[SEED_SIZE]; + var r = secureRandom != null ? secureRandom : JCAUtil.getDefSecureRandom(); + r.nextBytes(randomBytes); + + ML_KEM mlKem = new ML_KEM(name); + ML_KEM.ML_KEM_EncapsulateResult mlKemEncapsulateResult = null; + try { + mlKemEncapsulateResult = mlKem.encapsulate( + new ML_KEM.ML_KEM_EncapsulationKey( + encapsulationKey), randomBytes); + } finally { + Arrays.fill(randomBytes, (byte) 0); + } + + return new byte[][] { + mlKemEncapsulateResult.cipherText().encryptedBytes(), + mlKemEncapsulateResult.sharedSecret() + }; + } + + @Override + protected byte[] implDecapsulate(String name, byte[] decapsulationKey, + Object dk, byte[] cipherText) + throws DecapsulateException { + + ML_KEM mlKem = new ML_KEM(name); + var kpkeCipherText = new ML_KEM.K_PKE_CipherText(cipherText); + return mlKem.decapsulate(new ML_KEM.ML_KEM_DecapsulationKey( + decapsulationKey), kpkeCipherText); + } + + @Override + protected int implSecretSize(String name) { + return ML_KEM.SECRET_SIZE; + } + + @Override + protected int implEncapsulationSize(String name) { + ML_KEM mlKem = new ML_KEM(name); + return mlKem.getEncapsulationSize(); + } + + @Override + protected Object implCheckPublicKey(String name, byte[] pk) + throws InvalidKeyException { + + ML_KEM mlKem = new ML_KEM(name); + return mlKem.checkPublicKey(pk); + } + + @Override + protected Object implCheckPrivateKey(String name, byte[] sk) + throws InvalidKeyException { + + ML_KEM mlKem = new ML_KEM(name); + return mlKem.checkPrivateKey(sk); + } + + public K() { + super("ML-KEM", "ML-KEM-512", "ML-KEM-768", "ML-KEM-1024"); + } + + public K(String name) { + super("ML-KEM", name); + } + } + + public final static class K2 extends K { + public K2() { + super("ML-KEM-512"); + } + } + + public final static class K3 extends K { + public K3() { + super("ML-KEM-768"); + } + } + + public final static class K5 extends K { + public K5() { + super("ML-KEM-1024"); + } + } +} diff --git a/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java b/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java index 6a4e28372e50..0a5cb1abc4d9 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java @@ -78,6 +78,8 @@ * * - DHKEM * + * - ML-KEM + * */ public final class SunJCE extends Provider { @@ -87,7 +89,7 @@ public final class SunJCE extends Provider { private static final String info = "SunJCE Provider " + "(implements RSA, DES, Triple DES, AES, Blowfish, ARCFOUR, RC2, PBE, " - + "Diffie-Hellman, HMAC, ChaCha20)"; + + "Diffie-Hellman, HMAC, ChaCha20, DHKEM, and ML-KEM)"; /* Are we debugging? -- for developers */ static final boolean debug = false; @@ -759,6 +761,23 @@ void putEntries() { "|java.security.interfaces.XECKey"); ps("KEM", "DHKEM", "com.sun.crypto.provider.DHKEM", null, attrs); + attrs.clear(); + attrs.put("ImplementedIn", "Software"); + ps("KEM", "ML-KEM", "com.sun.crypto.provider.ML_KEM_Impls$K", null, attrs); + psA("KEM", "ML-KEM-512", "com.sun.crypto.provider.ML_KEM_Impls$K2", attrs); + psA("KEM", "ML-KEM-768", "com.sun.crypto.provider.ML_KEM_Impls$K3", attrs); + psA("KEM", "ML-KEM-1024", "com.sun.crypto.provider.ML_KEM_Impls$K5",attrs); + + ps("KeyPairGenerator", "ML-KEM", "com.sun.crypto.provider.ML_KEM_Impls$KPG", null, attrs); + psA("KeyPairGenerator", "ML-KEM-512", "com.sun.crypto.provider.ML_KEM_Impls$KPG2", attrs); + psA("KeyPairGenerator", "ML-KEM-768", "com.sun.crypto.provider.ML_KEM_Impls$KPG3", attrs); + psA("KeyPairGenerator", "ML-KEM-1024", "com.sun.crypto.provider.ML_KEM_Impls$KPG5", attrs); + + ps("KeyFactory", "ML-KEM", "com.sun.crypto.provider.ML_KEM_Impls$KF", null, attrs); + psA("KeyFactory", "ML-KEM-512", "com.sun.crypto.provider.ML_KEM_Impls$KF2", attrs); + psA("KeyFactory", "ML-KEM-768", "com.sun.crypto.provider.ML_KEM_Impls$KF3", attrs); + psA("KeyFactory", "ML-KEM-1024", "com.sun.crypto.provider.ML_KEM_Impls$KF5", attrs); + /* * SSL/TLS mechanisms * diff --git a/src/java.base/share/classes/java/lang/ref/Reference.java b/src/java.base/share/classes/java/lang/ref/Reference.java index ef4fd1ef20fc..b78be26dee76 100644 --- a/src/java.base/share/classes/java/lang/ref/Reference.java +++ b/src/java.base/share/classes/java/lang/ref/Reference.java @@ -357,11 +357,18 @@ public ReferenceQueue newNativeReferenceQueue() { * {@code null} if this reference object has been cleared * @see #refersTo */ - @IntrinsicCandidate public T get() { - return this.referent; + return get0(); } + /* Implementation of get(). This method exists to avoid making get() all + * of virtual, native, and intrinsic candidate. That could have the + * undesirable effect of having the native method used instead of the + * intrinsic when devirtualization fails. + */ + @IntrinsicCandidate + private native T get0(); + /** * Tests if the referent of this reference object is {@code obj}. * Using a {@code null} {@code obj} returns {@code true} if the diff --git a/src/java.base/share/classes/java/util/zip/ZipFile.java b/src/java.base/share/classes/java/util/zip/ZipFile.java index cb9070fc885d..07a5fa0b8970 100644 --- a/src/java.base/share/classes/java/util/zip/ZipFile.java +++ b/src/java.base/share/classes/java/util/zip/ZipFile.java @@ -1544,7 +1544,7 @@ private final int readAt(byte[] buf, int off, int len, long pos) private static class End { - int centot; // 4 bytes + long centot; // 4 bytes long cenlen; // 4 bytes long cenoff; // 4 bytes long endpos; // 4 bytes @@ -1639,7 +1639,7 @@ private End findEND() throws IOException { // to use the end64 values end.cenlen = cenlen64; end.cenoff = cenoff64; - end.centot = (int)centot64; // assume total < 2g + end.centot = centot64; end.endpos = end64pos; } catch (IOException x) {} // no zip64 loc/end return end; @@ -1675,11 +1675,14 @@ private void initCEN(int knownTotal) throws IOException { if (end.cenlen + ENDHDR >= Integer.MAX_VALUE) { zerror("invalid END header (central directory size too large)"); } + if (end.centot < 0 || end.centot > end.cenlen / CENHDR) { + zerror("invalid END header (total entries count too large)"); + } cen = this.cen = new byte[(int)(end.cenlen + ENDHDR)]; if (readFullyAt(cen, 0, cen.length, cenpos) != end.cenlen + ENDHDR) { zerror("read CEN tables failed"); } - this.total = end.centot; + this.total = Math.toIntExact(end.centot); } else { cen = this.cen; this.total = knownTotal; diff --git a/src/java.base/share/classes/sun/security/pkcs/NamedPKCS8Key.java b/src/java.base/share/classes/sun/security/pkcs/NamedPKCS8Key.java new file mode 100644 index 000000000000..b46234ba2882 --- /dev/null +++ b/src/java.base/share/classes/sun/security/pkcs/NamedPKCS8Key.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.security.pkcs; + +import sun.security.util.DerInputStream; +import sun.security.util.DerValue; +import sun.security.x509.AlgorithmId; + +import javax.security.auth.DestroyFailedException; +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.io.Serial; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.ProviderException; +import java.security.spec.NamedParameterSpec; +import java.util.Arrays; + +/// Represents a private key from an algorithm family that is specialized +/// with a named parameter set. +/// +/// This key is generated by either a [sun.security.provider.NamedKeyPairGenerator] +/// or [sun.security.provider.NamedKeyFactory]. Its [#getAlgorithm] method +/// returns the algorithm family name, while its [#getParams()] method returns +/// the parameter set name as a [NamedParameterSpec] object. The algorithm +/// identifier in the PKCS #8 encoding of the key is always a single OID derived +/// from the parameter set name. +/// +/// @see sun.security.provider.NamedKeyPairGenerator +public final class NamedPKCS8Key extends PKCS8Key { + @Serial + private static final long serialVersionUID = 1L; + + private final String fname; + private final transient NamedParameterSpec paramSpec; + private final byte[] rawBytes; + + private transient boolean destroyed = false; + + /// Ctor from family name, parameter set name, raw key bytes. + /// Key bytes won't be cloned, caller must relinquish ownership + public NamedPKCS8Key(String fname, String pname, byte[] rawBytes) { + this.fname = fname; + this.paramSpec = new NamedParameterSpec(pname); + try { + this.algid = AlgorithmId.get(pname); + } catch (NoSuchAlgorithmException e) { + throw new ProviderException(e); + } + this.rawBytes = rawBytes; + + DerValue val = new DerValue(DerValue.tag_OctetString, rawBytes); + try { + this.key = val.toByteArray(); + } finally { + val.clear(); + } + } + + /// Ctor from family name, and PKCS #8 bytes + public NamedPKCS8Key(String fname, byte[] encoded) throws InvalidKeyException { + super(encoded); + this.fname = fname; + try { + paramSpec = new NamedParameterSpec(algid.getName()); + if (algid.getEncodedParams() != null) { + throw new InvalidKeyException("algorithm identifier has params"); + } + rawBytes = new DerInputStream(key).getOctetString(); + } catch (IOException e) { + throw new InvalidKeyException("Cannot parse input", e); + } + } + + @Override + public String toString() { + // Do not modify: this can be used by earlier JDKs that + // do not have the getParams() method + return paramSpec.getName() + " private key"; + } + + /// Returns the reference to the internal key. Caller must not modify + /// the content or keep a reference. + public byte[] getRawBytes() { + return rawBytes; + } + + public NamedParameterSpec getParams() { + return paramSpec; + } + + @Override + public String getAlgorithm() { + return fname; + } + + @java.io.Serial + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + throw new InvalidObjectException( + "NamedPKCS8Key keys are not directly deserializable"); + } + + @Override + public void destroy() throws DestroyFailedException { + Arrays.fill(rawBytes, (byte)0); + Arrays.fill(key, (byte)0); + if (encodedKey != null) { + Arrays.fill(encodedKey, (byte)0); + } + destroyed = true; + } + + @Override + public boolean isDestroyed() { + return destroyed; + } +} diff --git a/src/java.base/share/classes/sun/security/pkcs/PKCS7.java b/src/java.base/share/classes/sun/security/pkcs/PKCS7.java index 302b5922bbc7..5f05af1c07e7 100644 --- a/src/java.base/share/classes/sun/security/pkcs/PKCS7.java +++ b/src/java.base/share/classes/sun/security/pkcs/PKCS7.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,7 +38,7 @@ import java.util.function.Function; import sun.security.jca.JCAUtil; -import sun.security.provider.SHAKE256; +import sun.security.provider.SHA3.SHAKE256; import sun.security.timestamp.*; import sun.security.util.*; import sun.security.x509.*; diff --git a/src/java.base/share/classes/sun/security/pkcs/SignerInfo.java b/src/java.base/share/classes/sun/security/pkcs/SignerInfo.java index 8f430f7b6b2b..6151069ea9a5 100644 --- a/src/java.base/share/classes/sun/security/pkcs/SignerInfo.java +++ b/src/java.base/share/classes/sun/security/pkcs/SignerInfo.java @@ -32,7 +32,7 @@ import java.security.spec.PSSParameterSpec; import java.util.*; -import sun.security.provider.SHAKE256; +import sun.security.provider.SHA3.SHAKE256; import sun.security.timestamp.TimestampToken; import sun.security.util.*; import sun.security.x509.AlgorithmId; diff --git a/src/java.base/share/classes/sun/security/provider/DigestBase.java b/src/java.base/share/classes/sun/security/provider/DigestBase.java index dbe59396ac0b..2aaf0a2fac6f 100644 --- a/src/java.base/share/classes/sun/security/provider/DigestBase.java +++ b/src/java.base/share/classes/sun/security/provider/DigestBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,7 +61,7 @@ abstract class DigestBase extends MessageDigestSpi implements Cloneable { private final int digestLength; // size of the input to the compression function in bytes - private final int blockSize; + protected final int blockSize; // buffer to store partial blocks, blockSize bytes large // Subclasses should not access this array directly except possibly in their // implDigest() method. See MD5.java as an example. diff --git a/src/java.base/share/classes/sun/security/provider/ML_DSA.java b/src/java.base/share/classes/sun/security/provider/ML_DSA.java new file mode 100644 index 000000000000..969b8fffa39f --- /dev/null +++ b/src/java.base/share/classes/sun/security/provider/ML_DSA.java @@ -0,0 +1,1567 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.security.provider; + +import jdk.internal.vm.annotation.IntrinsicCandidate; +import sun.security.provider.SHA3.SHAKE128; +import sun.security.provider.SHA3.SHAKE256; +import sun.security.provider.SHA3Parallel.Shake128Parallel; + +import java.security.InvalidAlgorithmParameterException; +import java.security.MessageDigest; +import java.security.InvalidKeyException; +import java.security.SignatureException; +import java.util.Arrays; + +public class ML_DSA { + // Security level constants + static final int ML_DSA_44 = 2; + static final int ML_DSA_65 = 3; + static final int ML_DSA_87 = 5; + + // Constants from FIPS 204 that do not depend on security level + private static final int ML_DSA_D = 13; + private static final int ML_DSA_Q = 8380417; + private static final int ML_DSA_N = 256; + private static final int SHAKE256_BLOCK_SIZE = 136; // the block length for SHAKE256 + private static final int SHAKE128_BLOCK_SIZE = 168; // the block length for SHAKE128 + private final int A_SEED_LEN = 32; + private final int S1S2_SEED_LEN = 64; + private final int K_LEN = 32; + private final int TR_LEN = 64; + private final int MU_LEN = 64; + private final int MASK_SEED_LEN = 64; + private static final int D_MASK = (1 << ML_DSA_D) - 1; + private final int T0_COEFF_SIZE = 13; + + private static final int MONT_R_BITS = 32; + private static final long MONT_R = 4294967296L; // 1 << MONT_R_BITS + private static final int MONT_Q = 8380417; + private static final int MONT_R_SQUARE_MOD_Q = 2365951; + private static final int MONT_Q_INV_MOD_R = 58728449; + private static final int MONT_R_MOD_Q = 4193792; + // toMont((ML_DSA_N)^-1 (mod ML_DSA_Q)) + private static final int MONT_DIM_INVERSE = 16382; + + // Zeta values for NTT with montgomery factor precomputed + private static final int[] MONT_ZETAS_FOR_NTT = new int[]{ + 25847, -2608894, -518909, 237124, -777960, -876248, 466468, 1826347, + 2353451, -359251, -2091905, 3119733, -2884855, 3111497, 2680103, 2725464, + 1024112, -1079900, 3585928, -549488, -1119584, 2619752, -2108549, -2118186, + -3859737, -1399561, -3277672, 1757237, -19422, 4010497, 280005, 2706023, + 95776, 3077325, 3530437, -1661693, -3592148, -2537516, 3915439, -3861115, + -3043716, 3574422, -2867647, 3539968, -300467, 2348700, -539299, -1699267, + -1643818, 3505694, -3821735, 3507263, -2140649, -1600420, 3699596, 811944, + 531354, 954230, 3881043, 3900724, -2556880, 2071892, -2797779, -3930395, + -1528703, -3677745, -3041255, -1452451, 3475950, 2176455, -1585221, -1257611, + 1939314, -4083598, -1000202, -3190144, -3157330, -3632928, 126922, 3412210, + -983419, 2147896, 2715295, -2967645, -3693493, -411027, -2477047, -671102, + -1228525, -22981, -1308169, -381987, 1349076, 1852771, -1430430, -3343383, + 264944, 508951, 3097992, 44288, -1100098, 904516, 3958618, -3724342, + -8578, 1653064, -3249728, 2389356, -210977, 759969, -1316856, 189548, + -3553272, 3159746, -1851402, -2409325, -177440, 1315589, 1341330, 1285669, + -1584928, -812732, -1439742, -3019102, -3881060, -3628969, 3839961, 2091667, + 3407706, 2316500, 3817976, -3342478, 2244091, -2446433, -3562462, 266997, + 2434439, -1235728, 3513181, -3520352, -3759364, -1197226, -3193378, 900702, + 1859098, 909542, 819034, 495491, -1613174, -43260, -522500, -655327, + -3122442, 2031748, 3207046, -3556995, -525098, -768622, -3595838, 342297, + 286988, -2437823, 4108315, 3437287, -3342277, 1735879, 203044, 2842341, + 2691481, -2590150, 1265009, 4055324, 1247620, 2486353, 1595974, -3767016, + 1250494, 2635921, -3548272, -2994039, 1869119, 1903435, -1050970, -1333058, + 1237275, -3318210, -1430225, -451100, 1312455, 3306115, -1962642, -1279661, + 1917081, -2546312, -1374803, 1500165, 777191, 2235880, 3406031, -542412, + -2831860, -1671176, -1846953, -2584293, -3724270, 594136, -3776993, -2013608, + 2432395, 2454455, -164721, 1957272, 3369112, 185531, -1207385, -3183426, + 162844, 1616392, 3014001, 810149, 1652634, -3694233, -1799107, -3038916, + 3523897, 3866901, 269760, 2213111, -975884, 1717735, 472078, -426683, + 1723600, -1803090, 1910376, -1667432, -1104333, -260646, -3833893, -2939036, + -2235985, -420899, -2286327, 183443, -976891, 1612842, -3545687, -554416, + 3919660, -48306, -1362209, 3937738, 1400424, -846154, 1976782 + }; + private static final int[] MONT_ZETAS_FOR_VECTOR_NTT = new int[]{ + 25847, 25847, 25847, 25847, 25847, 25847, 25847, 25847, + 25847, 25847, 25847, 25847, 25847, 25847, 25847, 25847, + 25847, 25847, 25847, 25847, 25847, 25847, 25847, 25847, + 25847, 25847, 25847, 25847, 25847, 25847, 25847, 25847, + 25847, 25847, 25847, 25847, 25847, 25847, 25847, 25847, + 25847, 25847, 25847, 25847, 25847, 25847, 25847, 25847, + 25847, 25847, 25847, 25847, 25847, 25847, 25847, 25847, + 25847, 25847, 25847, 25847, 25847, 25847, 25847, 25847, + 25847, 25847, 25847, 25847, 25847, 25847, 25847, 25847, + 25847, 25847, 25847, 25847, 25847, 25847, 25847, 25847, + 25847, 25847, 25847, 25847, 25847, 25847, 25847, 25847, + 25847, 25847, 25847, 25847, 25847, 25847, 25847, 25847, + 25847, 25847, 25847, 25847, 25847, 25847, 25847, 25847, + 25847, 25847, 25847, 25847, 25847, 25847, 25847, 25847, + 25847, 25847, 25847, 25847, 25847, 25847, 25847, 25847, + 25847, 25847, 25847, 25847, 25847, 25847, 25847, 25847, + + -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, + -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, + -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, + -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, + -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, + -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, + -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, + -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, -2608894, + -518909, -518909, -518909, -518909, -518909, -518909, -518909, -518909, + -518909, -518909, -518909, -518909, -518909, -518909, -518909, -518909, + -518909, -518909, -518909, -518909, -518909, -518909, -518909, -518909, + -518909, -518909, -518909, -518909, -518909, -518909, -518909, -518909, + -518909, -518909, -518909, -518909, -518909, -518909, -518909, -518909, + -518909, -518909, -518909, -518909, -518909, -518909, -518909, -518909, + -518909, -518909, -518909, -518909, -518909, -518909, -518909, -518909, + -518909, -518909, -518909, -518909, -518909, -518909, -518909, -518909, + + 237124, 237124, 237124, 237124, 237124, 237124, 237124, 237124, + 237124, 237124, 237124, 237124, 237124, 237124, 237124, 237124, + 237124, 237124, 237124, 237124, 237124, 237124, 237124, 237124, + 237124, 237124, 237124, 237124, 237124, 237124, 237124, 237124, + -777960, -777960, -777960, -777960, -777960, -777960, -777960, -777960, + -777960, -777960, -777960, -777960, -777960, -777960, -777960, -777960, + -777960, -777960, -777960, -777960, -777960, -777960, -777960, -777960, + -777960, -777960, -777960, -777960, -777960, -777960, -777960, -777960, + -876248, -876248, -876248, -876248, -876248, -876248, -876248, -876248, + -876248, -876248, -876248, -876248, -876248, -876248, -876248, -876248, + -876248, -876248, -876248, -876248, -876248, -876248, -876248, -876248, + -876248, -876248, -876248, -876248, -876248, -876248, -876248, -876248, + 466468, 466468, 466468, 466468, 466468, 466468, 466468, 466468, + 466468, 466468, 466468, 466468, 466468, 466468, 466468, 466468, + 466468, 466468, 466468, 466468, 466468, 466468, 466468, 466468, + 466468, 466468, 466468, 466468, 466468, 466468, 466468, 466468, + + 1826347, 1826347, 1826347, 1826347, 1826347, 1826347, 1826347, 1826347, + 1826347, 1826347, 1826347, 1826347, 1826347, 1826347, 1826347, 1826347, + 2353451, 2353451, 2353451, 2353451, 2353451, 2353451, 2353451, 2353451, + 2353451, 2353451, 2353451, 2353451, 2353451, 2353451, 2353451, 2353451, + -359251, -359251, -359251, -359251, -359251, -359251, -359251, -359251, + -359251, -359251, -359251, -359251, -359251, -359251, -359251, -359251, + -2091905, -2091905, -2091905, -2091905, -2091905, -2091905, -2091905, -2091905, + -2091905, -2091905, -2091905, -2091905, -2091905, -2091905, -2091905, -2091905, + 3119733, 3119733, 3119733, 3119733, 3119733, 3119733, 3119733, 3119733, + 3119733, 3119733, 3119733, 3119733, 3119733, 3119733, 3119733, 3119733, + -2884855, -2884855, -2884855, -2884855, -2884855, -2884855, -2884855, -2884855, + -2884855, -2884855, -2884855, -2884855, -2884855, -2884855, -2884855, -2884855, + 3111497, 3111497, 3111497, 3111497, 3111497, 3111497, 3111497, 3111497, + 3111497, 3111497, 3111497, 3111497, 3111497, 3111497, 3111497, 3111497, + 2680103, 2680103, 2680103, 2680103, 2680103, 2680103, 2680103, 2680103, + 2680103, 2680103, 2680103, 2680103, 2680103, 2680103, 2680103, 2680103, + + 2725464, 2725464, 2725464, 2725464, 2725464, 2725464, 2725464, 2725464, + 1024112, 1024112, 1024112, 1024112, 1024112, 1024112, 1024112, 1024112, + -1079900, -1079900, -1079900, -1079900, -1079900, -1079900, -1079900, -1079900, + 3585928, 3585928, 3585928, 3585928, 3585928, 3585928, 3585928, 3585928, + -549488, -549488, -549488, -549488, -549488, -549488, -549488, -549488, + -1119584, -1119584, -1119584, -1119584, -1119584, -1119584, -1119584, -1119584, + 2619752, 2619752, 2619752, 2619752, 2619752, 2619752, 2619752, 2619752, + -2108549, -2108549, -2108549, -2108549, -2108549, -2108549, -2108549, -2108549, + -2118186, -2118186, -2118186, -2118186, -2118186, -2118186, -2118186, -2118186, + -3859737, -3859737, -3859737, -3859737, -3859737, -3859737, -3859737, -3859737, + -1399561, -1399561, -1399561, -1399561, -1399561, -1399561, -1399561, -1399561, + -3277672, -3277672, -3277672, -3277672, -3277672, -3277672, -3277672, -3277672, + 1757237, 1757237, 1757237, 1757237, 1757237, 1757237, 1757237, 1757237, + -19422, -19422, -19422, -19422, -19422, -19422, -19422, -19422, + 4010497, 4010497, 4010497, 4010497, 4010497, 4010497, 4010497, 4010497, + 280005, 280005, 280005, 280005, 280005, 280005, 280005, 280005, + + 2706023, 2706023, 2706023, 2706023, 95776, 95776, 95776, 95776, + 3077325, 3077325, 3077325, 3077325, 3530437, 3530437, 3530437, 3530437, + -1661693, -1661693, -1661693, -1661693, -3592148, -3592148, -3592148, -3592148, + -2537516, -2537516, -2537516, -2537516, 3915439, 3915439, 3915439, 3915439, + -3861115, -3861115, -3861115, -3861115, -3043716, -3043716, -3043716, -3043716, + 3574422, 3574422, 3574422, 3574422, -2867647, -2867647, -2867647, -2867647, + 3539968, 3539968, 3539968, 3539968, -300467, -300467, -300467, -300467, + 2348700, 2348700, 2348700, 2348700, -539299, -539299, -539299, -539299, + -1699267, -1699267, -1699267, -1699267, -1643818, -1643818, -1643818, -1643818, + 3505694, 3505694, 3505694, 3505694, -3821735, -3821735, -3821735, -3821735, + 3507263, 3507263, 3507263, 3507263, -2140649, -2140649, -2140649, -2140649, + -1600420, -1600420, -1600420, -1600420, 3699596, 3699596, 3699596, 3699596, + 811944, 811944, 811944, 811944, 531354, 531354, 531354, 531354, + 954230, 954230, 954230, 954230, 3881043, 3881043, 3881043, 3881043, + 3900724, 3900724, 3900724, 3900724, -2556880, -2556880, -2556880, -2556880, + 2071892, 2071892, 2071892, 2071892, -2797779, -2797779, -2797779, -2797779, + + -3930395, -3930395, -1528703, -1528703, -3677745, -3677745, -3041255, -3041255, + -1452451, -1452451, 3475950, 3475950, 2176455, 2176455, -1585221, -1585221, + -1257611, -1257611, 1939314, 1939314, -4083598, -4083598, -1000202, -1000202, + -3190144, -3190144, -3157330, -3157330, -3632928, -3632928, 126922, 126922, + 3412210, 3412210, -983419, -983419, 2147896, 2147896, 2715295, 2715295, + -2967645, -2967645, -3693493, -3693493, -411027, -411027, -2477047, -2477047, + -671102, -671102, -1228525, -1228525, -22981, -22981, -1308169, -1308169, + -381987, -381987, 1349076, 1349076, 1852771, 1852771, -1430430, -1430430, + -3343383, -3343383, 264944, 264944, 508951, 508951, 3097992, 3097992, + 44288, 44288, -1100098, -1100098, 904516, 904516, 3958618, 3958618, + -3724342, -3724342, -8578, -8578, 1653064, 1653064, -3249728, -3249728, + 2389356, 2389356, -210977, -210977, 759969, 759969, -1316856, -1316856, + 189548, 189548, -3553272, -3553272, 3159746, 3159746, -1851402, -1851402, + -2409325, -2409325, -177440, -177440, 1315589, 1315589, 1341330, 1341330, + 1285669, 1285669, -1584928, -1584928, -812732, -812732, -1439742, -1439742, + -3019102, -3019102, -3881060, -3881060, -3628969, -3628969, 3839961, 3839961, + + 2091667, 3407706, 2316500, 3817976, -3342478, 2244091, -2446433, -3562462, + 266997, 2434439, -1235728, 3513181, -3520352, -3759364, -1197226, -3193378, + 900702, 1859098, 909542, 819034, 495491, -1613174, -43260, -522500, + -655327, -3122442, 2031748, 3207046, -3556995, -525098, -768622, -3595838, + 342297, 286988, -2437823, 4108315, 3437287, -3342277, 1735879, 203044, + 2842341, 2691481, -2590150, 1265009, 4055324, 1247620, 2486353, 1595974, + -3767016, 1250494, 2635921, -3548272, -2994039, 1869119, 1903435, -1050970, + -1333058, 1237275, -3318210, -1430225, -451100, 1312455, 3306115, -1962642, + -1279661, 1917081, -2546312, -1374803, 1500165, 777191, 2235880, 3406031, + -542412, -2831860, -1671176, -1846953, -2584293, -3724270, 594136, -3776993, + -2013608, 2432395, 2454455, -164721, 1957272, 3369112, 185531, -1207385, + -3183426, 162844, 1616392, 3014001, 810149, 1652634, -3694233, -1799107, + -3038916, 3523897, 3866901, 269760, 2213111, -975884, 1717735, 472078, + -426683, 1723600, -1803090, 1910376, -1667432, -1104333, -260646, -3833893, + -2939036, -2235985, -420899, -2286327, 183443, -976891, 1612842, -3545687, + -554416, 3919660, -48306, -1362209, 3937738, 1400424, -846154, 1976782 + }; + + private static final int[] MONT_ZETAS_FOR_VECTOR_INVERSE_NTT = new int[]{ + -1976782, 846154, -1400424, -3937738, 1362209, 48306, -3919660, 554416, + 3545687, -1612842, 976891, -183443, 2286327, 420899, 2235985, 2939036, + 3833893, 260646, 1104333, 1667432, -1910376, 1803090, -1723600, 426683, + -472078, -1717735, 975884, -2213111, -269760, -3866901, -3523897, 3038916, + 1799107, 3694233, -1652634, -810149, -3014001, -1616392, -162844, 3183426, + 1207385, -185531, -3369112, -1957272, 164721, -2454455, -2432395, 2013608, + 3776993, -594136, 3724270, 2584293, 1846953, 1671176, 2831860, 542412, + -3406031, -2235880, -777191, -1500165, 1374803, 2546312, -1917081, 1279661, + 1962642, -3306115, -1312455, 451100, 1430225, 3318210, -1237275, 1333058, + 1050970, -1903435, -1869119, 2994039, 3548272, -2635921, -1250494, 3767016, + -1595974, -2486353, -1247620, -4055324, -1265009, 2590150, -2691481, -2842341, + -203044, -1735879, 3342277, -3437287, -4108315, 2437823, -286988, -342297, + 3595838, 768622, 525098, 3556995, -3207046, -2031748, 3122442, 655327, + 522500, 43260, 1613174, -495491, -819034, -909542, -1859098, -900702, + 3193378, 1197226, 3759364, 3520352, -3513181, 1235728, -2434439, -266997, + 3562462, 2446433, -2244091, 3342478, -3817976, -2316500, -3407706, -2091667, + + -3839961, -3839961, 3628969, 3628969, 3881060, 3881060, 3019102, 3019102, + 1439742, 1439742, 812732, 812732, 1584928, 1584928, -1285669, -1285669, + -1341330, - 1341330, -1315589, -1315589, 177440, 177440, 2409325, 2409325, + 1851402, 1851402, -3159746, -3159746, 3553272, 3553272, -189548, -189548, + 1316856, 1316856, -759969, -759969, 210977, 210977, -2389356, -2389356, + 3249728, 3249728, -1653064, -1653064, 8578, 8578, 3724342, 3724342, + -3958618, -3958618, -904516, -904516, 1100098, 1100098, -44288, -44288, + -3097992, -3097992, -508951, -508951, -264944, -264944, 3343383, 3343383, + 1430430, 1430430, -1852771, -1852771, -1349076, -1349076, 381987, 381987, + 1308169, 1308169, 22981, 22981, 1228525, 1228525, 671102, 671102, + 2477047, 2477047, 411027, 411027, 3693493, 3693493, 2967645, 2967645, + -2715295, -2715295, -2147896, -2147896, 983419, 983419, -3412210, -3412210, + -126922, -126922, 3632928, 3632928, 3157330, 3157330, 3190144, 3190144, + 1000202, 1000202, 4083598, 4083598, -1939314, -1939314, 1257611, 1257611, + 1585221, 1585221, -2176455, -2176455, -3475950, -3475950, 1452451, 1452451, + 3041255, 3041255, 3677745, 3677745, 1528703, 1528703, 3930395, 3930395, + + 2797779, 2797779, 2797779, 2797779, -2071892, -2071892, -2071892, -2071892, + 2556880, 2556880, 2556880, 2556880, -3900724, -3900724, -3900724, -3900724, + -3881043, -3881043, -3881043, -3881043, -954230, -954230, -954230, -954230, + -531354, -531354, -531354, -531354, -811944, -811944, -811944, -811944, + -3699596, -3699596, -3699596, -3699596, 1600420, 1600420, 1600420, 1600420, + 2140649, 2140649, 2140649, 2140649, -3507263, -3507263, -3507263, -3507263, + 3821735, 3821735, 3821735, 3821735, -3505694, -3505694, -3505694, -3505694, + 1643818, 1643818, 1643818, 1643818, 1699267, 1699267, 1699267, 1699267, + 539299, 539299, 539299, 539299, -2348700, -2348700, -2348700, -2348700, + 300467, 300467, 300467, 300467, -3539968, -3539968, -3539968, -3539968, + 2867647, 2867647, 2867647, 2867647, -3574422, -3574422, -3574422, -3574422, + 3043716, 3043716, 3043716, 3043716, 3861115, 3861115, 3861115, 3861115, + -3915439, -3915439, -3915439, -3915439, 2537516, 2537516, 2537516, 2537516, + 3592148, 3592148, 3592148, 3592148, 1661693, 1661693, 1661693, 1661693, + -3530437, -3530437, -3530437, -3530437, -3077325, -3077325, -3077325, -3077325, + -95776, -95776, -95776, -95776, -2706023, -2706023, -2706023, -2706023, + + -280005, -280005, -280005, -280005, -280005, -280005, -280005, -280005, + -4010497, -4010497, -4010497, -4010497, -4010497, -4010497, -4010497, -4010497, + 19422, 19422, 19422, 19422, 19422, 19422, 19422, 19422, + -1757237, -1757237, -1757237, -1757237, -1757237, -1757237, -1757237, -1757237, + 3277672, 3277672, 3277672, 3277672, 3277672, 3277672, 3277672, 3277672, + 1399561, 1399561, 1399561, 1399561, 1399561, 1399561, 1399561, 1399561, + 3859737, 3859737, 3859737, 3859737, 3859737, 3859737, 3859737, 3859737, + 2118186, 2118186, 2118186, 2118186, 2118186, 2118186, 2118186, 2118186, + 2108549, 2108549, 2108549, 2108549, 2108549, 2108549, 2108549, 2108549, + -2619752, -2619752, -2619752, -2619752, -2619752, -2619752, -2619752, -2619752, + 1119584, 1119584, 1119584, 1119584, 1119584, 1119584, 1119584, 1119584, + 549488, 549488, 549488, 549488, 549488, 549488, 549488, 549488, + -3585928, -3585928, -3585928, -3585928, -3585928, -3585928, -3585928, -3585928, + 1079900, 1079900, 1079900, 1079900, 1079900, 1079900, 1079900, 1079900, + -1024112, -1024112, -1024112, -1024112, -1024112, -1024112, -1024112, -1024112, + -2725464, -2725464, -2725464, -2725464, -2725464, -2725464, -2725464, -2725464, + + -2680103, -2680103, -2680103, -2680103, -2680103, -2680103, -2680103, -2680103, + -2680103, -2680103, -2680103, -2680103, -2680103, -2680103, -2680103, -2680103, + -3111497, -3111497, -3111497, -3111497, -3111497, -3111497, -3111497, -3111497, + -3111497, -3111497, -3111497, -3111497, -3111497, -3111497, -3111497, -3111497, + 2884855, 2884855, 2884855, 2884855, 2884855, 2884855, 2884855, 2884855, + 2884855, 2884855, 2884855, 2884855, 2884855, 2884855, 2884855, 2884855, + -3119733, -3119733, -3119733, -3119733, -3119733, -3119733, -3119733, -3119733, + -3119733, -3119733, -3119733, -3119733, -3119733, -3119733, -3119733, -3119733, + 2091905, 2091905, 2091905, 2091905, 2091905, 2091905, 2091905, 2091905, + 2091905, 2091905, 2091905, 2091905, 2091905, 2091905, 2091905, 2091905, + 359251, 359251, 359251, 359251, 359251, 359251, 359251, 359251, + 359251, 359251, 359251, 359251, 359251, 359251, 359251, 359251, + -2353451, -2353451, -2353451, -2353451, -2353451, -2353451, -2353451, -2353451, + -2353451, -2353451, -2353451, -2353451, -2353451, -2353451, -2353451, -2353451, + -1826347, -1826347, -1826347, -1826347, -1826347, -1826347, -1826347, -1826347, + -1826347, -1826347, -1826347, -1826347, -1826347, -1826347, -1826347, -1826347, + + -466468, -466468, -466468, -466468, -466468, -466468, -466468, -466468, + -466468, -466468, -466468, -466468, -466468, -466468, -466468, -466468, + -466468, -466468, -466468, -466468, -466468, -466468, -466468, -466468, + -466468, -466468, -466468, -466468, -466468, -466468, -466468, -466468, + 876248, 876248, 876248, 876248, 876248, 876248, 876248, 876248, + 876248, 876248, 876248, 876248, 876248, 876248, 876248, 876248, + 876248, 876248, 876248, 876248, 876248, 876248, 876248, 876248, + 876248, 876248, 876248, 876248, 876248, 876248, 876248, 876248, + 777960, 777960, 777960, 777960, 777960, 777960, 777960, 777960, + 777960, 777960, 777960, 777960, 777960, 777960, 777960, 777960, + 777960, 777960, 777960, 777960, 777960, 777960, 777960, 777960, + 777960, 777960, 777960, 777960, 777960, 777960, 777960, 777960, + -237124, -237124, -237124, -237124, -237124, -237124, -237124, -237124, + -237124, -237124, -237124, -237124, -237124, -237124, -237124, -237124, + -237124, -237124, -237124, -237124, -237124, -237124, -237124, -237124, + -237124, -237124, -237124, -237124, -237124, -237124, -237124, -237124, + + 518909, 518909, 518909, 518909, 518909, 518909, 518909, 518909, + 518909, 518909, 518909, 518909, 518909, 518909, 518909, 518909, + 518909, 518909, 518909, 518909, 518909, 518909, 518909, 518909, + 518909, 518909, 518909, 518909, 518909, 518909, 518909, 518909, + 518909, 518909, 518909, 518909, 518909, 518909, 518909, 518909, + 518909, 518909, 518909, 518909, 518909, 518909, 518909, 518909, + 518909, 518909, 518909, 518909, 518909, 518909, 518909, 518909, + 518909, 518909, 518909, 518909, 518909, 518909, 518909, 518909, + 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, + 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, + 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, + 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, + 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, + 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, + 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, + 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, 2608894, + + -25847, -25847, -25847, -25847, -25847, -25847, -25847, -25847, + -25847, -25847, -25847, -25847, -25847, -25847, -25847, -25847, + -25847, -25847, -25847, -25847, -25847, -25847, -25847, -25847, + -25847, -25847, -25847, -25847, -25847, -25847, -25847, -25847, + -25847, -25847, -25847, -25847, -25847, -25847, -25847, -25847, + -25847, -25847, -25847, -25847, -25847, -25847, -25847, -25847, + -25847, -25847, -25847, -25847, -25847, -25847, -25847, -25847, + -25847, -25847, -25847, -25847, -25847, -25847, -25847, -25847, + -25847, -25847, -25847, -25847, -25847, -25847, -25847, -25847, + -25847, -25847, -25847, -25847, -25847, -25847, -25847, -25847, + -25847, -25847, -25847, -25847, -25847, -25847, -25847, -25847, + -25847, -25847, -25847, -25847, -25847, -25847, -25847, -25847, + -25847, -25847, -25847, -25847, -25847, -25847, -25847, -25847, + -25847, -25847, -25847, -25847, -25847, -25847, -25847, -25847, + -25847, -25847, -25847, -25847, -25847, -25847, -25847, -25847, + -25847, -25847, -25847, -25847, -25847, -25847, -25847, -25847 + }; + + // Constants defined for each security level + private final int level; + private final int tau; + private final int lambda; + private final int gamma1; + private final int gamma2; + private final int mlDsa_k; + private final int mlDsa_l; + private final int eta; + private final int beta; + private final int omega; + + // Second-class constants derived from above values + // log_2(gamma1) + private final int gamma1Bits; + // mlDsa_l * (eta + 1) * 256 / 8 + private final int s1PackedLength; + // mlDsa_k * (eta + 1) * 256 / 8 + private final int s2PackedLength; + // mlDsa_k * ML_DSA_D * 256 / 8 + private final int t0PackedLength; + // log_2(eta) + 1 + private final int s1s2CoeffSize; + // rho_size + t1_size + private final int publicKeyLength; + // c_tilde_size + z_size + h_size + private final int signatureLength; + // mlDsa_k * log_2((q-1)/(2*gamma2) - 1) * 256 / 8 + private final int wCoeffSize; + + public ML_DSA(int security_level) { + switch (security_level) { + case ML_DSA_44: + level = 2; + tau = 39; + lambda = 128; + gamma1 = 1 << 17; + gamma1Bits = 17; + gamma2 = (ML_DSA_Q - 1) / 88; + mlDsa_k = 4; + mlDsa_l = 4; + eta = 2; + beta = 78; + omega = 80; + publicKeyLength = 1312; + signatureLength = 2420; + s1PackedLength = 384; + s2PackedLength = 384; + t0PackedLength = 1664; + s1s2CoeffSize = 3; + wCoeffSize = 6; + break; + case ML_DSA_65: + level = 3; + tau = 49; + lambda = 192; + gamma1 = 1 << 19; + gamma2 = (ML_DSA_Q - 1) / 32; + mlDsa_k = 6; + mlDsa_l = 5; + eta = 4; + beta = 196; + omega = 55; + publicKeyLength = 1952; + signatureLength = 3293; + s1PackedLength = 640; + s2PackedLength = 768; + t0PackedLength = 2496; + s1s2CoeffSize = 4; + wCoeffSize = 4; + gamma1Bits = 19; + break; + case ML_DSA_87: + level = 4; + tau = 60; + lambda = 256; + gamma1 = 1 << 19; + gamma1Bits = 19; + gamma2 = (ML_DSA_Q - 1) / 32; + mlDsa_k = 8; + mlDsa_l = 7; + eta = 2; + beta = 120; + omega = 75; + publicKeyLength = 2592; + signatureLength = 4595; + s1PackedLength = 672; + s2PackedLength = 768; + t0PackedLength = 3328; + s1s2CoeffSize = 3; + wCoeffSize = 4; + break; + default: + throw new IllegalArgumentException("Wrong security level"); + } + } + + public record ML_DSA_PrivateKey(byte[] rho, byte[] k, byte[] tr, + int[][] s1, int[][] s2, int[][] t0) { + void destroy() { + Arrays.fill(k, (byte)0); + for (var b : s1) { + Arrays.fill(b, (byte) 0); + } + for (var b : s2) { + Arrays.fill(b, (byte) 0); + } + for (var b : t0) { + Arrays.fill(b, (byte) 0); + } + } + } + + public record ML_DSA_PublicKey(byte[] rho, int[][] t1) { + } + + public record ML_DSA_KeyPair(ML_DSA_PrivateKey privateKey, + ML_DSA_PublicKey publicKey) { + } + + public record ML_DSA_Signature(byte[] commitmentHash, + int[][] response, boolean[][] hint) { + } + + /* + Key validity checks + */ + public Object checkPublicKey(byte[] pk) throws InvalidKeyException { + int pk_size = 32 + (mlDsa_k * 32 * (23 - ML_DSA_D)); + if (pk.length != pk_size) { + throw new InvalidKeyException("Incorrect public key size"); + } + return null; + } + + public Object checkPrivateKey(byte[] sk) throws InvalidKeyException { + int eta_bits = eta == 4 ? 4 : 3; + + //SK size is 128 + 32 * ((l + k) * bitlen(2*eta) + d*k) + int sk_size = 128 + 32 * ((mlDsa_l + mlDsa_k) * eta_bits + ML_DSA_D * mlDsa_k); + if (sk.length != sk_size) { + throw new InvalidKeyException("Incorrect private key size"); + } + return null; + } + + //Internal functions in Section 6 of specification + public ML_DSA_KeyPair generateKeyPairInternal(byte[] randomBytes) { + //Initialize hash functions + var hash = new SHAKE256(0); + var crHash = new SHAKE256(TR_LEN); + + //Expand seed + hash.update(randomBytes); + hash.update((byte)mlDsa_k); + hash.update((byte)mlDsa_l); + byte[] rho = hash.squeeze(A_SEED_LEN); + byte[] rhoPrime = hash.squeeze(S1S2_SEED_LEN); + byte[] k = hash.squeeze(K_LEN); + hash.reset(); + + //Sample A + int[][][] keygenA = generateA(rho); //A is in NTT domain + + //Sample S1 and S2 + int[][] s1 = new int[mlDsa_l][ML_DSA_N]; + int[][] s2 = new int[mlDsa_k][ML_DSA_N]; + //hash is reset before being used in sampleS1S2 + sampleS1S2(s1, s2, hash, rhoPrime); + + //Compute t and tr + mlDsaVectorNtt(s1); //s1 now in NTT domain + int[][] As1 = new int[mlDsa_k][ML_DSA_N]; + matrixVectorPointwiseMultiply(As1, keygenA, s1); + mlDsaVectorInverseNtt(s1); //take s1 out of NTT domain + + mlDsaVectorInverseNtt(As1); + int[][] t = vectorAddPos(As1, s2); + int[][] t0 = new int[mlDsa_k][ML_DSA_N]; + int[][] t1 = new int[mlDsa_k][ML_DSA_N]; + power2Round(t, t0, t1); + + //Encode PK and SK + ML_DSA_PublicKey pk = new ML_DSA_PublicKey(rho, t1); + byte[] publicKeyBytes = pkEncode(pk); + crHash.update(publicKeyBytes); + byte[] tr = crHash.digest(); + ML_DSA_PrivateKey sk = new ML_DSA_PrivateKey(rho, k, tr, s1, s2, t0); + + return new ML_DSA_KeyPair(sk, pk); + } + + public ML_DSA_Signature signInternal(byte[] message, byte[] rnd, byte[] skBytes) { + //Decode private key and initialize hash function + ML_DSA_PrivateKey sk = skDecode(skBytes); + var hash = new SHAKE256(0); + + //Do some NTTs + mlDsaVectorNtt(sk.s1()); + mlDsaVectorNtt(sk.s2()); + mlDsaVectorNtt(sk.t0()); + int[][][] aHat = generateA(sk.rho()); + + //Compute mu + hash.update(sk.tr()); + hash.update(message); + byte[] mu = hash.squeeze(MU_LEN); + hash.reset(); + + //Compute rho' + hash.update(sk.k()); + hash.update(rnd); + hash.update(mu); + byte[] rhoDoublePrime = hash.squeeze(MASK_SEED_LEN); + hash.reset(); + + //Initialize vectors used in loop + int[][] z = new int[mlDsa_l][ML_DSA_N]; + boolean[][] h = new boolean[mlDsa_k][ML_DSA_N]; + byte[] commitmentHash = new byte[lambda/4]; + int[][] y = new int[mlDsa_l][ML_DSA_N]; + int[][] yy = new int[mlDsa_l][ML_DSA_N]; + int[][] w = new int[mlDsa_k][ML_DSA_N]; + int[][] w0 = new int[mlDsa_k][ML_DSA_N]; + int[][] w1 = new int[mlDsa_k][ML_DSA_N]; + int[][] w_ct0 = new int[mlDsa_k][ML_DSA_N]; + int[] c = new int[ML_DSA_N]; + int[][] cs1 = new int[mlDsa_l][ML_DSA_N]; + int[][] cs2 = new int[mlDsa_k][ML_DSA_N]; + int[][] ct0 = new int[mlDsa_k][ML_DSA_N]; + + int kappa = 0; + while (true) { + expandMask(y, rhoDoublePrime, kappa); + + //Save non-ntt version of y for later use + for (int i = 0; i < y.length; i++) { + System.arraycopy(y[i], 0, yy[i], 0, ML_DSA_N); + } + + //Compute w and w1 + mlDsaVectorNtt(y); //y is now in NTT domain + matrixVectorPointwiseMultiply(w, aHat, y); + mlDsaVectorInverseNtt(w); //w is now in normal domain + decompose(w, w0, w1); + //mlDsaVectorInverseNtt(y); + + //Get commitment hash + hash.update(mu); + hash.update(simpleBitPack(wCoeffSize, w1)); + commitmentHash = hash.squeeze(lambda/4); + hash.reset(); + + //Get z and r0 + sampleInBall(c, commitmentHash); + mlDsaNtt(c); //c is now in NTT domain + nttConstMultiply(cs1, c, sk.s1()); + nttConstMultiply(cs2, c, sk.s2()); + mlDsaVectorInverseNtt(cs1); + mlDsaVectorInverseNtt(cs2); + z = vectorAdd(z, yy, cs1); + + //w0 = w0 - cs2 (this is r0 in the spec) + vectorSub(w0, cs2, false); + + //Update z and h + kappa += mlDsa_l; + if (vectorNormBound(z, gamma1 - beta) || + vectorNormBound(w0, gamma2 - beta)) { + continue; + } else { + nttConstMultiply(ct0, c, sk.t0()); + mlDsaVectorInverseNtt(ct0); + w = vectorSub(w, cs2, false); + int hint_weight = makeHint(h, w, vectorAdd(w_ct0, w, ct0)); + if (vectorNormBound(ct0, gamma2) || (hint_weight > omega)) { + continue; + } + } + sk.destroy(); + return new ML_DSA_Signature(commitmentHash, z, h); + } + } + + public boolean verifyInternal(byte[] pkBytes, byte[] message, byte[] sigBytes) + throws SignatureException { + //Decode sig and initialize hash + ML_DSA_Signature sig = sigDecode(sigBytes); + var hash = new SHAKE256(0); + + //Decode pk + ML_DSA_PublicKey pk = pkDecode(pkBytes); + + //Expand A + int[][][] aHat = generateA(pk.rho()); + + //Generate tr + hash.update(pkBytes); + byte[] tr = hash.squeeze(TR_LEN); + hash.reset(); + + //Generate mu + hash.update(tr); + hash.update(message); + byte[] mu = hash.squeeze(MU_LEN); + hash.reset(); + + //Get verifiers challenge + int[] cHat = new int[ML_DSA_N]; + sampleInBall(cHat, sig.commitmentHash()); + mlDsaNtt(cHat); + + //Compute response norm and put it in NTT domain + boolean zNorm = vectorNormBound(sig.response(), gamma1 - beta); + mlDsaVectorNtt(sig.response()); + + //Reconstruct signer's commitment + int[][] aHatZ = new int[mlDsa_k][ML_DSA_N]; + matrixVectorPointwiseMultiply(aHatZ, aHat, sig.response()); + + int[][] t1Hat = vectorConstMul(1 << ML_DSA_D, pk.t1()); + mlDsaVectorNtt(t1Hat); + + int[][] ct1 = new int[mlDsa_k][ML_DSA_N]; + nttConstMultiply(ct1, cHat, t1Hat); + + int[][] wApprox = vectorSub(aHatZ, ct1, true); + mlDsaVectorInverseNtt(wApprox); + int[][] w1Prime = useHint(sig.hint(), wApprox); + + //Hash signer's commitment + hash.update(mu); + hash.update(simpleBitPack(wCoeffSize, w1Prime)); + byte[] cTildePrime = hash.squeeze(lambda/4); + + //Check verify conditions + boolean hashEq = MessageDigest.isEqual(sig.commitmentHash(), cTildePrime); + return !zNorm && hashEq; + } + + /* + Data conversion functions in Section 7.1 of specification + */ + + // Bit-pack the t1 and w1 vector into a byte array. + // The coefficients of the polynomials in the vector should be + // nonnegative and less than 2^bitsPerCoeff . + public byte[] simpleBitPack(int bitsPerCoeff, int[][] vector) { + byte[] result = new byte[(mlDsa_k * ML_DSA_N * bitsPerCoeff) / 8]; + int acc = 0; + int shift = 0; + int i = 0; + for (int[] poly : vector) { + for (int m = 0; m < ML_DSA_N; m++) { + acc += (poly[m] << shift); + shift += bitsPerCoeff; + while (shift >= 8) { + result[i++] = (byte) acc; + acc >>= 8; + shift -= 8; + } + } + } // Shift must now be 0 so we have all output bits + return result; + } + + public void bitPack(int[][] vector, int bitsPerCoeff, int maxValue, + byte[] output, int offset) { + int vecLen = vector.length; + int acc = 0; + int shift = 0; + for (int[] poly : vector) { + for (int m = 0; m < ML_DSA_N; m++) { + acc += (maxValue - poly[m]) << shift; + shift += bitsPerCoeff; + while (shift >= 8) { + output[offset++] = (byte) acc; + acc >>= 8; + shift -= 8; + } + } + } + } + + //This is simpleBitUnpack from FIPS 204. Since it is only called on the + //vector t1 we can optimize for that case + public int[][] t1Unpack(byte[] v) { + int[][] t1 = new int[mlDsa_k][ML_DSA_N]; + for (int i = 0; i < mlDsa_k; i++) { + for (int j = 0; j < ML_DSA_N / 4; j++) { + int tOffset = j*4; + int vOffset = (i*320) + (j*5); + t1[i][tOffset] = (v[vOffset] & 0xFF) + + ((v[vOffset+1] << 8) & 0x3FF); + t1[i][tOffset+1] = ((v[vOffset+1] >> 2) & 0x3F) + + ((v[vOffset+2] << 6) & 0x3FF); + t1[i][tOffset+2] = ((v[vOffset+2] >> 4) & 0xF) + + ((v[vOffset+3] << 4) & 0x3FF); + t1[i][tOffset+3] = ((v[vOffset+3] >> 6) & 0x3) + + ((v[vOffset+4] << 2) & 0x3FF); + } + } + return t1; + } + + public int[][] bitUnpack(int[][] result, byte[] v, int offset, int dim, + int maxValue, int bitsPerCoeff) { + + switch (bitsPerCoeff) { + case 3 -> { bitUnpackGeneral(result, v, offset, dim, maxValue, 3); } + case 4 -> { bitUnpackGeneral(result, v, offset, dim, maxValue, 4); } + case 13 -> { bitUnpackGeneral(result, v, offset, dim, maxValue, 13); } + case 18 -> { bitUnpack18(result, v, offset, dim, maxValue); } + case 20 -> { bitUnpack20(result, v, offset, dim, maxValue); } + default -> throw new RuntimeException( + "Wrong bitsPerCoeff value in bitUnpack (" + bitsPerCoeff + ")."); + } + return result; + } + public void bitUnpackGeneral(int[][] result, + byte[] v, int offset, int dim, int maxValue, int bitsPerCoeff) { + + int mask = (1 << bitsPerCoeff) - 1; + int top = 0; + int shift = 0; + int acc = 0; + for (int i = 0; i < dim; i++) { + for (int j = 0; j < ML_DSA_N; j++) { + while (top - shift < bitsPerCoeff) { + acc += ((v[offset++] & 0xff) << top); + top += 8; + } + result[i][j] = maxValue - ((acc >> shift) & mask); + shift += bitsPerCoeff; + while (shift >= 8) { + top -= 8; + shift -= 8; + acc >>>= 8; + } + } + } + } + public void bitUnpack18(int [][] result, byte[] v, int offset, + int dim, int maxValue) { + + int vIndex = offset; + for (int i = 0; i < dim; i++) { + for (int j = 0; j < ML_DSA_N; j += 4) { + result[i][j] = maxValue - ((v[vIndex] & 0xff) + + ((v[vIndex + 1] & 0xff) << 8) + + ((v[vIndex + 2] & 0x3) << 16)); + result[i][j + 1] = maxValue - (((v[vIndex + 2] >> 2) & 0x3f) + + ((v[vIndex + 3] & 0xff) << 6) + + ((v[vIndex + 4] & 0xf) << 14)); + result[i][j + 2] = maxValue - (((v[vIndex + 4] >> 4) & 0xf) + + ((v[vIndex + 5] & 0xff) << 4) + + ((v[vIndex + 6] & 0x3f) << 12)); + result[i][j + 3] = maxValue - (((v[vIndex + 6] >> 6) & 0x3) + + ((v[vIndex + 7] & 0xff) << 2) + + ((v[vIndex + 8] & 0xff) << 10)); + vIndex += 9; + } + } + } + + public void bitUnpack20(int[][] result, byte[] v, int offset, + int dim, int maxValue) { + int vIndex = offset; + + for (int i = 0; i < dim; i++) { + for (int j = 0; j < ML_DSA_N; j += 2) { + result[i][j] = maxValue - ((v[vIndex] & 0xff) + + ((v[vIndex + 1] & 0xff) << 8) + + ((v[vIndex + 2] & 0xf) << 16)); + result[i][j + 1] = maxValue - (((v[vIndex + 2] >> 4) & 0xf) + + ((v[vIndex + 3] & 0xff) << 4) + + ((v[vIndex + 4] & 0xff) << 12)); + vIndex += 5; + } + } + } + + private void hintBitPack(boolean[][] h, byte[] buffer, int offset) { + int idx = 0; + for (int i = 0; i < mlDsa_k; i++) { + for (int j = 0; j < ML_DSA_N; j++) { + if (h[i][j]) { + buffer[offset + idx] = (byte)j; + idx++; + } + } + buffer[offset + omega + i] = (byte)idx; + } + } + + private boolean[][] hintBitUnpack(byte[] y, int offset) { + boolean[][] h = new boolean[mlDsa_k][ML_DSA_N]; + int idx = 0; + for (int i = 0; i < mlDsa_k; i++) { + int j = y[offset + omega + i]; + if (j < idx || j > omega) { + return null; + } + int first = idx; + while (idx < j) { + if (idx > first) { + if ((y[offset + idx - 1] & 0xff) >= (y[offset + idx] & 0xff)) { + return null; + } + } + int hintIndex = y[offset + idx] & 0xff; + h[i][hintIndex] = true; + idx++; + } + } + + while (idx < omega) { + if (y[offset + idx] != 0) { + return null; + } + idx++; + } + return h; + } + + /* + Encoding functions as specified in Section 7.2 of the specification + */ + + public byte[] pkEncode(ML_DSA_PublicKey key) { + byte[] t1Packed = simpleBitPack(10, key.t1); + byte[] publicKeyBytes = new byte[A_SEED_LEN + t1Packed.length]; + System.arraycopy(key.rho, 0, publicKeyBytes, 0, A_SEED_LEN); + System.arraycopy(t1Packed, 0, publicKeyBytes, A_SEED_LEN, t1Packed.length); + + return publicKeyBytes; + } + + public ML_DSA_PublicKey pkDecode(byte[] pk) { + byte[] rho = Arrays.copyOfRange(pk, 0, A_SEED_LEN); + byte[] v = Arrays.copyOfRange(pk, A_SEED_LEN, pk.length); + int[][] t1 = t1Unpack(v); + return new ML_DSA_PublicKey(rho, t1); + } + + public byte[] skEncode(ML_DSA_PrivateKey key) { + + byte[] skBytes = new byte[A_SEED_LEN + K_LEN + key.tr.length + + s1PackedLength + s2PackedLength + t0PackedLength]; + + int pos = 0; + System.arraycopy(key.rho, 0, skBytes, pos, A_SEED_LEN); + pos += A_SEED_LEN; + System.arraycopy(key.k, 0, skBytes, pos, K_LEN); + pos += K_LEN; + System.arraycopy(key.tr, 0, skBytes, pos, TR_LEN); + pos += TR_LEN; + + bitPack(key.s1, s1s2CoeffSize, eta, skBytes, pos); + pos += s1PackedLength; + bitPack(key.s2, s1s2CoeffSize, eta, skBytes, pos); + pos += s2PackedLength; + bitPack(key.t0, T0_COEFF_SIZE, 1 << 12, skBytes, pos); + + return skBytes; + } + + public ML_DSA_PrivateKey skDecode(byte[] sk) { + byte[] rho = new byte[A_SEED_LEN]; + System.arraycopy(sk, 0, rho, 0, A_SEED_LEN); + + byte[] k = new byte[K_LEN]; + System.arraycopy(sk, A_SEED_LEN, k, 0, K_LEN); + + byte[] tr = new byte[TR_LEN]; + System.arraycopy(sk, A_SEED_LEN + K_LEN, tr, 0, TR_LEN); + + //Parse s1 + int start = A_SEED_LEN + K_LEN + TR_LEN; + int end = start + (32 * mlDsa_l * s1s2CoeffSize); + int[][] s1 = new int[mlDsa_l][ML_DSA_N]; + bitUnpack(s1, sk, start, mlDsa_l, eta, s1s2CoeffSize); + + //Parse s2 + start = end; + end += 32 * s1s2CoeffSize * mlDsa_k; + int[][] s2 = new int[mlDsa_k][ML_DSA_N]; + bitUnpack(s2, sk, start, mlDsa_k, eta, s1s2CoeffSize); + + //Parse t0 + start = end; + int[][] t0 = new int[mlDsa_k][ML_DSA_N]; + bitUnpack(t0, sk, start, mlDsa_k, 1 << 12, T0_COEFF_SIZE); + + return new ML_DSA_PrivateKey(rho, k, tr, s1, s2, t0); + } + + public byte[] sigEncode(ML_DSA_Signature sig) { + int cSize = lambda / 4; + int zSize = mlDsa_l * 32 * (1 + gamma1Bits); + + byte[] sigBytes = new byte[cSize + zSize + omega + mlDsa_k]; + + System.arraycopy(sig.commitmentHash, 0, sigBytes, 0, cSize); + bitPack(sig.response, gamma1Bits + 1, gamma1, sigBytes, cSize); + hintBitPack(sig.hint, sigBytes, cSize + zSize); + + return sigBytes; + } + + public ML_DSA_Signature sigDecode(byte[] sig) throws SignatureException { + + int cSize = lambda / 4; + int zSize = mlDsa_l * 32 * (1 + gamma1Bits); + + int sigLen = cSize + zSize + omega + mlDsa_k; + if (sig.length != sigLen) { + throw new SignatureException("Incorrect signature length"); + } + + //Decode cTilde + byte[] cTilde = Arrays.copyOfRange(sig, 0, lambda/4); + + //Decode z + int start = cSize; + int end = start + zSize; + int[][] z = new int[mlDsa_l][ML_DSA_N]; + bitUnpack(z, sig, start, mlDsa_l, gamma1, gamma1Bits + 1); + + //Decode h + start = end; + boolean[][] h = hintBitUnpack(sig, start); + if (h == null) { + throw new SignatureException("Invalid hints encoding"); + } + + return new ML_DSA_Signature(cTilde, z, h); + } + + /* + Auxiliary functions defined in Section 7.3 of specification + */ + + private class Shake256Slicer { + SHAKE256 xof; + byte[] block; + int byteOffset; + int current; + int bitsInCurrent; + int bitsPerCall; + int bitMask; + + Shake256Slicer(SHAKE256 xof, int bitsPerCall) { + this.xof = xof; + //BitsPerCall can only be 4 (when called from sampleS1S2), + //or 8 (when called from sampleInBall) + this.bitsPerCall = bitsPerCall; + bitMask = (1 << bitsPerCall) - 1; + current = 0; + byteOffset = SHAKE256_BLOCK_SIZE; + bitsInCurrent = 0; + block = new byte[SHAKE256_BLOCK_SIZE]; + } + + void reset() { + xof.reset(); + current = 0; + byteOffset = SHAKE256_BLOCK_SIZE; + bitsInCurrent = 0; + } + + int squeezeBits() { + while (bitsInCurrent < bitsPerCall) { + if (byteOffset == SHAKE256_BLOCK_SIZE) { + xof.squeeze(block, 0, SHAKE256_BLOCK_SIZE); + byteOffset = 0; + } + current += ((block[byteOffset++] & 0xff) << bitsInCurrent); + bitsInCurrent += 8; + } + int result = current & bitMask; + current >>= bitsPerCall; + bitsInCurrent -= bitsPerCall; + return result; + } + } + + private void sampleInBall(int[] c, byte[] rho) { + var xof = new SHAKE256(0); + Shake256Slicer slicer = new Shake256Slicer(xof, 8); + xof.update(rho); + + long parity = 0; + for (int i = 0; i < 8; i++) { + long sample = slicer.squeezeBits(); + parity |= sample << 8 * i; + } + + Arrays.fill(c, 0); + + int k = 8; + for (int i = 256 - tau; i < 256; i++) { + //Get random index < i + int j = slicer.squeezeBits(); + while (j > i) { + j = slicer.squeezeBits(); + } + + //Swap c[i] and c[j], set c[j] based on parity + c[i] = c[j]; + c[j] = (int) (1 - 2 * (parity & 1)); + parity >>= 1; + } + } + + private int[][][] generateA(byte[] seed) { + int[][][] a = new int[mlDsa_k][mlDsa_l][]; + + int nrPar = 2; + int rhoLen = seed.length; + byte[] seedBuf = new byte[SHAKE128_BLOCK_SIZE]; + System.arraycopy(seed, 0, seedBuf, 0, seed.length); + seedBuf[rhoLen + 2] = 0x1F; + seedBuf[SHAKE128_BLOCK_SIZE - 1] = (byte)0x80; + byte[][] xofBufArr = new byte[nrPar][SHAKE128_BLOCK_SIZE]; + int[] iIndex = new int[nrPar]; + int[] jIndex = new int[nrPar]; + + int[] parsedBuf = new int[SHAKE128_BLOCK_SIZE / 3]; + + int parInd = 0; + boolean allDone; + int[] ofs = new int[nrPar]; + Arrays.fill(ofs, 0); + int[][] aij = new int[nrPar][]; + try { + Shake128Parallel parXof = new Shake128Parallel(xofBufArr); + + for (int i = 0; i < mlDsa_k; i++) { + for (int j = 0; j < mlDsa_l; j++) { + xofBufArr[parInd] = seedBuf.clone(); + xofBufArr[parInd][rhoLen] = (byte) j; + xofBufArr[parInd][rhoLen + 1] = (byte) i; + iIndex[parInd] = i; + jIndex[parInd] = j; + ofs[parInd] = 0; + aij[parInd] = new int[ML_DSA_N]; + parInd++; + + if ((parInd == nrPar) || + ((i == mlDsa_k - 1) && (j == mlDsa_l - 1))) { + parXof.reset(xofBufArr); + + allDone = false; + while (!allDone) { + allDone = true; + parXof.squeezeBlock(); + for (int k = 0; k < parInd; k++) { + int parsedOfs = 0; + int tmp; + if (ofs[k] < ML_DSA_N) { + for (int l = 0; l < SHAKE128_BLOCK_SIZE; l += 3) { + byte[] rawBuf = xofBufArr[k]; + parsedBuf[l / 3] = (rawBuf[l] & 0xFF) + + ((rawBuf[l + 1] & 0xFF) << 8) + + ((rawBuf[l + 2] & 0x7F) << 16); + } + } + while ((ofs[k] < ML_DSA_N) && + (parsedOfs < SHAKE128_BLOCK_SIZE / 3)) { + tmp = parsedBuf[parsedOfs++]; + if (tmp < ML_DSA_Q) { + aij[k][ofs[k]] = tmp; + ofs[k]++; + } + } + if (ofs[k] < ML_DSA_N) { + allDone = false; + } + } + } + + for (int k = 0; k < parInd; k++) { + a[iIndex[k]][jIndex[k]] = aij[k]; + } + parInd = 0; + } + } + } + } catch (InvalidAlgorithmParameterException e) { + // This should never happen since xofBufArr is of the correct size + throw new RuntimeException("Internal error."); + } + + return a; + } + + private void sampleS1S2(int[][] s1, int[][] s2, SHAKE256 xof, byte[] rhoPrime) { + byte[] seed = new byte[S1S2_SEED_LEN + 2]; + System.arraycopy(rhoPrime, 0, seed, 0, S1S2_SEED_LEN); + + Shake256Slicer slicer = new Shake256Slicer(xof, 4); + for (int i = 0; i < mlDsa_l; i++) { + seed[S1S2_SEED_LEN] = (byte) i; + seed[S1S2_SEED_LEN + 1] = 0; + slicer.reset(); + xof.update(seed); + if (eta == 2) { + for (int j = 0; j < ML_DSA_N; j++) { + int sample; + do { + sample = slicer.squeezeBits(); + } while (sample > 14); + // 2 - sample mod 5 + s1[i][j] = eta - sample + (205 * sample >> 10) * 5; + } + } else { // eta == 4 + for (int j = 0; j < ML_DSA_N; j++) { + int sample; + do { + sample = slicer.squeezeBits(); + } while (sample > 2 * eta); + s1[i][j] = eta - sample; + } + } + } + for (int i = 0; i < mlDsa_k; i++) { + seed[S1S2_SEED_LEN] = (byte) (mlDsa_l + i); + seed[S1S2_SEED_LEN + 1] = 0; + slicer.reset(); + xof.update(seed); + if (eta == 2) { + for (int j = 0; j < ML_DSA_N; j++) { + int sample; + do { + sample = slicer.squeezeBits(); + } while (sample > 14); + s2[i][j] = eta - sample + (205 * sample >> 10) * 5; + } + } else { + for (int j = 0; j < ML_DSA_N; j++) { + int sample; + do { + sample = slicer.squeezeBits(); + } while (sample > 2 * eta); + s2[i][j] = eta - sample; + } + } + } + } + + private void expandMask(int[][] result, byte[] rho, int mu) { + var xof = new SHAKE256(0); + + int c = 1 + gamma1Bits; + byte[] v = new byte[mlDsa_l * 32 * c]; + for (int r = 0; r < mlDsa_l; r++) { + int a = mu + r; + byte[] n = {(byte) a, (byte) (a >> 8)}; + + xof.update(rho); + xof.update(n); + xof.squeeze(v, r * 32 * c, 32 * c); + xof.reset(); + } + bitUnpack(result, v, 0, mlDsa_l, gamma1, c); + } + + /* + Auxiliary functions defined in section 7.4 of specification + */ + + private void power2Round(int[][] input, int[][] lowPart, int[][] highPart) { + for (int i = 0; i < mlDsa_k; i++) { + for (int m = 0; m < ML_DSA_N; m++) { + int rplus = input[i][m]; + int r0 = input[i][m] & D_MASK; + int r00 = (1 << (ML_DSA_D - 1)) - r0 ; // 2^d/2 - r+ + r0 -= (r00 >> 31) & (1 << ML_DSA_D); //0 if r+ < 2^d/2 + lowPart[i][m] = r0; + highPart[i][m] = (rplus - r0) >> ML_DSA_D; + } + } + } + + private void decompose(int[][] input, int[][] lowPart, int[][] highPart) { + int multiplier = (gamma2 == 95232 ? 22 : 8); + for (int i = 0; i < mlDsa_k; i++) { + mlDsaDecomposePoly(input[i], lowPart[i], + highPart[i], gamma2 * 2, multiplier); + } + } + + private int[][] highBits(int[][] input) { + int[][] lowPart = new int[mlDsa_k][ML_DSA_N]; + int[][] highPart = new int[mlDsa_k][ML_DSA_N]; + decompose(input, lowPart, highPart); + return highPart; + } + + //Creates the hint polynomial and returns its hamming weight + private int makeHint(boolean[][] res, int[][] z, int[][] r) { + int hammingWeight = 0; + int[][] r1 = highBits(r); + int[][] v1 = highBits(z); + for (int i = 0; i < mlDsa_k; i++) { + for (int j = 0; j < ML_DSA_N; j++) { + if (r1[i][j] != v1[i][j]) { + res[i][j] = true; + hammingWeight++; + } else { + res[i][j] = false; + } + } + } + return hammingWeight; + } + + private int[][] useHint(boolean[][] h, int[][] r) { + int m = (ML_DSA_Q - 1) / (2*gamma2); + int[][] lowPart = r; + int[][] highPart = new int[mlDsa_k][ML_DSA_N]; + decompose(r, lowPart, highPart); + + for (int i = 0; i < mlDsa_k; i++) { + for (int j = 0; j < ML_DSA_N; j++) { + if (h[i][j]) { + highPart[i][j] += lowPart[i][j] > 0 ? 1 : -1; + } + highPart[i][j] = ((highPart[i][j] % m) + m) % m; + } + } + return highPart; + } + + /* + NTT functions as specified in Section 7.5 of specification + */ + + public static void mlDsaNtt(int[] coeffs) { + implDilithiumAlmostNtt(coeffs, MONT_ZETAS_FOR_VECTOR_NTT); + implDilithiumMontMulByConstant(coeffs, MONT_R_MOD_Q); + } + + @IntrinsicCandidate + static int implDilithiumAlmostNtt(int[] coeffs, int[] zetas) { + implDilithiumAlmostNttJava(coeffs); + return 1; + } + + static void implDilithiumAlmostNttJava(int[] coeffs) { + int dimension = ML_DSA_N; + int m = 0; + for (int l = dimension / 2; l > 0; l /= 2) { + for (int s = 0; s < dimension; s += 2 * l) { + for (int j = s; j < s + l; j++) { + int tmp = montMul(MONT_ZETAS_FOR_NTT[m], coeffs[j + l]); + coeffs[j + l] = coeffs[j] - tmp; + coeffs[j] = coeffs[j] + tmp; + } + m++; + } + } + } + + public static void mlDsaInverseNtt(int[] coeffs) { + implDilithiumAlmostInverseNtt(coeffs, MONT_ZETAS_FOR_VECTOR_INVERSE_NTT); + implDilithiumMontMulByConstant(coeffs, MONT_DIM_INVERSE); + } + + @IntrinsicCandidate + static int implDilithiumAlmostInverseNtt(int[] coeffs, int[] zetas) { + implDilithiumAlmostInverseNttJava(coeffs); + return 1; + } + + static void implDilithiumAlmostInverseNttJava(int[] coeffs) { + int dimension = ML_DSA_N; + int m = MONT_ZETAS_FOR_NTT.length - 1; + for (int l = 1; l < dimension; l *= 2) { + for (int s = 0; s < dimension; s += 2 * l) { + for (int j = s; j < s + l; j++) { + int tmp = coeffs[j]; + coeffs[j] = (tmp + coeffs[j + l]); + coeffs[j + l] = montMul(tmp - coeffs[j + l], + -MONT_ZETAS_FOR_NTT[m]); + } + m--; + } + } + } + + void mlDsaVectorNtt(int[][] vector) { + for (int[] ints : vector) { + mlDsaNtt(ints); + } + } + + void mlDsaVectorInverseNtt(int[][] vector) { + for (int[] ints : vector) { + mlDsaInverseNtt(ints); + } + } + + public static void mlDsaNttMultiply(int[] product, int[] coeffs1, int[] coeffs2) { + implDilithiumNttMult(product, coeffs1, coeffs2); + } + + + @IntrinsicCandidate + static int implDilithiumNttMult(int[] product, int[] coeffs1, int[] coeffs2) { + implDilithiumNttMultJava(product, coeffs1, coeffs2); + return 1; + } + + static void implDilithiumNttMultJava(int[] product, int[] coeffs1, int[] coeffs2) { + for (int i = 0; i < ML_DSA_N; i++) { + product[i] = montMul(coeffs1[i], toMont(coeffs2[i])); + } + } + + @IntrinsicCandidate + static int implDilithiumMontMulByConstant(int[] coeffs, int constant) { + implDilithiumMontMulByConstantJava(coeffs, constant); + return 1; + } + + static void implDilithiumMontMulByConstantJava(int[] coeffs, int constant) { + for (int i = 0; i < ML_DSA_N; i++) { + coeffs[i] = montMul((coeffs[i]), constant); + } + } + + public static void mlDsaDecomposePoly(int[] input, int[] lowPart, int[] highPart, + int twoGamma2, int multiplier) { + implDilithiumDecomposePoly(input, lowPart, highPart,twoGamma2, multiplier); + } + + @IntrinsicCandidate + static int implDilithiumDecomposePoly(int[] input, int[] lowPart, int[] highPart, + int twoGamma2, int multiplier) { + decomposePolyJava(input, lowPart, highPart, twoGamma2, multiplier); + return 1; + } + + static void decomposePolyJava(int[] input, int[] lowPart, int[] highPart, + int twoGamma2, int multiplier) { + int dilithiumBarrettAddend = 5373807; + for (int m = 0; m < ML_DSA_N; m++) { + int rplus = input[m]; + rplus -= ((rplus + dilithiumBarrettAddend) >> 23) * ML_DSA_Q; + rplus += ((rplus >> 31) & ML_DSA_Q); + + int quotient = (rplus * multiplier) >> 22; + int r0 = rplus - quotient * twoGamma2; + int mask = (twoGamma2 - r0) >> 22; + r0 -= (mask & twoGamma2); + quotient += (mask & 1); + mask = (twoGamma2 / 2 - r0) >> 31; + r0 -= (mask & twoGamma2); + quotient += (mask & 1); + + int r1 = rplus - r0 - (ML_DSA_Q - 1); + r1 = (r1 | (-r1)) >> 31; // 0 if rplus - r0 == (dilithium_q - 1), -1 otherwise + r0 += ~r1; + // quotient = (rplus - r0) / twoGamma2; + r1 = r1 & quotient; + + lowPart[m] = r0; + highPart[m] = r1; + } + } + + private void matrixVectorPointwiseMultiply(int[][] res, int[][][] matrix, + int[][] vector) { + + int resulti[] = new int[ML_DSA_N]; + int[] product = new int[ML_DSA_N]; + for (int i = 0; i < mlDsa_k; i++) { + for (int m = 0; m < ML_DSA_N; m++) { + resulti[m] = 0; + } + for (int j = 0; j < mlDsa_l; j++) { + mlDsaNttMultiply(product, matrix[i][j], vector[j]); + for (int m = 0; m < ML_DSA_N; m++) { + resulti[m] += product[m]; + } + } + for (int m = 0; m < ML_DSA_N; m++) { + res[i][m] = montMul(resulti[m], MONT_R_MOD_Q); + } + } + } + + private void nttConstMultiply(int[][] res, int[] a, int[][] b) { + for (int i = 0; i < b.length; i++) { + mlDsaNttMultiply(res[i], a, b[i]); + } + } + + private int[][] vectorConstMul(int c, int[][] vec) { + int[][] res = new int[vec.length][vec[0].length]; + for (int i = 0; i < vec.length; i++) { + for (int j = 0; j < vec[0].length; j++) { + res[i][j] = montMul(c, toMont(vec[i][j])); + } + } + return res; // -q < res[i][j] < q + } + + // Adds two vectors of polynomials + // The coefficients in the input should be between -MONT_Q and MONT_Q . + // The coefficients in the output will be nonnegative and less than MONT_Q + int[][] vectorAddPos(int[][] vec1, int[][] vec2) { + int dim = vec1.length; + int[][] result = new int[dim][ML_DSA_N]; + for (int i = 0; i < dim; i++) { + for (int m = 0; m < ML_DSA_N; m++) { + int r = vec1[i][m] + vec2[i][m]; // -2 * MONT_Q < r < 2 * MONT_Q + r += (((r >> 31) & (2 * MONT_Q)) - MONT_Q); // -MONT_Q < r < MONT_Q + r += ((r >> 31) & MONT_Q); // 0 <= r < MONT_Q + result[i][m] = r; + } + } + return result; + } + + int[][] vectorAdd(int[][] result, int[][] vec1, int[][] vec2) { + for (int i = 0; i < result.length; i++) { + for (int j = 0; j < ML_DSA_N; j++) { + int tmp = vec1[i][j] + vec2[i][j]; + result[i][j] = tmp; + } + } + return result; + } + + int[][] vectorSub(int[][] vec1, int[][] vec2, boolean needsAdjustment) { + int dim = vec1.length; + for (int i = 0; i < dim; i++) { + for (int j = 0; j < ML_DSA_N; j++) { + int tmp = vec1[i][j] - vec2[i][j]; + if (needsAdjustment) { + if (tmp <= -ML_DSA_Q) { + tmp += ML_DSA_Q; + } else if (tmp >= ML_DSA_Q) { + tmp -= ML_DSA_Q; + } + } + vec1[i][j] = tmp; + } + } + return vec1; + } + + //Precondition: 2^-31 <= r1 <= 2^31 - 5 * 2^20, and bound < q - 5234431 + //Computes whether the infinity norm of a vector is >= bound + boolean vectorNormBound(int[][] vec, int bound) { + boolean res = false; + for (int i = 0; i < vec.length; i++) { + for (int j = 0; j < ML_DSA_N; j++) { + int r1 = vec[i][j]; + r1 = r1 - ((r1 + (5 << 20)) >> 23) * ML_DSA_Q; + r1 = r1 - ((r1 >> 31) & r1) * 2; + res |= (r1 >= bound); + } + } + return res; + } + + // precondition: -2^31 * MONT_Q <= a, b < 2^31, -2^31 < a * b < 2^31 * MONT_Q + // computes a * b * 2^-32 mod MONT_Q + // the result is greater than -MONT_Q and less than MONT_Q + // see e.g. Algorithm 3 in https://eprint.iacr.org/2018/039.pdf + private static int montMul(int b, int c) { + long a = (long) b * (long) c; + int aHigh = (int) (a >> MONT_R_BITS); + int aLow = (int) a; + int m = MONT_Q_INV_MOD_R * aLow; // signed low product + + // subtract signed high product + return (aHigh - (int) (((long)m * MONT_Q) >> MONT_R_BITS)); + } + + static int toMont(int a) { + return montMul(a, MONT_R_SQUARE_MOD_Q); + } +} diff --git a/src/java.base/share/classes/sun/security/provider/ML_DSA_Impls.java b/src/java.base/share/classes/sun/security/provider/ML_DSA_Impls.java new file mode 100644 index 000000000000..dffe7c5cdb18 --- /dev/null +++ b/src/java.base/share/classes/sun/security/provider/ML_DSA_Impls.java @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.security.provider; + +import sun.security.jca.JCAUtil; +import java.security.*; +import java.security.SecureRandom; +import java.util.Arrays; + +public class ML_DSA_Impls { + + public enum Version { + DRAFT, FINAL + } + + // This implementation works in FIPS 204 final. If for some reason + // (for example, interop with an old version, or running an old test), + // set the version to an older one. The following VM option is required: + // + // --add-exports java.base/sun.security.provider=ALL-UNNAMED + public static Version version = Version.FINAL; + + static int name2int(String name) { + if (name.endsWith("44")) { + return 2; + } else if (name.endsWith("65")) { + return 3; + } else if (name.endsWith("87")) { + return 5; + } else { + // should not happen + throw new ProviderException("Unknown name " + name); + } + } + + public sealed static class KPG + extends NamedKeyPairGenerator permits KPG2, KPG3, KPG5 { + + public KPG() { + // ML-DSA-65 is default + super("ML-DSA", "ML-DSA-65", "ML-DSA-44", "ML-DSA-87"); + } + + public KPG(String pname) { + super("ML-DSA", pname); + } + + @Override + protected byte[][] implGenerateKeyPair(String name, SecureRandom sr) { + byte[] seed = new byte[32]; + var r = sr != null ? sr : JCAUtil.getDefSecureRandom(); + r.nextBytes(seed); + ML_DSA mlDsa = new ML_DSA(name2int(name)); + ML_DSA.ML_DSA_KeyPair kp = mlDsa.generateKeyPairInternal(seed); + try { + return new byte[][]{ + mlDsa.pkEncode(kp.publicKey()), + mlDsa.skEncode(kp.privateKey()) + }; + } finally { + kp.privateKey().destroy(); + Arrays.fill(seed, (byte)0); + } + } + } + + public final static class KPG2 extends KPG { + public KPG2() { + super("ML-DSA-44"); + } + } + + public final static class KPG3 extends KPG { + public KPG3() { + super("ML-DSA-65"); + } + } + + public final static class KPG5 extends KPG { + public KPG5() { + super("ML-DSA-87"); + } + } + + public sealed static class KF extends NamedKeyFactory permits KF2, KF3, KF5 { + public KF() { + super("ML-DSA", "ML-DSA-44", "ML-DSA-65", "ML-DSA-87"); + } + public KF(String name) { + super("ML-DSA", name); + } + } + + public final static class KF2 extends KF { + public KF2() { + super("ML-DSA-44"); + } + } + + public final static class KF3 extends KF { + public KF3() { + super("ML-DSA-65"); + } + } + + public final static class KF5 extends KF { + public KF5() { + super("ML-DSA-87"); + } + } + + public sealed static class SIG extends NamedSignature permits SIG2, SIG3, SIG5 { + public SIG() { + super("ML-DSA", "ML-DSA-44", "ML-DSA-65", "ML-DSA-87"); + } + public SIG(String name) { + super("ML-DSA", name); + } + + @Override + protected byte[] implSign(String name, byte[] skBytes, + Object sk2, byte[] msg, SecureRandom sr) { + var size = name2int(name); + var r = sr != null ? sr : JCAUtil.getDefSecureRandom(); + byte[] rnd = new byte[32]; + r.nextBytes(rnd); + var mlDsa = new ML_DSA(size); + if (version == Version.FINAL) { + // FIPS 204 Algorithm 2 ML-DSA.Sign prepend {0, len(ctx)} + // to message before passing it to Sign_internal. + var m = new byte[msg.length + 2]; + System.arraycopy(msg, 0, m, 2, msg.length); // len(ctx) = 0 + msg = m; + } + ML_DSA.ML_DSA_Signature sig = mlDsa.signInternal(msg, rnd, skBytes); + return mlDsa.sigEncode(sig); + } + + @Override + protected boolean implVerify(String name, byte[] pkBytes, + Object pk2, byte[] msg, byte[] sigBytes) + throws SignatureException { + var size = name2int(name); + var mlDsa = new ML_DSA(size); + if (version == Version.FINAL) { + // FIPS 204 Algorithm 3 ML-DSA.Verify prepend {0, len(ctx)} + // to message before passing it to Verify_internal. + var m = new byte[msg.length + 2]; + System.arraycopy(msg, 0, m, 2, msg.length); // len(ctx) = 0 + msg = m; + } + return mlDsa.verifyInternal(pkBytes, msg, sigBytes); + } + + @Override + protected Object implCheckPublicKey(String name, byte[] pk) + throws InvalidKeyException { + + ML_DSA mlDsa = new ML_DSA(name2int(name)); + return mlDsa.checkPublicKey(pk); + } + + @Override + protected Object implCheckPrivateKey(String name, byte[] sk) + throws InvalidKeyException { + + ML_DSA mlDsa = new ML_DSA(name2int(name)); + return mlDsa.checkPrivateKey(sk); + } + } + + public final static class SIG2 extends SIG { + public SIG2() { + super("ML-DSA-44"); + } + } + + public final static class SIG3 extends SIG { + public SIG3() { + super("ML-DSA-65"); + } + } + + public final static class SIG5 extends SIG { + public SIG5() { + super("ML-DSA-87"); + } + } +} diff --git a/src/java.base/share/classes/sun/security/provider/NamedKEM.java b/src/java.base/share/classes/sun/security/provider/NamedKEM.java new file mode 100644 index 000000000000..2731b3460af3 --- /dev/null +++ b/src/java.base/share/classes/sun/security/provider/NamedKEM.java @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.security.provider; + +import sun.security.pkcs.NamedPKCS8Key; +import sun.security.x509.NamedX509Key; + +import javax.crypto.DecapsulateException; +import javax.crypto.KEM; +import javax.crypto.KEMSpi; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.PrivateKey; +import java.security.ProviderException; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.NamedParameterSpec; +import java.util.Arrays; +import java.util.Objects; + +/// A base class for all `KEM` implementations that can be +/// configured with a named parameter set. See [NamedKeyPairGenerator] +/// for more details. +public abstract class NamedKEM implements KEMSpi { + + private final String fname; // family name + private final String[] pnames; // allowed parameter set name (at least one) + + /// Creates a new `NamedKEM` object. + /// + /// @param fname the family name + /// @param pnames the standard parameter set names, at least one is needed. + protected NamedKEM(String fname, String... pnames) { + if (fname == null) { + throw new AssertionError("fname cannot be null"); + } + if (pnames == null || pnames.length == 0) { + throw new AssertionError("pnames cannot be null or empty"); + } + this.fname = fname; + this.pnames = pnames; + } + + @Override + public EncapsulatorSpi engineNewEncapsulator(PublicKey publicKey, + AlgorithmParameterSpec spec, SecureRandom secureRandom) + throws InvalidAlgorithmParameterException, InvalidKeyException { + if (spec != null) { + throw new InvalidAlgorithmParameterException( + "The " + fname + " algorithm does not take any parameters"); + } + // translate also check the key + var nk = (NamedX509Key) new NamedKeyFactory(fname, pnames) + .engineTranslateKey(publicKey); + var pk = nk.getRawBytes(); + return getKeyConsumerImpl(this, nk.getParams(), pk, + implCheckPublicKey(nk.getParams().getName(), pk), secureRandom); + } + + @Override + public DecapsulatorSpi engineNewDecapsulator( + PrivateKey privateKey, AlgorithmParameterSpec spec) + throws InvalidAlgorithmParameterException, InvalidKeyException { + if (spec != null) { + throw new InvalidAlgorithmParameterException( + "The " + fname + " algorithm does not take any parameters"); + } + // translate also check the key + var nk = (NamedPKCS8Key) new NamedKeyFactory(fname, pnames) + .engineTranslateKey(privateKey); + var sk = nk.getRawBytes(); + return getKeyConsumerImpl(this, nk.getParams(), sk, + implCheckPrivateKey(nk.getParams().getName(), sk), null); + } + + // We don't have a flag on whether key is public key or private key. + // The correct method should always be called. + private record KeyConsumerImpl(NamedKEM kem, String name, int sslen, + int clen, byte[] key, Object k2, SecureRandom sr) + implements KEMSpi.EncapsulatorSpi, KEMSpi.DecapsulatorSpi { + @Override + public SecretKey engineDecapsulate(byte[] encapsulation, int from, int to, + String algorithm) throws DecapsulateException { + if (encapsulation.length != clen) { + throw new DecapsulateException("Invalid key encapsulation message length"); + } + var ss = kem.implDecapsulate(name, key, k2, encapsulation); + try { + return new SecretKeySpec(ss, + from, to - from, algorithm); + } finally { + Arrays.fill(ss, (byte)0); + } + } + + @Override + public KEM.Encapsulated engineEncapsulate(int from, int to, String algorithm) { + var enc = kem.implEncapsulate(name, key, k2, sr); + try { + return new KEM.Encapsulated( + new SecretKeySpec(enc[1], + from, to - from, algorithm), + enc[0], + null); + } finally { + Arrays.fill(enc[1], (byte)0); + } + } + + @Override + public int engineSecretSize() { + return sslen; + } + + @Override + public int engineEncapsulationSize() { + return clen; + } + } + + private static KeyConsumerImpl getKeyConsumerImpl(NamedKEM kem, + NamedParameterSpec nps, byte[] key, Object k2, SecureRandom sr) { + String name = nps.getName(); + return new KeyConsumerImpl(kem, name, kem.implSecretSize(name), kem.implEncapsulationSize(name), + key, k2, sr); + } + + /// User-defined encap function. + /// + /// @param name parameter name + /// @param pk public key in raw bytes + /// @param pk2 parsed public key, `null` if none. See [#implCheckPublicKey]. + /// @param sr SecureRandom object, `null` if not initialized + /// @return the key encapsulation message and the shared key (in this order) + /// @throws ProviderException if there is an internal error + protected abstract byte[][] implEncapsulate(String name, byte[] pk, Object pk2, SecureRandom sr); + + /// User-defined decap function. + /// + /// @param name parameter name + /// @param sk private key in raw bytes + /// @param sk2 parsed private key, `null` if none. See [#implCheckPrivateKey]. + /// @param encap the key encapsulation message + /// @return the shared key + /// @throws ProviderException if there is an internal error + /// @throws DecapsulateException if there is another error + protected abstract byte[] implDecapsulate(String name, byte[] sk, Object sk2, byte[] encap) + throws DecapsulateException; + + /// User-defined function returning shared secret key length. + /// + /// @param name parameter name + /// @return shared secret key length + /// @throws ProviderException if there is an internal error + protected abstract int implSecretSize(String name); + + /// User-defined function returning key encapsulation message length. + /// + /// @param name parameter name + /// @return key encapsulation message length + /// @throws ProviderException if there is an internal error + protected abstract int implEncapsulationSize(String name); + + /// User-defined function to validate a public key. + /// + /// This method will be called in `newEncapsulator`. This gives the provider a chance to + /// reject the key so an `InvalidKeyException` can be thrown earlier. + /// An implementation can optionally return a "parsed key" as an `Object` value. + /// This object will be passed into the [#implEncapsulate] method along with the raw key. + /// + /// The default implementation returns `null`. + /// + /// @param name parameter name + /// @param pk public key in raw bytes + /// @return a parsed key, `null` if none. + /// @throws InvalidKeyException if the key is invalid + protected Object implCheckPublicKey(String name, byte[] pk) throws InvalidKeyException { + return null; + } + + /// User-defined function to validate a private key. + /// + /// This method will be called in `newDecapsulator`. This gives the provider a chance to + /// reject the key so an `InvalidKeyException` can be thrown earlier. + /// An implementation can optionally return a "parsed key" as an `Object` value. + /// This object will be passed into the [#implDecapsulate] method along with the raw key. + /// + /// The default implementation returns `null`. + /// + /// @param name parameter name + /// @param sk private key in raw bytes + /// @return a parsed key, `null` if none. + /// @throws InvalidKeyException if the key is invalid + protected Object implCheckPrivateKey(String name, byte[] sk) throws InvalidKeyException { + return null; + } +} diff --git a/src/java.base/share/classes/sun/security/provider/NamedKeyFactory.java b/src/java.base/share/classes/sun/security/provider/NamedKeyFactory.java new file mode 100644 index 000000000000..f7be5905a533 --- /dev/null +++ b/src/java.base/share/classes/sun/security/provider/NamedKeyFactory.java @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.security.provider; + +import sun.security.pkcs.NamedPKCS8Key; +import sun.security.util.KeyUtil; +import sun.security.util.RawKeySpec; +import sun.security.x509.NamedX509Key; + +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.KeyFactorySpi; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.spec.EncodedKeySpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; +import java.security.spec.NamedParameterSpec; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.Arrays; +import java.util.Objects; + +/// A base class for all `KeyFactory` implementations that can be +/// configured with a named parameter set. See [NamedKeyPairGenerator] +/// for more details. +/// +/// This factory supports reading and writing to RAW formats: +/// +/// 1. It reads from a RAW key using `translateKey` if `key.getFormat` is "RAW". +/// 2. It writes to a RAW [EncodedKeySpec] if `getKeySpec(key, EncodedKeySpec.class)` +/// is called. The format of the output is "RAW" and the algorithm is +/// intentionally left unspecified. +/// 3. It reads from and writes to the internal type [RawKeySpec]. +/// +/// When reading from a RAW format, it needs enough info to derive the +/// parameter set name. +public class NamedKeyFactory extends KeyFactorySpi { + + private final String fname; // family name + private final String[] pnames; // allowed parameter set name (at least one) + + /// Creates a new `NamedKeyFactory` object. + /// + /// @param fname the family name + /// @param pnames the standard parameter set names, at least one is needed. + protected NamedKeyFactory(String fname, String... pnames) { + if (fname == null) { + throw new AssertionError("fname cannot be null"); + } + if (pnames == null || pnames.length == 0) { + throw new AssertionError("pnames cannot be null or empty"); + } + this.fname = fname; + this.pnames = pnames; + } + + private String checkName(String name) throws InvalidKeyException { + for (var pname : pnames) { + if (pname.equalsIgnoreCase(name)) { + // return the stored standard name + return pname; + } + } + throw new InvalidKeyException("Unsupported parameter set name: " + name); + } + + @Override + protected PublicKey engineGeneratePublic(KeySpec keySpec) + throws InvalidKeySpecException { + if (keySpec instanceof X509EncodedKeySpec xspec) { + try { + return fromX509(xspec.getEncoded()); + } catch (InvalidKeyException e) { + throw new InvalidKeySpecException(e); + } + } else if (keySpec instanceof RawKeySpec rks) { + if (pnames.length == 1) { + return new NamedX509Key(fname, pnames[0], rks.getKeyArr()); + } else { + throw new InvalidKeySpecException("Parameter set name unavailable"); + } + } else if (keySpec instanceof EncodedKeySpec espec + && espec.getFormat().equalsIgnoreCase("RAW")) { + if (pnames.length == 1) { + return new NamedX509Key(fname, pnames[0], espec.getEncoded()); + } else { + throw new InvalidKeySpecException("Parameter set name unavailable"); + } + } else { + throw new InvalidKeySpecException("Unsupported keyspec: " + keySpec); + } + } + + @Override + protected PrivateKey engineGeneratePrivate(KeySpec keySpec) + throws InvalidKeySpecException { + if (keySpec instanceof PKCS8EncodedKeySpec pspec) { + var bytes = pspec.getEncoded(); + try { + return fromPKCS8(bytes); + } catch (InvalidKeyException e) { + throw new InvalidKeySpecException(e); + } finally { + Arrays.fill(bytes, (byte) 0); + } + } else if (keySpec instanceof RawKeySpec rks) { + if (pnames.length == 1) { + var bytes = rks.getKeyArr(); + try { + return new NamedPKCS8Key(fname, pnames[0], bytes); + } finally { + Arrays.fill(bytes, (byte) 0); + } + } else { + throw new InvalidKeySpecException("Parameter set name unavailable"); + } + } else if (keySpec instanceof EncodedKeySpec espec + && espec.getFormat().equalsIgnoreCase("RAW")) { + if (pnames.length == 1) { + var bytes = espec.getEncoded(); + try { + return new NamedPKCS8Key(fname, pnames[0], bytes); + } finally { + Arrays.fill(bytes, (byte) 0); + } + } else { + throw new InvalidKeySpecException("Parameter set name unavailable"); + } + } else { + throw new InvalidKeySpecException("Unsupported keyspec: " + keySpec); + } + } + + private PrivateKey fromPKCS8(byte[] bytes) + throws InvalidKeyException, InvalidKeySpecException { + var k = new NamedPKCS8Key(fname, bytes); + checkName(k.getParams().getName()); + return k; + } + + private PublicKey fromX509(byte[] bytes) + throws InvalidKeyException, InvalidKeySpecException { + var k = new NamedX509Key(fname, bytes); + checkName(k.getParams().getName()); + return k; + } + + private static class RawEncodedKeySpec extends EncodedKeySpec { + public RawEncodedKeySpec(byte[] encodedKey) { + super(encodedKey); + } + + @Override + public String getFormat() { + return "RAW"; + } + } + + @Override + protected T engineGetKeySpec(Key key, Class keySpec) + throws InvalidKeySpecException { + try { + key = engineTranslateKey(key); + } catch (InvalidKeyException e) { + throw new InvalidKeySpecException(e); + } + // key is now either NamedPKCS8Key or NamedX509Key of permitted param set + if (key instanceof NamedPKCS8Key nk) { + byte[] bytes = null; + try { + if (keySpec == PKCS8EncodedKeySpec.class) { + return keySpec.cast( + new PKCS8EncodedKeySpec(bytes = key.getEncoded())); + } else if (keySpec == RawKeySpec.class) { + return keySpec.cast(new RawKeySpec(nk.getRawBytes())); + } else if (keySpec.isAssignableFrom(EncodedKeySpec.class)) { + return keySpec.cast( + new RawEncodedKeySpec(nk.getRawBytes())); + } else { + throw new InvalidKeySpecException("Unsupported type: " + keySpec); + } + } finally { + if (bytes != null) { + Arrays.fill(bytes, (byte)0); + } + } + } else if (key instanceof NamedX509Key nk) { + if (keySpec == X509EncodedKeySpec.class + && key.getFormat().equalsIgnoreCase("X.509")) { + return keySpec.cast(new X509EncodedKeySpec(key.getEncoded())); + } else if (keySpec == RawKeySpec.class) { + return keySpec.cast(new RawKeySpec(nk.getRawBytes())); + } else if (keySpec.isAssignableFrom(EncodedKeySpec.class)) { + return keySpec.cast(new RawEncodedKeySpec(nk.getRawBytes())); + } else { + throw new InvalidKeySpecException("Unsupported type: " + keySpec); + } + } + throw new AssertionError("No " + keySpec.getName() + " for " + key.getClass()); + } + + @Override + protected Key engineTranslateKey(Key key) throws InvalidKeyException { + if (key == null) { + throw new InvalidKeyException("Key must not be null"); + } + if (key instanceof NamedX509Key nk) { + checkName(nk.getParams().getName()); + return key; + } + if (key instanceof NamedPKCS8Key nk) { + checkName(nk.getParams().getName()); + return key; + } + var format = key.getFormat(); + if (format == null) { + throw new InvalidKeyException("Unextractable key"); + } else if (format.equalsIgnoreCase("RAW")) { + var kAlg = key.getAlgorithm(); + if (key instanceof PrivateKey || key instanceof PublicKey) { + String name; + // Three cases that we can find the parameter set name from a RAW key: + // 1. getParams() returns one + // 2. getAlgorithm() returns param set name (some provider does this) + // 3. getAlgorithm() returns family name but this KF is for param set name + if (KeyUtil.getParams(key) instanceof NamedParameterSpec nps) { + name = checkName(nps.getName()); + } else { + if (kAlg.equalsIgnoreCase(fname)) { + if (pnames.length == 1) { + name = pnames[0]; + } else { + throw new InvalidKeyException("No parameter set info"); + } + } else { + name = checkName(kAlg); + } + } + return key instanceof PrivateKey + ? new NamedPKCS8Key(fname, name, key.getEncoded()) + : new NamedX509Key(fname, name, key.getEncoded()); + } else { + throw new InvalidKeyException("Unsupported key type: " + key.getClass()); + } + } else if (format.equalsIgnoreCase("PKCS#8") && key instanceof PrivateKey) { + var bytes = key.getEncoded(); + try { + return fromPKCS8(bytes); + } catch (InvalidKeySpecException e) { + throw new InvalidKeyException("Invalid PKCS#8 key", e); + } finally { + Arrays.fill(bytes, (byte) 0); + } + } else if (format.equalsIgnoreCase("X.509") && key instanceof PublicKey) { + try { + return fromX509(key.getEncoded()); + } catch (InvalidKeySpecException e) { + throw new InvalidKeyException("Invalid X.509 key", e); + } + } else { + throw new InvalidKeyException("Unsupported key format: " + key.getFormat()); + } + } +} diff --git a/src/java.base/share/classes/sun/security/provider/NamedKeyPairGenerator.java b/src/java.base/share/classes/sun/security/provider/NamedKeyPairGenerator.java new file mode 100644 index 000000000000..5be2b2b2a08b --- /dev/null +++ b/src/java.base/share/classes/sun/security/provider/NamedKeyPairGenerator.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.security.provider; + +import sun.security.pkcs.NamedPKCS8Key; +import sun.security.x509.NamedX509Key; + +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidParameterException; +import java.security.KeyPair; +import java.security.KeyPairGeneratorSpi; +import java.security.ProviderException; +import java.security.SecureRandom; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.NamedParameterSpec; +import java.util.Objects; + +/// A base class for all `KeyPairGenerator` implementations that can be +/// configured with a named parameter set. +/// +/// Together with [NamedKeyFactory], [NamedKEM], and [NamedSignature], these +/// classes form a compact framework designed to support any public key +/// algorithm standardized with named parameter sets. In this scenario, +/// the algorithm name is the "family name" and each standardized parameter +/// set has a "parameter set name". Implementations of these classes are able +/// to instantiate a `KeyPairGenerator`, `KeyFactory`, or `KEM` or `Signature` +/// object using either the family name or a parameter set name. All keys used +/// in this context will be of the type [NamedPKCS8Key] or [NamedX509Key], +/// with `getAlgorithm` returning the family name, and `getParams` returning +/// the parameter set name as a [NamedParameterSpec] object. +/// +/// An implementation must include a zero-argument public constructor that +/// calls `super(fname, pnames)`, where `fname` is the family name of the +/// algorithm and `pnames` are its supported parameter set names. `pnames` +/// must contain at least one element. For an implementation of +/// `NamedKeyPairGenerator`, the first element becomes its default parameter +/// set, i.e. the parameter set to be used in key pair generation unless +/// [#initialize(AlgorithmParameterSpec, java.security.SecureRandom)] +/// is called on a different parameter set. +/// +/// An implementation must implement all abstract methods. For all these +/// methods, the implementation must relinquish any "ownership" of any input +/// and output array argument. Precisely, the implementation must not retain +/// any reference to a returning array so that it won't be able to modify its +/// content later. Similarly, the implementation must not modify any input +/// array argument and must not retain any reference to an input array argument +/// after the call. +/// +/// Also, an implementation must not keep any extra copy of a private key. +/// For key generation, the only copy is the one returned in the +/// [#implGenerateKeyPair] call. For all other methods, it must not make +/// a copy of the input private key. A `KEM` implementation also must not +/// keep a copy of the shared secret key, no matter if it's an encapsulator +/// or a decapsulator. Only the code that owns these sensitive data can +/// choose to perform cleanup when it determines they are no longer needed. +/// +/// The `NamedSignature` and `NamedKEM` classes provide `implCheckPublicKey` +/// and `implCheckPrivateKey` methods that allow an implementation to validate +/// a key before using it. An implementation may return a parsed key in +/// a local type, and this parsed key will be passed to an operational method +/// (For example, `implSign`) later. An implementation must not retain +/// a reference of the parsed key. +/// +/// When constructing a [NamedX509Key] or [NamedPKCS8Key] object from raw key +/// bytes, the key bytes are directly referenced within the object, so the +/// caller must not modify them afterward. Similarly, the key's `getRawBytes` +/// method returns direct references to the underlying raw key bytes, meaning +/// the caller must not alter the contents of the returned value. +/// +/// Together, these measures ensure the classes are as efficient as possible, +/// preventing unnecessary array cloning and potential data leaks. While these +/// classes should not be considered immutable, strictly adhering to the rules +/// above will ensure data integrity is maintained. +/// +/// Note: A limitation of `NamedKeyPairGenerator` and `NamedKeyFactory` is +/// that the keys generated by their implementations will always be of type +/// `NamedX509Key` or `NamedPKCS8Key`. Existing implementations of algorithms +/// like EdDSA and XDH have been generating keys implementing `EdECKey` or +/// `XECKey` interfaces, and they are not rewritten with this framework. +/// `NamedParameterSpec` fields not implemented with this framework include +/// Ed25519, Ed448, X25519, and X448. +public abstract class NamedKeyPairGenerator extends KeyPairGeneratorSpi { + + private final String fname; // family name + private final String[] pnames; // allowed parameter set name (at least one) + + protected String name; // init as + private SecureRandom secureRandom; + + /// Creates a new `NamedKeyPairGenerator` object. + /// + /// @param fname the family name + /// @param pnames supported parameter set names, at least one is needed. + /// If multiple, the first one becomes the default parameter set name. + protected NamedKeyPairGenerator(String fname, String... pnames) { + if (fname == null) { + throw new AssertionError("fname cannot be null"); + } + if (pnames == null || pnames.length == 0) { + throw new AssertionError("pnames cannot be null or empty"); + } + this.fname = fname; + this.pnames = pnames; + } + + private String checkName(String name) throws InvalidAlgorithmParameterException { + for (var pname : pnames) { + if (pname.equalsIgnoreCase(name)) { + // return the stored standard name + return pname; + } + } + throw new InvalidAlgorithmParameterException( + "Unsupported parameter set name: " + name); + } + + @Override + public void initialize(AlgorithmParameterSpec params, SecureRandom random) + throws InvalidAlgorithmParameterException { + if (params instanceof NamedParameterSpec spec) { + name = checkName(spec.getName()); + } else { + throw new InvalidAlgorithmParameterException( + "Unsupported AlgorithmParameterSpec: " + params); + } + this.secureRandom = random; + } + + @Override + public void initialize(int keysize, SecureRandom random) { + if (keysize != -1) { + // User can call initialize(-1, sr) to provide a SecureRandom + // without touching the parameter set currently used + throw new InvalidParameterException("keysize not supported"); + } + this.secureRandom = random; + } + + @Override + public KeyPair generateKeyPair() { + String pname = name != null ? name : pnames[0]; + var keys = implGenerateKeyPair(pname, secureRandom); + return new KeyPair(new NamedX509Key(fname, pname, keys[0]), + new NamedPKCS8Key(fname, pname, keys[1])); + } + + /// User-defined key pair generator. + /// + /// @param pname parameter set name + /// @param sr `SecureRandom` object, `null` if not initialized + /// @return public key and private key (in this order) in raw bytes + /// @throws ProviderException if there is an internal error + protected abstract byte[][] implGenerateKeyPair(String pname, SecureRandom sr); +} diff --git a/src/java.base/share/classes/sun/security/provider/NamedSignature.java b/src/java.base/share/classes/sun/security/provider/NamedSignature.java new file mode 100644 index 000000000000..921a39cfc926 --- /dev/null +++ b/src/java.base/share/classes/sun/security/provider/NamedSignature.java @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.security.provider; + +import sun.security.pkcs.NamedPKCS8Key; +import sun.security.x509.NamedX509Key; + +import java.io.ByteArrayOutputStream; +import java.security.AlgorithmParameters; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.InvalidParameterException; +import java.security.PrivateKey; +import java.security.ProviderException; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.SignatureException; +import java.security.SignatureSpi; +import java.security.spec.AlgorithmParameterSpec; +import java.util.Objects; + +/// A base class for all `Signature` implementations that can be +/// configured with a named parameter set. See [NamedKeyPairGenerator] +/// for more details. +/// +/// This class does not work with preHash signatures. +public abstract class NamedSignature extends SignatureSpi { + + private final String fname; // family name + private final String[] pnames; // allowed parameter set name (at least one) + + private final ByteArrayOutputStream bout = new ByteArrayOutputStream(); + + // init with... + private String name; + private byte[] secKey; + private byte[] pubKey; + + private Object sk2; + private Object pk2; + + /// Creates a new `NamedSignature` object. + /// + /// @param fname the family name + /// @param pnames the standard parameter set names, at least one is needed. + protected NamedSignature(String fname, String... pnames) { + if (fname == null) { + throw new AssertionError("fname cannot be null"); + } + if (pnames == null || pnames.length == 0) { + throw new AssertionError("pnames cannot be null or empty"); + } + this.fname = fname; + this.pnames = pnames; + } + + @Override + protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException { + // translate also check the key + var nk = (NamedX509Key) new NamedKeyFactory(fname, pnames) + .engineTranslateKey(publicKey); + name = nk.getParams().getName(); + pubKey = nk.getRawBytes(); + pk2 = implCheckPublicKey(name, pubKey); + secKey = null; + bout.reset(); + } + + @Override + protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException { + // translate also check the key + var nk = (NamedPKCS8Key) new NamedKeyFactory(fname, pnames) + .engineTranslateKey(privateKey); + name = nk.getParams().getName(); + secKey = nk.getRawBytes(); + sk2 = implCheckPrivateKey(name, secKey); + pubKey = null; + bout.reset(); + } + + @Override + protected void engineUpdate(byte b) throws SignatureException { + bout.write(b); + } + + @Override + protected void engineUpdate(byte[] b, int off, int len) throws SignatureException { + bout.write(b, off, len); + } + + @Override + protected byte[] engineSign() throws SignatureException { + if (secKey != null) { + var msg = bout.toByteArray(); + bout.reset(); + return implSign(name, secKey, sk2, msg, appRandom); + } else { + throw new SignatureException("No private key"); + } + } + + @Override + protected boolean engineVerify(byte[] sig) throws SignatureException { + if (pubKey != null) { + var msg = bout.toByteArray(); + bout.reset(); + return implVerify(name, pubKey, pk2, msg, sig); + } else { + throw new SignatureException("No public key"); + } + } + + @Override + @SuppressWarnings("deprecation") + protected void engineSetParameter(String param, Object value) + throws InvalidParameterException { + throw new InvalidParameterException("setParameter() not supported"); + } + + @Override + @SuppressWarnings("deprecation") + protected Object engineGetParameter(String param) throws InvalidParameterException { + throw new InvalidParameterException("getParameter() not supported"); + } + + @Override + protected void engineSetParameter(AlgorithmParameterSpec params) + throws InvalidAlgorithmParameterException { + if (params != null) { + throw new InvalidAlgorithmParameterException( + "The " + fname + " algorithm does not take any parameters"); + } + } + + @Override + protected AlgorithmParameters engineGetParameters() { + return null; + } + + /// User-defined sign function. + /// + /// @param name parameter name + /// @param sk private key in raw bytes + /// @param sk2 parsed private key, `null` if none. See [#implCheckPrivateKey]. + /// @param msg the message + /// @param sr SecureRandom object, `null` if not initialized + /// @return the signature + /// @throws ProviderException if there is an internal error + /// @throws SignatureException if there is another error + protected abstract byte[] implSign(String name, byte[] sk, Object sk2, + byte[] msg, SecureRandom sr) throws SignatureException; + + /// User-defined verify function. + /// + /// @param name parameter name + /// @param pk public key in raw bytes + /// @param pk2 parsed public key, `null` if none. See [#implCheckPublicKey]. + /// @param msg the message + /// @param sig the signature + /// @return true if verified + /// @throws ProviderException if there is an internal error + /// @throws SignatureException if there is another error + protected abstract boolean implVerify(String name, byte[] pk, Object pk2, + byte[] msg, byte[] sig) throws SignatureException; + + /// User-defined function to validate a public key. + /// + /// This method will be called in `initVerify`. This gives the provider a chance to + /// reject the key so an `InvalidKeyException` can be thrown earlier. + /// An implementation can optionally return a "parsed key" as an `Object` value. + /// This object will be passed into the [#implVerify] method along with the raw key. + /// + /// The default implementation returns `null`. + /// + /// @param name parameter name + /// @param pk public key in raw bytes + /// @return a parsed key, `null` if none. + /// @throws InvalidKeyException if the key is invalid + protected Object implCheckPublicKey(String name, byte[] pk) throws InvalidKeyException { + return null; + } + + /// User-defined function to validate a private key. + /// + /// This method will be called in `initSign`. This gives the provider a chance to + /// reject the key so an `InvalidKeyException` can be thrown earlier. + /// An implementation can optionally return a "parsed key" as an `Object` value. + /// This object will be passed into the [#implSign] method along with the raw key. + /// + /// The default implementation returns `null`. + /// + /// @param name parameter name + /// @param sk private key in raw bytes + /// @return a parsed key, `null` if none. + /// @throws InvalidKeyException if the key is invalid + protected Object implCheckPrivateKey(String name, byte[] sk) throws InvalidKeyException { + return null; + } +} diff --git a/src/java.base/share/classes/sun/security/provider/SHA3.java b/src/java.base/share/classes/sun/security/provider/SHA3.java index 2b8bf8afbeda..5f974bc6ea65 100644 --- a/src/java.base/share/classes/sun/security/provider/SHA3.java +++ b/src/java.base/share/classes/sun/security/provider/SHA3.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,13 +25,17 @@ package sun.security.provider; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; +import java.nio.ByteOrder; import java.security.ProviderException; import java.util.Arrays; import java.util.Objects; +import jdk.internal.util.Preconditions; import jdk.internal.vm.annotation.IntrinsicCandidate; -import static sun.security.provider.ByteArrayAccess.b2lLittle; -import static sun.security.provider.ByteArrayAccess.l2bLittle; + +import static java.lang.Math.min; /** * This class implements the Secure Hash Algorithm SHA-3 developed by @@ -45,10 +49,10 @@ * @since 9 * @author Valerie Peng */ -abstract class SHA3 extends DigestBase { +public abstract class SHA3 extends DigestBase { private static final int WIDTH = 200; // in bytes, e.g. 1600 bits - private static final int DM = 5; // dimension of lanes + private static final int DM = 5; // dimension of state matrix private static final int NR = 24; // number of rounds @@ -64,20 +68,39 @@ abstract class SHA3 extends DigestBase { 0x8000000000008080L, 0x80000001L, 0x8000000080008008L, }; + // The starting byte combining the 2 or 4-bit domain separator and + // leading bits of the 10*1 padding, see Table 6 in B.2 of FIPS PUB 202 + // for examples private final byte suffix; - private byte[] state = new byte[WIDTH]; - private long[] lanes = new long[DM*DM]; + + // the state matrix flattened into an array + private long[] state = new long[DM*DM]; + + // The byte offset in the state where the next squeeze() will start. + // -1 indicates that either we are in the absorbing phase (only + // update() calls were made so far) in an extendable-output function (XOF) + // or the class was initialized as a hash. + // The first squeeze() call (after a possibly empty sequence of update() + // calls) will set it to 0 at its start. + // When a squeeze() call uses up all available bytes from this state + // and so a new keccak() call is made, squeezeOffset is reset to 0. + protected int squeezeOffset = -1; + + static final VarHandle asLittleEndian + = MethodHandles.byteArrayViewVarHandle(long[].class, + ByteOrder.LITTLE_ENDIAN).withInvokeExactBehavior(); /** * Creates a new SHA-3 object. */ - SHA3(String name, int digestLength, byte suffix, int c) { + private SHA3(String name, int digestLength, byte suffix, int c) { super(name, digestLength, (WIDTH - c)); this.suffix = suffix; } private void implCompressCheck(byte[] b, int ofs) { Objects.requireNonNull(b); + Preconditions.checkIndex(ofs + blockSize - 1, b.length, Preconditions.AIOOBE_FORMATTER); } /** @@ -91,10 +114,21 @@ void implCompress(byte[] b, int ofs) { @IntrinsicCandidate private void implCompress0(byte[] b, int ofs) { - for (int i = 0; i < buffer.length; i++) { - state[i] ^= b[ofs++]; - } - keccak(); + for (int i = 0; i < blockSize / 8; i++) { + state[i] ^= (long) asLittleEndian.get(b, ofs); + ofs += 8; + } + + keccak(); + } + + void finishAbsorb() { + int numOfPadding = + setPaddingBytes(suffix, buffer, (int)(bytesProcessed % blockSize)); + if (numOfPadding < 1) { + throw new ProviderException("Incorrect pad size: " + numOfPadding); + } + implCompress(buffer, 0); } /** @@ -102,35 +136,127 @@ private void implCompress0(byte[] b, int ofs) { * DigestBase calls implReset() when necessary. */ void implDigest(byte[] out, int ofs) { - int numOfPadding = - setPaddingBytes(suffix, buffer, (int)(bytesProcessed % buffer.length)); - if (numOfPadding < 1) { - throw new ProviderException("Incorrect pad size: " + numOfPadding); + // Moving this allocation to the block where it is used causes a little + // performance drop, that is why it is here. + byte[] byteState = new byte[8]; + if (engineGetDigestLength() == 0) { + // This is an XOF, so the digest() call is illegal. + throw new ProviderException("Calling digest() is not allowed in an XOF"); } - implCompress(buffer, 0); - int availableBytes = buffer.length; + + finishAbsorb(); + + int availableBytes = blockSize; int numBytes = engineGetDigestLength(); + while (numBytes > availableBytes) { - System.arraycopy(state, 0, out, ofs, availableBytes); + for (int i = 0; i < availableBytes / 8; i++) { + asLittleEndian.set(out, ofs, state[i]); + ofs += 8; + } numBytes -= availableBytes; - ofs += availableBytes; keccak(); } - System.arraycopy(state, 0, out, ofs, numBytes); + int numLongs = numBytes / 8; + + for (int i = 0; i < numLongs; i++) { + asLittleEndian.set(out, ofs, state[i]); + ofs += 8; + } + if (numBytes % 8 != 0) { + asLittleEndian.set(byteState, 0, state[numLongs]); + System.arraycopy(byteState, 0, out, ofs, numBytes % 8); + } + } + + void implSqueeze(byte[] output, int offset, int numBytes) { + // Moving this allocation to the block where it is used causes a little + // performance drop, that is why it is here. + byte[] byteState = new byte[8]; + if (engineGetDigestLength() != 0) { + // This is not an XOF, so the squeeze() call is illegal. + throw new ProviderException("Squeezing is only allowed in XOF mode."); + } + + if (squeezeOffset == -1) { + finishAbsorb(); + squeezeOffset = 0; + } + + int availableBytes = blockSize - squeezeOffset; + + while (numBytes > availableBytes) { + int longOffset = squeezeOffset / 8; + int bytesToCopy = 0; + + if (longOffset * 8 < squeezeOffset) { + asLittleEndian.set(byteState, 0, state[longOffset]); + longOffset++; + bytesToCopy = longOffset * 8 - squeezeOffset; + System.arraycopy(byteState, 8 - bytesToCopy, + output, offset, bytesToCopy); + offset += bytesToCopy; + } + for (int i = longOffset; i < blockSize / 8; i++) { + asLittleEndian.set(output, offset, state[i]); + offset += 8; + } + keccak(); + squeezeOffset = 0; + numBytes -= availableBytes; + availableBytes = blockSize; + } + // now numBytes <= availableBytes + int longOffset = squeezeOffset / 8; + + if (longOffset * 8 < squeezeOffset) { + asLittleEndian.set(byteState, 0, state[longOffset]); + int bytesToCopy = min((longOffset + 1) * 8 - squeezeOffset, numBytes); + System.arraycopy(byteState, squeezeOffset - 8 * longOffset, + output, offset, bytesToCopy); + longOffset++; + numBytes -= bytesToCopy; + offset += bytesToCopy; + squeezeOffset += bytesToCopy; + + if (numBytes == 0) return; + } + + int numLongs = numBytes / 8; + + for (int i = longOffset; i < longOffset + numLongs; i++) { + asLittleEndian.set(output, offset, state[i]); + offset += 8; + numBytes -= 8; + squeezeOffset += 8; + } + + if (numBytes > 0) { + asLittleEndian.set(byteState, 0, state[squeezeOffset / 8]); + System.arraycopy(byteState, 0, output, offset, numBytes); + squeezeOffset += numBytes; + } + } + + byte[] implSqueeze(int numBytes) { + byte[] result = new byte[numBytes]; + implSqueeze(result, 0, numBytes); + return result; } /** * Resets the internal state to start a new hash. */ void implReset() { - Arrays.fill(state, (byte)0); - Arrays.fill(lanes, 0L); + Arrays.fill(state, 0L); + squeezeOffset = -1; } /** * Utility function for padding the specified data based on the - * pad10*1 algorithm (section 5.1) and the 2-bit suffix "01" required - * for SHA-3 hash (section 6.1). + * pad10*1 algorithm (section 5.1) and the 2-bit suffix "01" or 4-bit + * suffix "1111" required for SHA-3 hash functions (section 6.1) and + * extendable-output functions (section 6.1) respectively. */ private static int setPaddingBytes(byte suffix, byte[] in, int len) { if (len != in.length) { @@ -144,48 +270,25 @@ private static int setPaddingBytes(byte suffix, byte[] in, int len) { return (in.length - len); } - /** - * Utility function for transforming the specified byte array 's' - * into array of lanes 'm' as defined in section 3.1.2. - */ - private static void bytes2Lanes(byte[] s, long[] m) { - int sOfs = 0; - // Conversion traverses along x-axis before y-axis - for (int y = 0; y < DM; y++, sOfs += 40) { - b2lLittle(s, sOfs, m, DM*y, 40); - } - } - - /** - * Utility function for transforming the specified array of - * lanes 'm' into a byte array 's' as defined in section 3.1.3. - */ - private static void lanes2Bytes(long[] m, byte[] s) { - int sOfs = 0; - // Conversion traverses along x-axis before y-axis - for (int y = 0; y < DM; y++, sOfs += 40) { - l2bLittle(m, DM*y, s, sOfs, 40); - } - } - /** * The function Keccak as defined in section 5.2 with * rate r = 1600 and capacity c. */ private void keccak() { - // convert the 200-byte state into 25 lanes - bytes2Lanes(state, lanes); + keccak(state); + } + public static void keccak(long[] stateArr) { long a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12; long a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24; // move data into local variables - a0 = lanes[0]; a1 = lanes[1]; a2 = lanes[2]; a3 = lanes[3]; a4 = lanes[4]; - a5 = lanes[5]; a6 = lanes[6]; a7 = lanes[7]; a8 = lanes[8]; a9 = lanes[9]; - a10 = lanes[10]; a11 = lanes[11]; a12 = lanes[12]; a13 = lanes[13]; a14 = lanes[14]; - a15 = lanes[15]; a16 = lanes[16]; a17 = lanes[17]; a18 = lanes[18]; a19 = lanes[19]; - a20 = lanes[20]; a21 = lanes[21]; a22 = lanes[22]; a23 = lanes[23]; a24 = lanes[24]; + a0 = stateArr[0]; a1 = stateArr[1]; a2 = stateArr[2]; a3 = stateArr[3]; a4 = stateArr[4]; + a5 = stateArr[5]; a6 = stateArr[6]; a7 = stateArr[7]; a8 = stateArr[8]; a9 = stateArr[9]; + a10 = stateArr[10]; a11 = stateArr[11]; a12 = stateArr[12]; a13 = stateArr[13]; a14 = stateArr[14]; + a15 = stateArr[15]; a16 = stateArr[16]; a17 = stateArr[17]; a18 = stateArr[18]; a19 = stateArr[19]; + a20 = stateArr[20]; a21 = stateArr[21]; a22 = stateArr[22]; a23 = stateArr[23]; a24 = stateArr[24]; - // process the lanes through step mappings + // process the stateArr through step mappings for (int ir = 0; ir < NR; ir++) { // Step mapping Theta as defined in section 3.2.1. long c0 = a0^a5^a10^a15^a20; @@ -287,20 +390,16 @@ private void keccak() { a0 ^= RC_CONSTANTS[ir]; } - lanes[0] = a0; lanes[1] = a1; lanes[2] = a2; lanes[3] = a3; lanes[4] = a4; - lanes[5] = a5; lanes[6] = a6; lanes[7] = a7; lanes[8] = a8; lanes[9] = a9; - lanes[10] = a10; lanes[11] = a11; lanes[12] = a12; lanes[13] = a13; lanes[14] = a14; - lanes[15] = a15; lanes[16] = a16; lanes[17] = a17; lanes[18] = a18; lanes[19] = a19; - lanes[20] = a20; lanes[21] = a21; lanes[22] = a22; lanes[23] = a23; lanes[24] = a24; - - // convert the resulting 25 lanes back into 200-byte state - lanes2Bytes(lanes, state); + stateArr[0] = a0; stateArr[1] = a1; stateArr[2] = a2; stateArr[3] = a3; stateArr[4] = a4; + stateArr[5] = a5; stateArr[6] = a6; stateArr[7] = a7; stateArr[8] = a8; stateArr[9] = a9; + stateArr[10] = a10; stateArr[11] = a11; stateArr[12] = a12; stateArr[13] = a13; stateArr[14] = a14; + stateArr[15] = a15; stateArr[16] = a16; stateArr[17] = a17; stateArr[18] = a18; stateArr[19] = a19; + stateArr[20] = a20; stateArr[21] = a21; stateArr[22] = a22; stateArr[23] = a23; stateArr[24] = a24; } public Object clone() throws CloneNotSupportedException { SHA3 copy = (SHA3) super.clone(); copy.state = copy.state.clone(); - copy.lanes = new long[DM*DM]; return copy; } @@ -339,4 +438,85 @@ public SHA512() { super("SHA3-512", 64, (byte)0x06, 128); } } + + public abstract static class SHA3XOF extends SHA3 { + public SHA3XOF(String name, int digestLength, byte offset, int c) { + super(name, digestLength, offset, c); + } + public void update(byte in) { + if (squeezeOffset != -1) { + throw new ProviderException("update() after squeeze() is not allowed."); + } + engineUpdate(in); + } + public void update(byte[] in, int off, int len) { + if (squeezeOffset != -1) { + throw new ProviderException("update() after squeeze() is not allowed."); + } + engineUpdate(in, off, len); + } + + public void update(byte[] in) { + if (squeezeOffset != -1) { + throw new ProviderException("update() after squeeze() is not allowed."); + } + engineUpdate(in, 0, in.length); + } + + public byte[] digest() { + return engineDigest(); + } + + public void squeeze(byte[] output, int offset, int numBytes) { + implSqueeze(output, offset, numBytes); + } + public byte[] squeeze(int numBytes) { + return implSqueeze(numBytes); + } + + public void reset() { + engineReset(); + } + } + + /* + * The SHAKE128 extendable output function. + */ + public static final class SHAKE128 extends SHA3XOF { + // d is the required number of output bytes. + // If this constructor is used with d > 0, the squeezing methods + // will throw a ProviderException. + public SHAKE128(int d) { + super("SHAKE128", d, (byte) 0x1F, 32); + } + + // If this constructor is used to get an instance of the class, then, + // after the last update, one can get the generated bytes using the + // squeezing methods. + // Calling digest method will throw a ProviderException. + public SHAKE128() { + super("SHAKE128", 0, (byte) 0x1F, 32); + } + } + + /* + * The SHAKE256 extendable output function. + */ + public static final class SHAKE256 extends SHA3XOF { + // d is the required number of output bytes. + // If this constructor is used with d > 0, the squeezing methods will + // throw a ProviderException. + public SHAKE256(int d) { + super("SHAKE256", d, (byte) 0x1F, 64); + } + + // If this constructor is used to get an instance of the class, then, + // after the last update, one can get the generated bytes using the + // squeezing methods. + // Calling a digest method will throw a ProviderException. + public SHAKE256() { + super("SHAKE256", 0, (byte) 0x1F, 64); + } + } + } diff --git a/src/java.base/share/classes/sun/security/provider/SHA3Parallel.java b/src/java.base/share/classes/sun/security/provider/SHA3Parallel.java new file mode 100644 index 000000000000..0851d4a9216b --- /dev/null +++ b/src/java.base/share/classes/sun/security/provider/SHA3Parallel.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.security.provider; + +import jdk.internal.vm.annotation.IntrinsicCandidate; + +import java.security.InvalidAlgorithmParameterException; +import java.util.Arrays; + +import static sun.security.provider.ByteArrayAccess.b2lLittle; +import static sun.security.provider.ByteArrayAccess.l2bLittle; + +import static sun.security.provider.SHA3.keccak; + +/* + * This class is for making it possible that NRPAR (= 2) (rather restricted) + * SHAKE computations execute in parallel. + * The restrictions are: + * 1. The messages processed should be such that the absorb phase should + * execute a single keccak() call and the byte arrays passed to the constructor + * (or reset() method) of this class should be the message padded with the + * appropriate padding described in + * https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf. + * 2. The only available way for extracting data is the squeeze() method + * that extracts exactly 1 block of data of each computation, delivering it + * in the arrays that were passed to the class in the constructor (or the + * reset() call). + */ +public class SHA3Parallel { + private int blockSize = 0; + private static final int DM = 5; // dimension of lanesArr + private byte[][] buffers; + private long[][] lanesArr; + private static final int NRPAR = 2; + + private SHA3Parallel(byte[][] buffers, int blockSize) throws InvalidAlgorithmParameterException { + if ((buffers.length != NRPAR) || (buffers[0].length < blockSize)) { + throw new InvalidAlgorithmParameterException("Bad buffersize."); + } + this.buffers = buffers; + this.blockSize = blockSize; + lanesArr = new long[NRPAR][]; + for (int i = 0; i < NRPAR; i++) { + lanesArr[i] = new long[DM * DM]; + b2lLittle(buffers[i], 0, lanesArr[i], 0, blockSize); + } + } + + public void reset(byte[][] buffers) throws InvalidAlgorithmParameterException { + if ((buffers.length != NRPAR) || (buffers[0].length < blockSize)) { + throw new InvalidAlgorithmParameterException("Bad buffersize."); + } + this.buffers = buffers; + for (int i = 0; i < NRPAR; i++) { + Arrays.fill(lanesArr[i], 0L); + b2lLittle(buffers[i], 0, lanesArr[i], 0, blockSize); + } + } + + public int squeezeBlock() { + int retVal = doubleKeccak(lanesArr[0], lanesArr[1]); + for (int i = 0; i < NRPAR; i++) { + l2bLittle(lanesArr[i], 0, buffers[i], 0, blockSize); + } + return retVal; + } + + @IntrinsicCandidate + private static int doubleKeccak(long[] lanes0, long[] lanes1) { + doubleKeccakJava(lanes0, lanes1); + return 1; + } + + private static int doubleKeccakJava(long[] lanes0, long[] lanes1) { + keccak(lanes0); + keccak(lanes1); + return 1; + } + + public static final class Shake128Parallel extends SHA3Parallel { + public Shake128Parallel(byte[][] buf) throws InvalidAlgorithmParameterException { + super(buf, 168); + } + } +} diff --git a/src/java.base/share/classes/sun/security/provider/SHAKE256.java b/src/java.base/share/classes/sun/security/provider/SHAKE256.java deleted file mode 100644 index 5dab92fdd783..000000000000 --- a/src/java.base/share/classes/sun/security/provider/SHAKE256.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package sun.security.provider; - -/* - * The SHAKE256 extendable output function. - */ -public final class SHAKE256 extends SHA3 { - public SHAKE256(int d) { - super("SHAKE256", d, (byte) 0x1F, 64); - } - - public void update(byte in) { - engineUpdate(in); - } - public void update(byte[] in, int off, int len) { - engineUpdate(in, off, len); - } - - public byte[] digest() { - return engineDigest(); - } - - public void reset() { - engineReset(); - } -} diff --git a/src/java.base/share/classes/sun/security/provider/SunEntries.java b/src/java.base/share/classes/sun/security/provider/SunEntries.java index f036a411f1de..1487e521c547 100644 --- a/src/java.base/share/classes/sun/security/provider/SunEntries.java +++ b/src/java.base/share/classes/sun/security/provider/SunEntries.java @@ -189,20 +189,33 @@ public final class SunEntries { attrs.clear(); attrs.put("ImplementedIn", "Software"); addWithAlias(p, "Signature", "HSS/LMS", "sun.security.provider.HSS", attrs); + + add(p, "Signature", "ML-DSA", "sun.security.provider.ML_DSA_Impls$SIG", attrs); + addWithAlias(p, "Signature", "ML-DSA-44", "sun.security.provider.ML_DSA_Impls$SIG2", attrs); + addWithAlias(p, "Signature", "ML-DSA-65", "sun.security.provider.ML_DSA_Impls$SIG3", attrs); + addWithAlias(p, "Signature", "ML-DSA-87", "sun.security.provider.ML_DSA_Impls$SIG5", attrs); + /* * Key Pair Generator engines */ attrs.clear(); attrs.put("ImplementedIn", "Software"); - attrs.put("KeySize", "2048"); // for DSA KPG and APG only String dsaKPGImplClass = "sun.security.provider.DSAKeyPairGenerator$"; dsaKPGImplClass += (useLegacyDSA? "Legacy" : "Current"); + attrs.put("KeySize", "2048"); addWithAlias(p, "KeyPairGenerator", "DSA", dsaKPGImplClass, attrs); + attrs.remove("KeySize"); + + add(p, "KeyPairGenerator", "ML-DSA", "sun.security.provider.ML_DSA_Impls$KPG", attrs); + addWithAlias(p, "KeyPairGenerator", "ML-DSA-44", "sun.security.provider.ML_DSA_Impls$KPG2", attrs); + addWithAlias(p, "KeyPairGenerator", "ML-DSA-65", "sun.security.provider.ML_DSA_Impls$KPG3", attrs); + addWithAlias(p, "KeyPairGenerator", "ML-DSA-87", "sun.security.provider.ML_DSA_Impls$KPG5", attrs); /* * Algorithm Parameter Generator engines */ + attrs.put("KeySize", "2048"); addWithAlias(p, "AlgorithmParameterGenerator", "DSA", "sun.security.provider.DSAParameterGenerator", attrs); attrs.remove("KeySize"); @@ -221,6 +234,11 @@ public final class SunEntries { addWithAlias(p, "KeyFactory", "HSS/LMS", "sun.security.provider.HSS$KeyFactoryImpl", attrs); + add(p, "KeyFactory", "ML-DSA", "sun.security.provider.ML_DSA_Impls$KF", attrs); + addWithAlias(p, "KeyFactory", "ML-DSA-44", "sun.security.provider.ML_DSA_Impls$KF2", attrs); + addWithAlias(p, "KeyFactory", "ML-DSA-65", "sun.security.provider.ML_DSA_Impls$KF3", attrs); + addWithAlias(p, "KeyFactory", "ML-DSA-87", "sun.security.provider.ML_DSA_Impls$KF5", attrs); + /* * Digest engines */ diff --git a/src/java.base/share/classes/sun/security/util/KeyUtil.java b/src/java.base/share/classes/sun/security/util/KeyUtil.java index f9e92c14cb96..33a4296e9ce9 100644 --- a/src/java.base/share/classes/sun/security/util/KeyUtil.java +++ b/src/java.base/share/classes/sun/security/util/KeyUtil.java @@ -26,9 +26,13 @@ package sun.security.util; import java.math.BigInteger; +import java.security.AccessController; import java.security.AlgorithmParameters; import java.security.InvalidKeyException; import java.security.Key; +import java.security.PrivilegedAction; +import java.security.PrivateKey; +import java.security.PublicKey; import java.security.SecureRandom; import java.security.interfaces.*; import java.security.spec.*; @@ -186,13 +190,13 @@ public static final int getKeySize(AlgorithmParameters parameters) { */ public static final String fullDisplayAlgName(Key key) { String result = key.getAlgorithm(); - if (key instanceof ECKey) { - ECParameterSpec paramSpec = ((ECKey) key).getParams(); + if (key instanceof PrivateKey || key instanceof PublicKey) { + AlgorithmParameterSpec paramSpec = getParams(key); if (paramSpec instanceof NamedCurve nc) { result += " (" + nc.getNameAndAliases()[0] + ")"; + } else if (paramSpec instanceof NamedParameterSpec nps) { + result = nps.getName(); } - } else if (key instanceof EdECKey) { - result = ((EdECKey) key).getParams().getName(); } return result; } @@ -426,5 +430,25 @@ public static byte[] trimZeroes(byte[] b) { return t; } + @SuppressWarnings({"deprecation", "removal"}) + public static AlgorithmParameterSpec getParams(Key key) { + try { + var m = key.getClass().getMethod("getParams"); + if (!m.isAccessible()) { + PrivilegedAction pa = () -> { + m.setAccessible(true); + return null; + }; + AccessController.doPrivileged(pa); + } + var result = m.invoke(key); + if (result instanceof AlgorithmParameterSpec spec) { + return spec; + } + } catch (NoSuchMethodException e) { + } catch (ReflectiveOperationException e) { + } + return null; + } } diff --git a/src/java.base/share/classes/sun/security/util/KnownOIDs.java b/src/java.base/share/classes/sun/security/util/KnownOIDs.java index b1426c530557..bca4ee72b394 100644 --- a/src/java.base/share/classes/sun/security/util/KnownOIDs.java +++ b/src/java.base/share/classes/sun/security/util/KnownOIDs.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -178,6 +178,14 @@ public enum KnownOIDs { SHA3_256withRSA("2.16.840.1.101.3.4.3.14", "SHA3-256withRSA"), SHA3_384withRSA("2.16.840.1.101.3.4.3.15", "SHA3-384withRSA"), SHA3_512withRSA("2.16.840.1.101.3.4.3.16", "SHA3-512withRSA"), + ML_DSA_44("2.16.840.1.101.3.4.3.17", "ML-DSA-44"), + ML_DSA_65("2.16.840.1.101.3.4.3.18", "ML-DSA-65"), + ML_DSA_87("2.16.840.1.101.3.4.3.19", "ML-DSA-87"), + + // kems 2.16.840.1.101.3.4.4.* + ML_KEM_512("2.16.840.1.101.3.4.4.1", "ML-KEM-512"), + ML_KEM_768("2.16.840.1.101.3.4.4.2", "ML-KEM-768"), + ML_KEM_1024("2.16.840.1.101.3.4.4.3", "ML-KEM-1024"), // RSASecurity // PKCS1 1.2.840.113549.1.1.* diff --git a/src/java.base/share/classes/sun/security/util/SignatureUtil.java b/src/java.base/share/classes/sun/security/util/SignatureUtil.java index 61d8be3ca8c3..36b65b28c206 100644 --- a/src/java.base/share/classes/sun/security/util/SignatureUtil.java +++ b/src/java.base/share/classes/sun/security/util/SignatureUtil.java @@ -33,7 +33,9 @@ import java.security.spec.*; import java.util.Locale; +import sun.security.pkcs.NamedPKCS8Key; import sun.security.rsa.RSAUtil; +import sun.security.util.KeyUtil; import jdk.internal.access.SharedSecrets; import sun.security.x509.AlgorithmId; @@ -273,7 +275,7 @@ public static String extractDigestAlgFromDwithE(String signatureAlgorithm) { return signatureAlgorithm.substring(0, with); } else { throw new IllegalArgumentException( - "Unknown algorithm: " + signatureAlgorithm); + "Cannot extract digest algorithm from " + signatureAlgorithm); } } @@ -386,8 +388,8 @@ private static Signature autoInitInternal(String alg, PrivateKey key, Signature public static AlgorithmId fromSignature(Signature sigEngine, PrivateKey key) throws SignatureException { try { - if (key instanceof EdECKey) { - return AlgorithmId.get(((EdECKey) key).getParams().getName()); + if (KeyUtil.getParams(key) instanceof NamedParameterSpec nps) { + return AlgorithmId.get(nps.getName()); } AlgorithmParameters params = null; @@ -427,6 +429,14 @@ public static AlgorithmId fromSignature(Signature sigEngine, PrivateKey key) public static void checkKeyAndSigAlgMatch(PrivateKey key, String sAlg) { String kAlg = key.getAlgorithm().toUpperCase(Locale.ENGLISH); sAlg = checkName(sAlg); + if (key instanceof NamedPKCS8Key n8k) { + if (!sAlg.equalsIgnoreCase(n8k.getAlgorithm()) + && !sAlg.equalsIgnoreCase(n8k.getParams().getName())) { + throw new IllegalArgumentException( + "key algorithm not compatible with signature algorithm"); + } + return; + } switch (sAlg) { case "RSASSA-PSS" -> { if (!kAlg.equals("RSASSA-PSS") diff --git a/src/java.base/share/classes/sun/security/x509/DNSName.java b/src/java.base/share/classes/sun/security/x509/DNSName.java index e5111b6bcecd..824f58e825ad 100644 --- a/src/java.base/share/classes/sun/security/x509/DNSName.java +++ b/src/java.base/share/classes/sun/security/x509/DNSName.java @@ -54,8 +54,8 @@ public class DNSName implements GeneralNameInterface { private static final HostnameChecker HOSTNAME_CHECKER = HostnameChecker.getInstance(HostnameChecker.TYPE_TLS); - private static final String alphaDigits = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + private static final String DNS_ALLOWED = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-"; /** * Create the DNSName object from the passed encoded Der value. @@ -75,52 +75,64 @@ public DNSName(DerValue derValue) throws IOException { * @throws IOException if the name is not a valid DNSName */ public DNSName(String name, boolean allowWildcard) throws IOException { - if (name == null || name.isEmpty()) + + // Check the full name. + if (name == null || name.isEmpty()) { throw new IOException("DNSName must not be null or empty"); - if (name.contains(" ")) - throw new IOException("DNSName with blank components is not permitted"); - if (name.startsWith(".") || name.endsWith(".")) + } + + if (name.contains(" ")) { + throw new IOException( + "DNSName with blank labels is not permitted"); + } + + if (name.startsWith(".") || name.endsWith(".")) { throw new IOException("DNSName may not begin or end with a ."); - /* - * Name will consist of label components separated by "." - * startIndex is the index of the first character of a component - * endIndex is the index of the last character of a component plus 1 - */ - for (int endIndex,startIndex = 0; startIndex < name.length(); startIndex = endIndex+1) { - endIndex = name.indexOf('.', startIndex); - if (endIndex < 0) { - endIndex = name.length(); + } + + // RFC 1123 Section 2.1 and RFC 2181 Section 11 + if (name.length() > 253) { + throw new IOException( + "DNSName can't be longer than 253 characters"); + } + + // Check the labels. + String[] labels = name.split("\\."); + + for (int i = 0; i < labels.length; i++) { + String label = labels[i]; + + if (label.isEmpty()) { + throw new IOException( + "DNSName with empty labels is not permitted"); } - if (endIndex - startIndex < 1) - throw new IOException("DNSName with empty components are not permitted"); - - if (allowWildcard) { - // RFC 1123: DNSName components must begin with a letter or digit - // or RFC 4592: the first component of a DNSName can have only a wildcard - // character * (asterisk), i.e. *.example.com. Asterisks at other components - // will not be allowed as a wildcard. - if (alphaDigits.indexOf(name.charAt(startIndex)) < 0) { - // Checking to make sure the wildcard only appears in the first component, - // and it has to be at least 3-char long with the form of *.[alphaDigit] - if ((name.length() < 3) || (name.indexOf('*') != 0) || - (name.charAt(startIndex+1) != '.') || - (alphaDigits.indexOf(name.charAt(startIndex+2)) < 0)) - throw new IOException("DNSName components must begin with a letter, digit, " - + "or the first component can have only a wildcard character *"); - } - } else { - // RFC 1123: DNSName components must begin with a letter or digit - if (alphaDigits.indexOf(name.charAt(startIndex)) < 0) - throw new IOException("DNSName components must begin with a letter or digit"); + + // RFC 1123 Section 2.1 + if (label.length() > 63) { + throw new IOException( + "DNSName label can't be longer than 63 characters"); + } + + // RFC 1035 Section 2.3.1 + if (label.startsWith("-") || label.endsWith("-")) { + throw new IOException( + "DNSName label may not begin or end with a hyphen"); } - //nonStartIndex: index for characters in the component beyond the first one - for (int nonStartIndex=startIndex+1; nonStartIndex < endIndex; nonStartIndex++) { - char x = name.charAt(nonStartIndex); - if ((alphaDigits).indexOf(x) < 0 && x != '-') - throw new IOException("DNSName components must consist of letters, digits, and hyphens"); + // RFC 9525 Section 6.3 + if (allowWildcard && label.equals("*") && i == 0 + && labels.length > 1) { + continue; + } + + for (char c : label.toCharArray()) { + if (DNS_ALLOWED.indexOf(c) < 0) { + throw new IOException("DNSName labels must consist of " + + "letters, digits, and hyphens"); + } } } + this.name = name; } diff --git a/src/java.base/share/classes/sun/security/x509/NamedX509Key.java b/src/java.base/share/classes/sun/security/x509/NamedX509Key.java new file mode 100644 index 000000000000..c30ce96659e4 --- /dev/null +++ b/src/java.base/share/classes/sun/security/x509/NamedX509Key.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.security.x509; + +import sun.security.util.BitArray; + +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.io.Serial; +import java.security.InvalidKeyException; +import java.security.KeyRep; +import java.security.NoSuchAlgorithmException; +import java.security.ProviderException; +import java.security.spec.NamedParameterSpec; + +/// Represents a public key from an algorithm family that is specialized +/// with a named parameter set. +/// +/// This key is generated by either a [sun.security.provider.NamedKeyPairGenerator] +/// or [sun.security.provider.NamedKeyFactory]. Its [#getAlgorithm] method +/// returns the algorithm family name, while its [#getParams()] method returns +/// the parameter set name as a [NamedParameterSpec] object. The algorithm +/// identifier in the X.509 encoding of the key is always a single OID derived +/// from the parameter set name. +/// +/// @see sun.security.provider.NamedKeyPairGenerator +public final class NamedX509Key extends X509Key { + @Serial + private static final long serialVersionUID = 1L; + + private final String fname; + private final transient NamedParameterSpec paramSpec; + private final byte[] rawBytes; + + /// Ctor from family name, parameter set name, raw key bytes. + /// Key bytes won't be cloned, caller must relinquish ownership + public NamedX509Key(String fname, String pname, byte[] rawBytes) { + this.fname = fname; + this.paramSpec = new NamedParameterSpec(pname); + try { + this.algid = AlgorithmId.get(pname); + } catch (NoSuchAlgorithmException e) { + throw new ProviderException(e); + } + this.rawBytes = rawBytes; + + setKey(new BitArray(rawBytes.length * 8, rawBytes)); + } + + /// Ctor from family name, and X.509 bytes + public NamedX509Key(String fname, byte[] encoded) throws InvalidKeyException { + this.fname = fname; + decode(encoded); + this.paramSpec = new NamedParameterSpec(algid.getName()); + if (algid.encodedParams != null) { + throw new InvalidKeyException("algorithm identifier has params"); + } + this.rawBytes = getKey().toByteArray(); + } + + @Override + public String toString() { + // Do not modify: this can be used by earlier JDKs that + // do not have the getParams() method + return paramSpec.getName() + " public key"; + } + + /// Returns the reference to the internal key. Caller must not modify + /// the content or keep a reference. + public byte[] getRawBytes() { + return rawBytes; + } + + public NamedParameterSpec getParams() { + return paramSpec; + } + + @Override + public String getAlgorithm() { + return fname; + } + + @java.io.Serial + private Object writeReplace() throws java.io.ObjectStreamException { + return new KeyRep(KeyRep.Type.PUBLIC, getAlgorithm(), getFormat(), + getEncoded()); + } + + @java.io.Serial + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + throw new InvalidObjectException( + "NamedX509Key keys are not directly deserializable"); + } +} diff --git a/src/java.base/share/native/libjava/Reference.c b/src/java.base/share/native/libjava/Reference.c index ce5b34299ada..7fef23c2ba86 100644 --- a/src/java.base/share/native/libjava/Reference.c +++ b/src/java.base/share/native/libjava/Reference.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,6 +44,12 @@ Java_java_lang_ref_Reference_waitForReferencePendingList(JNIEnv *env, jclass ign JVM_WaitForReferencePendingList(env); } +JNIEXPORT jobject JNICALL +Java_java_lang_ref_Reference_get0(JNIEnv *env, jobject ref) +{ + return JVM_ReferenceGet(env, ref); +} + JNIEXPORT jboolean JNICALL Java_java_lang_ref_Reference_refersTo0(JNIEnv *env, jobject ref, jobject o) { diff --git a/src/java.base/share/native/libjli/java.c b/src/java.base/share/native/libjli/java.c index 1afdb5f40ac7..f9e148ce0b82 100644 --- a/src/java.base/share/native/libjli/java.c +++ b/src/java.base/share/native/libjli/java.c @@ -988,7 +988,7 @@ static void SetMainModule(const char *s) { static const char format[] = "-Djdk.module.main=%s"; - char* slash = JLI_StrChr(s, '/'); + const char* slash = JLI_StrChr(s, '/'); size_t s_len, def_len; char *def; diff --git a/src/java.base/share/native/libjli/jli_util.c b/src/java.base/share/native/libjli/jli_util.c index 3b24a784491f..51c2d8b85731 100644 --- a/src/java.base/share/native/libjli/jli_util.c +++ b/src/java.base/share/native/libjli/jli_util.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -87,7 +87,7 @@ JLI_MemFree(void *ptr) jboolean JLI_HasSuffix(const char *s1, const char *s2) { - char *p = JLI_StrRChr(s1, '.'); + const char* p = JLI_StrRChr(s1, '.'); if (p == NULL || *p == '\0') { return JNI_FALSE; } diff --git a/src/java.base/share/native/libverify/check_code.c b/src/java.base/share/native/libverify/check_code.c index 49b4c23c2b75..8eb35b6ea590 100644 --- a/src/java.base/share/native/libverify/check_code.c +++ b/src/java.base/share/native/libverify/check_code.c @@ -3832,7 +3832,7 @@ signature_to_fieldtype(context_type *context, case JVM_SIGNATURE_CLASS: { char buffer_space[256]; char *buffer = buffer_space; - char *finish = strchr(p, JVM_SIGNATURE_ENDCLASS); + const char* finish = strchr(p, JVM_SIGNATURE_ENDCLASS); int length; if (finish == NULL) { /* Signature must have ';' after the class name. diff --git a/src/java.base/unix/native/libjava/TimeZone_md.c b/src/java.base/unix/native/libjava/TimeZone_md.c index ac44133b791a..7ebe92ec0b38 100644 --- a/src/java.base/unix/native/libjava/TimeZone_md.c +++ b/src/java.base/unix/native/libjava/TimeZone_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -113,7 +113,7 @@ getZoneName(char *str) { static const char *zidir = "zoneinfo/"; - char *pos = strstr((const char *)str, zidir); + char* pos = strstr(str, zidir); if (pos == NULL) { return NULL; } @@ -369,33 +369,15 @@ getPlatformTimeZoneID() } static char * -mapPlatformToJavaTimezone(const char *java_home_dir, const char *tz) { +getJavaTimezoneFromPlatform(const char *tz_buf, size_t tz_len, const char *mapfilename) { FILE *tzmapf; - char mapfilename[PATH_MAX + 1]; char line[256]; int linecount = 0; - char *tz_buf = NULL; - char *temp_tz = NULL; char *javatz = NULL; - size_t tz_len = 0; - - /* On AIX, the TZ environment variable may end with a comma - * followed by modifier fields until early AIX6.1. - * This restriction has been removed from AIX7. */ - tz_buf = strdup(tz); - tz_len = strlen(tz_buf); - - /* Open tzmappings file, with buffer overrun check */ - if ((strlen(java_home_dir) + 15) > PATH_MAX) { - jio_fprintf(stderr, "Path %s/lib/tzmappings exceeds maximum path length\n", java_home_dir); - goto tzerr; - } - strcpy(mapfilename, java_home_dir); - strcat(mapfilename, "/lib/tzmappings"); if ((tzmapf = fopen(mapfilename, "r")) == NULL) { jio_fprintf(stderr, "can't open %s\n", mapfilename); - goto tzerr; + return NULL; } while (fgets(line, sizeof(line), tzmapf) != NULL) { @@ -448,10 +430,58 @@ mapPlatformToJavaTimezone(const char *java_home_dir, const char *tz) { break; } } + (void) fclose(tzmapf); + return javatz; +} + +static char * +mapPlatformToJavaTimezone(const char *java_home_dir, const char *tz) { + char mapfilename[PATH_MAX + 1]; + char *tz_buf = NULL; + char *javatz = NULL; + char *temp_tz = NULL; + size_t tz_len = 0; + + /* On AIX, the TZ environment variable may end with a comma + * followed by modifier fields until early AIX6.1. + * This restriction has been removed from AIX7. */ + + tz_buf = strdup(tz); + if (tz_buf == NULL) { + jio_fprintf(stderr, "Failed to allocate timezone buffer\n"); + goto tzerr; + } + tz_len = strlen(tz_buf); + + /* Open tzmappings file, with buffer overrun check */ + if ((strlen(java_home_dir) + 15) > PATH_MAX) { + jio_fprintf(stderr, "Path %s/lib/tzmappings exceeds maximum path length\n", java_home_dir); + goto tzerr; + } + strcpy(mapfilename, java_home_dir); + strcat(mapfilename, "/lib/tzmappings"); + + // First attempt to find the Java timezone for the full tz string + javatz = getJavaTimezoneFromPlatform(tz_buf, tz_len, mapfilename); + + // If no match was found, check for timezone with truncated value + if (javatz == NULL) { + temp_tz = strchr(tz, ','); + tz_len = (temp_tz == NULL) ? strlen(tz) : temp_tz - tz; + free((void *) tz_buf); + tz_buf = (char *)malloc(tz_len + 1); + if (tz_buf == NULL) { + jio_fprintf(stderr, "Failed to allocate timezone buffer\n"); + goto tzerr; + } + memcpy(tz_buf, tz, tz_len); + tz_buf[tz_len] = '\0'; + javatz = getJavaTimezoneFromPlatform(tz_buf, tz_len, mapfilename); + } tzerr: - if (tz_buf != NULL ) { + if (tz_buf != NULL) { free((void *) tz_buf); } diff --git a/src/java.base/unix/native/libnet/NetworkInterface.c b/src/java.base/unix/native/libnet/NetworkInterface.c index 0cd69399d918..152fed27a139 100644 --- a/src/java.base/unix/native/libnet/NetworkInterface.c +++ b/src/java.base/unix/native/libnet/NetworkInterface.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -201,7 +201,7 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByName0 netif *ifs, *curr; jboolean isCopy; const char* name_utf; - char *colonP; + const char* colonP; jobject obj = NULL; if (name != NULL) { diff --git a/src/java.base/unix/native/libnio/ch/Net.c b/src/java.base/unix/native/libnio/ch/Net.c index 3c3f3fb6e5b1..b9ab0baf5413 100644 --- a/src/java.base/unix/native/libnio/ch/Net.c +++ b/src/java.base/unix/native/libnio/ch/Net.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -910,13 +910,13 @@ Java_sun_nio_ch_Net_pollConnect(JNIEnv *env, jobject this, jobject fdo, jlong ti errno = 0; result = getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &n); if (result < 0) { - handleSocketError(env, errno); + handleSocketErrorWithMessage(env, errno, "getsockopt failed"); return JNI_FALSE; } else if (error) { - handleSocketError(env, error); + handleSocketErrorWithMessage(env, error, "connect failed"); return JNI_FALSE; } else if ((poller.revents & POLLHUP) != 0) { - handleSocketError(env, ENOTCONN); + handleSocketErrorWithMessage(env, ENOTCONN, "peer closed connection after accepting"); return JNI_FALSE; } // connected diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/MenuAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/MenuAccessibility.m index 90a147aa5a21..14b7ee8c6b5f 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/MenuAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/MenuAccessibility.m @@ -68,6 +68,11 @@ - (NSArray *)accessibilityChildren { sjm_getCurrentAccessiblePopupMenu, fAccessible, fComponent); + CHECK_EXCEPTION(); + if (axComponent == nil) { + return nil; + } + CommonComponentAccessibility *currentElement = [CommonComponentAccessibility createWithAccessible:axComponent withEnv:env withView:self->fView isCurrent:YES]; diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLRenderQueue.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLRenderQueue.m index 257269e647f0..8951ae8e110d 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLRenderQueue.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLRenderQueue.m @@ -161,35 +161,21 @@ void MTLRenderQueue_CheckPreviousOp(jint op) { case sun_java2d_pipe_BufferedOpCodes_DRAW_POLY: { CHECK_PREVIOUS_OP(MTL_OP_OTHER); - jint nPoints = NEXT_INT(b); - jboolean isClosed = NEXT_BOOLEAN(b); - jint transX = NEXT_INT(b); - jint transY = NEXT_INT(b); - jint *xPoints = (jint *)b; - jint *yPoints = ((jint *)b) + nPoints; if ([mtlc useXORComposite]) { commitEncodedCommands(); J2dTraceLn(J2D_TRACE_VERBOSE, "DRAW_POLY in XOR mode - Force commit earlier draw calls before DRAW_POLY."); - // draw separate (N-1) lines using N points - for(int point = 0; point < nPoints-1; point++) { - jint x1 = xPoints[point] + transX; - jint y1 = yPoints[point] + transY; - jint x2 = xPoints[point + 1] + transX; - jint y2 = yPoints[point + 1] + transY; - MTLRenderer_DrawLine(mtlc, dstOps, x1, y1, x2, y2); - } - - if (isClosed) { - MTLRenderer_DrawLine(mtlc, dstOps, xPoints[0] + transX, yPoints[0] + transY, - xPoints[nPoints-1] + transX, yPoints[nPoints-1] + transY); - } - } else { - MTLRenderer_DrawPoly(mtlc, dstOps, nPoints, isClosed, transX, transY, xPoints, yPoints); } + jint nPoints = NEXT_INT(b); + jboolean isClosed = NEXT_BOOLEAN(b); + jint transX = NEXT_INT(b); + jint transY = NEXT_INT(b); + jint *xPoints = (jint *)b; + jint *yPoints = ((jint *)b) + nPoints; + MTLRenderer_DrawPoly(mtlc, dstOps, nPoints, isClosed, transX, transY, xPoints, yPoints); SKIP_BYTES(b, nPoints * BYTES_PER_POLY_POINT); break; } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/shaders.metal b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/shaders.metal index 722506ab2c33..8718e5cac2ff 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/shaders.metal +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/shaders.metal @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -84,13 +84,11 @@ struct GradShaderInOut { struct ColShaderInOut_XOR { float4 position [[position]]; float ptSize [[point_size]]; - float2 orig_pos; half4 color; }; struct TxtShaderInOut_XOR { float4 position [[position]]; - float2 orig_pos; float2 texCoords; float2 tpCoords; }; @@ -677,7 +675,6 @@ vertex ColShaderInOut_XOR vert_col_xorMode(VertexInput in [[stage_in]], float4 pos4 = float4(in.position, 0.0, 1.0); out.position = transform.transformMatrix*pos4; out.ptSize = 1.0; - out.orig_pos = in.position; out.color = half4(uniforms.color.r, uniforms.color.g, uniforms.color.b, uniforms.color.a); return out; } @@ -685,7 +682,7 @@ vertex ColShaderInOut_XOR vert_col_xorMode(VertexInput in [[stage_in]], fragment half4 frag_col_xorMode(ColShaderInOut_XOR in [[stage_in]], texture2d renderTexture [[texture(0)]]) { - uint2 texCoord = {(unsigned int)(in.orig_pos.x), (unsigned int)(in.orig_pos.y)}; + uint2 texCoord = {(unsigned int)(in.position.x), (unsigned int)(in.position.y)}; float4 pixelColor = renderTexture.read(texCoord); half4 color = in.color; @@ -707,7 +704,6 @@ vertex TxtShaderInOut_XOR vert_txt_xorMode( TxtShaderInOut_XOR out; float4 pos4 = float4(in.position, 0.0, 1.0); out.position = transform.transformMatrix*pos4; - out.orig_pos = in.position; out.texCoords = in.texCoords; return out; } @@ -719,7 +715,7 @@ fragment half4 frag_txt_xorMode( constant TxtFrameUniforms& uniforms [[buffer(1)]], sampler textureSampler [[sampler(0)]]) { - uint2 texCoord = {(unsigned int)(vert.orig_pos.x), (unsigned int)(vert.orig_pos.y)}; + uint2 texCoord = {(unsigned int)(vert.position.x), (unsigned int)(vert.position.y)}; float4 bgColor = backgroundTexture.read(texCoord); float4 pixelColor = renderTexture.sample(textureSampler, vert.texCoords); diff --git a/src/java.instrument/share/native/libinstrument/JPLISAgent.c b/src/java.instrument/share/native/libinstrument/JPLISAgent.c index c65bfb9f2f96..a48defd471d0 100644 --- a/src/java.instrument/share/native/libinstrument/JPLISAgent.c +++ b/src/java.instrument/share/native/libinstrument/JPLISAgent.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -780,7 +780,7 @@ getModuleObject(jvmtiEnv* jvmti, jobject moduleObject = NULL; /* find last slash in the class name */ - char* last_slash = (cname == NULL) ? NULL : strrchr(cname, '/'); + const char* last_slash = (cname == NULL) ? NULL : strrchr(cname, '/'); int len = (last_slash == NULL) ? 0 : (int)(last_slash - cname); char* pkg_name_buf = (char*)malloc(len + 1); diff --git a/src/java.instrument/unix/native/libinstrument/FileSystemSupport_md.c b/src/java.instrument/unix/native/libinstrument/FileSystemSupport_md.c index a58c1579f0c6..e29631ea2499 100644 --- a/src/java.instrument/unix/native/libinstrument/FileSystemSupport_md.c +++ b/src/java.instrument/unix/native/libinstrument/FileSystemSupport_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ #define slash '/' char* basePath(const char* path) { - char* last = strrchr(path, slash); + const char* last = strrchr(path, slash); if (last == NULL) { return (char*)path; } else { diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java index f8dd5a71c2cf..a76b37dd4c83 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java @@ -945,7 +945,7 @@ private synchronized void fetchValues() { params = new DSAParameterSpec(res[0], res[1], res[2]); } - protected DSAParams getParams() { + public DSAParams getParams() { fetchValues(); return params; } @@ -1248,7 +1248,7 @@ private synchronized void fetchValues() { } } - protected ECParameterSpec getParams() { + public ECParameterSpec getParams() { fetchValues(); return params; } diff --git a/src/jdk.crypto.ec/share/classes/sun/security/ec/ed/EdDSAParameters.java b/src/jdk.crypto.ec/share/classes/sun/security/ec/ed/EdDSAParameters.java index 8221b3a528ed..cd92949b1c46 100644 --- a/src/jdk.crypto.ec/share/classes/sun/security/ec/ed/EdDSAParameters.java +++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/ed/EdDSAParameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ package sun.security.ec.ed; import sun.security.ec.ParametersMap; -import sun.security.provider.SHAKE256; +import sun.security.provider.SHA3.SHAKE256; import sun.security.util.ObjectIdentifier; import sun.security.util.KnownOIDs; import sun.security.util.math.*; diff --git a/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp b/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp index f4af44421462..add1d21c6810 100644 --- a/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp +++ b/src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1364,7 +1364,7 @@ JNIEXPORT jobject JNICALL Java_sun_security_mscapi_CKeyPairGenerator_00024RSA_ge PROV_RSA_FULL, CRYPT_NEWKEYSET) == FALSE) { - ThrowException(env, KEY_EXCEPTION, GetLastError()); + ThrowExceptionWithMessageAndErrcode(env, KEY_EXCEPTION, "CryptAcquireContext failure", GetLastError()); __leave; } } @@ -1376,7 +1376,7 @@ JNIEXPORT jobject JNICALL Java_sun_security_mscapi_CKeyPairGenerator_00024RSA_ge dwFlags, &hKeyPair) == FALSE) { - ThrowException(env, KEY_EXCEPTION, GetLastError()); + ThrowExceptionWithMessageAndErrcode(env, KEY_EXCEPTION, "CryptGenKey failure", GetLastError()); __leave; } diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/log_messages.c b/src/jdk.jdwp.agent/share/native/libjdwp/log_messages.c index ebc39febff9c..36ec72bfdcfd 100644 --- a/src/jdk.jdwp.agent/share/native/libjdwp/log_messages.c +++ b/src/jdk.jdwp.agent/share/native/libjdwp/log_messages.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -90,8 +90,8 @@ get_time_stamp(char *tbuf, size_t ltbuf) static const char * file_basename(const char *file) { - char *p1; - char *p2; + const char* p1; + const char* p2; if ( file==NULL ) return "unknown"; diff --git a/src/jdk.jpackage/linux/native/applauncher/LinuxPackage.c b/src/jdk.jpackage/linux/native/applauncher/LinuxPackage.c index 26d65f8061c7..d346e241035a 100644 --- a/src/jdk.jpackage/linux/native/applauncher/LinuxPackage.c +++ b/src/jdk.jpackage/linux/native/applauncher/LinuxPackage.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -109,7 +109,7 @@ static PackageDesc* initPackageDesc(PackageDesc* desc, const char* str, #define POPEN_CALLBACK_USE 1 #define POPEN_CALLBACK_IGNORE 0 -typedef int (*popenCallbackType)(void*, const char*); +typedef int (*popenCallbackType)(void*, char*); static int popenCommand(const char* cmdlineFormat, const char* arg, popenCallbackType callback, void* callbackData) { @@ -220,13 +220,13 @@ static char* concat(const char *x, const char *y) { } -static int initRpmPackage(void* desc, const char* str) { +static int initRpmPackage(void* desc, char* str) { initPackageDesc((PackageDesc*)desc, str, PACKAGE_TYPE_RPM); return POPEN_CALLBACK_IGNORE; } -static int initDebPackage(void* desc, const char* str) { +static int initDebPackage(void* desc, char* str) { char* colonChrPos = strchr(str, ':'); if (colonChrPos) { *colonChrPos = 0; @@ -238,7 +238,7 @@ static int initDebPackage(void* desc, const char* str) { #define LAUNCHER_LIB_NAME "/libapplauncher.so" -static int findLauncherLib(void* launcherLibPath, const char* str) { +static int findLauncherLib(void* launcherLibPath, char* str) { char* buf = 0; const size_t strLen = strlen(str); const size_t launcherLibNameLen = strlen(LAUNCHER_LIB_NAME); diff --git a/test/docs/TEST.ROOT b/test/docs/TEST.ROOT index af2e58967795..9a7e66b631c1 100644 --- a/test/docs/TEST.ROOT +++ b/test/docs/TEST.ROOT @@ -1,5 +1,5 @@ # -# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -38,7 +38,7 @@ groups=TEST.groups # Minimum jtreg version -requiredVersion=7.4+1 +requiredVersion=8.2.1+1 # Use new module options useNewOptions=true diff --git a/test/hotspot/gtest/aarch64/aarch64-asmtest.py b/test/hotspot/gtest/aarch64/aarch64-asmtest.py index 64f3e787356e..45ecf57e971e 100644 --- a/test/hotspot/gtest/aarch64/aarch64-asmtest.py +++ b/test/hotspot/gtest/aarch64/aarch64-asmtest.py @@ -1833,6 +1833,11 @@ def generate(kind, names): ["sminp", "sminp", "8B"], ["sminp", "sminp", "16B"], ["sminp", "sminp", "4H"], ["sminp", "sminp", "8H"], ["sminp", "sminp", "2S"], ["sminp", "sminp", "4S"], + ["sqdmulh", "sqdmulh", "4H"], ["sqdmulh", "sqdmulh", "8H"], + ["sqdmulh", "sqdmulh", "2S"], ["sqdmulh", "sqdmulh", "4S"], + ["shsubv", "shsub", "8B"], ["shsubv", "shsub", "16B"], + ["shsubv", "shsub", "4H"], ["shsubv", "shsub", "8H"], + ["shsubv", "shsub", "2S"], ["shsubv", "shsub", "4S"], ["fmin", "fmin", "2S"], ["fmin", "fmin", "4S"], ["fmin", "fmin", "2D"], ["facgt", "facgt", "2S"], ["facgt", "facgt", "4S"], diff --git a/test/hotspot/gtest/aarch64/asmtest.out.h b/test/hotspot/gtest/aarch64/asmtest.out.h index 9805a05c5c15..3bcd40ba2aaa 100644 --- a/test/hotspot/gtest/aarch64/asmtest.out.h +++ b/test/hotspot/gtest/aarch64/asmtest.out.h @@ -745,93 +745,103 @@ __ sminp(v2, __ T8H, v3, v4); // sminp v2.8H, v3.8H, v4.8H __ sminp(v0, __ T2S, v1, v2); // sminp v0.2S, v1.2S, v2.2S __ sminp(v9, __ T4S, v10, v11); // sminp v9.4S, v10.4S, v11.4S - __ fmin(v24, __ T2S, v25, v26); // fmin v24.2S, v25.2S, v26.2S - __ fmin(v26, __ T4S, v27, v28); // fmin v26.4S, v27.4S, v28.4S - __ fmin(v16, __ T2D, v17, v18); // fmin v16.2D, v17.2D, v18.2D - __ facgt(v30, __ T2S, v31, v0); // facgt v30.2S, v31.2S, v0.2S - __ facgt(v3, __ T4S, v4, v5); // facgt v3.4S, v4.4S, v5.4S - __ facgt(v10, __ T2D, v11, v12); // facgt v10.2D, v11.2D, v12.2D + __ sqdmulh(v24, __ T4H, v25, v26); // sqdmulh v24.4H, v25.4H, v26.4H + __ sqdmulh(v26, __ T8H, v27, v28); // sqdmulh v26.8H, v27.8H, v28.8H + __ sqdmulh(v16, __ T2S, v17, v18); // sqdmulh v16.2S, v17.2S, v18.2S + __ sqdmulh(v30, __ T4S, v31, v0); // sqdmulh v30.4S, v31.4S, v0.4S + __ shsubv(v3, __ T8B, v4, v5); // shsub v3.8B, v4.8B, v5.8B + __ shsubv(v10, __ T16B, v11, v12); // shsub v10.16B, v11.16B, v12.16B + __ shsubv(v23, __ T4H, v24, v25); // shsub v23.4H, v24.4H, v25.4H + __ shsubv(v10, __ T8H, v11, v12); // shsub v10.8H, v11.8H, v12.8H + __ shsubv(v4, __ T2S, v5, v6); // shsub v4.2S, v5.2S, v6.2S + __ shsubv(v18, __ T4S, v19, v20); // shsub v18.4S, v19.4S, v20.4S + __ fmin(v2, __ T2S, v3, v4); // fmin v2.2S, v3.2S, v4.2S + __ fmin(v11, __ T4S, v12, v13); // fmin v11.4S, v12.4S, v13.4S + __ fmin(v8, __ T2D, v9, v10); // fmin v8.2D, v9.2D, v10.2D + __ facgt(v10, __ T2S, v11, v12); // facgt v10.2S, v11.2S, v12.2S + __ facgt(v15, __ T4S, v16, v17); // facgt v15.4S, v16.4S, v17.4S + __ facgt(v17, __ T2D, v18, v19); // facgt v17.2D, v18.2D, v19.2D // VectorScalarNEONInstruction - __ fmlavs(v5, __ T2S, v6, v7, 1); // fmla v5.2S, v6.2S, v7.S[1] - __ mulvs(v9, __ T4S, v10, v11, 0); // mul v9.4S, v10.4S, v11.S[0] - __ fmlavs(v5, __ T2D, v6, v7, 0); // fmla v5.2D, v6.2D, v7.D[0] - __ fmlsvs(v5, __ T2S, v6, v7, 0); // fmls v5.2S, v6.2S, v7.S[0] - __ mulvs(v8, __ T4S, v9, v10, 1); // mul v8.4S, v9.4S, v10.S[1] - __ fmlsvs(v5, __ T2D, v6, v7, 0); // fmls v5.2D, v6.2D, v7.D[0] - __ fmulxvs(v6, __ T2S, v7, v8, 0); // fmulx v6.2S, v7.2S, v8.S[0] + __ fmlavs(v5, __ T2S, v6, v7, 0); // fmla v5.2S, v6.2S, v7.S[0] __ mulvs(v6, __ T4S, v7, v8, 1); // mul v6.4S, v7.4S, v8.S[1] - __ fmulxvs(v3, __ T2D, v4, v5, 0); // fmulx v3.2D, v4.2D, v5.D[0] - __ mulvs(v13, __ T4H, v14, v15, 2); // mul v13.4H, v14.4H, v15.H[2] - __ mulvs(v2, __ T8H, v3, v4, 4); // mul v2.8H, v3.8H, v4.H[4] - __ mulvs(v2, __ T2S, v3, v4, 0); // mul v2.2S, v3.2S, v4.S[0] + __ fmlavs(v6, __ T2D, v7, v8, 0); // fmla v6.2D, v7.2D, v8.D[0] + __ fmlsvs(v3, __ T2S, v4, v5, 0); // fmls v3.2S, v4.2S, v5.S[0] + __ mulvs(v13, __ T4S, v14, v15, 2); // mul v13.4S, v14.4S, v15.S[2] + __ fmlsvs(v2, __ T2D, v3, v4, 1); // fmls v2.2D, v3.2D, v4.D[1] + __ fmulxvs(v2, __ T2S, v3, v4, 0); // fmulx v2.2S, v3.2S, v4.S[0] __ mulvs(v9, __ T4S, v10, v11, 1); // mul v9.4S, v10.4S, v11.S[1] + __ fmulxvs(v8, __ T2D, v9, v10, 1); // fmulx v8.2D, v9.2D, v10.D[1] + __ mulvs(v5, __ T4H, v6, v7, 2); // mul v5.4H, v6.4H, v7.H[2] + __ mulvs(v11, __ T8H, v12, v13, 5); // mul v11.8H, v12.8H, v13.H[5] + __ mulvs(v13, __ T2S, v14, v15, 0); // mul v13.2S, v14.2S, v15.S[0] + __ mulvs(v14, __ T4S, v15, v16, 2); // mul v14.4S, v15.4S, v16.S[2] // NEONVectorCompare - __ cm(Assembler::GT, v21, __ T8B, v22, v23); // cmgt v21.8B, v22.8B, v23.8B - __ cm(Assembler::GT, v16, __ T16B, v17, v18); // cmgt v16.16B, v17.16B, v18.16B - __ cm(Assembler::GT, v18, __ T4H, v19, v20); // cmgt v18.4H, v19.4H, v20.4H - __ cm(Assembler::GT, v11, __ T8H, v12, v13); // cmgt v11.8H, v12.8H, v13.8H - __ cm(Assembler::GT, v21, __ T2S, v22, v23); // cmgt v21.2S, v22.2S, v23.2S - __ cm(Assembler::GT, v23, __ T4S, v24, v25); // cmgt v23.4S, v24.4S, v25.4S - __ cm(Assembler::GT, v12, __ T2D, v13, v14); // cmgt v12.2D, v13.2D, v14.2D - __ cm(Assembler::GE, v26, __ T8B, v27, v28); // cmge v26.8B, v27.8B, v28.8B - __ cm(Assembler::GE, v23, __ T16B, v24, v25); // cmge v23.16B, v24.16B, v25.16B - __ cm(Assembler::GE, v28, __ T4H, v29, v30); // cmge v28.4H, v29.4H, v30.4H - __ cm(Assembler::GE, v14, __ T8H, v15, v16); // cmge v14.8H, v15.8H, v16.8H - __ cm(Assembler::GE, v11, __ T2S, v12, v13); // cmge v11.2S, v12.2S, v13.2S - __ cm(Assembler::GE, v24, __ T4S, v25, v26); // cmge v24.4S, v25.4S, v26.4S - __ cm(Assembler::GE, v1, __ T2D, v2, v3); // cmge v1.2D, v2.2D, v3.2D - __ cm(Assembler::EQ, v12, __ T8B, v13, v14); // cmeq v12.8B, v13.8B, v14.8B - __ cm(Assembler::EQ, v31, __ T16B, v0, v1); // cmeq v31.16B, v0.16B, v1.16B - __ cm(Assembler::EQ, v10, __ T4H, v11, v12); // cmeq v10.4H, v11.4H, v12.4H - __ cm(Assembler::EQ, v16, __ T8H, v17, v18); // cmeq v16.8H, v17.8H, v18.8H - __ cm(Assembler::EQ, v7, __ T2S, v8, v9); // cmeq v7.2S, v8.2S, v9.2S - __ cm(Assembler::EQ, v2, __ T4S, v3, v4); // cmeq v2.4S, v3.4S, v4.4S - __ cm(Assembler::EQ, v3, __ T2D, v4, v5); // cmeq v3.2D, v4.2D, v5.2D - __ cm(Assembler::HI, v13, __ T8B, v14, v15); // cmhi v13.8B, v14.8B, v15.8B - __ cm(Assembler::HI, v19, __ T16B, v20, v21); // cmhi v19.16B, v20.16B, v21.16B - __ cm(Assembler::HI, v17, __ T4H, v18, v19); // cmhi v17.4H, v18.4H, v19.4H - __ cm(Assembler::HI, v16, __ T8H, v17, v18); // cmhi v16.8H, v17.8H, v18.8H - __ cm(Assembler::HI, v3, __ T2S, v4, v5); // cmhi v3.2S, v4.2S, v5.2S - __ cm(Assembler::HI, v1, __ T4S, v2, v3); // cmhi v1.4S, v2.4S, v3.4S - __ cm(Assembler::HI, v11, __ T2D, v12, v13); // cmhi v11.2D, v12.2D, v13.2D - __ cm(Assembler::HS, v30, __ T8B, v31, v0); // cmhs v30.8B, v31.8B, v0.8B - __ cm(Assembler::HS, v5, __ T16B, v6, v7); // cmhs v5.16B, v6.16B, v7.16B - __ cm(Assembler::HS, v8, __ T4H, v9, v10); // cmhs v8.4H, v9.4H, v10.4H - __ cm(Assembler::HS, v15, __ T8H, v16, v17); // cmhs v15.8H, v16.8H, v17.8H - __ cm(Assembler::HS, v29, __ T2S, v30, v31); // cmhs v29.2S, v30.2S, v31.2S - __ cm(Assembler::HS, v30, __ T4S, v31, v0); // cmhs v30.4S, v31.4S, v0.4S - __ cm(Assembler::HS, v0, __ T2D, v1, v2); // cmhs v0.2D, v1.2D, v2.2D - __ fcm(Assembler::EQ, v20, __ T2S, v21, v22); // fcmeq v20.2S, v21.2S, v22.2S - __ fcm(Assembler::EQ, v7, __ T4S, v8, v9); // fcmeq v7.4S, v8.4S, v9.4S - __ fcm(Assembler::EQ, v20, __ T2D, v21, v22); // fcmeq v20.2D, v21.2D, v22.2D - __ fcm(Assembler::GT, v23, __ T2S, v24, v25); // fcmgt v23.2S, v24.2S, v25.2S - __ fcm(Assembler::GT, v28, __ T4S, v29, v30); // fcmgt v28.4S, v29.4S, v30.4S - __ fcm(Assembler::GT, v21, __ T2D, v22, v23); // fcmgt v21.2D, v22.2D, v23.2D - __ fcm(Assembler::GE, v27, __ T2S, v28, v29); // fcmge v27.2S, v28.2S, v29.2S - __ fcm(Assembler::GE, v25, __ T4S, v26, v27); // fcmge v25.4S, v26.4S, v27.4S - __ fcm(Assembler::GE, v5, __ T2D, v6, v7); // fcmge v5.2D, v6.2D, v7.2D + __ cm(Assembler::GT, v14, __ T8B, v15, v16); // cmgt v14.8B, v15.8B, v16.8B + __ cm(Assembler::GT, v11, __ T16B, v12, v13); // cmgt v11.16B, v12.16B, v13.16B + __ cm(Assembler::GT, v24, __ T4H, v25, v26); // cmgt v24.4H, v25.4H, v26.4H + __ cm(Assembler::GT, v1, __ T8H, v2, v3); // cmgt v1.8H, v2.8H, v3.8H + __ cm(Assembler::GT, v12, __ T2S, v13, v14); // cmgt v12.2S, v13.2S, v14.2S + __ cm(Assembler::GT, v31, __ T4S, v0, v1); // cmgt v31.4S, v0.4S, v1.4S + __ cm(Assembler::GT, v10, __ T2D, v11, v12); // cmgt v10.2D, v11.2D, v12.2D + __ cm(Assembler::GE, v16, __ T8B, v17, v18); // cmge v16.8B, v17.8B, v18.8B + __ cm(Assembler::GE, v7, __ T16B, v8, v9); // cmge v7.16B, v8.16B, v9.16B + __ cm(Assembler::GE, v2, __ T4H, v3, v4); // cmge v2.4H, v3.4H, v4.4H + __ cm(Assembler::GE, v3, __ T8H, v4, v5); // cmge v3.8H, v4.8H, v5.8H + __ cm(Assembler::GE, v13, __ T2S, v14, v15); // cmge v13.2S, v14.2S, v15.2S + __ cm(Assembler::GE, v19, __ T4S, v20, v21); // cmge v19.4S, v20.4S, v21.4S + __ cm(Assembler::GE, v17, __ T2D, v18, v19); // cmge v17.2D, v18.2D, v19.2D + __ cm(Assembler::EQ, v16, __ T8B, v17, v18); // cmeq v16.8B, v17.8B, v18.8B + __ cm(Assembler::EQ, v3, __ T16B, v4, v5); // cmeq v3.16B, v4.16B, v5.16B + __ cm(Assembler::EQ, v1, __ T4H, v2, v3); // cmeq v1.4H, v2.4H, v3.4H + __ cm(Assembler::EQ, v11, __ T8H, v12, v13); // cmeq v11.8H, v12.8H, v13.8H + __ cm(Assembler::EQ, v30, __ T2S, v31, v0); // cmeq v30.2S, v31.2S, v0.2S + __ cm(Assembler::EQ, v5, __ T4S, v6, v7); // cmeq v5.4S, v6.4S, v7.4S + __ cm(Assembler::EQ, v8, __ T2D, v9, v10); // cmeq v8.2D, v9.2D, v10.2D + __ cm(Assembler::HI, v15, __ T8B, v16, v17); // cmhi v15.8B, v16.8B, v17.8B + __ cm(Assembler::HI, v29, __ T16B, v30, v31); // cmhi v29.16B, v30.16B, v31.16B + __ cm(Assembler::HI, v30, __ T4H, v31, v0); // cmhi v30.4H, v31.4H, v0.4H + __ cm(Assembler::HI, v0, __ T8H, v1, v2); // cmhi v0.8H, v1.8H, v2.8H + __ cm(Assembler::HI, v20, __ T2S, v21, v22); // cmhi v20.2S, v21.2S, v22.2S + __ cm(Assembler::HI, v7, __ T4S, v8, v9); // cmhi v7.4S, v8.4S, v9.4S + __ cm(Assembler::HI, v20, __ T2D, v21, v22); // cmhi v20.2D, v21.2D, v22.2D + __ cm(Assembler::HS, v23, __ T8B, v24, v25); // cmhs v23.8B, v24.8B, v25.8B + __ cm(Assembler::HS, v28, __ T16B, v29, v30); // cmhs v28.16B, v29.16B, v30.16B + __ cm(Assembler::HS, v21, __ T4H, v22, v23); // cmhs v21.4H, v22.4H, v23.4H + __ cm(Assembler::HS, v27, __ T8H, v28, v29); // cmhs v27.8H, v28.8H, v29.8H + __ cm(Assembler::HS, v25, __ T2S, v26, v27); // cmhs v25.2S, v26.2S, v27.2S + __ cm(Assembler::HS, v5, __ T4S, v6, v7); // cmhs v5.4S, v6.4S, v7.4S + __ cm(Assembler::HS, v1, __ T2D, v2, v3); // cmhs v1.2D, v2.2D, v3.2D + __ fcm(Assembler::EQ, v23, __ T2S, v24, v25); // fcmeq v23.2S, v24.2S, v25.2S + __ fcm(Assembler::EQ, v16, __ T4S, v17, v18); // fcmeq v16.4S, v17.4S, v18.4S + __ fcm(Assembler::EQ, v31, __ T2D, v0, v1); // fcmeq v31.2D, v0.2D, v1.2D + __ fcm(Assembler::GT, v5, __ T2S, v6, v7); // fcmgt v5.2S, v6.2S, v7.2S + __ fcm(Assembler::GT, v12, __ T4S, v13, v14); // fcmgt v12.4S, v13.4S, v14.4S + __ fcm(Assembler::GT, v9, __ T2D, v10, v11); // fcmgt v9.2D, v10.2D, v11.2D + __ fcm(Assembler::GE, v28, __ T2S, v29, v30); // fcmge v28.2S, v29.2S, v30.2S + __ fcm(Assembler::GE, v15, __ T4S, v16, v17); // fcmge v15.4S, v16.4S, v17.4S + __ fcm(Assembler::GE, v29, __ T2D, v30, v31); // fcmge v29.2D, v30.2D, v31.2D // SVEComparisonWithZero - __ sve_fcm(Assembler::EQ, p0, __ D, p7, z23, 0.0); // fcmeq p0.d, p7/z, z23.d, #0.0 - __ sve_fcm(Assembler::GT, p2, __ S, p7, z12, 0.0); // fcmgt p2.s, p7/z, z12.s, #0.0 - __ sve_fcm(Assembler::GE, p7, __ D, p7, z29, 0.0); // fcmge p7.d, p7/z, z29.d, #0.0 - __ sve_fcm(Assembler::LT, p9, __ S, p3, z31, 0.0); // fcmlt p9.s, p3/z, z31.s, #0.0 - __ sve_fcm(Assembler::LE, p9, __ D, p6, z31, 0.0); // fcmle p9.d, p6/z, z31.d, #0.0 - __ sve_fcm(Assembler::NE, p10, __ S, p2, z16, 0.0); // fcmne p10.s, p2/z, z16.s, #0.0 + __ sve_fcm(Assembler::EQ, p11, __ D, p7, z31, 0.0); // fcmeq p11.d, p7/z, z31.d, #0.0 + __ sve_fcm(Assembler::GT, p2, __ D, p7, z14, 0.0); // fcmgt p2.d, p7/z, z14.d, #0.0 + __ sve_fcm(Assembler::GE, p9, __ D, p4, z27, 0.0); // fcmge p9.d, p4/z, z27.d, #0.0 + __ sve_fcm(Assembler::LT, p6, __ S, p1, z11, 0.0); // fcmlt p6.s, p1/z, z11.s, #0.0 + __ sve_fcm(Assembler::LE, p15, __ D, p7, z17, 0.0); // fcmle p15.d, p7/z, z17.d, #0.0 + __ sve_fcm(Assembler::NE, p15, __ S, p5, z7, 0.0); // fcmne p15.s, p5/z, z7.s, #0.0 // SVEComparisonWithImm - __ sve_cmp(Assembler::EQ, p4, __ D, p4, z6, 11); // cmpeq p4.d, p4/z, z6.d, #11 - __ sve_cmp(Assembler::GT, p14, __ B, p2, z30, 4); // cmpgt p14.b, p2/z, z30.b, #4 - __ sve_cmp(Assembler::GE, p5, __ D, p4, z4, 1); // cmpge p5.d, p4/z, z4.d, #1 - __ sve_cmp(Assembler::LT, p11, __ D, p3, z3, 6); // cmplt p11.d, p3/z, z3.d, #6 - __ sve_cmp(Assembler::LE, p9, __ S, p0, z19, -1); // cmple p9.s, p0/z, z19.s, #-1 - __ sve_cmp(Assembler::NE, p3, __ S, p2, z12, -3); // cmpne p3.s, p2/z, z12.s, #-3 - __ sve_cmp(Assembler::HS, p11, __ D, p4, z1, 20); // cmphs p11.d, p4/z, z1.d, #20 - __ sve_cmp(Assembler::HI, p8, __ S, p5, z2, 53); // cmphi p8.s, p5/z, z2.s, #53 - __ sve_cmp(Assembler::LS, p5, __ D, p6, z21, 49); // cmpls p5.d, p6/z, z21.d, #49 - __ sve_cmp(Assembler::LO, p13, __ B, p7, z3, 97); // cmplo p13.b, p7/z, z3.b, #97 + __ sve_cmp(Assembler::EQ, p5, __ D, p4, z4, 1); // cmpeq p5.d, p4/z, z4.d, #1 + __ sve_cmp(Assembler::GT, p11, __ D, p3, z3, 6); // cmpgt p11.d, p3/z, z3.d, #6 + __ sve_cmp(Assembler::GE, p9, __ S, p0, z19, -1); // cmpge p9.s, p0/z, z19.s, #-1 + __ sve_cmp(Assembler::LT, p3, __ S, p2, z12, -3); // cmplt p3.s, p2/z, z12.s, #-3 + __ sve_cmp(Assembler::LE, p11, __ D, p4, z1, -11); // cmple p11.d, p4/z, z1.d, #-11 + __ sve_cmp(Assembler::NE, p8, __ S, p5, z2, -3); // cmpne p8.s, p5/z, z2.s, #-3 + __ sve_cmp(Assembler::HS, p5, __ D, p6, z21, 49); // cmphs p5.d, p6/z, z21.d, #49 + __ sve_cmp(Assembler::HI, p13, __ B, p7, z3, 97); // cmphi p13.b, p7/z, z3.b, #97 + __ sve_cmp(Assembler::LS, p9, __ H, p7, z17, 109); // cmpls p9.h, p7/z, z17.h, #109 + __ sve_cmp(Assembler::LO, p7, __ S, p5, z7, 127); // cmplo p7.s, p5/z, z7.s, #127 // SpecialCases __ ccmn(zr, zr, 3u, Assembler::LE); // ccmn xzr, xzr, #3, LE @@ -1086,229 +1096,229 @@ __ fmovd(v0, -1.0625); // fmov d0, #-1.0625 // LSEOp - __ swp(Assembler::xword, r19, r17, r9); // swp x19, x17, [x9] - __ ldadd(Assembler::xword, r28, r27, r15); // ldadd x28, x27, [x15] - __ ldbic(Assembler::xword, r7, r21, r23); // ldclr x7, x21, [x23] - __ ldeor(Assembler::xword, zr, r25, r2); // ldeor xzr, x25, [x2] - __ ldorr(Assembler::xword, zr, r27, r15); // ldset xzr, x27, [x15] - __ ldsmin(Assembler::xword, r10, r23, r19); // ldsmin x10, x23, [x19] - __ ldsmax(Assembler::xword, r3, r16, r0); // ldsmax x3, x16, [x0] - __ ldumin(Assembler::xword, r25, r26, r23); // ldumin x25, x26, [x23] - __ ldumax(Assembler::xword, r2, r16, r12); // ldumax x2, x16, [x12] + __ swp(Assembler::xword, r25, r2, sp); // swp x25, x2, [sp] + __ ldadd(Assembler::xword, r27, r16, r10); // ldadd x27, x16, [x10] + __ ldbic(Assembler::xword, r23, r19, r3); // ldclr x23, x19, [x3] + __ ldeor(Assembler::xword, r16, r0, r25); // ldeor x16, x0, [x25] + __ ldorr(Assembler::xword, r26, r23, r2); // ldset x26, x23, [x2] + __ ldsmin(Assembler::xword, r16, r12, r4); // ldsmin x16, x12, [x4] + __ ldsmax(Assembler::xword, r28, r30, r29); // ldsmax x28, x30, [x29] + __ ldumin(Assembler::xword, r16, r27, r6); // ldumin x16, x27, [x6] + __ ldumax(Assembler::xword, r9, r29, r15); // ldumax x9, x29, [x15] // LSEOp - __ swpa(Assembler::xword, r4, r28, r30); // swpa x4, x28, [x30] - __ ldadda(Assembler::xword, r29, r16, r27); // ldadda x29, x16, [x27] - __ ldbica(Assembler::xword, r6, r9, r29); // ldclra x6, x9, [x29] - __ ldeora(Assembler::xword, r16, r7, r4); // ldeora x16, x7, [x4] - __ ldorra(Assembler::xword, r7, r15, r9); // ldseta x7, x15, [x9] - __ ldsmina(Assembler::xword, r23, r8, r2); // ldsmina x23, x8, [x2] - __ ldsmaxa(Assembler::xword, r28, r21, sp); // ldsmaxa x28, x21, [sp] - __ ldumina(Assembler::xword, r5, r27, r0); // ldumina x5, x27, [x0] - __ ldumaxa(Assembler::xword, r17, r15, r4); // ldumaxa x17, x15, [x4] + __ swpa(Assembler::xword, r7, r4, r7); // swpa x7, x4, [x7] + __ ldadda(Assembler::xword, r15, r9, r23); // ldadda x15, x9, [x23] + __ ldbica(Assembler::xword, r8, r2, r28); // ldclra x8, x2, [x28] + __ ldeora(Assembler::xword, r21, zr, r5); // ldeora x21, xzr, [x5] + __ ldorra(Assembler::xword, r27, r0, r17); // ldseta x27, x0, [x17] + __ ldsmina(Assembler::xword, r15, r4, r26); // ldsmina x15, x4, [x26] + __ ldsmaxa(Assembler::xword, r8, r28, r22); // ldsmaxa x8, x28, [x22] + __ ldumina(Assembler::xword, r27, r27, r25); // ldumina x27, x27, [x25] + __ ldumaxa(Assembler::xword, r23, r0, r4); // ldumaxa x23, x0, [x4] // LSEOp - __ swpal(Assembler::xword, r26, r8, r28); // swpal x26, x8, [x28] - __ ldaddal(Assembler::xword, r22, r27, r27); // ldaddal x22, x27, [x27] - __ ldbical(Assembler::xword, r25, r23, r0); // ldclral x25, x23, [x0] - __ ldeoral(Assembler::xword, r4, r6, r15); // ldeoral x4, x6, [x15] - __ ldorral(Assembler::xword, r0, r4, r15); // ldsetal x0, x4, [x15] - __ ldsminal(Assembler::xword, r1, r10, r7); // ldsminal x1, x10, [x7] - __ ldsmaxal(Assembler::xword, r5, r10, r28); // ldsmaxal x5, x10, [x28] - __ lduminal(Assembler::xword, r7, r20, r23); // lduminal x7, x20, [x23] - __ ldumaxal(Assembler::xword, r21, r6, r11); // ldumaxal x21, x6, [x11] + __ swpal(Assembler::xword, r6, r16, r0); // swpal x6, x16, [x0] + __ ldaddal(Assembler::xword, r4, r15, r1); // ldaddal x4, x15, [x1] + __ ldbical(Assembler::xword, r10, r7, r5); // ldclral x10, x7, [x5] + __ ldeoral(Assembler::xword, r10, r28, r7); // ldeoral x10, x28, [x7] + __ ldorral(Assembler::xword, r20, r23, r21); // ldsetal x20, x23, [x21] + __ ldsminal(Assembler::xword, r6, r11, r8); // ldsminal x6, x11, [x8] + __ ldsmaxal(Assembler::xword, r17, zr, r6); // ldsmaxal x17, xzr, [x6] + __ lduminal(Assembler::xword, r17, r2, r12); // lduminal x17, x2, [x12] + __ ldumaxal(Assembler::xword, r30, r29, r3); // ldumaxal x30, x29, [x3] // LSEOp - __ swpl(Assembler::xword, r8, r17, sp); // swpl x8, x17, [sp] - __ ldaddl(Assembler::xword, r6, r17, r2); // ldaddl x6, x17, [x2] - __ ldbicl(Assembler::xword, r12, r30, r29); // ldclrl x12, x30, [x29] - __ ldeorl(Assembler::xword, r3, r27, r22); // ldeorl x3, x27, [x22] - __ ldorrl(Assembler::xword, r29, r14, r13); // ldsetl x29, x14, [x13] - __ ldsminl(Assembler::xword, r28, r17, r24); // ldsminl x28, x17, [x24] - __ ldsmaxl(Assembler::xword, r5, r2, r14); // ldsmaxl x5, x2, [x14] - __ lduminl(Assembler::xword, r10, r16, r11); // lduminl x10, x16, [x11] - __ ldumaxl(Assembler::xword, r27, r23, r12); // ldumaxl x27, x23, [x12] + __ swpl(Assembler::xword, r27, r22, r29); // swpl x27, x22, [x29] + __ ldaddl(Assembler::xword, r14, r13, r28); // ldaddl x14, x13, [x28] + __ ldbicl(Assembler::xword, r17, r24, r5); // ldclrl x17, x24, [x5] + __ ldeorl(Assembler::xword, r2, r14, r10); // ldeorl x2, x14, [x10] + __ ldorrl(Assembler::xword, r16, r11, r27); // ldsetl x16, x11, [x27] + __ ldsminl(Assembler::xword, r23, r12, r4); // ldsminl x23, x12, [x4] + __ ldsmaxl(Assembler::xword, r22, r17, r4); // ldsmaxl x22, x17, [x4] + __ lduminl(Assembler::xword, r1, r19, r16); // lduminl x1, x19, [x16] + __ ldumaxl(Assembler::xword, r16, r13, r14); // ldumaxl x16, x13, [x14] // LSEOp - __ swp(Assembler::word, r4, r22, r17); // swp w4, w22, [x17] - __ ldadd(Assembler::word, r4, r1, r19); // ldadd w4, w1, [x19] - __ ldbic(Assembler::word, r16, r16, r13); // ldclr w16, w16, [x13] - __ ldeor(Assembler::word, r14, r12, r2); // ldeor w14, w12, [x2] - __ ldorr(Assembler::word, r17, r3, r21); // ldset w17, w3, [x21] - __ ldsmin(Assembler::word, r23, r5, r6); // ldsmin w23, w5, [x6] - __ ldsmax(Assembler::word, r7, r19, r13); // ldsmax w7, w19, [x13] - __ ldumin(Assembler::word, r28, r17, r16); // ldumin w28, w17, [x16] - __ ldumax(Assembler::word, r6, r2, r29); // ldumax w6, w2, [x29] + __ swp(Assembler::word, r12, r2, r17); // swp w12, w2, [x17] + __ ldadd(Assembler::word, r3, r21, r23); // ldadd w3, w21, [x23] + __ ldbic(Assembler::word, r5, r6, r7); // ldclr w5, w6, [x7] + __ ldeor(Assembler::word, r19, r13, r28); // ldeor w19, w13, [x28] + __ ldorr(Assembler::word, r17, r16, r6); // ldset w17, w16, [x6] + __ ldsmin(Assembler::word, r2, r29, r3); // ldsmin w2, w29, [x3] + __ ldsmax(Assembler::word, r4, r6, r15); // ldsmax w4, w6, [x15] + __ ldumin(Assembler::word, r20, r13, r12); // ldumin w20, w13, [x12] + __ ldumax(Assembler::word, r20, r8, r25); // ldumax w20, w8, [x25] // LSEOp - __ swpa(Assembler::word, r3, r4, r6); // swpa w3, w4, [x6] - __ ldadda(Assembler::word, r16, r20, r13); // ldadda w16, w20, [x13] - __ ldbica(Assembler::word, r12, r20, r8); // ldclra w12, w20, [x8] - __ ldeora(Assembler::word, r25, r20, r19); // ldeora w25, w20, [x19] - __ ldorra(Assembler::word, r0, r11, r24); // ldseta w0, w11, [x24] - __ ldsmina(Assembler::word, r6, r20, sp); // ldsmina w6, w20, [sp] - __ ldsmaxa(Assembler::word, r14, r16, r6); // ldsmaxa w14, w16, [x6] - __ ldumina(Assembler::word, r0, r7, r15); // ldumina w0, w7, [x15] - __ ldumaxa(Assembler::word, r19, r26, r9); // ldumaxa w19, w26, [x9] + __ swpa(Assembler::word, r20, r19, r0); // swpa w20, w19, [x0] + __ ldadda(Assembler::word, r11, r24, r6); // ldadda w11, w24, [x6] + __ ldbica(Assembler::word, r20, zr, r14); // ldclra w20, wzr, [x14] + __ ldeora(Assembler::word, r16, r6, r0); // ldeora w16, w6, [x0] + __ ldorra(Assembler::word, r7, r15, r19); // ldseta w7, w15, [x19] + __ ldsmina(Assembler::word, r26, r9, r10); // ldsmina w26, w9, [x10] + __ ldsmaxa(Assembler::word, r23, r21, r22); // ldsmaxa w23, w21, [x22] + __ ldumina(Assembler::word, r28, r2, r3); // ldumina w28, w2, [x3] + __ ldumaxa(Assembler::word, r15, r19, r20); // ldumaxa w15, w19, [x20] // LSEOp - __ swpal(Assembler::word, r10, r23, r21); // swpal w10, w23, [x21] - __ ldaddal(Assembler::word, r22, r28, r2); // ldaddal w22, w28, [x2] - __ ldbical(Assembler::word, r3, r15, r19); // ldclral w3, w15, [x19] - __ ldeoral(Assembler::word, r20, r7, r4); // ldeoral w20, w7, [x4] - __ ldorral(Assembler::word, r29, r7, r0); // ldsetal w29, w7, [x0] - __ ldsminal(Assembler::word, r9, r16, r20); // ldsminal w9, w16, [x20] - __ ldsmaxal(Assembler::word, r23, r4, r16); // ldsmaxal w23, w4, [x16] - __ lduminal(Assembler::word, r10, r23, r11); // lduminal w10, w23, [x11] - __ ldumaxal(Assembler::word, r25, r6, sp); // ldumaxal w25, w6, [sp] + __ swpal(Assembler::word, r7, r4, r29); // swpal w7, w4, [x29] + __ ldaddal(Assembler::word, r7, r0, r9); // ldaddal w7, w0, [x9] + __ ldbical(Assembler::word, r16, r20, r23); // ldclral w16, w20, [x23] + __ ldeoral(Assembler::word, r4, r16, r10); // ldeoral w4, w16, [x10] + __ ldorral(Assembler::word, r23, r11, r25); // ldsetal w23, w11, [x25] + __ ldsminal(Assembler::word, r6, zr, r16); // ldsminal w6, wzr, [x16] + __ ldsmaxal(Assembler::word, r13, r23, r12); // ldsmaxal w13, w23, [x12] + __ lduminal(Assembler::word, r1, r14, r9); // lduminal w1, w14, [x9] + __ ldumaxal(Assembler::word, r21, r16, r26); // ldumaxal w21, w16, [x26] // LSEOp - __ swpl(Assembler::word, r16, r13, r23); // swpl w16, w13, [x23] - __ ldaddl(Assembler::word, r12, r1, r14); // ldaddl w12, w1, [x14] - __ ldbicl(Assembler::word, r9, r21, r16); // ldclrl w9, w21, [x16] - __ ldeorl(Assembler::word, r26, r15, r4); // ldeorl w26, w15, [x4] - __ ldorrl(Assembler::word, r4, r16, r8); // ldsetl w4, w16, [x8] - __ ldsminl(Assembler::word, r6, r30, r4); // ldsminl w6, w30, [x4] - __ ldsmaxl(Assembler::word, r29, r17, r29); // ldsmaxl w29, w17, [x29] - __ lduminl(Assembler::word, r26, r9, r15); // lduminl w26, w9, [x15] - __ ldumaxl(Assembler::word, r2, r11, r29); // ldumaxl w2, w11, [x29] + __ swpl(Assembler::word, r15, r4, r4); // swpl w15, w4, [x4] + __ ldaddl(Assembler::word, r16, r8, r6); // ldaddl w16, w8, [x6] + __ ldbicl(Assembler::word, r30, r4, r29); // ldclrl w30, w4, [x29] + __ ldeorl(Assembler::word, r17, r29, r26); // ldeorl w17, w29, [x26] + __ ldorrl(Assembler::word, r9, r15, r2); // ldsetl w9, w15, [x2] + __ ldsminl(Assembler::word, r11, r29, r3); // ldsminl w11, w29, [x3] + __ ldsmaxl(Assembler::word, r7, r1, r27); // ldsmaxl w7, w1, [x27] + __ lduminl(Assembler::word, r21, r16, r14); // lduminl w21, w16, [x14] + __ ldumaxl(Assembler::word, r8, r16, r22); // ldumaxl w8, w16, [x22] // SHA3SIMDOp - __ bcax(v3, __ T16B, v7, v1, v27); // bcax v3.16B, v7.16B, v1.16B, v27.16B - __ eor3(v21, __ T16B, v18, v14, v8); // eor3 v21.16B, v18.16B, v14.16B, v8.16B - __ rax1(v18, __ T2D, v22, v25); // rax1 v18.2D, v22.2D, v25.2D - __ xar(v5, __ T2D, v20, v21, 37); // xar v5.2D, v20.2D, v21.2D, #37 + __ bcax(v25, __ T16B, v5, v20, v21); // bcax v25.16B, v5.16B, v20.16B, v21.16B + __ eor3(v18, __ T16B, v23, v16, v30); // eor3 v18.16B, v23.16B, v16.16B, v30.16B + __ rax1(v20, __ T2D, v20, v0); // rax1 v20.2D, v20.2D, v0.2D + __ xar(v4, __ T2D, v19, v24, 9); // xar v4.2D, v19.2D, v24.2D, #9 // SHA512SIMDOp - __ sha512h(v23, __ T2D, v16, v30); // sha512h q23, q16, v30.2D - __ sha512h2(v20, __ T2D, v20, v0); // sha512h2 q20, q20, v0.2D - __ sha512su0(v4, __ T2D, v19); // sha512su0 v4.2D, v19.2D - __ sha512su1(v24, __ T2D, v4, v20); // sha512su1 v24.2D, v4.2D, v20.2D + __ sha512h(v20, __ T2D, v4, v24); // sha512h q20, q4, v24.2D + __ sha512h2(v26, __ T2D, v19, v2); // sha512h2 q26, q19, v2.2D + __ sha512su0(v8, __ T2D, v8); // sha512su0 v8.2D, v8.2D + __ sha512su1(v14, __ T2D, v24, v18); // sha512su1 v14.2D, v24.2D, v18.2D // SVEBinaryImmOp - __ sve_add(z4, __ D, 210u); // add z4.d, z4.d, #0xd2 - __ sve_sub(z19, __ B, 71u); // sub z19.b, z19.b, #0x47 - __ sve_and(z8, __ H, 49663u); // and z8.h, z8.h, #0xc1ff - __ sve_eor(z31, __ S, 4294967231u); // eor z31.s, z31.s, #0xffffffbf - __ sve_orr(z1, __ H, 16368u); // orr z1.h, z1.h, #0x3ff0 + __ sve_add(z31, __ S, 36u); // add z31.s, z31.s, #0x24 + __ sve_sub(z31, __ B, 85u); // sub z31.b, z31.b, #0x55 + __ sve_and(z20, __ H, 4032u); // and z20.h, z20.h, #0xfc0 + __ sve_eor(z7, __ D, 274877904896u); // eor z7.d, z7.d, #0x3ffffff800 + __ sve_orr(z27, __ B, 243u); // orr z27.b, z27.b, #0xf3 // SVEBinaryImmOp - __ sve_add(z0, __ H, 61u); // add z0.h, z0.h, #0x3d - __ sve_sub(z24, __ S, 36u); // sub z24.s, z24.s, #0x24 - __ sve_and(z27, __ B, 243u); // and z27.b, z27.b, #0xf3 - __ sve_eor(z24, __ H, 65534u); // eor z24.h, z24.h, #0xfffe - __ sve_orr(z22, __ S, 4294967293u); // orr z22.s, z22.s, #0xfffffffd + __ sve_add(z24, __ H, 132u); // add z24.h, z24.h, #0x84 + __ sve_sub(z31, __ S, 183u); // sub z31.s, z31.s, #0xb7 + __ sve_and(z20, __ D, 4503599627354112u); // and z20.d, z20.d, #0xfffffffffc000 + __ sve_eor(z14, __ S, 4042322160u); // eor z14.s, z14.s, #0xf0f0f0f0 + __ sve_orr(z28, __ H, 32256u); // orr z28.h, z28.h, #0x7e00 // SVEBinaryImmOp - __ sve_add(z29, __ H, 113u); // add z29.h, z29.h, #0x71 - __ sve_sub(z20, __ B, 165u); // sub z20.b, z20.b, #0xa5 - __ sve_and(z28, __ H, 32256u); // and z28.h, z28.h, #0x7e00 - __ sve_eor(z12, __ S, 4287102855u); // eor z12.s, z12.s, #0xff87ff87 - __ sve_orr(z9, __ S, 3825205247u); // orr z9.s, z9.s, #0xe3ffffff + __ sve_add(z12, __ S, 13u); // add z12.s, z12.s, #0xd + __ sve_sub(z24, __ H, 159u); // sub z24.h, z24.h, #0x9f + __ sve_and(z13, __ S, 2151677951u); // and z13.s, z13.s, #0x803fffff + __ sve_eor(z5, __ B, 124u); // eor z5.b, z5.b, #0x7c + __ sve_orr(z8, __ H, 32768u); // orr z8.h, z8.h, #0x8000 // SVEBinaryImmOp - __ sve_add(z18, __ S, 41u); // add z18.s, z18.s, #0x29 - __ sve_sub(z0, __ B, 98u); // sub z0.b, z0.b, #0x62 - __ sve_and(z8, __ H, 32768u); // and z8.h, z8.h, #0x8000 - __ sve_eor(z4, __ H, 508u); // eor z4.h, z4.h, #0x1fc - __ sve_orr(z0, __ H, 64512u); // orr z0.h, z0.h, #0xfc00 + __ sve_add(z4, __ H, 243u); // add z4.h, z4.h, #0xf3 + __ sve_sub(z5, __ B, 86u); // sub z5.b, z5.b, #0x56 + __ sve_and(z22, __ D, 8064u); // and z22.d, z22.d, #0x1f80 + __ sve_eor(z9, __ S, 130023424u); // eor z9.s, z9.s, #0x7c00000 + __ sve_orr(z24, __ B, 62u); // orr z24.b, z24.b, #0x3e // SVEBinaryImmOp - __ sve_add(z3, __ B, 79u); // add z3.b, z3.b, #0x4f - __ sve_sub(z19, __ D, 84u); // sub z19.d, z19.d, #0x54 - __ sve_and(z24, __ B, 62u); // and z24.b, z24.b, #0x3e - __ sve_eor(z24, __ D, 18428729675200069887u); // eor z24.d, z24.d, #0xffc00000000000ff - __ sve_orr(z11, __ D, 17296056810822168583u); // orr z11.d, z11.d, #0xf007f007f007f007 + __ sve_add(z24, __ D, 113u); // add z24.d, z24.d, #0x71 + __ sve_sub(z21, __ H, 217u); // sub z21.h, z21.h, #0xd9 + __ sve_and(z13, __ S, 3221229567u); // and z13.s, z13.s, #0xc0000fff + __ sve_eor(z14, __ B, 131u); // eor z14.b, z14.b, #0x83 + __ sve_orr(z22, __ S, 4042322160u); // orr z22.s, z22.s, #0xf0f0f0f0 // SVEBinaryImmOp - __ sve_add(z31, __ S, 115u); // add z31.s, z31.s, #0x73 - __ sve_sub(z3, __ D, 134u); // sub z3.d, z3.d, #0x86 - __ sve_and(z22, __ S, 4042322160u); // and z22.s, z22.s, #0xf0f0f0f0 - __ sve_eor(z3, __ B, 225u); // eor z3.b, z3.b, #0xe1 - __ sve_orr(z9, __ S, 4164941887u); // orr z9.s, z9.s, #0xf83ff83f + __ sve_add(z3, __ B, 215u); // add z3.b, z3.b, #0xd7 + __ sve_sub(z19, __ H, 134u); // sub z19.h, z19.h, #0x86 + __ sve_and(z17, __ S, 491520u); // and z17.s, z17.s, #0x78000 + __ sve_eor(z2, __ D, 8796093020160u); // eor z2.d, z2.d, #0x7fffffff800 + __ sve_orr(z11, __ S, 3221229567u); // orr z11.s, z11.s, #0xc0000fff // SVEVectorOp - __ sve_add(z0, __ D, z4, z2); // add z0.d, z4.d, z2.d - __ sve_sub(z14, __ S, z6, z11); // sub z14.s, z6.s, z11.s - __ sve_fadd(z14, __ S, z17, z30); // fadd z14.s, z17.s, z30.s - __ sve_fmul(z3, __ S, z3, z23); // fmul z3.s, z3.s, z23.s - __ sve_fsub(z3, __ S, z24, z28); // fsub z3.s, z24.s, z28.s - __ sve_abs(z19, __ D, p5, z7); // abs z19.d, p5/m, z7.d - __ sve_add(z21, __ H, p3, z5); // add z21.h, p3/m, z21.h, z5.h - __ sve_and(z26, __ S, p1, z22); // and z26.s, p1/m, z26.s, z22.s - __ sve_asr(z17, __ H, p0, z3); // asr z17.h, p0/m, z17.h, z3.h - __ sve_bic(z20, __ H, p3, z8); // bic z20.h, p3/m, z20.h, z8.h - __ sve_clz(z14, __ H, p4, z17); // clz z14.h, p4/m, z17.h - __ sve_cnt(z13, __ D, p6, z18); // cnt z13.d, p6/m, z18.d - __ sve_eor(z19, __ H, p2, z16); // eor z19.h, p2/m, z19.h, z16.h - __ sve_lsl(z27, __ S, p5, z28); // lsl z27.s, p5/m, z27.s, z28.s - __ sve_lsr(z8, __ D, p2, z5); // lsr z8.d, p2/m, z8.d, z5.d - __ sve_mul(z28, __ H, p2, z0); // mul z28.h, p2/m, z28.h, z0.h - __ sve_neg(z25, __ B, p5, z21); // neg z25.b, p5/m, z21.b - __ sve_not(z3, __ B, p5, z26); // not z3.b, p5/m, z26.b - __ sve_orr(z26, __ S, p7, z19); // orr z26.s, p7/m, z26.s, z19.s - __ sve_rbit(z1, __ D, p3, z14); // rbit z1.d, p3/m, z14.d - __ sve_revb(z14, __ H, p0, z18); // revb z14.h, p0/m, z18.h - __ sve_smax(z31, __ S, p5, z23); // smax z31.s, p5/m, z31.s, z23.s - __ sve_smin(z30, __ B, p3, z8); // smin z30.b, p3/m, z30.b, z8.b - __ sve_sub(z0, __ S, p3, z23); // sub z0.s, p3/m, z0.s, z23.s - __ sve_fabs(z0, __ D, p4, z26); // fabs z0.d, p4/m, z26.d - __ sve_fadd(z24, __ D, p3, z22); // fadd z24.d, p3/m, z24.d, z22.d - __ sve_fdiv(z2, __ D, p0, z11); // fdiv z2.d, p0/m, z2.d, z11.d - __ sve_fmax(z12, __ D, p5, z24); // fmax z12.d, p5/m, z12.d, z24.d - __ sve_fmin(z9, __ D, p7, z17); // fmin z9.d, p7/m, z9.d, z17.d - __ sve_fmul(z20, __ D, p5, z4); // fmul z20.d, p5/m, z20.d, z4.d - __ sve_fneg(z13, __ D, p7, z22); // fneg z13.d, p7/m, z22.d - __ sve_frintm(z31, __ D, p6, z18); // frintm z31.d, p6/m, z18.d - __ sve_frintn(z15, __ D, p2, z13); // frintn z15.d, p2/m, z13.d - __ sve_frintp(z20, __ S, p1, z1); // frintp z20.s, p1/m, z1.s - __ sve_fsqrt(z14, __ S, p0, z7); // fsqrt z14.s, p0/m, z7.s - __ sve_fsub(z12, __ D, p4, z4); // fsub z12.d, p4/m, z12.d, z4.d - __ sve_fmad(z15, __ S, p0, z3, z30); // fmad z15.s, p0/m, z3.s, z30.s - __ sve_fmla(z20, __ D, p1, z20, z31); // fmla z20.d, p1/m, z20.d, z31.d - __ sve_fmls(z13, __ D, p3, z9, z14); // fmls z13.d, p3/m, z9.d, z14.d - __ sve_fmsb(z1, __ S, p3, z28, z3); // fmsb z1.s, p3/m, z28.s, z3.s - __ sve_fnmad(z26, __ S, p2, z25, z9); // fnmad z26.s, p2/m, z25.s, z9.s - __ sve_fnmsb(z26, __ D, p2, z14, z1); // fnmsb z26.d, p2/m, z14.d, z1.d - __ sve_fnmla(z26, __ D, p1, z29, z20); // fnmla z26.d, p1/m, z29.d, z20.d - __ sve_fnmls(z6, __ D, p7, z13, z1); // fnmls z6.d, p7/m, z13.d, z1.d - __ sve_mla(z11, __ B, p2, z1, z1); // mla z11.b, p2/m, z1.b, z1.b - __ sve_mls(z27, __ B, p6, z15, z2); // mls z27.b, p6/m, z15.b, z2.b - __ sve_and(z30, z17, z25); // and z30.d, z17.d, z25.d - __ sve_eor(z2, z24, z3); // eor z2.d, z24.d, z3.d - __ sve_orr(z29, z13, z3); // orr z29.d, z13.d, z3.d - __ sve_bic(z14, z16, z28); // bic z14.d, z16.d, z28.d - __ sve_uzp1(z4, __ S, z11, z27); // uzp1 z4.s, z11.s, z27.s - __ sve_uzp2(z2, __ D, z16, z1); // uzp2 z2.d, z16.d, z1.d - __ sve_fabd(z7, __ D, p5, z31); // fabd z7.d, p5/m, z7.d, z31.d - __ sve_bext(z16, __ S, z10, z22); // bext z16.s, z10.s, z22.s - __ sve_bdep(z29, __ B, z7, z22); // bdep z29.b, z7.b, z22.b - __ sve_eor3(z12, z24, z11); // eor3 z12.d, z12.d, z24.d, z11.d + __ sve_add(z30, __ B, z12, z3); // add z30.b, z12.b, z3.b + __ sve_sub(z23, __ D, z9, z3); // sub z23.d, z9.d, z3.d + __ sve_fadd(z28, __ D, z3, z19); // fadd z28.d, z3.d, z19.d + __ sve_fmul(z7, __ S, z26, z21); // fmul z7.s, z26.s, z21.s + __ sve_fsub(z5, __ S, z8, z26); // fsub z5.s, z8.s, z26.s + __ sve_abs(z22, __ B, p4, z17); // abs z22.b, p4/m, z17.b + __ sve_add(z3, __ H, p2, z20); // add z3.h, p2/m, z3.h, z20.h + __ sve_and(z8, __ S, p3, z14); // and z8.s, p3/m, z8.s, z14.s + __ sve_asr(z17, __ D, p2, z13); // asr z17.d, p2/m, z17.d, z13.d + __ sve_bic(z18, __ H, p7, z19); // bic z18.h, p7/m, z18.h, z19.h + __ sve_clz(z16, __ S, p3, z27); // clz z16.s, p3/m, z27.s + __ sve_cnt(z28, __ H, p5, z8); // cnt z28.h, p5/m, z8.h + __ sve_eor(z5, __ H, p7, z28); // eor z5.h, p7/m, z5.h, z28.h + __ sve_lsl(z0, __ S, p3, z25); // lsl z0.s, p3/m, z0.s, z25.s + __ sve_lsr(z21, __ S, p0, z3); // lsr z21.s, p0/m, z21.s, z3.s + __ sve_mul(z26, __ D, p1, z26); // mul z26.d, p1/m, z26.d, z26.d + __ sve_neg(z19, __ H, p4, z1); // neg z19.h, p4/m, z1.h + __ sve_not(z14, __ B, p7, z14); // not z14.b, p7/m, z14.b + __ sve_orr(z18, __ S, p0, z31); // orr z18.s, p0/m, z18.s, z31.s + __ sve_rbit(z23, __ H, p5, z30); // rbit z23.h, p5/m, z30.h + __ sve_revb(z8, __ S, p0, z0); // revb z8.s, p0/m, z0.s + __ sve_smax(z23, __ S, p5, z0); // smax z23.s, p5/m, z23.s, z0.s + __ sve_smin(z26, __ H, p6, z24); // smin z26.h, p6/m, z26.h, z24.h + __ sve_sub(z22, __ B, p5, z2); // sub z22.b, p5/m, z22.b, z2.b + __ sve_fabs(z11, __ D, p5, z12); // fabs z11.d, p5/m, z12.d + __ sve_fadd(z24, __ D, p6, z9); // fadd z24.d, p6/m, z24.d, z9.d + __ sve_fdiv(z17, __ D, p5, z20); // fdiv z17.d, p5/m, z17.d, z20.d + __ sve_fmax(z4, __ D, p5, z13); // fmax z4.d, p5/m, z4.d, z13.d + __ sve_fmin(z22, __ D, p7, z31); // fmin z22.d, p7/m, z22.d, z31.d + __ sve_fmul(z18, __ S, p4, z15); // fmul z18.s, p4/m, z18.s, z15.s + __ sve_fneg(z13, __ S, p7, z20); // fneg z13.s, p7/m, z20.s + __ sve_frintm(z1, __ S, p3, z14); // frintm z1.s, p3/m, z14.s + __ sve_frintn(z7, __ D, p2, z12); // frintn z7.d, p2/m, z12.d + __ sve_frintp(z4, __ S, p6, z15); // frintp z4.s, p6/m, z15.s + __ sve_fsqrt(z3, __ D, p7, z1); // fsqrt z3.d, p7/m, z1.d + __ sve_fsub(z5, __ D, p5, z31); // fsub z5.d, p5/m, z5.d, z31.d + __ sve_fmad(z13, __ D, p3, z9, z14); // fmad z13.d, p3/m, z9.d, z14.d + __ sve_fmla(z1, __ S, p3, z28, z3); // fmla z1.s, p3/m, z28.s, z3.s + __ sve_fmls(z26, __ S, p2, z25, z9); // fmls z26.s, p2/m, z25.s, z9.s + __ sve_fmsb(z26, __ D, p2, z14, z1); // fmsb z26.d, p2/m, z14.d, z1.d + __ sve_fnmad(z26, __ D, p1, z29, z20); // fnmad z26.d, p1/m, z29.d, z20.d + __ sve_fnmsb(z6, __ D, p7, z13, z1); // fnmsb z6.d, p7/m, z13.d, z1.d + __ sve_fnmla(z11, __ S, p2, z1, z1); // fnmla z11.s, p2/m, z1.s, z1.s + __ sve_fnmls(z27, __ S, p6, z15, z2); // fnmls z27.s, p6/m, z15.s, z2.s + __ sve_mla(z30, __ B, p4, z25, z2); // mla z30.b, p4/m, z25.b, z2.b + __ sve_mls(z24, __ H, p0, z26, z29); // mls z24.h, p0/m, z26.h, z29.h + __ sve_and(z3, z22, z14); // and z3.d, z22.d, z14.d + __ sve_eor(z28, z17, z4); // eor z28.d, z17.d, z4.d + __ sve_orr(z27, z16, z2); // orr z27.d, z16.d, z2.d + __ sve_bic(z1, z28, z7); // bic z1.d, z28.d, z7.d + __ sve_uzp1(z31, __ H, z28, z16); // uzp1 z31.h, z28.h, z16.h + __ sve_uzp2(z22, __ B, z17, z29); // uzp2 z22.b, z17.b, z29.b + __ sve_fabd(z22, __ D, p1, z12); // fabd z22.d, p1/m, z22.d, z12.d + __ sve_bext(z11, __ H, z9, z11); // bext z11.h, z9.h, z11.h + __ sve_bdep(z0, __ S, z4, z23); // bdep z0.s, z4.s, z23.s + __ sve_eor3(z20, z4, z3); // eor3 z20.d, z20.d, z4.d, z3.d // SVEReductionOp - __ sve_andv(v11, __ B, p2, z0); // andv b11, p2, z0.b - __ sve_orv(v23, __ B, p5, z20); // orv b23, p5, z20.b - __ sve_eorv(v3, __ B, p3, z15); // eorv b3, p3, z15.b - __ sve_smaxv(v30, __ B, p6, z27); // smaxv b30, p6, z27.b - __ sve_sminv(v21, __ D, p6, z10); // sminv d21, p6, z10.d - __ sve_fminv(v3, __ S, p6, z4); // fminv s3, p6, z4.s - __ sve_fmaxv(v6, __ S, p0, z21); // fmaxv s6, p0, z21.s - __ sve_fadda(v25, __ D, p6, z30); // fadda d25, p6, d25, z30.d - __ sve_uaddv(v31, __ H, p4, z1); // uaddv d31, p4, z1.h + __ sve_andv(v15, __ D, p1, z30); // andv d15, p1, z30.d + __ sve_orv(v27, __ D, p1, z21); // orv d27, p1, z21.d + __ sve_eorv(v10, __ D, p7, z3); // eorv d10, p7, z3.d + __ sve_smaxv(v4, __ B, p2, z6); // smaxv b4, p2, z6.b + __ sve_sminv(v21, __ D, p1, z25); // sminv d21, p1, z25.d + __ sve_fminv(v30, __ D, p6, z31); // fminv d30, p6, z31.d + __ sve_fmaxv(v1, __ D, p2, z12); // fmaxv d1, p2, z12.d + __ sve_fadda(v13, __ D, p2, z25); // fadda d13, p2, d13, z25.d + __ sve_uaddv(v1, __ D, p7, z23); // uaddv d1, p7, z23.d // AddWideNEONOp - __ saddwv(v12, v13, __ T8H, v14, __ T8B); // saddw v12.8H, v13.8H, v14.8B - __ saddwv2(v30, v31, __ T8H, v0, __ T16B); // saddw2 v30.8H, v31.8H, v0.16B - __ saddwv(v13, v14, __ T4S, v15, __ T4H); // saddw v13.4S, v14.4S, v15.4H - __ saddwv2(v8, v9, __ T4S, v10, __ T8H); // saddw2 v8.4S, v9.4S, v10.8H - __ saddwv(v25, v26, __ T2D, v27, __ T2S); // saddw v25.2D, v26.2D, v27.2S + __ saddwv(v20, v21, __ T8H, v22, __ T8B); // saddw v20.8H, v21.8H, v22.8B + __ saddwv2(v0, v1, __ T8H, v2, __ T16B); // saddw2 v0.8H, v1.8H, v2.16B + __ saddwv(v21, v22, __ T4S, v23, __ T4H); // saddw v21.4S, v22.4S, v23.4H + __ saddwv2(v7, v8, __ T4S, v9, __ T8H); // saddw2 v7.4S, v8.4S, v9.8H + __ saddwv(v31, v0, __ T2D, v1, __ T2S); // saddw v31.2D, v0.2D, v1.2S __ saddwv2(v29, v30, __ T2D, v31, __ T4S); // saddw2 v29.2D, v30.2D, v31.4S - __ uaddwv(v1, v2, __ T8H, v3, __ T8B); // uaddw v1.8H, v2.8H, v3.8B - __ uaddwv2(v31, v0, __ T8H, v1, __ T16B); // uaddw2 v31.8H, v0.8H, v1.16B - __ uaddwv(v23, v24, __ T4S, v25, __ T4H); // uaddw v23.4S, v24.4S, v25.4H - __ uaddwv2(v31, v0, __ T4S, v1, __ T8H); // uaddw2 v31.4S, v0.4S, v1.8H - __ uaddwv(v20, v21, __ T2D, v22, __ T2S); // uaddw v20.2D, v21.2D, v22.2S - __ uaddwv2(v0, v1, __ T2D, v2, __ T4S); // uaddw2 v0.2D, v1.2D, v2.4S + __ uaddwv(v27, v28, __ T8H, v29, __ T8B); // uaddw v27.8H, v28.8H, v29.8B + __ uaddwv2(v22, v23, __ T8H, v24, __ T16B); // uaddw2 v22.8H, v23.8H, v24.16B + __ uaddwv(v8, v9, __ T4S, v10, __ T4H); // uaddw v8.4S, v9.4S, v10.4H + __ uaddwv2(v29, v30, __ T4S, v31, __ T8H); // uaddw2 v29.4S, v30.4S, v31.8H + __ uaddwv(v26, v27, __ T2D, v28, __ T2S); // uaddw v26.2D, v27.2D, v28.2S + __ uaddwv2(v20, v21, __ T2D, v22, __ T4S); // uaddw2 v20.2D, v21.2D, v22.4S __ bind(forth); @@ -1327,30 +1337,30 @@ 0x9101a1a0, 0xb10a5cc8, 0xd10810aa, 0xf10fd061, 0x120cb166, 0x321764bc, 0x52174681, 0x720c0227, 0x9241018e, 0xb25a2969, 0xd278b411, 0xf26aad01, - 0x14000000, 0x17ffffd7, 0x14000441, 0x94000000, - 0x97ffffd4, 0x9400043e, 0x3400000a, 0x34fffa2a, - 0x3400876a, 0x35000008, 0x35fff9c8, 0x35008708, - 0xb400000b, 0xb4fff96b, 0xb40086ab, 0xb500001d, - 0xb5fff91d, 0xb500865d, 0x10000013, 0x10fff8b3, - 0x100085f3, 0x90000013, 0x36300016, 0x3637f836, - 0x36308576, 0x3758000c, 0x375ff7cc, 0x3758850c, + 0x14000000, 0x17ffffd7, 0x1400044b, 0x94000000, + 0x97ffffd4, 0x94000448, 0x3400000a, 0x34fffa2a, + 0x340088aa, 0x35000008, 0x35fff9c8, 0x35008848, + 0xb400000b, 0xb4fff96b, 0xb40087eb, 0xb500001d, + 0xb5fff91d, 0xb500879d, 0x10000013, 0x10fff8b3, + 0x10008733, 0x90000013, 0x36300016, 0x3637f836, + 0x363086b6, 0x3758000c, 0x375ff7cc, 0x3758864c, 0x128313a0, 0x528a32c7, 0x7289173b, 0x92ab3acc, 0xd2a0bf94, 0xf2c285e8, 0x9358722f, 0x330e652f, 0x53067f3b, 0x93577c53, 0xb34a1aac, 0xd35a4016, 0x13946c63, 0x93c3dbc8, 0x54000000, 0x54fff5a0, - 0x540082e0, 0x54000001, 0x54fff541, 0x54008281, - 0x54000002, 0x54fff4e2, 0x54008222, 0x54000002, - 0x54fff482, 0x540081c2, 0x54000003, 0x54fff423, - 0x54008163, 0x54000003, 0x54fff3c3, 0x54008103, - 0x54000004, 0x54fff364, 0x540080a4, 0x54000005, - 0x54fff305, 0x54008045, 0x54000006, 0x54fff2a6, - 0x54007fe6, 0x54000007, 0x54fff247, 0x54007f87, - 0x54000008, 0x54fff1e8, 0x54007f28, 0x54000009, - 0x54fff189, 0x54007ec9, 0x5400000a, 0x54fff12a, - 0x54007e6a, 0x5400000b, 0x54fff0cb, 0x54007e0b, - 0x5400000c, 0x54fff06c, 0x54007dac, 0x5400000d, - 0x54fff00d, 0x54007d4d, 0x5400000e, 0x54ffefae, - 0x54007cee, 0x5400000f, 0x54ffef4f, 0x54007c8f, + 0x54008420, 0x54000001, 0x54fff541, 0x540083c1, + 0x54000002, 0x54fff4e2, 0x54008362, 0x54000002, + 0x54fff482, 0x54008302, 0x54000003, 0x54fff423, + 0x540082a3, 0x54000003, 0x54fff3c3, 0x54008243, + 0x54000004, 0x54fff364, 0x540081e4, 0x54000005, + 0x54fff305, 0x54008185, 0x54000006, 0x54fff2a6, + 0x54008126, 0x54000007, 0x54fff247, 0x540080c7, + 0x54000008, 0x54fff1e8, 0x54008068, 0x54000009, + 0x54fff189, 0x54008009, 0x5400000a, 0x54fff12a, + 0x54007faa, 0x5400000b, 0x54fff0cb, 0x54007f4b, + 0x5400000c, 0x54fff06c, 0x54007eec, 0x5400000d, + 0x54fff00d, 0x54007e8d, 0x5400000e, 0x54ffefae, + 0x54007e2e, 0x5400000f, 0x54ffef4f, 0x54007dcf, 0xd40658e1, 0xd4014d22, 0xd4046543, 0xd4273f60, 0xd44cad80, 0xd503201f, 0xd503203f, 0xd503205f, 0xd503209f, 0xd50320bf, 0xd503219f, 0xd50323bf, @@ -1471,134 +1481,137 @@ 0x4e60f7fe, 0x0e3c6f7a, 0x4e346e72, 0x0e6b6d49, 0x4e6a6d28, 0x0eae6dac, 0x4ea26c20, 0x0e36aeb4, 0x4e23ac41, 0x0e7aaf38, 0x4e64ac62, 0x0ea2ac20, - 0x4eabad49, 0x0ebaf738, 0x4ebcf77a, 0x4ef2f630, - 0x2ea0effe, 0x6ea5ec83, 0x6eeced6a, 0x0fa710c5, - 0x4f8b8149, 0x4fc710c5, 0x0f8750c5, 0x4faa8128, - 0x4fc750c5, 0x2f8890e6, 0x4fa880e6, 0x6fc59083, - 0x0f6f81cd, 0x4f448862, 0x0f848062, 0x4fab8149, - 0x0e3736d5, 0x4e323630, 0x0e743672, 0x4e6d358b, - 0x0eb736d5, 0x4eb93717, 0x4eee35ac, 0x0e3c3f7a, - 0x4e393f17, 0x0e7e3fbc, 0x4e703dee, 0x0ead3d8b, - 0x4eba3f38, 0x4ee33c41, 0x2e2e8dac, 0x6e218c1f, - 0x2e6c8d6a, 0x6e728e30, 0x2ea98d07, 0x6ea48c62, - 0x6ee58c83, 0x2e2f35cd, 0x6e353693, 0x2e733651, - 0x6e723630, 0x2ea53483, 0x6ea33441, 0x6eed358b, - 0x2e203ffe, 0x6e273cc5, 0x2e6a3d28, 0x6e713e0f, - 0x2ebf3fdd, 0x6ea03ffe, 0x6ee23c20, 0x0e36e6b4, - 0x4e29e507, 0x4e76e6b4, 0x2eb9e717, 0x6ebee7bc, - 0x6ef7e6d5, 0x2e3de79b, 0x6e3be759, 0x6e67e4c5, - 0x65d23ee0, 0x65903d92, 0x65d03fa7, 0x65912fe9, - 0x65d13bf9, 0x65932a0a, 0x25cb90c4, 0x25040bde, - 0x25c11085, 0x25c62c6b, 0x259f2279, 0x259d8993, - 0x24e5102b, 0x24ad5458, 0x24ec7ab5, 0x24387c6d, - 0xba5fd3e3, 0x3a5f03e5, 0xfa411be4, 0x7a42cbe2, - 0x93df03ff, 0xc820ffff, 0x8822fc7f, 0xc8247cbf, - 0x88267fff, 0x4e010fe0, 0x5e040420, 0x4e081fe1, - 0x4e0c1fe1, 0x4e0a1fe1, 0x4e071fe1, 0x4e042c20, - 0x4e062c20, 0x4e052c20, 0x4e083c20, 0x0e0c3c20, - 0x0e0a3c20, 0x0e073c20, 0x9eae0020, 0x0f03f409, - 0x6f03f40e, 0x4cc0ac3f, 0x0ea1b820, 0x4e21c862, - 0x4e61b8a4, 0x05a08020, 0x05104fe0, 0x05505001, - 0x05906fe2, 0x05d03005, 0x05101fea, 0x05901feb, - 0x04b0e3e0, 0x0470e7e1, 0x042f9c20, 0x043f9c35, - 0x047f9c20, 0x04ff9c20, 0x04299420, 0x04319160, - 0x0461943e, 0x04a19020, 0x04038100, 0x040381a0, - 0x040387e1, 0x04438be2, 0x04c38fe3, 0x040181e0, - 0x04018100, 0x04018621, 0x04418b22, 0x04418822, - 0x04818c23, 0x040081e0, 0x04008120, 0x04008761, - 0x04008621, 0x04408822, 0x04808c23, 0x042053ff, - 0x047f5401, 0x25208028, 0x2538cfe0, 0x2578d001, - 0x25b8efe2, 0x25f8f007, 0x2538dfea, 0x25b8dfeb, - 0xa400a3e0, 0xa420a7e0, 0xa4484be0, 0xa467afe0, - 0xa4a8a7ea, 0xa547a814, 0xa4084ffe, 0xa55c53e0, - 0xa5e1540b, 0xe400fbf6, 0xe408ffff, 0xe420e7e0, - 0xe4484be0, 0xe460efe0, 0xe547e400, 0xe4014be0, - 0xe4a84fe0, 0xe5f15000, 0x858043e0, 0x85a043ff, - 0xe59f5d08, 0x0420e3e9, 0x0460e3ea, 0x04a0e3eb, - 0x04e0e3ec, 0x25104042, 0x25104871, 0x25904861, - 0x25904c92, 0x05344020, 0x05744041, 0x05b44062, - 0x05f44083, 0x252c8840, 0x253c1420, 0x25681572, - 0x25a21ce3, 0x25ea1e34, 0x253c0421, 0x25680572, - 0x25a20ce3, 0x25ea0e34, 0x0522c020, 0x05e6c0a4, - 0x2401a001, 0x2443a051, 0x24858881, 0x24c78cd1, - 0x24850891, 0x24c70cc1, 0x250f9001, 0x25508051, - 0x25802491, 0x25df28c1, 0x25850c81, 0x251e10d1, - 0x65816001, 0x65c36051, 0x65854891, 0x65c74cc1, - 0x05733820, 0x05b238a4, 0x05f138e6, 0x0570396a, - 0x65d0a001, 0x65d6a443, 0x65d4a826, 0x6594ac26, - 0x6554ac26, 0x6556ac26, 0x6552ac26, 0x65cbac85, - 0x65caac01, 0x6589ac85, 0x6588ac01, 0x65c9ac85, - 0x65c8ac01, 0x65dea833, 0x659ca509, 0x65d8a801, - 0x65dcac01, 0x655cb241, 0x0520a1e0, 0x0521a601, - 0x052281e0, 0x05238601, 0x04a14026, 0x042244a6, - 0x046344a6, 0x04a444a6, 0x04e544a7, 0x0568aca7, - 0x05b23230, 0x853040af, 0xc5b040af, 0xe57080af, - 0xe5b080af, 0x25034440, 0x254054c4, 0x25034640, - 0x25415a05, 0x25834440, 0x25c54489, 0x250b5d3a, - 0x2550dc20, 0x2518e3e1, 0x2518e021, 0x2518e0a1, - 0x2518e121, 0x2518e1a1, 0x2558e3e2, 0x2558e042, - 0x2558e0c2, 0x2558e142, 0x2598e3e3, 0x2598e063, - 0x2598e0e3, 0x2598e163, 0x25d8e3e4, 0x25d8e084, - 0x25d8e104, 0x25d8e184, 0x2518e407, 0x05214800, - 0x05614800, 0x05a14800, 0x05e14800, 0x05214c00, - 0x05614c00, 0x05a14c00, 0x05e14c00, 0x05304001, - 0x05314001, 0x05a18610, 0x05e18610, 0x05271e11, - 0x6545e891, 0x6585e891, 0x65c5e891, 0x6545c891, - 0x6585c891, 0x65c5c891, 0x45b0c210, 0x45f1c231, - 0x1e601000, 0x1e603000, 0x1e621000, 0x1e623000, - 0x1e641000, 0x1e643000, 0x1e661000, 0x1e663000, - 0x1e681000, 0x1e683000, 0x1e6a1000, 0x1e6a3000, - 0x1e6c1000, 0x1e6c3000, 0x1e6e1000, 0x1e6e3000, - 0x1e701000, 0x1e703000, 0x1e721000, 0x1e723000, - 0x1e741000, 0x1e743000, 0x1e761000, 0x1e763000, - 0x1e781000, 0x1e783000, 0x1e7a1000, 0x1e7a3000, - 0x1e7c1000, 0x1e7c3000, 0x1e7e1000, 0x1e7e3000, - 0xf8338131, 0xf83c01fb, 0xf82712f5, 0xf83f2059, - 0xf83f31fb, 0xf82a5277, 0xf8234010, 0xf83972fa, - 0xf8226190, 0xf8a483dc, 0xf8bd0370, 0xf8a613a9, - 0xf8b02087, 0xf8a7312f, 0xf8b75048, 0xf8bc43f5, - 0xf8a5701b, 0xf8b1608f, 0xf8fa8388, 0xf8f6037b, - 0xf8f91017, 0xf8e421e6, 0xf8e031e4, 0xf8e150ea, - 0xf8e5438a, 0xf8e772f4, 0xf8f56166, 0xf86883f1, - 0xf8660051, 0xf86c13be, 0xf86322db, 0xf87d31ae, - 0xf87c5311, 0xf86541c2, 0xf86a7170, 0xf87b6197, - 0xb8248236, 0xb8240261, 0xb83011b0, 0xb82e204c, - 0xb83132a3, 0xb83750c5, 0xb82741b3, 0xb83c7211, - 0xb82663a2, 0xb8a380c4, 0xb8b001b4, 0xb8ac1114, - 0xb8b92274, 0xb8a0330b, 0xb8a653f4, 0xb8ae40d0, - 0xb8a071e7, 0xb8b3613a, 0xb8ea82b7, 0xb8f6005c, - 0xb8e3126f, 0xb8f42087, 0xb8fd3007, 0xb8e95290, - 0xb8f74204, 0xb8ea7177, 0xb8f963e6, 0xb87082ed, - 0xb86c01c1, 0xb8691215, 0xb87a208f, 0xb8643110, - 0xb866509e, 0xb87d43b1, 0xb87a71e9, 0xb86263ab, - 0xce216ce3, 0xce0e2255, 0xce798ed2, 0xce959685, - 0xce7e8217, 0xce608694, 0xcec08264, 0xce748898, - 0x25e0da44, 0x2521c8f3, 0x05801548, 0x0540cbdf, - 0x05006521, 0x2560c7a0, 0x25a1c498, 0x058026bb, - 0x05407dd8, 0x0500f3d6, 0x2560ce3d, 0x2521d4b4, - 0x05803cbc, 0x05404d6c, 0x05001b89, 0x25a0c532, - 0x2521cc40, 0x05800c08, 0x054074c4, 0x050034a0, - 0x2520c9e3, 0x25e1ca93, 0x05803e98, 0x05425238, - 0x050024cb, 0x25a0ce7f, 0x25e1d0c3, 0x05802676, - 0x05401e63, 0x05002d49, 0x04e20080, 0x04ab04ce, - 0x659e022e, 0x65970863, 0x659c0703, 0x04d6b4f3, - 0x04400cb5, 0x049a06da, 0x04508071, 0x045b0d14, - 0x0459b22e, 0x04daba4d, 0x04590a13, 0x0493979b, - 0x04d188a8, 0x0450081c, 0x0417b6b9, 0x041eb743, - 0x04981e7a, 0x05e78dc1, 0x0564824e, 0x048816ff, - 0x040a0d1e, 0x04810ee0, 0x04dcb340, 0x65c08ed8, - 0x65cd8162, 0x65c6970c, 0x65c79e29, 0x65c29494, - 0x04ddbecd, 0x65c2ba5f, 0x65c0a9af, 0x6581a434, - 0x658da0ee, 0x65c1908c, 0x65be806f, 0x65ff0694, - 0x65ee2d2d, 0x65a3af81, 0x65a9cb3a, 0x65e1e9da, - 0x65f447ba, 0x65e17da6, 0x0401482b, 0x040279fb, - 0x0439323e, 0x04a33302, 0x046331bd, 0x04fc320e, - 0x05bb6964, 0x05e16e02, 0x65c897e7, 0x4596b150, - 0x4516b4fd, 0x0438396c, 0x041a280b, 0x04183697, - 0x04192de3, 0x04083b7e, 0x04ca3955, 0x65873883, - 0x658622a6, 0x65d83bd9, 0x0441303f, 0x0e2e11ac, - 0x4e2013fe, 0x0e6f11cd, 0x4e6a1128, 0x0ebb1359, - 0x4ebf13dd, 0x2e231041, 0x6e21101f, 0x2e791317, - 0x6e61101f, 0x2eb612b4, 0x6ea21020, + 0x4eabad49, 0x0e7ab738, 0x4e7cb77a, 0x0eb2b630, + 0x4ea0b7fe, 0x0e252483, 0x4e2c256a, 0x0e792717, + 0x4e6c256a, 0x0ea624a4, 0x4eb42672, 0x0ea4f462, + 0x4eadf58b, 0x4eeaf528, 0x2eaced6a, 0x6eb1ee0f, + 0x6ef3ee51, 0x0f8710c5, 0x4fa880e6, 0x4fc810e6, + 0x0f855083, 0x4f8f89cd, 0x4fc45862, 0x2f849062, + 0x4fab8149, 0x6fca9928, 0x0f6780c5, 0x4f5d898b, + 0x0f8f81cd, 0x4f9089ee, 0x0e3035ee, 0x4e2d358b, + 0x0e7a3738, 0x4e633441, 0x0eae35ac, 0x4ea1341f, + 0x4eec356a, 0x0e323e30, 0x4e293d07, 0x0e643c62, + 0x4e653c83, 0x0eaf3dcd, 0x4eb53e93, 0x4ef33e51, + 0x2e328e30, 0x6e258c83, 0x2e638c41, 0x6e6d8d8b, + 0x2ea08ffe, 0x6ea78cc5, 0x6eea8d28, 0x2e31360f, + 0x6e3f37dd, 0x2e6037fe, 0x6e623420, 0x2eb636b4, + 0x6ea93507, 0x6ef636b4, 0x2e393f17, 0x6e3e3fbc, + 0x2e773ed5, 0x6e7d3f9b, 0x2ebb3f59, 0x6ea73cc5, + 0x6ee33c41, 0x0e39e717, 0x4e32e630, 0x4e61e41f, + 0x2ea7e4c5, 0x6eaee5ac, 0x6eebe549, 0x2e3ee7bc, + 0x6e31e60f, 0x6e7fe7dd, 0x65d23feb, 0x65d03dd2, + 0x65d03369, 0x65912566, 0x65d13e3f, 0x659334ef, + 0x25c19085, 0x25c60c7b, 0x259f0269, 0x259d2983, + 0x25d5303b, 0x259d9458, 0x24ec5aa5, 0x24385c7d, + 0x247b7e39, 0x24bff4e7, 0xba5fd3e3, 0x3a5f03e5, + 0xfa411be4, 0x7a42cbe2, 0x93df03ff, 0xc820ffff, + 0x8822fc7f, 0xc8247cbf, 0x88267fff, 0x4e010fe0, + 0x5e040420, 0x4e081fe1, 0x4e0c1fe1, 0x4e0a1fe1, + 0x4e071fe1, 0x4e042c20, 0x4e062c20, 0x4e052c20, + 0x4e083c20, 0x0e0c3c20, 0x0e0a3c20, 0x0e073c20, + 0x9eae0020, 0x0f03f409, 0x6f03f40e, 0x4cc0ac3f, + 0x0ea1b820, 0x4e21c862, 0x4e61b8a4, 0x05a08020, + 0x05104fe0, 0x05505001, 0x05906fe2, 0x05d03005, + 0x05101fea, 0x05901feb, 0x04b0e3e0, 0x0470e7e1, + 0x042f9c20, 0x043f9c35, 0x047f9c20, 0x04ff9c20, + 0x04299420, 0x04319160, 0x0461943e, 0x04a19020, + 0x04038100, 0x040381a0, 0x040387e1, 0x04438be2, + 0x04c38fe3, 0x040181e0, 0x04018100, 0x04018621, + 0x04418b22, 0x04418822, 0x04818c23, 0x040081e0, + 0x04008120, 0x04008761, 0x04008621, 0x04408822, + 0x04808c23, 0x042053ff, 0x047f5401, 0x25208028, + 0x2538cfe0, 0x2578d001, 0x25b8efe2, 0x25f8f007, + 0x2538dfea, 0x25b8dfeb, 0xa400a3e0, 0xa420a7e0, + 0xa4484be0, 0xa467afe0, 0xa4a8a7ea, 0xa547a814, + 0xa4084ffe, 0xa55c53e0, 0xa5e1540b, 0xe400fbf6, + 0xe408ffff, 0xe420e7e0, 0xe4484be0, 0xe460efe0, + 0xe547e400, 0xe4014be0, 0xe4a84fe0, 0xe5f15000, + 0x858043e0, 0x85a043ff, 0xe59f5d08, 0x0420e3e9, + 0x0460e3ea, 0x04a0e3eb, 0x04e0e3ec, 0x25104042, + 0x25104871, 0x25904861, 0x25904c92, 0x05344020, + 0x05744041, 0x05b44062, 0x05f44083, 0x252c8840, + 0x253c1420, 0x25681572, 0x25a21ce3, 0x25ea1e34, + 0x253c0421, 0x25680572, 0x25a20ce3, 0x25ea0e34, + 0x0522c020, 0x05e6c0a4, 0x2401a001, 0x2443a051, + 0x24858881, 0x24c78cd1, 0x24850891, 0x24c70cc1, + 0x250f9001, 0x25508051, 0x25802491, 0x25df28c1, + 0x25850c81, 0x251e10d1, 0x65816001, 0x65c36051, + 0x65854891, 0x65c74cc1, 0x05733820, 0x05b238a4, + 0x05f138e6, 0x0570396a, 0x65d0a001, 0x65d6a443, + 0x65d4a826, 0x6594ac26, 0x6554ac26, 0x6556ac26, + 0x6552ac26, 0x65cbac85, 0x65caac01, 0x6589ac85, + 0x6588ac01, 0x65c9ac85, 0x65c8ac01, 0x65dea833, + 0x659ca509, 0x65d8a801, 0x65dcac01, 0x655cb241, + 0x0520a1e0, 0x0521a601, 0x052281e0, 0x05238601, + 0x04a14026, 0x042244a6, 0x046344a6, 0x04a444a6, + 0x04e544a7, 0x0568aca7, 0x05b23230, 0x853040af, + 0xc5b040af, 0xe57080af, 0xe5b080af, 0x25034440, + 0x254054c4, 0x25034640, 0x25415a05, 0x25834440, + 0x25c54489, 0x250b5d3a, 0x2550dc20, 0x2518e3e1, + 0x2518e021, 0x2518e0a1, 0x2518e121, 0x2518e1a1, + 0x2558e3e2, 0x2558e042, 0x2558e0c2, 0x2558e142, + 0x2598e3e3, 0x2598e063, 0x2598e0e3, 0x2598e163, + 0x25d8e3e4, 0x25d8e084, 0x25d8e104, 0x25d8e184, + 0x2518e407, 0x05214800, 0x05614800, 0x05a14800, + 0x05e14800, 0x05214c00, 0x05614c00, 0x05a14c00, + 0x05e14c00, 0x05304001, 0x05314001, 0x05a18610, + 0x05e18610, 0x05271e11, 0x6545e891, 0x6585e891, + 0x65c5e891, 0x6545c891, 0x6585c891, 0x65c5c891, + 0x45b0c210, 0x45f1c231, 0x1e601000, 0x1e603000, + 0x1e621000, 0x1e623000, 0x1e641000, 0x1e643000, + 0x1e661000, 0x1e663000, 0x1e681000, 0x1e683000, + 0x1e6a1000, 0x1e6a3000, 0x1e6c1000, 0x1e6c3000, + 0x1e6e1000, 0x1e6e3000, 0x1e701000, 0x1e703000, + 0x1e721000, 0x1e723000, 0x1e741000, 0x1e743000, + 0x1e761000, 0x1e763000, 0x1e781000, 0x1e783000, + 0x1e7a1000, 0x1e7a3000, 0x1e7c1000, 0x1e7c3000, + 0x1e7e1000, 0x1e7e3000, 0xf83983e2, 0xf83b0150, + 0xf8371073, 0xf8302320, 0xf83a3057, 0xf830508c, + 0xf83c43be, 0xf83070db, 0xf82961fd, 0xf8a780e4, + 0xf8af02e9, 0xf8a81382, 0xf8b520bf, 0xf8bb3220, + 0xf8af5344, 0xf8a842dc, 0xf8bb733b, 0xf8b76080, + 0xf8e68010, 0xf8e4002f, 0xf8ea10a7, 0xf8ea20fc, + 0xf8f432b7, 0xf8e6510b, 0xf8f140df, 0xf8f17182, + 0xf8fe607d, 0xf87b83b6, 0xf86e038d, 0xf87110b8, + 0xf862214e, 0xf870336b, 0xf877508c, 0xf8764091, + 0xf8617213, 0xf87061cd, 0xb82c8222, 0xb82302f5, + 0xb82510e6, 0xb833238d, 0xb83130d0, 0xb822507d, + 0xb82441e6, 0xb834718d, 0xb8346328, 0xb8b48013, + 0xb8ab00d8, 0xb8b411df, 0xb8b02006, 0xb8a7326f, + 0xb8ba5149, 0xb8b742d5, 0xb8bc7062, 0xb8af6293, + 0xb8e783a4, 0xb8e70120, 0xb8f012f4, 0xb8e42150, + 0xb8f7332b, 0xb8e6521f, 0xb8ed4197, 0xb8e1712e, + 0xb8f56350, 0xb86f8084, 0xb87000c8, 0xb87e13a4, + 0xb871235d, 0xb869304f, 0xb86b507d, 0xb8674361, + 0xb87571d0, 0xb86862d0, 0xce3454b9, 0xce107af2, + 0xce608e94, 0xce982664, 0xce788094, 0xce62867a, + 0xcec08108, 0xce728b0e, 0x25a0c49f, 0x2521cabf, + 0x058054b4, 0x0543ab47, 0x050026bb, 0x2560d098, + 0x25a1d6ff, 0x058394b4, 0x0540266e, 0x05003cbc, + 0x25a0c1ac, 0x2561d3f8, 0x05800acd, 0x05403685, + 0x05000c08, 0x2560de64, 0x2521cac5, 0x0583c8b6, + 0x05405089, 0x05003e98, 0x25e0ce38, 0x2561db35, + 0x058011ad, 0x05400e4e, 0x05002676, 0x2520dae3, + 0x2561d0d3, 0x05808871, 0x0543abe2, 0x050011ab, + 0x0423019e, 0x04e30537, 0x65d3007c, 0x65950b47, + 0x659a0505, 0x0416b236, 0x04400a83, 0x049a0dc8, + 0x04d089b1, 0x045b1e72, 0x0499af70, 0x045ab51c, + 0x04591f85, 0x04938f20, 0x04918075, 0x04d0075a, + 0x0457b033, 0x041ebdce, 0x049803f2, 0x056797d7, + 0x05a48008, 0x04881417, 0x044a1b1a, 0x04011456, + 0x04dcb58b, 0x65c09938, 0x65cd9691, 0x65c695a4, + 0x65c79ff6, 0x658291f2, 0x049dbe8d, 0x6582adc1, + 0x65c0a987, 0x6581b9e4, 0x65cdbc23, 0x65c197e5, + 0x65ee8d2d, 0x65a30f81, 0x65a92b3a, 0x65e1a9da, + 0x65f4c7ba, 0x65e1fda6, 0x65a1482b, 0x65a279fb, + 0x0402533e, 0x045d6358, 0x042e32c3, 0x04a4323c, + 0x0462321b, 0x04e73381, 0x05706b9f, 0x053d6e36, + 0x65c88596, 0x454bb12b, 0x4597b480, 0x04243874, + 0x04da27cf, 0x04d826bb, 0x04d93c6a, 0x040828c4, + 0x04ca2735, 0x65c73bfe, 0x65c62981, 0x65d82b2d, + 0x04c13ee1, 0x0e3612b4, 0x4e221020, 0x0e7712d5, + 0x4e691107, 0x0ea1101f, 0x4ebf13dd, 0x2e3d139b, + 0x6e3812f6, 0x2e6a1128, 0x6e7f13dd, 0x2ebc137a, + 0x6eb612b4, }; // END Generated code -- do not edit diff --git a/test/hotspot/jtreg/TEST.ROOT b/test/hotspot/jtreg/TEST.ROOT index 02fd021c0001..ac7573ae9afb 100644 --- a/test/hotspot/jtreg/TEST.ROOT +++ b/test/hotspot/jtreg/TEST.ROOT @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -94,7 +94,7 @@ requires.properties= \ jdk.containerized # Minimum jtreg version -requiredVersion=7.5.2+1 +requiredVersion=8.2.1+1 # Path to libraries in the topmost test directory. This is needed so @library # does not need ../../../ notation to reach them diff --git a/test/hotspot/jtreg/compiler/intrinsics/TestLongUnsignedDivMod.java b/test/hotspot/jtreg/compiler/intrinsics/TestLongUnsignedDivMod.java index 694860a2d9b7..3ecdb4270129 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/TestLongUnsignedDivMod.java +++ b/test/hotspot/jtreg/compiler/intrinsics/TestLongUnsignedDivMod.java @@ -110,7 +110,6 @@ public TestLongUnsignedDivMod() { } @Test // needs to be run in (fast) debug mode - @Warmup(10000) @IR(counts = {IRNode.UDIV_L, ">= 1"}) // At least one UDivL node is generated if intrinsic is used public void testDivideUnsigned() { for (int i = 0; i < BUFFER_SIZE; i++) { @@ -124,7 +123,6 @@ public void testDivideUnsigned() { } @Test // needs to be run in (fast) debug mode - @Warmup(10000) @IR(counts = {IRNode.UMOD_L, ">= 1"}) // At least one UModL node is generated if intrinsic is used public void testRemainderUnsigned() { for (int i = 0; i < BUFFER_SIZE; i++) { @@ -139,7 +137,6 @@ public void testRemainderUnsigned() { @Test // needs to be run in (fast) debug mode - @Warmup(10000) @IR(applyIfPlatform = {"x64", "true"}, counts = {IRNode.UDIV_MOD_L, ">= 1"}) // At least one UDivModL node is generated if intrinsic is used public void testDivModUnsigned() { diff --git a/test/hotspot/jtreg/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java b/test/hotspot/jtreg/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java index 689c7c8cc2f6..028a3a815b9b 100644 --- a/test/hotspot/jtreg/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java +++ b/test/hotspot/jtreg/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java @@ -102,8 +102,10 @@ public class IntrinsicPredicates { new CPUSpecificPredicate("x86_64", new String[] { "avx2", "bmi2" }, null)))))))))); public static final BooleanSupplier SHA3_INSTRUCTION_AVAILABLE - // sha3 is only implemented on aarch64 for now - = new CPUSpecificPredicate("aarch64.*", new String[] {"sha3" }, null); + // sha3 is only implemented on aarch64 and avx512 for now + = new OrPredicate(new CPUSpecificPredicate("aarch64.*", new String[] {"sha3" }, null), + new OrPredicate(new CPUSpecificPredicate("amd64.*", new String[] {"avx512f", "avx512bw"}, null), + new CPUSpecificPredicate("x86_64", new String[] {"avx512f", "avx512bw"}, null))); public static final BooleanSupplier ANY_SHA_INSTRUCTION_AVAILABLE = new OrPredicate(IntrinsicPredicates.SHA1_INSTRUCTION_AVAILABLE, diff --git a/test/hotspot/jtreg/containers/docker/DockerBasicTest.java b/test/hotspot/jtreg/containers/docker/DockerBasicTest.java index e908f2a5bf32..403f46f6ab40 100644 --- a/test/hotspot/jtreg/containers/docker/DockerBasicTest.java +++ b/test/hotspot/jtreg/containers/docker/DockerBasicTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.misc + * java.base/jdk.internal.platform * java.management * jdk.jartool/sun.tools.jar * @build HelloDocker @@ -45,10 +46,7 @@ public class DockerBasicTest { private static final String imageNameAndTag = Common.imageName("basic"); public static void main(String[] args) throws Exception { - if (!DockerTestUtils.canTestDocker()) { - return; - } - + DockerTestUtils.checkCanTestDocker(); DockerTestUtils.buildJdkContainerImage(imageNameAndTag); try { diff --git a/test/hotspot/jtreg/containers/docker/ShareTmpDir.java b/test/hotspot/jtreg/containers/docker/ShareTmpDir.java index 48876ca37fe2..b7f807d76a30 100644 --- a/test/hotspot/jtreg/containers/docker/ShareTmpDir.java +++ b/test/hotspot/jtreg/containers/docker/ShareTmpDir.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ * @requires container.support * @requires !vm.asan * @library /test/lib + * @modules java.base/jdk.internal.platform * @build WaitForFlagFile * @run driver ShareTmpDir */ @@ -50,10 +51,7 @@ public class ShareTmpDir { private static final String imageName = Common.imageName("sharetmpdir"); public static void main(String[] args) throws Exception { - if (!DockerTestUtils.canTestDocker()) { - return; - } - + DockerTestUtils.checkCanTestDocker(); DockerTestUtils.buildJdkContainerImage(imageName); try { diff --git a/test/hotspot/jtreg/containers/docker/TestCPUAwareness.java b/test/hotspot/jtreg/containers/docker/TestCPUAwareness.java index dc73dd1b5445..6b0a536e4d46 100644 --- a/test/hotspot/jtreg/containers/docker/TestCPUAwareness.java +++ b/test/hotspot/jtreg/containers/docker/TestCPUAwareness.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,9 +48,8 @@ public class TestCPUAwareness { private static final int availableCPUs = Runtime.getRuntime().availableProcessors(); public static void main(String[] args) throws Exception { - if (!DockerTestUtils.canTestDocker()) { - return; - } + DockerTestUtils.checkCanTestDocker(); + DockerTestUtils.checkCanUseResourceLimits(); System.out.println("Test Environment: detected availableCPUs = " + availableCPUs); DockerTestUtils.buildJdkContainerImage(imageName); diff --git a/test/hotspot/jtreg/containers/docker/TestCPUSets.java b/test/hotspot/jtreg/containers/docker/TestCPUSets.java index 7894172e4015..001914a66866 100644 --- a/test/hotspot/jtreg/containers/docker/TestCPUSets.java +++ b/test/hotspot/jtreg/containers/docker/TestCPUSets.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ * @requires (os.arch != "s390x") * @library /test/lib * @modules java.base/jdk.internal.misc + * java.base/jdk.internal.platform * java.management * jdk.jartool/sun.tools.jar * @build AttemptOOM jdk.test.whitebox.WhiteBox PrintContainerInfo @@ -52,11 +53,8 @@ public class TestCPUSets { private static final String imageName = Common.imageName("cpusets"); public static void main(String[] args) throws Exception { - if (!DockerTestUtils.canTestDocker()) { - return; - } - - + DockerTestUtils.checkCanTestDocker(); + DockerTestUtils.checkCanUseResourceLimits(); Common.prepareWhiteBox(); DockerTestUtils.buildJdkContainerImage(imageName); diff --git a/test/hotspot/jtreg/containers/docker/TestContainerInfo.java b/test/hotspot/jtreg/containers/docker/TestContainerInfo.java index b9b6fb65b756..a5579aa9528f 100644 --- a/test/hotspot/jtreg/containers/docker/TestContainerInfo.java +++ b/test/hotspot/jtreg/containers/docker/TestContainerInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2024, Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -31,6 +31,7 @@ * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.misc + * java.base/jdk.internal.platform * java.management * jdk.jartool/sun.tools.jar * @build CheckContainerized jdk.test.whitebox.WhiteBox PrintContainerInfo @@ -49,10 +50,7 @@ public class TestContainerInfo { private static final String imageName = Common.imageName("container-info"); public static void main(String[] args) throws Exception { - if (!DockerTestUtils.canTestDocker()) { - return; - } - + DockerTestUtils.checkCanTestDocker(); Common.prepareWhiteBox(); DockerTestUtils.buildJdkContainerImage(imageName); diff --git a/test/hotspot/jtreg/containers/docker/TestJFREvents.java b/test/hotspot/jtreg/containers/docker/TestJFREvents.java index c9f8734b714f..65eb4906383e 100644 --- a/test/hotspot/jtreg/containers/docker/TestJFREvents.java +++ b/test/hotspot/jtreg/containers/docker/TestJFREvents.java @@ -33,6 +33,7 @@ * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.misc + * java.base/jdk.internal.platform * java.management * jdk.jartool/sun.tools.jar * @build JfrReporter @@ -56,9 +57,7 @@ public class TestJFREvents { public static void main(String[] args) throws Exception { System.out.println("Test Environment: detected availableCPUs = " + availableCPUs); - if (!DockerTestUtils.canTestDocker()) { - return; - } + DockerTestUtils.checkCanTestDocker(); DockerTestUtils.buildJdkContainerImage(imageName); diff --git a/test/hotspot/jtreg/containers/docker/TestJFRNetworkEvents.java b/test/hotspot/jtreg/containers/docker/TestJFRNetworkEvents.java index c0dde368d1e0..2c7120c577c5 100644 --- a/test/hotspot/jtreg/containers/docker/TestJFRNetworkEvents.java +++ b/test/hotspot/jtreg/containers/docker/TestJFRNetworkEvents.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.misc + * java.base/jdk.internal.platform * java.management * jdk.jartool/sun.tools.jar * @build JfrNetwork @@ -48,10 +49,7 @@ public class TestJFRNetworkEvents { public static void main(String[] args) throws Exception { System.out.println("Test Environment: detected availableCPUs = " + availableCPUs); - if (!DockerTestUtils.canTestDocker()) { - return; - } - + DockerTestUtils.checkCanTestDocker(); DockerTestUtils.buildJdkContainerImage(imageName); try { diff --git a/test/hotspot/jtreg/containers/docker/TestJFRWithJMX.java b/test/hotspot/jtreg/containers/docker/TestJFRWithJMX.java index efe1fa4ffbcc..7c26af9b27a4 100644 --- a/test/hotspot/jtreg/containers/docker/TestJFRWithJMX.java +++ b/test/hotspot/jtreg/containers/docker/TestJFRWithJMX.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.misc + * java.base/jdk.internal.platform * java.management * jdk.jartool/sun.tools.jar * @build EventProducer @@ -73,9 +74,7 @@ public class TestJFRWithJMX { static final AtomicReference ipAddr = new AtomicReference(); public static void main(String[] args) throws Exception { - if (!DockerTestUtils.canTestDocker()) { - throw new SkippedException("Docker is not supported on this host"); - } + DockerTestUtils.checkCanTestDocker(); if (DockerTestUtils.isPodman() & !Platform.isRoot()) { throw new SkippedException("test cannot be run under rootless podman configuration"); diff --git a/test/hotspot/jtreg/containers/docker/TestJcmd.java b/test/hotspot/jtreg/containers/docker/TestJcmd.java index 3f5afd31801f..5819afe8d38d 100644 --- a/test/hotspot/jtreg/containers/docker/TestJcmd.java +++ b/test/hotspot/jtreg/containers/docker/TestJcmd.java @@ -29,6 +29,7 @@ * @requires container.support * @requires vm.flagless * @modules java.base/jdk.internal.misc + * java.base/jdk.internal.platform * java.management * jdk.jartool/sun.tools.jar * @library /test/lib @@ -62,7 +63,7 @@ public class TestJcmd { public static void main(String[] args) throws Exception { - DockerTestUtils.canTestDocker(); + DockerTestUtils.checkCanTestDocker(); // podman versions below 3.3.1 hava a bug where cross-container testing with correct // permissions fails. See JDK-8273216 diff --git a/test/hotspot/jtreg/containers/docker/TestJcmdWithSideCar.java b/test/hotspot/jtreg/containers/docker/TestJcmdWithSideCar.java index 91a07012f003..28a7a20553f8 100644 --- a/test/hotspot/jtreg/containers/docker/TestJcmdWithSideCar.java +++ b/test/hotspot/jtreg/containers/docker/TestJcmdWithSideCar.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ * @requires vm.flagless * @requires !vm.asan * @modules java.base/jdk.internal.misc + * java.base/jdk.internal.platform * java.management * jdk.jartool/sun.tools.jar * @library /test/lib @@ -95,10 +96,7 @@ public class TestJcmdWithSideCar { private static final String NET_BIND_SERVICE = "--cap-add=NET_BIND_SERVICE"; public static void main(String[] args) throws Exception { - if (!DockerTestUtils.canTestDocker()) { - return; - } - + DockerTestUtils.checkCanTestDocker(); DockerTestUtils.buildJdkContainerImage(IMAGE_NAME); try { diff --git a/test/hotspot/jtreg/containers/docker/TestLimitsUpdating.java b/test/hotspot/jtreg/containers/docker/TestLimitsUpdating.java index e8cb54d7d7b9..069cae8a59b7 100644 --- a/test/hotspot/jtreg/containers/docker/TestLimitsUpdating.java +++ b/test/hotspot/jtreg/containers/docker/TestLimitsUpdating.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2023, Red Hat, Inc. - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -32,6 +32,7 @@ * @requires container.support * @requires !vm.asan * @library /test/lib + * @modules java.base/jdk.internal.platform * @build jdk.test.whitebox.WhiteBox LimitUpdateChecker * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar whitebox.jar jdk.test.whitebox.WhiteBox * @run driver TestLimitsUpdating @@ -48,16 +49,18 @@ import jdk.test.lib.containers.docker.DockerRunOptions; import jdk.test.lib.containers.docker.DockerTestUtils; import jdk.test.lib.process.OutputAnalyzer; +import jtreg.SkippedException; public class TestLimitsUpdating { + private static final int CPU_PERIOD = 100_000; + private static final int INITIAL_CPU_COUNT = 1; + private static final int UPDATED_CPU_COUNT = 2; private static final String TARGET_CONTAINER = "limitsUpdatingHS_" + Runtime.getRuntime().version().major(); private static final String imageName = Common.imageName("limitsUpdating"); public static void main(String[] args) throws Exception { - if (!DockerTestUtils.canTestDocker()) { - return; - } - + DockerTestUtils.checkCanTestDocker(); + DockerTestUtils.checkCanUseResourceLimits(); Common.prepareWhiteBox(); DockerTestUtils.buildJdkContainerImage(imageName); @@ -69,6 +72,10 @@ public static void main(String[] args) throws Exception { } private static void testLimitUpdates() throws Exception { + if (Runtime.getRuntime().availableProcessors() < UPDATED_CPU_COUNT) { + throw new SkippedException("Need at least " + UPDATED_CPU_COUNT + + " available CPUs to test CPU limit updates"); + } File sharedtmpdir = new File("test-sharedtmp"); File flag = new File(sharedtmpdir, "limitsUpdated"); // shared with LimitUpdateChecker File started = new File(sharedtmpdir, "started"); // shared with LimitUpdateChecker @@ -78,8 +85,8 @@ private static void testLimitUpdates() throws Exception { DockerRunOptions opts = new DockerRunOptions(imageName, "/jdk/bin/java", "LimitUpdateChecker"); opts.addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/"); opts.addDockerOpts("--volume", sharedtmpdir.getAbsolutePath() + ":/tmp"); - opts.addDockerOpts("--cpu-period", "100000"); - opts.addDockerOpts("--cpu-quota", "200000"); + opts.addDockerOpts("--cpu-period", Integer.toString(CPU_PERIOD)); + opts.addDockerOpts("--cpu-quota", Integer.toString(INITIAL_CPU_COUNT * CPU_PERIOD)); opts.addDockerOpts("--memory", "500m"); opts.addDockerOpts("--memory-swap", "500m"); opts.addDockerOpts("--name", TARGET_CONTAINER); @@ -104,7 +111,7 @@ public void run() { Thread.sleep(100); } - final List containerCommand = getContainerUpdate(300_000, 100_000, "300m"); + final List containerCommand = getContainerUpdate(UPDATED_CPU_COUNT * CPU_PERIOD, CPU_PERIOD, "300m"); // Run the update command so as to increase resources once the container signaled it has started. Thread t2 = new Thread() { public void run() { @@ -127,8 +134,8 @@ public void run() { // Do assertions based on the output in target container OutputAnalyzer targetOut = out[0]; - targetOut.shouldContain("active_processor_count: 2"); // initial value - targetOut.shouldContain("active_processor_count: 3"); // updated value + targetOut.shouldContain("active_processor_count: 1"); // initial value + targetOut.shouldContain("active_processor_count: 2"); // updated value targetOut.shouldContain("memory_limit_in_bytes: 512000 k"); // initial value targetOut.shouldContain("memory_and_swap_limit_in_bytes: 512000 k"); // initial value targetOut.shouldContain("memory_limit_in_bytes: 307200 k"); // updated value diff --git a/test/hotspot/jtreg/containers/docker/TestMemoryAwareness.java b/test/hotspot/jtreg/containers/docker/TestMemoryAwareness.java index a5fb3f829135..6e56024726b6 100644 --- a/test/hotspot/jtreg/containers/docker/TestMemoryAwareness.java +++ b/test/hotspot/jtreg/containers/docker/TestMemoryAwareness.java @@ -59,10 +59,7 @@ private static String getHostSwap() { } public static void main(String[] args) throws Exception { - if (!DockerTestUtils.canTestDocker()) { - return; - } - + DockerTestUtils.checkCanTestDocker(); Common.prepareWhiteBox(); DockerTestUtils.buildJdkContainerImage(imageName); diff --git a/test/hotspot/jtreg/containers/docker/TestMemoryInvisibleParent.java b/test/hotspot/jtreg/containers/docker/TestMemoryInvisibleParent.java index 208dd603615f..29856590469a 100644 --- a/test/hotspot/jtreg/containers/docker/TestMemoryInvisibleParent.java +++ b/test/hotspot/jtreg/containers/docker/TestMemoryInvisibleParent.java @@ -54,10 +54,7 @@ public static void main(String[] args) throws Exception { System.out.println("Cgroup not configured."); return; } - if (!DockerTestUtils.canTestDocker()) { - System.out.println("Unable to run docker tests."); - return; - } + DockerTestUtils.checkCanTestDocker(); ContainerRuntimeVersionTestUtils.checkContainerVersionSupported(); diff --git a/test/hotspot/jtreg/containers/docker/TestMemoryWithCgroupV1.java b/test/hotspot/jtreg/containers/docker/TestMemoryWithCgroupV1.java index 3340f9de03c3..1edc98035e48 100644 --- a/test/hotspot/jtreg/containers/docker/TestMemoryWithCgroupV1.java +++ b/test/hotspot/jtreg/containers/docker/TestMemoryWithCgroupV1.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2022, Tencent. All rights reserved. + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,10 +52,8 @@ public static void main(String[] args) throws Exception { return; } if ("cgroupv1".equals(metrics.getProvider())) { - if (!DockerTestUtils.canTestDocker()) { - return; - } - + DockerTestUtils.checkCanTestDocker(); + DockerTestUtils.checkCanUseResourceLimits(); Common.prepareWhiteBox(); DockerTestUtils.buildJdkContainerImage(imageName); diff --git a/test/hotspot/jtreg/containers/docker/TestMemoryWithSubgroups.java b/test/hotspot/jtreg/containers/docker/TestMemoryWithSubgroups.java index f449008bf44e..265215c9cd49 100644 --- a/test/hotspot/jtreg/containers/docker/TestMemoryWithSubgroups.java +++ b/test/hotspot/jtreg/containers/docker/TestMemoryWithSubgroups.java @@ -51,10 +51,7 @@ public static void main(String[] args) throws Exception { System.out.println("Cgroup not configured."); return; } - if (!DockerTestUtils.canTestDocker()) { - System.out.println("Unable to run docker tests."); - return; - } + DockerTestUtils.checkCanTestDocker(); ContainerRuntimeVersionTestUtils.checkContainerVersionSupported(); diff --git a/test/hotspot/jtreg/containers/docker/TestMisc.java b/test/hotspot/jtreg/containers/docker/TestMisc.java index 400119dac9df..fca3cef55139 100644 --- a/test/hotspot/jtreg/containers/docker/TestMisc.java +++ b/test/hotspot/jtreg/containers/docker/TestMisc.java @@ -46,14 +46,10 @@ public class TestMisc { - private static final Metrics metrics = Metrics.systemMetrics(); private static final String imageName = Common.imageName("misc"); public static void main(String[] args) throws Exception { - if (!DockerTestUtils.canTestDocker()) { - return; - } - + DockerTestUtils.checkCanTestDocker(); Common.prepareWhiteBox(); DockerTestUtils.buildJdkContainerImage(imageName); @@ -102,14 +98,8 @@ private static void testPrintContainerInfo() throws Exception { // Test the mapping function on cgroups v2. Should also pass on cgroups v1 as it's // a direct mapping there. private static void testPrintContainerInfoCPUShares() throws Exception { - // Test won't work on cgv1 rootless podman since resource limits don't - // work there. - if ("cgroupv1".equals(metrics.getProvider()) && - DockerTestUtils.isPodman() && - DockerTestUtils.isRootless()) { - throw new SkippedException("Resource limits required for testPrintContainerInfoCPUShares(). " + - "This is cgv1 with podman in rootless mode. Test skipped."); - } + // Test won't work on cgv1 rootless since resource limits don't work there. + DockerTestUtils.checkCanUseResourceLimits(); // Anything less than 1024 should return the back-mapped cpu-shares value without // rounding to next multiple of 1024 (on cg v2). Only ensure that we get // 'cpu_shares: ' over 'cpu_shares: no shares'. diff --git a/test/hotspot/jtreg/containers/docker/TestPids.java b/test/hotspot/jtreg/containers/docker/TestPids.java index 07a0cbd295dc..61d0fb814073 100644 --- a/test/hotspot/jtreg/containers/docker/TestPids.java +++ b/test/hotspot/jtreg/containers/docker/TestPids.java @@ -31,6 +31,7 @@ * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.misc + * java.base/jdk.internal.platform * java.management * @build jdk.test.whitebox.WhiteBox PrintContainerInfo * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar whitebox.jar jdk.test.whitebox.WhiteBox @@ -54,10 +55,8 @@ public class TestPids { static final String warning_kernel_no_pids_support = "WARNING: Your kernel does not support pids limit capabilities"; public static void main(String[] args) throws Exception { - if (!DockerTestUtils.canTestDocker()) { - return; - } - + DockerTestUtils.checkCanTestDocker(); + DockerTestUtils.checkCanUseResourceLimits(); Common.prepareWhiteBox(); DockerTestUtils.buildJdkContainerImage(imageName); diff --git a/test/hotspot/jtreg/gc/TestNativeReferenceGet.java b/test/hotspot/jtreg/gc/TestNativeReferenceGet.java new file mode 100644 index 000000000000..222d250f79af --- /dev/null +++ b/test/hotspot/jtreg/gc/TestNativeReferenceGet.java @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package gc; + +/** + * @test + * @bug 8352565 + * @summary Determine whether the native method implementation of + * Reference.get() works as expected. Disable the intrinsic implementation to + * force use of the native method. + * @library /test/lib + * @modules java.base/java.lang.ref:open + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm + * -Xbootclasspath/a:. + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:DisableIntrinsic=_Reference_get0 + * gc.TestNativeReferenceGet + */ + +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.List; +import jdk.test.whitebox.WhiteBox; + +public final class TestNativeReferenceGet { + + private static final WhiteBox WB = WhiteBox.getWhiteBox(); + + private static void gcUntilOld(Object o) { + while (!WB.isObjectInOldGen(o)) { + WB.fullGC(); + } + } + + private static final class TestObject { + public final int value; + + public TestObject(int value) { + this.value = value; + } + } + + private static final ReferenceQueue queue = + new ReferenceQueue(); + + private static final class Ref extends WeakReference { + public Ref(TestObject obj) { + super(obj, queue); + } + } + + private static final int NUM_REFS = 100; + + private static List references = null; + private static List referents = null; + + // Create all the objects used by the test, and ensure they are all in the + // old generation. + private static void setup() { + references = new ArrayList(NUM_REFS); + referents = new ArrayList(NUM_REFS); + + for (int i = 0; i < NUM_REFS; ++i) { + TestObject obj = new TestObject(i); + referents.add(obj); + references.add(new Ref(obj)); + } + + gcUntilOld(references); + gcUntilOld(referents); + for (int i = 0; i < NUM_REFS; ++i) { + gcUntilOld(references.get(i)); + gcUntilOld(referents.get(i)); + } + } + + // Discard all the strong references. + private static void dropReferents() { + // Not using List.clear() because it doesn't document null'ing elements. + for (int i = 0; i < NUM_REFS; ++i) { + referents.set(i, null); + } + } + + // Create new strong references from the weak references, by using the + // native method implementation of Reference.get() and recording the value + // in references. + private static void strengthenReferents() { + for (int i = 0; i < NUM_REFS; ++i) { + referents.set(i, references.get(i).get()); + } + } + + private static void check() { + // None of the references should have been cleared and enqueued, + // because we have strong references to all the referents. + try { + while (WB.waitForReferenceProcessing()) {} + } catch (InterruptedException e) { + throw new RuntimeException("Test interrupted"); + } + if (queue.poll() != null) { + throw new RuntimeException("Reference enqueued"); + } + + // Check details of expected state. + for (int i = 0; i < NUM_REFS; ++i) { + Ref reference = (Ref) references.get(i); + TestObject referent = reference.get(); + if (referent == null) { + throw new RuntimeException("Referent not strengthened"); + } else if (referent != referents.get(i)) { + throw new RuntimeException( + "Reference referent differs from saved referent: " + i); + } else if (referent.value != i) { + throw new RuntimeException( + "Referent " + i + " value: " + referent.value); + } + } + } + + private static void testConcurrent() { + System.out.println("Testing concurrent GC"); + try { + WB.concurrentGCAcquireControl(); + dropReferents(); + WB.concurrentGCRunTo(WB.BEFORE_MARKING_COMPLETED); + strengthenReferents(); + WB.concurrentGCRunToIdle(); + check(); + } finally { + WB.concurrentGCReleaseControl(); + } + } + + private static void testNonconcurrent() { + System.out.println("Testing nonconcurrent GC"); + // A GC between clearing and strengthening will result in test failure. + // We try to make that unlikely via this immediately preceeding GC. + WB.fullGC(); + dropReferents(); + strengthenReferents(); + WB.fullGC(); + check(); + } + + public static final void main(String[] args) { + setup(); + if (WB.supportsConcurrentGCBreakpoints()) { + testConcurrent(); + } else { + testNonconcurrent(); + } + } +} diff --git a/test/hotspot/jtreg/runtime/os/TestTrimNativeHeapIntervalTablesCleanup.java b/test/hotspot/jtreg/runtime/os/TestTrimNativeHeapIntervalTablesCleanup.java new file mode 100644 index 000000000000..3ced98b616d5 --- /dev/null +++ b/test/hotspot/jtreg/runtime/os/TestTrimNativeHeapIntervalTablesCleanup.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + /** + * @test + * @bug 8375125 + * @summary Trigger StringTable::clean_dead_entries or SymbolTable::clean_dead_entries + * with -XX:TrimNativeHeapInterval enabled,should not violate lock ordering. + * @requires vm.debug + * @requires vm.gc != "Epsilon" + * @library /test/lib + * @modules java.compiler + * @run main/othervm -Xms128m -Xmx128m + * -XX:TrimNativeHeapInterval=300000 + * TestTrimNativeHeapIntervalTablesCleanup string + * @run main/othervm -Xms128m -Xmx128m + * -XX:TrimNativeHeapInterval=300000 + * TestTrimNativeHeapIntervalTablesCleanup symbol + */ + +import java.util.LinkedList; +import jdk.test.lib.compiler.InMemoryJavaCompiler; + +public class TestTrimNativeHeapIntervalTablesCleanup { + + public static void main(String[] args) throws Exception{ + if (args.length != 1) { + throw new IllegalArgumentException("Expected 1 argument: string|symbol"); + } + switch (args[0]) { + case "string": + testStringTableCleanup(); + break; + case "symbol": + testSymbolTableCleanup(); + break; + default: + throw new IllegalArgumentException("Unknown mode: " + args[0]); + } + System.out.println("passed: " + args[0]); + } + + static void testStringTableCleanup() throws Exception{ + final int rounds = 30; + final int maxSize = 200_000; + final int pruneEvery = 50_000; + final int pruneCount = 25_000; + long stringNum = 0; + + for (int round = 0; round < rounds; round++) { + LinkedList list = new LinkedList<>(); + for (int i = 0; i < maxSize; i++, stringNum++) { + if (i != 0 && (i % pruneEvery) == 0) { + int toRemove = Math.min(pruneCount, list.size()); + list.subList(0, toRemove).clear(); + } + list.push(Long.toString(stringNum).intern()); + } + System.gc(); + Thread.sleep(1000); + } + } + + static void testSymbolTableCleanup() throws Exception { + final int rounds = 10; + final int classesPerRound = 100; + + for (int r = 0; r < rounds; r++) { + for (int i = 0; i < classesPerRound; i++) { + String cn = "C" + r + "_" + i; + byte[] bytes = InMemoryJavaCompiler.compile( + cn, + "public class " + cn + " { int m" + i + "() { return " + i + "; } }" + ); + new ClassLoader(null) { + @Override + protected Class findClass(String name) throws ClassNotFoundException { + if (!name.equals(cn)) throw new ClassNotFoundException(name); + return defineClass(name, bytes, 0, bytes.length); + } + }.loadClass(cn).getDeclaredConstructor().newInstance(); + } + System.gc(); + Thread.sleep(1000); + } + } +} \ No newline at end of file diff --git a/test/hotspot/jtreg/serviceability/dcmd/thread/PrintTest.java b/test/hotspot/jtreg/serviceability/dcmd/thread/PrintTest.java index 29c462a56b39..a4a5eb5721b5 100644 --- a/test/hotspot/jtreg/serviceability/dcmd/thread/PrintTest.java +++ b/test/hotspot/jtreg/serviceability/dcmd/thread/PrintTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -168,6 +168,9 @@ public void run(CommandExecutor executor) { output.shouldNotMatch(jucLockPattern1); output.shouldNotMatch(jucLockPattern2); } + + /* Check for presence of version string */ + output.shouldContain("JDK version:"); } @Test diff --git a/test/hotspot/jtreg/testlibrary/jittester/conf/exclude.methods.lst b/test/hotspot/jtreg/testlibrary/jittester/conf/exclude.methods.lst index 8055241380dc..befd0ed66dbb 100644 --- a/test/hotspot/jtreg/testlibrary/jittester/conf/exclude.methods.lst +++ b/test/hotspot/jtreg/testlibrary/jittester/conf/exclude.methods.lst @@ -1,4 +1,5 @@ java/lang/EnumConstantNotPresentException::EnumConstantNotPresentException(Ljava/lang/Class;Ljava/lang/String;) +java/lang/Math::random() java/lang/Object::notify() java/lang/Object::notifyAll() java/lang/Object::toString() diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted003.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted003.java index 8cc997fa4ab7..f1d18211f3d3 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted003.java @@ -25,9 +25,10 @@ import java.io.File; import java.io.FileInputStream; import java.io.PrintStream; +import java.net.URI; +import java.nio.file.Path; +import java.security.CodeSource; import java.security.ProtectionDomain; -import java.util.regex.Pattern; -import java.util.regex.Matcher; import nsk.share.Consts; import nsk.share.test.Stresser; @@ -80,24 +81,12 @@ static byte[] fileBytes(String fileName) { public static int run(String args[], PrintStream out) { - String testclasspath = System.getProperty("test.class.path"); - String [] testpaths = testclasspath.split(System.getProperty("path.separator")); - String classesDir = ""; - - Pattern pattern = Pattern.compile("^(.*)classes(.*)vmTestbase(.*)$"); - for (int i = 0 ; i < testpaths.length; i++) { - if (pattern.matcher(testpaths[i]).matches()) { - classesDir = testpaths[i]; - } - } - if (classesDir.equals("")) { - System.err.println("TEST BUG: Classes directory not found in test,class.path."); - return Consts.TEST_FAILED; - } Stresser stress = new Stresser(args); String className = Helper.class.getName(); - byte[] bloatBytes = fileBytes(classesDir + File.separator + className.replace('.', '/') + ".class"); + CodeSource classCodeSource = Helper.class.getProtectionDomain().getCodeSource(); + Path classFilePath = Path.of(URI.create(classCodeSource.getLocation().toString())); + byte[] bloatBytes = fileBytes(classFilePath.resolve(className.replace('.', '/') + ".class").toString()); int count = 0; Helper.resetExhaustedEvent(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/ArgumentHandler.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/ArgumentHandler.java index 3f924c6ac47b..41f9bb57b9e0 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/ArgumentHandler.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/ArgumentHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -605,6 +605,9 @@ class CheckedFeatures { {"windows-x64", "com.sun.jdi.CommandLineLaunch", "dt_socket"}, {"windows-x64", "com.sun.jdi.RawCommandLineLaunch", "dt_socket"}, + {"windows-aarch64", "com.sun.jdi.CommandLineLaunch", "dt_socket"}, + {"windows-aarch64", "com.sun.jdi.RawCommandLineLaunch", "dt_socket"}, + {"macosx-amd64", "com.sun.jdi.CommandLineLaunch", "dt_shmem"}, {"macosx-amd64", "com.sun.jdi.RawCommandLineLaunch", "dt_shmem"}, diff --git a/test/jaxp/TEST.ROOT b/test/jaxp/TEST.ROOT index 6398c399f0a5..aff3b7698304 100644 --- a/test/jaxp/TEST.ROOT +++ b/test/jaxp/TEST.ROOT @@ -23,7 +23,7 @@ modules=java.xml groups=TEST.groups # Minimum jtreg version -requiredVersion=7.5.2+1 +requiredVersion=8.2.1+1 # Path to libraries in the topmost test directory. This is needed so @library # does not need ../../ notation to reach them diff --git a/test/jdk/TEST.ROOT b/test/jdk/TEST.ROOT index 778c5c5669ad..5ea89ededc2c 100644 --- a/test/jdk/TEST.ROOT +++ b/test/jdk/TEST.ROOT @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This file identifies the root of the test-suite hierarchy. @@ -115,7 +115,7 @@ requires.properties= \ jdk.foreign.linker # Minimum jtreg version -requiredVersion=7.5.2+1 +requiredVersion=8.2.1+1 # Path to libraries in the topmost test directory. This is needed so @library # does not need ../../ notation to reach them diff --git a/test/jdk/com/sun/net/httpserver/simpleserver/SecurityManagerTestNoRead.policy b/test/jdk/com/sun/net/httpserver/simpleserver/SecurityManagerTestNoRead.policy index b91171b41458..7c043dce7e67 100644 --- a/test/jdk/com/sun/net/httpserver/simpleserver/SecurityManagerTestNoRead.policy +++ b/test/jdk/com/sun/net/httpserver/simpleserver/SecurityManagerTestNoRead.policy @@ -21,11 +21,6 @@ // questions. // -// for JTwork/classes/test/lib/jdk/test/lib/util/FileUtils.class -grant codeBase "file:${test.classes}/../../../../../../test/lib/-" { - permission java.util.PropertyPermission "*", "read"; -}; - grant codeBase "file:${test.classes}/*" { permission java.net.URLPermission "http://localhost:*/*", "GET"; diff --git a/test/jdk/com/sun/net/httpserver/simpleserver/SecurityManagerTestRead.policy b/test/jdk/com/sun/net/httpserver/simpleserver/SecurityManagerTestRead.policy index b8b6b3a5f37a..8f636183e53f 100644 --- a/test/jdk/com/sun/net/httpserver/simpleserver/SecurityManagerTestRead.policy +++ b/test/jdk/com/sun/net/httpserver/simpleserver/SecurityManagerTestRead.policy @@ -21,11 +21,6 @@ // questions. // -// for JTwork/classes/test/lib/jdk/test/lib/util/FileUtils.class -grant codeBase "file:${test.classes}/../../../../../../test/lib/-" { - permission java.util.PropertyPermission "*", "read"; -}; - grant codeBase "file:${test.classes}/*" { permission java.net.URLPermission "http://localhost:*/*", "GET"; diff --git a/test/jdk/java/awt/Graphics2D/ClearPolyLineUsingXORTest.java b/test/jdk/java/awt/Graphics2D/ClearPolyLineUsingXORTest.java new file mode 100644 index 000000000000..7afecfdee3b8 --- /dev/null +++ b/test/jdk/java/awt/Graphics2D/ClearPolyLineUsingXORTest.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @key headful + * @bug 8387593 + * @summary Tests that clearing a polyline using XOR mode does not + * leave any traces. Using uiScale 1 helps us to + * reproduce the issue. + * @run main/othervm -Dsun.java2d.uiScale=1 ClearPolyLineUsingXORTest + */ + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsEnvironment; +import java.awt.image.BufferedImage; +import java.awt.image.VolatileImage; + +public class ClearPolyLineUsingXORTest { + private static final int SIZE = 500; + + private static BufferedImage clearUsingXOR(GraphicsConfiguration gc) { + VolatileImage vImg = gc.createCompatibleVolatileImage(SIZE, SIZE); + int attempt = 0; + while (true) { + if (++attempt > 10) { + throw new RuntimeException("Unable to use VolatileImage after " + + attempt + " attempts"); + } + + int status = vImg.validate(gc); + if (status == VolatileImage.IMAGE_INCOMPATIBLE) { + vImg = gc.createCompatibleVolatileImage(SIZE, SIZE); + } + + Graphics2D g2d = vImg.createGraphics(); + g2d.setBackground(Color.BLACK); + g2d.clearRect(0, 0, 500, 500); + + int min = 10; + int max = 210; + int mid = 110; + + int xdp[] = {min, max, min, max, min, max}; + int ydp[] = {min, min, mid, max, max, mid}; + + g2d.setXORMode(Color.GREEN); + g2d.drawPolygon(xdp, ydp, xdp.length); + g2d.drawPolygon(xdp, ydp, xdp.length); + + BufferedImage snapshot = vImg.getSnapshot(); + if (vImg.contentsLost()) { + continue; + } + return snapshot; + } + } + public static void main(String[] args) { + GraphicsConfiguration gc = + GraphicsEnvironment.getLocalGraphicsEnvironment(). + getDefaultScreenDevice().getDefaultConfiguration(); + BufferedImage bImg = clearUsingXOR(gc); + + for (int x = 0; x < SIZE; x++) { + for (int y = 0; y < SIZE; y++) { + if (bImg.getRGB(x, y) != Color.BLACK.getRGB()) { + throw new RuntimeException("Clear using XOR is not" + + " working at x: " + x + " y: " + y); + } + } + } + } +} diff --git a/test/jdk/java/awt/Graphics2D/CopyAreaOOB.java b/test/jdk/java/awt/Graphics2D/CopyAreaOOB.java index 27a1a3a868a9..9ee44037f14d 100644 --- a/test/jdk/java/awt/Graphics2D/CopyAreaOOB.java +++ b/test/jdk/java/awt/Graphics2D/CopyAreaOOB.java @@ -27,6 +27,8 @@ * @bug 6430601 8198613 * @summary Verifies that copyArea() works properly when the * destination parameters are outside the destination bounds. + * @library /test/lib + * @build jdk.test.lib.Platform * @run main/othervm CopyAreaOOB */ @@ -49,23 +51,29 @@ import java.io.File; import java.io.IOException; import java.util.List; - import javax.imageio.ImageIO; +import jdk.test.lib.Platform; public class CopyAreaOOB extends Canvas { + private static final int PRIMARY_TOLERANCE = 2; + private static int TOLERANCE = 30; + private static final boolean DEBUG = false; private static Frame frame; private static Robot robot; private static BufferedImage captureImg; - private static StringBuffer errorLog = new StringBuffer(); + private static final StringBuffer errorLog = new StringBuffer(); private static final Point OFF_FRAME_LOC = new Point(50, 50); private static final int SIZE = 400; public static void main(String[] args) throws Exception { try { - robot = new Robot(); + if (!Platform.isOSX()) { + TOLERANCE = PRIMARY_TOLERANCE; + } + robot = new Robot(); // added to move mouse pointer away from test UI // so that it is not captured in the screenshot robot.mouseMove(OFF_FRAME_LOC.x, OFF_FRAME_LOC.y); @@ -77,7 +85,7 @@ public static void main(String[] args) throws Exception { if (!errorLog.isEmpty()) { saveImages(); - throw new RuntimeException("Test failed: \n" + errorLog.toString()); + throw new RuntimeException("Test failed for the following region(s)" + errorLog); } } finally { if (frame != null) { @@ -101,13 +109,13 @@ public void paint(Graphics g) { int h = getHeight(); Graphics2D g2d = (Graphics2D)g; - g2d.setColor(Color.black); + g2d.setColor(Color.BLUE); g2d.fillRect(0, 0, w, h); - g2d.setColor(Color.green); + g2d.setColor(Color.GREEN); g2d.fillRect(0, 0, w, 10); - g2d.setColor(Color.red); + g2d.setColor(Color.RED); g2d.fillRect(0, 10, 50, h - 10); // copy the region such that part of it goes below the bottom of the @@ -123,12 +131,12 @@ public void paint(Graphics g) { captureImg = robot.createScreenCapture(rect); // Test pixels - testRegion("green", 0, 0, 400, 10, 0xff00ff00); - testRegion("original-red", 0, 10, 50, 400, 0xffff0000); - testRegion("background", 50, 10, 60, 400, 0xff000000); - testRegion("in-between", 60, 10, 110, 20, 0xff000000); - testRegion("copied-red", 60, 20, 110, 400, 0xffff0000); - testRegion("background", 110, 10, 400, 400, 0xff000000); + testRegion("green", 0, 0, 400, 10, Color.GREEN); + testRegion("original-red", 0, 10, 50, 400, Color.RED); + testRegion("background", 50, 10, 60, 400, Color.BLUE); + testRegion("in-between", 60, 10, 110, 20, Color.BLUE); + testRegion("copied-red", 60, 20, 110, 400, Color.RED); + testRegion("background", 110, 10, 400, 400, Color.BLUE); } public Dimension getPreferredSize() { @@ -137,24 +145,23 @@ public Dimension getPreferredSize() { private static void testRegion(String region, int x1, int y1, int x2, int y2, - int expected) { - System.out.print("Test region: " + region); + Color expected) { for (int y = y1; y < y2; y++) { for (int x = x1; x < x2; x++) { - int actual = captureImg.getRGB(x, y); - if (actual != expected) { - System.out.print(" Status: FAILED\n"); - errorLog.append("Test failed for " + region - + " region at x: " + x + " y: " + y - + " (expected: " - + Integer.toHexString(expected) - + " actual: " - + Integer.toHexString(actual) + ")\n"); + Color actual = new Color(captureImg.getRGB(x, y)); + if (DEBUG) { + System.out.println("Actual color: " + actual); + } + if (!compareColor(expected, actual)) { + errorLog.append("\nTest region: " + region + " Status: FAILED!!!\n"); + errorLog.append("Test failed at x : " + x + " y : " + y + "\n" + + "Expected Color: " + expected + "\n" + + "Actual Color: " + actual + "\n"); return; } } } - System.out.print(" Status: PASSED\n"); + System.out.println("Test region: " + region + " Status: PASSED"); } private static void saveImages() { @@ -173,4 +180,14 @@ private static void saveImages() { System.err.println("Can't write image " + e); } } + + private static boolean compareColor(Color expected, Color actual) { + return Math.abs(expected.getRed() - actual.getRed()) + < (expected.equals(Color.RED) ? PRIMARY_TOLERANCE : TOLERANCE) + && Math.abs(expected.getGreen() - actual.getGreen()) + < (expected.equals(Color.GREEN) ? PRIMARY_TOLERANCE : TOLERANCE) + && Math.abs(expected.getBlue() - actual.getBlue()) + < (expected.equals(Color.BLUE) ? PRIMARY_TOLERANCE : TOLERANCE); + } } + diff --git a/test/jdk/java/awt/SplashScreen/MultiResolutionSplash/unix/UnixMultiResolutionSplashTest.java b/test/jdk/java/awt/SplashScreen/MultiResolutionSplash/unix/UnixMultiResolutionSplashTest.java deleted file mode 100644 index 99cc58e13a39..000000000000 --- a/test/jdk/java/awt/SplashScreen/MultiResolutionSplash/unix/UnixMultiResolutionSplashTest.java +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.awt.Color; -import java.awt.Dialog; -import java.awt.Frame; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Panel; -import java.awt.Rectangle; -import java.awt.Robot; -import java.awt.SplashScreen; -import java.awt.TextField; -import java.awt.Window; -import java.awt.event.KeyEvent; -import java.awt.image.BufferedImage; -import java.io.BufferedReader; -import java.io.File; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import javax.imageio.ImageIO; - -/** - * @test - * @key headful - * @bug 8145174 8151787 8168657 - * @summary HiDPI splash screen support on Linux - * @modules java.desktop/sun.java2d - * @requires (os.family == "linux") - * @run main UnixMultiResolutionSplashTest - */ - -public class UnixMultiResolutionSplashTest { - - private static final int IMAGE_WIDTH = 300; - private static final int IMAGE_HEIGHT = 200; - private static int inx = 0; - private static final ImageInfo[] tests = { - new ImageInfo("splash1.png", "splash1@200pct.png", Color.BLUE, Color.GREEN), - new ImageInfo("splash2", "splash2@2x", Color.WHITE, Color.BLACK), - new ImageInfo("splash3.", "splash3@200pct.", Color.YELLOW, Color.RED) - }; - - public static void main(String[] args) throws Exception { - - if (args.length == 0) { - generateImages(); - for (ImageInfo test : tests) { - createChildProcess(test); - } - } else { - int index = Integer.parseInt(args[0]); - testSplash(tests[index]); - } - } - - static void createChildProcess(ImageInfo test) { - String javaPath = System.getProperty("java.home"); - File file = new File(test.name1x); - String classPathDir = System.getProperty("java.class.path"); - Map env = new HashMap(); - env.put("GDK_SCALE", "2"); - int exitValue = doExec(env, javaPath + File.separator + "bin" + File.separator - + "java", "-splash:" + file.getAbsolutePath(), "-cp", - classPathDir, "UnixMultiResolutionSplashTest", String.valueOf(inx++)); - if (exitValue != 0) { - throw new RuntimeException("Test Failed"); - } - } - - static void testSplash(ImageInfo test) throws Exception { - SplashScreen splashScreen = SplashScreen.getSplashScreen(); - if (splashScreen == null) { - throw new RuntimeException("Splash screen is not shown!"); - } - Graphics2D g = splashScreen.createGraphics(); - Rectangle splashBounds = splashScreen.getBounds(); - int screenX = (int) splashBounds.getCenterX(); - int screenY = (int) splashBounds.getCenterY(); - Robot robot = new Robot(); - Color splashScreenColor = robot.getPixelColor(screenX, screenY); - - float scaleFactor = getScaleFactor(); - Color testColor = (1 < scaleFactor) ? test.color2x : test.color1x; - if (!compare(testColor, splashScreenColor)) { - throw new RuntimeException( - "Image with wrong resolution is used for splash screen!"); - } - } - - static int doExec(Map envToSet, String... cmds) { - Process p = null; - ProcessBuilder pb = new ProcessBuilder(cmds); - Map env = pb.environment(); - for (String cmd : cmds) { - System.out.print(cmd + " "); - } - System.out.println(); - if (envToSet != null) { - env.putAll(envToSet); - } - BufferedReader rdr = null; - try { - List outputList = new ArrayList<>(); - pb.redirectErrorStream(true); - p = pb.start(); - rdr = new BufferedReader(new InputStreamReader(p.getInputStream())); - String in = rdr.readLine(); - while (in != null) { - outputList.add(in); - in = rdr.readLine(); - System.out.println(in); - } - p.waitFor(); - p.destroy(); - } catch (Exception ex) { - ex.printStackTrace(); - } - return p.exitValue(); - } - - static void testFocus() throws Exception { - - System.out.println("Focus Test!"); - Robot robot = new Robot(); - robot.setAutoDelay(50); - Frame frame = new Frame(); - frame.setSize(100, 100); - String test = "123"; - TextField textField = new TextField(test); - textField.selectAll(); - frame.add(textField); - frame.setVisible(true); - robot.waitForIdle(); - - robot.keyPress(KeyEvent.VK_A); - robot.keyRelease(KeyEvent.VK_A); - robot.keyPress(KeyEvent.VK_B); - robot.keyRelease(KeyEvent.VK_B); - robot.waitForIdle(); - - frame.dispose(); - if (!textField.getText().equals("ab")) { - throw new RuntimeException("Focus is lost! " + - "Expected 'ab' got " + "'" + textField.getText() + "'."); - } - } - - static boolean compare(Color c1, Color c2) { - return compare(c1.getRed(), c2.getRed()) - && compare(c1.getGreen(), c2.getGreen()) - && compare(c1.getBlue(), c2.getBlue()); - } - - static boolean compare(int n, int m) { - return Math.abs(n - m) <= 50; - } - - static float getScaleFactor() { - - final Dialog dialog = new Dialog((Window) null); - dialog.setSize(100, 100); - dialog.setModal(true); - float[] scaleFactors = new float[1]; - Panel panel = new Panel() { - - @Override - public void paint(Graphics g) { - String scaleStr = System.getenv("GDK_SCALE"); - if (scaleStr != null && !scaleStr.equals("")) { - try { - scaleFactors[0] = Float.valueOf(scaleStr); - } catch (NumberFormatException ex) { - scaleFactors[0] = 1.0f; - } - } - dialog.setVisible(false); - } - }; - dialog.add(panel); - dialog.setVisible(true); - dialog.dispose(); - return scaleFactors[0]; - } - - static void generateImages() throws Exception { - for (ImageInfo test : tests) { - generateImage(test.name1x, test.color1x, 1); - generateImage(test.name2x, test.color2x, 2); - } - } - - static void generateImage(String name, Color color, int scale) throws Exception { - File file = new File(name); - if (file.exists()) { - return; - } - BufferedImage image = new BufferedImage(scale * IMAGE_WIDTH, scale * IMAGE_HEIGHT, - BufferedImage.TYPE_INT_RGB); - Graphics g = image.getGraphics(); - g.setColor(color); - g.fillRect(0, 0, scale * IMAGE_WIDTH, scale * IMAGE_HEIGHT); - ImageIO.write(image, "png", file); - } - - static class ImageInfo { - - final String name1x; - final String name2x; - final Color color1x; - final Color color2x; - - public ImageInfo(String name1x, String name2x, Color color1x, Color color2x) { - this.name1x = name1x; - this.name2x = name2x; - this.color1x = color1x; - this.color2x = color2x; - } - } -} - diff --git a/test/jdk/java/awt/event/KeyEvent/ExtendedKeyCode/ExtendedKeyCodeTest.java b/test/jdk/java/awt/event/KeyEvent/ExtendedKeyCode/ExtendedKeyCodeTest.java index c76f879446f5..fae72f45bfab 100644 --- a/test/jdk/java/awt/event/KeyEvent/ExtendedKeyCode/ExtendedKeyCodeTest.java +++ b/test/jdk/java/awt/event/KeyEvent/ExtendedKeyCode/ExtendedKeyCodeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,8 +30,7 @@ * @test * @key headful * @bug 8007156 8025126 - * @summary Extended key code is not set for a key event - * @author Alexandr Scherbatiy + * @summary Tests that ExtendedKeyCode is set for key events * @library /lib/client * @build ExtendedRobot * @run main ExtendedKeyCodeTest @@ -75,7 +74,8 @@ public void keyReleased(KeyEvent e) { frame.dispose(); if (eventsCount != 2 || !setExtendedKeyCode) { - throw new RuntimeException("Wrong extended key code"); + throw new RuntimeException("Wrong extended key code\n" + + "eventsCount: " + eventsCount); } frame = new Frame(); diff --git a/test/jdk/java/net/IPSupport/MinimumPermissions.policy b/test/jdk/java/net/IPSupport/MinimumPermissions.policy index 6e370ca8e37b..cfcad8927e7b 100644 --- a/test/jdk/java/net/IPSupport/MinimumPermissions.policy +++ b/test/jdk/java/net/IPSupport/MinimumPermissions.policy @@ -21,7 +21,7 @@ // questions. // -grant codeBase "file:${test.classes}/../../../../test/lib/-" { +grant codeBase "file:${test.classes}/test/lib/-" { permission java.net.SocketPermission "localhost:0", "listen,resolve"; permission java.util.PropertyPermission "java.net.preferIPv4Stack", "read"; permission java.util.PropertyPermission "java.net.preferIPv6Addresses", "read"; diff --git a/test/jdk/java/net/httpclient/AsFileDownloadTest.policy b/test/jdk/java/net/httpclient/AsFileDownloadTest.policy index dec2b8bb0a45..629198750e38 100644 --- a/test/jdk/java/net/httpclient/AsFileDownloadTest.policy +++ b/test/jdk/java/net/httpclient/AsFileDownloadTest.policy @@ -22,13 +22,13 @@ // // for JTwork/classes/0/test/lib/jdk/test/lib/net/SimpleSSLContext.class -grant codeBase "file:${test.classes}/../../../../test/lib/-" { +grant codeBase "file:${test.classes}/test/lib/-" { permission java.util.PropertyPermission "test.src.path", "read"; permission java.io.FilePermission "${test.src}/../../../../lib/jdk/test/lib/net/testkeys", "read"; }; // for classes in JTwork//classes/0/test/jdk/java/net/httpclient/lib/ -grant codeBase "file:${test.classes}/../../../../test/jdk/java/net/httpclient/lib/-" { +grant codeBase "file:${test.classes}/test/jdk/java/net/httpclient/lib/-" { permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.net.http.common"; permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.net.http.frame"; permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.net.http.hpack"; diff --git a/test/jdk/java/net/httpclient/FilePublisher/FilePublisherPermsTest1.policy b/test/jdk/java/net/httpclient/FilePublisher/FilePublisherPermsTest1.policy index bbc3e3596397..2eaf6bab2d68 100644 --- a/test/jdk/java/net/httpclient/FilePublisher/FilePublisherPermsTest1.policy +++ b/test/jdk/java/net/httpclient/FilePublisher/FilePublisherPermsTest1.policy @@ -22,13 +22,13 @@ // // for JTwork/classes/0/test/lib/jdk/test/lib/net/SimpleSSLContext.class -grant codeBase "file:${test.classes}/../../../../../test/lib/-" { +grant codeBase "file:${test.classes}/test/lib/-" { permission java.util.PropertyPermission "test.src.path", "read"; permission java.io.FilePermission "${test.src}/../../../../../lib/jdk/test/lib/net/testkeys", "read"; }; // for jdk/httpclient/test/lib/* classes -grant codeBase "file:${test.classes}/../../../../../test/jdk/java/net/httpclient/lib/-" { +grant codeBase "file:${test.classes}/test/jdk/java/net/httpclient/lib/-" { permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.net.http.common"; permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.net.http.frame"; permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.net.http.hpack"; diff --git a/test/jdk/java/net/httpclient/FilePublisher/FilePublisherPermsTest2.policy b/test/jdk/java/net/httpclient/FilePublisher/FilePublisherPermsTest2.policy index 0ff462568bae..6da3b06d4b06 100644 --- a/test/jdk/java/net/httpclient/FilePublisher/FilePublisherPermsTest2.policy +++ b/test/jdk/java/net/httpclient/FilePublisher/FilePublisherPermsTest2.policy @@ -24,13 +24,13 @@ // same as FilePublisherPermsTest1.policy with custom permission for test classes // for JTwork/classes/0/test/lib/jdk/test/lib/net/SimpleSSLContext.class -grant codeBase "file:${test.classes}/../../../../../test/lib/-" { +grant codeBase "file:${test.classes}/test/lib/-" { permission java.util.PropertyPermission "test.src.path", "read"; permission java.io.FilePermission "${test.src}/../../../../../lib/jdk/test/lib/net/testkeys", "read"; }; // for jdk/httpclient/test/lib/* classes -grant codeBase "file:${test.classes}/../../../../../test/jdk/java/net/httpclient/lib/-" { +grant codeBase "file:${test.classes}/test/jdk/java/net/httpclient/lib/-" { permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.net.http.common"; permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.net.http.frame"; permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.net.http.hpack"; diff --git a/test/jdk/java/net/httpclient/FilePublisher/FilePublisherPermsTest3.policy b/test/jdk/java/net/httpclient/FilePublisher/FilePublisherPermsTest3.policy index e55aec16ecdf..5c67101bf4fd 100644 --- a/test/jdk/java/net/httpclient/FilePublisher/FilePublisherPermsTest3.policy +++ b/test/jdk/java/net/httpclient/FilePublisher/FilePublisherPermsTest3.policy @@ -29,13 +29,13 @@ grant codeBase "jrt:/java.net.http" { }; // for JTwork/classes/0/test/lib/jdk/test/lib/net/SimpleSSLContext.class -grant codeBase "file:${test.classes}/../../../../../test/lib/-" { +grant codeBase "file:${test.classes}/test/lib/-" { permission java.util.PropertyPermission "test.src.path", "read"; permission java.io.FilePermission "${test.src}/../../../../../lib/jdk/test/lib/net/testkeys", "read"; }; // for jdk/httpclient/test/lib/* classes -grant codeBase "file:${test.classes}/../../../../../test/jdk/java/net/httpclient/lib/-" { +grant codeBase "file:${test.classes}/test/jdk/java/net/httpclient/lib/-" { permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.net.http.common"; permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.net.http.frame"; permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.net.http.hpack"; diff --git a/test/jdk/java/net/httpclient/FilePublisher/FilePublisherTest.policy b/test/jdk/java/net/httpclient/FilePublisher/FilePublisherTest.policy index 6ee4f3abdbf2..e0f1c58404a4 100644 --- a/test/jdk/java/net/httpclient/FilePublisher/FilePublisherTest.policy +++ b/test/jdk/java/net/httpclient/FilePublisher/FilePublisherTest.policy @@ -22,13 +22,13 @@ // // for JTwork/classes/0/test/lib/jdk/test/lib/net/SimpleSSLContext.class -grant codeBase "file:${test.classes}/../../../../../test/lib/-" { +grant codeBase "file:${test.classes}/test/lib/-" { permission java.util.PropertyPermission "test.src.path", "read"; permission java.io.FilePermission "${test.src}/../../../../../lib/jdk/test/lib/net/testkeys", "read"; }; // for JTwork/classes/0/java/net/httpclient/http2/server/* -grant codeBase "file:${test.classes}/../../../../../test/jdk/java/net/httpclient/lib/-" { +grant codeBase "file:${test.classes}/test/jdk/java/net/httpclient/lib/-" { permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.net.http.common"; permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.net.http.frame"; permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.net.http.hpack"; diff --git a/test/jdk/java/net/httpclient/PathSubscriber/ofFile.policy b/test/jdk/java/net/httpclient/PathSubscriber/ofFile.policy index cc6fe61814d2..efd16b52aa41 100644 --- a/test/jdk/java/net/httpclient/PathSubscriber/ofFile.policy +++ b/test/jdk/java/net/httpclient/PathSubscriber/ofFile.policy @@ -22,7 +22,7 @@ // // for test/lib library classes -grant codeBase "file:${test.classes}/../../../../../test/lib/-" { +grant codeBase "file:${test.classes}/test/lib/-" { permission java.util.PropertyPermission "java.vm.info", "read"; permission java.util.PropertyPermission "jdk.debug", "read"; permission java.util.PropertyPermission "sun.arch.data.model", "read"; @@ -39,7 +39,7 @@ grant codeBase "file:${test.classes}/../../../../../test/lib/-" { }; // for jdk/httpclient/test/lib/* classes -grant codeBase "file:${test.classes}/../../../../../test/jdk/java/net/httpclient/lib/-" { +grant codeBase "file:${test.classes}/test/jdk/java/net/httpclient/lib/-" { permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.net.http.common"; permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.net.http.frame"; permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.net.http.hpack"; diff --git a/test/jdk/java/net/httpclient/PathSubscriber/ofFileDownload.policy b/test/jdk/java/net/httpclient/PathSubscriber/ofFileDownload.policy index e211981f78e7..e4b3f1ad2fd8 100644 --- a/test/jdk/java/net/httpclient/PathSubscriber/ofFileDownload.policy +++ b/test/jdk/java/net/httpclient/PathSubscriber/ofFileDownload.policy @@ -22,7 +22,7 @@ // // for test/lib library classes -grant codeBase "file:${test.classes}/../../../../../test/lib/-" { +grant codeBase "file:${test.classes}/test/lib/-" { permission java.util.PropertyPermission "java.vm.info", "read"; permission java.util.PropertyPermission "jdk.debug", "read"; permission java.util.PropertyPermission "sun.arch.data.model", "read"; @@ -39,7 +39,7 @@ grant codeBase "file:${test.classes}/../../../../../test/lib/-" { }; // for jdk/httpclient/test/lib/* classes -grant codeBase "file:${test.classes}/../../../../../test/jdk/java/net/httpclient/lib/-" { +grant codeBase "file:${test.classes}/test/jdk/java/net/httpclient/lib/-" { permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.net.http.common"; permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.net.http.frame"; permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.net.http.hpack"; diff --git a/test/jdk/java/net/httpclient/RequestBodyTest.policy b/test/jdk/java/net/httpclient/RequestBodyTest.policy index d1ff89cbcd57..a2c68e3f4c12 100644 --- a/test/jdk/java/net/httpclient/RequestBodyTest.policy +++ b/test/jdk/java/net/httpclient/RequestBodyTest.policy @@ -22,19 +22,19 @@ // // for JTwork//classes/0/test/lib/jdk/test/lib/util/FileUtils.class -grant codeBase "file:${test.classes}/../../../../test/lib/-" { +grant codeBase "file:${test.classes}/test/lib/-" { permission java.util.PropertyPermission "*", "read"; permission java.io.FilePermission "RequestBodyTest.tmp", "read,delete"; }; // for JTwork/classes/0/test/lib/jdk/test/lib/net/SimpleSSLContext.class -grant codeBase "file:${test.classes}/../../../../test/lib/-" { +grant codeBase "file:${test.classes}/test/lib/-" { permission java.util.PropertyPermission "test.src.path", "read"; permission java.io.FilePermission "${test.src}/../../../../lib/jdk/test/lib/net/testkeys", "read"; }; // for jdk/httpclient/test/lib/* classes -grant codeBase "file:${test.classes}/../../../../test/jdk/java/net/httpclient/lib/-" { +grant codeBase "file:${test.classes}/test/jdk/java/net/httpclient/lib/-" { permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.net.http.common"; }; diff --git a/test/jdk/java/net/httpclient/dependent.policy b/test/jdk/java/net/httpclient/dependent.policy index 6cfbc1c1e3b9..1be563b08104 100644 --- a/test/jdk/java/net/httpclient/dependent.policy +++ b/test/jdk/java/net/httpclient/dependent.policy @@ -22,13 +22,13 @@ // // for JTwork/classes/0/test/lib/jdk/test/lib/net/SimpleSSLContext.class -grant codeBase "file:${test.classes}/../../../../test/lib/-" { +grant codeBase "file:${test.classes}/test/lib/-" { permission java.util.PropertyPermission "test.src.path", "read"; permission java.io.FilePermission "${test.src}/../../../../lib/jdk/test/lib/net/testkeys", "read"; }; // for jdk/httpclient/test/lib/* classes -grant codeBase "file:${test.classes}/../../../../test/jdk/java/net/httpclient/lib/-" { +grant codeBase "file:${test.classes}/test/jdk/java/net/httpclient/lib/-" { permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.net.http.common"; permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.net.http.frame"; permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.net.http.hpack"; diff --git a/test/jdk/java/net/httpclient/httpclient-localaddr-security.policy b/test/jdk/java/net/httpclient/httpclient-localaddr-security.policy index bbf83425682e..cf4bbc81c237 100644 --- a/test/jdk/java/net/httpclient/httpclient-localaddr-security.policy +++ b/test/jdk/java/net/httpclient/httpclient-localaddr-security.policy @@ -23,7 +23,7 @@ // for JTwork/classes/0/test/lib/jdk/test/lib/net/SimpleSSLContext.class and // JTwork/classes/0/test/lib/jdk/test/lib/net/IPSupport.class -grant codeBase "file:${test.classes}/../../../../test/lib/-" { +grant codeBase "file:${test.classes}/test/lib/-" { permission java.util.PropertyPermission "test.src.path", "read"; permission java.io.FilePermission "${test.src}/../../../../lib/jdk/test/lib/net/testkeys", "read"; permission java.util.PropertyPermission "java.net.preferIPv4Stack", "read"; @@ -31,7 +31,7 @@ grant codeBase "file:${test.classes}/../../../../test/lib/-" { }; // for classes in JTwork//classes/0/test/jdk/java/net/httpclient/lib/ -grant codeBase "file:${test.classes}/../../../../test/jdk/java/net/httpclient/lib/-" { +grant codeBase "file:${test.classes}/test/jdk/java/net/httpclient/lib/-" { permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.net.http.common"; permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.net.http.frame"; permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.net.http.hpack"; diff --git a/test/jdk/java/security/SignedJar/spi-calendar-provider/TestSPISigned.java b/test/jdk/java/security/SignedJar/spi-calendar-provider/TestSPISigned.java index 83c2d85f6e44..fb54d468d188 100644 --- a/test/jdk/java/security/SignedJar/spi-calendar-provider/TestSPISigned.java +++ b/test/jdk/java/security/SignedJar/spi-calendar-provider/TestSPISigned.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2022, Red Hat, Inc. + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +31,7 @@ import java.util.Locale; import java.util.List; import java.util.ArrayList; +import java.net.URI; import java.nio.file.Paths; import java.nio.file.Path; import java.nio.file.Files; @@ -54,12 +56,9 @@ */ public class TestSPISigned { - private static final String TEST_CLASSES = System.getProperty("test.classes", "."); private static final String TEST_SRC = System.getProperty("test.src", "."); private static final Path META_INF_DIR = Paths.get(TEST_SRC, "provider", "meta"); - private static final Path PROVIDER_PARENT = Paths.get(TEST_CLASSES, ".."); - private static final Path PROVIDER_DIR = PROVIDER_PARENT.resolve("provider"); private static final Path MODS_DIR = Paths.get("mods"); private static final Path UNSIGNED_JAR = MODS_DIR.resolve("unsigned-with-locale.jar"); private static final Path SIGNED_JAR = MODS_DIR.resolve("signed-with-locale.jar"); @@ -81,7 +80,9 @@ public static void main(String[] args) throws Throwable { // Set up signed jar with custom calendar data provider // // 1. Create jar with custom CalendarDataProvider - JarUtils.createJarFile(UNSIGNED_JAR, PROVIDER_DIR); + var codeSource = baz.CalendarDataProviderImpl.class.getProtectionDomain().getCodeSource(); + var providerDir = Path.of(URI.create(codeSource.getLocation().toString())); + JarUtils.createJarFile(UNSIGNED_JAR, providerDir); JarUtils.updateJarFile(UNSIGNED_JAR, META_INF_DIR); // create signer's keypair SecurityTools.keytool("-genkeypair -keyalg RSA -keystore ks " + diff --git a/test/jdk/java/security/spec/TestNamedParameterSpec.java b/test/jdk/java/security/spec/TestNamedParameterSpec.java new file mode 100644 index 000000000000..24f0760bb8f0 --- /dev/null +++ b/test/jdk/java/security/spec/TestNamedParameterSpec.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8345057 + * @summary Test the existence of constants inside the + * java.security.spec.NamedParameterSpec class. + * @run main TestNamedParameterSpec + */ +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.security.spec.NamedParameterSpec; +import java.util.Arrays; +import java.util.TreeSet; + +public class TestNamedParameterSpec { + + // names of the static fields in NamedParameterSpec class + private static String[] EXPECTED = { + "ED25519", "ED448", "X25519", "X448", + }; + + public static void main(String[] args) throws Exception { + Arrays.sort(EXPECTED); + var actual = getSortedConstNames(NamedParameterSpec.class); + // both arrays should be sorted before comparison + if (Arrays.compare(EXPECTED, actual) != 0) { + System.out.println("expected: " + Arrays.toString(EXPECTED)); + System.out.println("actual: " + Arrays.toString(actual)); + throw new RuntimeException("Name check failed"); + } + System.out.println("Test Passed"); + } + + public static String[] getSortedConstNames(Class clazz) { + TreeSet names = new TreeSet(); + for (Field field : clazz.getDeclaredFields()) { + int mods = field.getModifiers(); + if (Modifier.isPublic(mods) && Modifier.isStatic(mods) + && Modifier.isFinal(mods)){ + names.add(field.getName()); + } + } + return names.toArray(new String[0]); + } +} diff --git a/test/jdk/java/util/TimeZone/AIXTzMappingTest.java b/test/jdk/java/util/TimeZone/AIXTzMappingTest.java new file mode 100644 index 000000000000..6324bb8581a5 --- /dev/null +++ b/test/jdk/java/util/TimeZone/AIXTzMappingTest.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 8380993 + * @library /test/lib + * @summary Validates AIX timezone mapping behavior where POSIX TZ strings + * with comma-separated DST rules are truncated and mapped through tzmappings + * to the expected IANA timezone IDs. + * @requires os.family == "aix" + * @run main/othervm AIXTzMappingTest + */ + +import java.util.TimeZone; + +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; + +public class AIXTzMappingTest { + + // POSIX TZ strings that should be mapped via tzmappings + private static final String TZ_CET = "CET-1CEST,M3.5.0,M10.5.0"; + private static final String TZ_MEZ = "MEZ-1MESZ,M3.5.0,M10.5.0/3"; + + private static final String ID_PARIS = "Europe/Paris"; + private static final String ID_BERLIN = "Europe/Berlin"; + + public static void main(String[] args) throws Throwable { + if (args.length == 0) { + runWithTZ(TZ_CET, ID_PARIS); + runWithTZ(TZ_MEZ, ID_BERLIN); + } else if (args.length == 1) { + runTZTest(args[0]); + } else { + throw new RuntimeException( + "Expected 0 or 1 arguments, got " + args.length); + } + } + + private static void runWithTZ(String tz, String expectedId) + throws Throwable { + ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( + "AIXTzMappingTest", expectedId); + + pb.environment().put("TZ", tz); + + OutputAnalyzer output = ProcessTools.executeProcess(pb); + output.shouldHaveExitValue(0); + } + + /* + * On AIX, POSIX TZ strings such as: + * CET-1CEST,M3.5.0,M10.5.0 + * MEZ-1MESZ,M3.5.0,M10.5.0/3 + * are truncated at the comma and mapped through tzmappings to + * IANA timezone IDs. + * + * This test verifies that the expected IANA timezone ID is selected. + */ + private static void runTZTest(String expectedId) { + String tzStr = System.getenv("TZ"); + + if (tzStr == null) { + throw new RuntimeException( + "Got unexpected timezone information: TZ is null"); + } + + TimeZone tz = TimeZone.getDefault(); + String tzId = tz.getID(); + + if (!expectedId.equals(tzId)) { + throw new RuntimeException( + "Expected timezone ID " + expectedId + + " but got " + tzId + + " for TZ=" + tzStr); + } + + System.out.println( + "AIX timezone mapping test passed: " + + tzId + " for TZ=" + tzStr); + } +} diff --git a/test/jdk/java/util/TimeZone/CustomTzIDCheckDST.java b/test/jdk/java/util/TimeZone/CustomTzIDCheckDST.java index 5fd48efadcc3..9a332202ab3c 100644 --- a/test/jdk/java/util/TimeZone/CustomTzIDCheckDST.java +++ b/test/jdk/java/util/TimeZone/CustomTzIDCheckDST.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,10 @@ * @library /test/lib * @summary This test will ensure that daylight savings rules are followed * appropriately when setting a custom timezone ID via the TZ env variable. - * @requires os.family != "windows" + * AIX is excluded because it uses a different timezone mapping mechanism + * through the tzmappings file; see AIXTzMappingTest.java for AIX-specific + * coverage. + * @requires os.family != "windows" & os.family != "aix" * @run main/othervm CustomTzIDCheckDST */ diff --git a/test/jdk/java/util/zip/ZipFile/EndOfCenValidation.java b/test/jdk/java/util/zip/ZipFile/EndOfCenValidation.java index 51ed2c28c12c..c957aab2ed82 100644 --- a/test/jdk/java/util/zip/ZipFile/EndOfCenValidation.java +++ b/test/jdk/java/util/zip/ZipFile/EndOfCenValidation.java @@ -24,12 +24,14 @@ /* @test * @bug 8272746 * @summary Verify that ZipFile rejects files with CEN sizes exceeding the implementation limit - * @run testng/othervm EndOfCenValidation + * @run junit/othervm EndOfCenValidation */ -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import java.io.*; import java.nio.ByteBuffer; @@ -41,12 +43,13 @@ import java.nio.file.StandardOpenOption; import java.util.Arrays; import java.util.EnumSet; +import java.util.HexFormat; import java.util.zip.ZipEntry; import java.util.zip.ZipException; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; /** * This test augments {@link TestTooManyEntries}. It creates sparse ZIPs where @@ -68,7 +71,7 @@ public class EndOfCenValidation { private static final int ENDSIZ = ZipFile.ENDSIZ; // Offset of CEN size field within ENDHDR private static final int ENDOFF = ZipFile.ENDOFF; // Offset of CEN offset field within ENDHDR // Maximum allowed CEN size allowed by ZipFile - private static int MAX_CEN_SIZE = Integer.MAX_VALUE - ENDHDR - 1; + private static final int MAX_CEN_SIZE = Integer.MAX_VALUE - ENDHDR - 1; // Expected message when CEN size does not match file size private static final String INVALID_CEN_BAD_SIZE = "invalid END header (bad central directory size)"; @@ -76,6 +79,8 @@ public class EndOfCenValidation { private static final String INVALID_CEN_BAD_OFFSET = "invalid END header (bad central directory offset)"; // Expected message when CEN size is too large private static final String INVALID_CEN_SIZE_TOO_LARGE = "invalid END header (central directory size too large)"; + // Expected message when total entry count is too large + private static final String INVALID_BAD_ENTRY_COUNT = "invalid END header (total entries count too large)"; // A valid ZIP file, used as a template private byte[] zipBytes; @@ -84,7 +89,7 @@ public class EndOfCenValidation { * Create a valid ZIP file, used as a template * @throws IOException if an error occurs */ - @BeforeTest + @BeforeEach public void setup() throws IOException { zipBytes = templateZip(); } @@ -93,7 +98,7 @@ public void setup() throws IOException { * Delete big files after test, in case the file system did not support sparse files. * @throws IOException if an error occurs */ - @AfterTest + @AfterEach public void cleanup() throws IOException { Files.deleteIfExists(CEN_TOO_LARGE_ZIP); Files.deleteIfExists(INVALID_CEN_SIZE); @@ -111,11 +116,11 @@ public void shouldRejectTooLargeCenSize() throws IOException { Path zip = zipWithModifiedEndRecord(size, true, 0, CEN_TOO_LARGE_ZIP); - ZipException ex = expectThrows(ZipException.class, () -> { + ZipException ex = assertThrows(ZipException.class, () -> { new ZipFile(zip.toFile()); }); - assertEquals(ex.getMessage(), INVALID_CEN_SIZE_TOO_LARGE); + assertEquals(INVALID_CEN_SIZE_TOO_LARGE, ex.getMessage()); } /** @@ -131,11 +136,11 @@ public void shouldRejectInvalidCenSize() throws IOException { Path zip = zipWithModifiedEndRecord(size, false, 0, INVALID_CEN_SIZE); - ZipException ex = expectThrows(ZipException.class, () -> { + ZipException ex = assertThrows(ZipException.class, () -> { new ZipFile(zip.toFile()); }); - assertEquals(ex.getMessage(), INVALID_CEN_BAD_SIZE); + assertEquals(INVALID_CEN_BAD_SIZE, ex.getMessage()); } /** @@ -151,11 +156,138 @@ public void shouldRejectInvalidCenOffset() throws IOException { Path zip = zipWithModifiedEndRecord(size, true, 100, BAD_CEN_OFFSET_ZIP); - ZipException ex = expectThrows(ZipException.class, () -> { + ZipException ex = assertThrows(ZipException.class, () -> { new ZipFile(zip.toFile()); }); - assertEquals(ex.getMessage(), INVALID_CEN_BAD_OFFSET); + assertEquals(INVALID_CEN_BAD_OFFSET, ex.getMessage()); + } + + /** + * Validate that a 'Zip64 End of Central Directory' record (the END header) + * where the value of the 'total entries' field is larger than what fits + * in the CEN size is rejected. + * + * @throws IOException if an error occurs + */ + @ParameterizedTest + @ValueSource(longs = { + -1, // Negative + Long.MIN_VALUE, // Very negative + 0x3B / 3L - 1, // Cannot fit in test ZIP's CEN + MAX_CEN_SIZE / 3 + 1, // Too large to allocate int[] entries array + Long.MAX_VALUE // Unreasonably large + }) + public void shouldRejectBadTotalEntries(long totalEntries) throws IOException { + /** + * A small ZIP using the ZIP64 format. + * + * ZIP created using: "echo -n hello | zip zip64.zip -" + * Hex encoded using: "cat zip64.zip | xxd -ps" + * + * The file has the following structure: + * + * 0000 LOCAL HEADER #1 04034B50 + * 0004 Extract Zip Spec 2D '4.5' + * 0005 Extract OS 00 'MS-DOS' + * 0006 General Purpose Flag 0000 + * 0008 Compression Method 0000 'Stored' + * 000A Last Mod Time 5947AB78 'Mon Oct 7 21:27:48 2024' + * 000E CRC 363A3020 + * 0012 Compressed Length FFFFFFFF + * 0016 Uncompressed Length FFFFFFFF + * 001A Filename Length 0001 + * 001C Extra Length 0014 + * 001E Filename '-' + * 001F Extra ID #0001 0001 'ZIP64' + * 0021 Length 0010 + * 0023 Uncompressed Size 0000000000000006 + * 002B Compressed Size 0000000000000006 + * 0033 PAYLOAD hello. + * + * 0039 CENTRAL HEADER #1 02014B50 + * 003D Created Zip Spec 1E '3.0' + * 003E Created OS 03 'Unix' + * 003F Extract Zip Spec 2D '4.5' + * 0040 Extract OS 00 'MS-DOS' + * 0041 General Purpose Flag 0000 + * 0043 Compression Method 0000 'Stored' + * 0045 Last Mod Time 5947AB78 'Mon Oct 7 21:27:48 2024' + * 0049 CRC 363A3020 + * 004D Compressed Length 00000006 + * 0051 Uncompressed Length FFFFFFFF + * 0055 Filename Length 0001 + * 0057 Extra Length 000C + * 0059 Comment Length 0000 + * 005B Disk Start 0000 + * 005D Int File Attributes 0001 + * [Bit 0] 1 Text Data + * 005F Ext File Attributes 11B00000 + * 0063 Local Header Offset 00000000 + * 0067 Filename '-' + * 0068 Extra ID #0001 0001 'ZIP64' + * 006A Length 0008 + * 006C Uncompressed Size 0000000000000006 + * + * 0074 ZIP64 END CENTRAL DIR 06064B50 + * RECORD + * 0078 Size of record 000000000000002C + * 0080 Created Zip Spec 1E '3.0' + * 0081 Created OS 03 'Unix' + * 0082 Extract Zip Spec 2D '4.5' + * 0083 Extract OS 00 'MS-DOS' + * 0084 Number of this disk 00000000 + * 0088 Central Dir Disk no 00000000 + * 008C Entries in this disk 0000000000000001 + * 0094 Total Entries 0000000000000001 + * 009C Size of Central Dir 000000000000003B + * 00A4 Offset to Central dir 0000000000000039 + * + * 00AC ZIP64 END CENTRAL DIR 07064B50 + * LOCATOR + * 00B0 Central Dir Disk no 00000000 + * 00B4 Offset to Central dir 0000000000000074 + * 00BC Total no of Disks 00000001 + * + * 00C0 END CENTRAL HEADER 06054B50 + * 00C4 Number of this disk 0000 + * 00C6 Central Dir Disk no 0000 + * 00C8 Entries in this disk 0001 + * 00CA Total Entries 0001 + * 00CC Size of Central Dir 0000003B + * 00D0 Offset to Central Dir FFFFFFFF + * 00D4 Comment Length 0000 + */ + + byte[] zipBytes = HexFormat.of().parseHex(""" + 504b03042d000000000078ab475920303a36ffffffffffffffff01001400 + 2d010010000600000000000000060000000000000068656c6c6f0a504b01 + 021e032d000000000078ab475920303a3606000000ffffffff01000c0000 + 00000001000000b011000000002d010008000600000000000000504b0606 + 2c000000000000001e032d00000000000000000001000000000000000100 + 0000000000003b000000000000003900000000000000504b060700000000 + 740000000000000001000000504b050600000000010001003b000000ffff + ffff0000 + """.replaceAll("\n","")); + + // Buffer to manipulate the above ZIP + ByteBuffer buf = ByteBuffer.wrap(zipBytes).order(ByteOrder.LITTLE_ENDIAN); + // Offset of the 'total entries' in the 'ZIP64 END CENTRAL DIR' record + // Update ZIP64 entry count to a value which cannot possibly fit in the small CEN + buf.putLong(0x94, totalEntries); + // The corresponding END field needs the ZIP64 magic value + buf.putShort(0xCA, (short) 0xFFFF); + // Write the ZIP to disk + Path zipFile = Path.of("bad-entry-count.zip"); + Files.write(zipFile, zipBytes); + + // Verify that the END header is rejected + ZipException ex = assertThrows(ZipException.class, () -> { + try (var zf = new ZipFile(zipFile.toFile())) { + } + }); + + assertEquals(INVALID_BAD_ENTRY_COUNT, ex.getMessage()); } /** diff --git a/test/jdk/javax/swing/SwingWorker/TestDoneBeforeDoInBackground.java b/test/jdk/javax/swing/SwingWorker/TestDoneBeforeDoInBackground.java index 56534928f6ec..119d9efaab9e 100644 --- a/test/jdk/javax/swing/SwingWorker/TestDoneBeforeDoInBackground.java +++ b/test/jdk/javax/swing/SwingWorker/TestDoneBeforeDoInBackground.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ /* * @test * @bug 8081474 + * @library /test/lib * @summary Verifies if SwingWorker calls 'done' * before the 'doInBackground' is finished * @run main TestDoneBeforeDoInBackground @@ -34,22 +35,25 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import jdk.test.lib.Utils; + public class TestDoneBeforeDoInBackground { - private static final int WAIT_TIME = 200; + private static final long WAIT_TIME = Utils.adjustTimeout(200); private static final long CLEANUP_TIME = 1000; private static final AtomicBoolean doInBackgroundStarted = new AtomicBoolean(false); private static final AtomicBoolean doInBackgroundFinished = new AtomicBoolean(false); private static final AtomicBoolean doneFinished = new AtomicBoolean(false); private static final CountDownLatch doneLatch = new CountDownLatch(1); + private static final CountDownLatch workerStarted = new CountDownLatch(1); public static void main(String[] args) throws InterruptedException { SwingWorker worker = new SwingWorker<>() { @Override protected String doInBackground() throws Exception { try { - while (!Thread.currentThread().isInterrupted()) { + while (true) { System.out.println("Working..."); Thread.sleep(WAIT_TIME); } @@ -85,6 +89,12 @@ protected void done() { worker.addPropertyChangeListener( new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { + if (worker.getState() == SwingWorker.StateValue.STARTED) { + // Now the worker has started and we got a STARTED + // notification. It should be save to cancel now. + workerStarted.countDown(); + } + System.out.println("doInBackgroundStarted: " + doInBackgroundStarted.get() + " doInBackgroundFinished: " + @@ -121,7 +131,9 @@ public void propertyChange(PropertyChangeEvent evt) { } }); worker.execute(); - Thread.sleep(WAIT_TIME * 3); + if (!workerStarted.await(5 * WAIT_TIME, TimeUnit.MILLISECONDS)) { + throw new RuntimeException("worker didn't start in time"); + } final long start = System.currentTimeMillis(); worker.cancel(true); diff --git a/test/jdk/jdk/internal/platform/docker/TestDockerBasic.java b/test/jdk/jdk/internal/platform/docker/TestDockerBasic.java index 9a531d692ed4..bfc628a25fc8 100644 --- a/test/jdk/jdk/internal/platform/docker/TestDockerBasic.java +++ b/test/jdk/jdk/internal/platform/docker/TestDockerBasic.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2022, Red Hat, Inc. - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ * @requires container.support * @requires !vm.asan * @library /test/lib + * @modules java.base/jdk.internal.platform * @run main/timeout=360 TestDockerBasic */ @@ -42,10 +43,8 @@ public class TestDockerBasic { private static final String imageName = Common.imageName("javaDockerBasic"); public static void main(String[] args) throws Exception { - if (!DockerTestUtils.canTestDocker()) { - return; - } - + DockerTestUtils.checkCanTestDocker(); + DockerTestUtils.checkCanUseResourceLimits(); DockerTestUtils.buildJdkContainerImage(imageName); try { diff --git a/test/jdk/jdk/internal/platform/docker/TestDockerCpuMetrics.java b/test/jdk/jdk/internal/platform/docker/TestDockerCpuMetrics.java index ff039913b8fc..042996a353bf 100644 --- a/test/jdk/jdk/internal/platform/docker/TestDockerCpuMetrics.java +++ b/test/jdk/jdk/internal/platform/docker/TestDockerCpuMetrics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,9 +46,8 @@ public class TestDockerCpuMetrics { private static final String imageName = Common.imageName("metrics-cpu"); public static void main(String[] args) throws Exception { - if (!DockerTestUtils.canTestDocker()) { - return; - } + DockerTestUtils.checkCanTestDocker(); + DockerTestUtils.checkCanUseResourceLimits(); // These tests create a docker image and run this image with // varying docker cpu options. The arguments passed to the docker diff --git a/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java b/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java index 8d63e76c141e..12f90d655169 100644 --- a/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java +++ b/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java @@ -45,9 +45,8 @@ public class TestDockerMemoryMetrics { private static final String imageName = Common.imageName("metrics-memory"); public static void main(String[] args) throws Exception { - if (!DockerTestUtils.canTestDocker()) { - return; - } + DockerTestUtils.checkCanTestDocker(); + DockerTestUtils.checkCanUseResourceLimits(); // These tests create a docker image and run this image with // varying docker memory options. The arguments passed to the docker diff --git a/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetricsSubgroup.java b/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetricsSubgroup.java index 82e69da79479..fcca9066fde3 100644 --- a/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetricsSubgroup.java +++ b/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetricsSubgroup.java @@ -57,10 +57,7 @@ public static void main(String[] args) throws Exception { System.out.println("Cgroup not configured."); return; } - if (!DockerTestUtils.canTestDocker()) { - System.out.println("Unable to run docker tests."); - return; - } + DockerTestUtils.checkCanTestDocker(); ContainerRuntimeVersionTestUtils.checkContainerVersionSupported(); diff --git a/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java b/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java index 5a89c04796aa..6ab6a78281e4 100644 --- a/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java +++ b/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java @@ -29,9 +29,11 @@ * @requires container.support * @requires !vm.asan * @library /test/lib + * @modules java.base/jdk.internal.platform * @build GetFreeSwapSpaceSize * @run driver TestGetFreeSwapSpaceSize */ + import jdk.test.lib.containers.docker.Common; import jdk.test.lib.containers.docker.DockerRunOptions; import jdk.test.lib.containers.docker.DockerTestUtils; @@ -41,10 +43,8 @@ public class TestGetFreeSwapSpaceSize { private static final String imageName = Common.imageName("osbeanSwapSpace"); public static void main(String[] args) throws Exception { - if (!DockerTestUtils.canTestDocker()) { - return; - } - + DockerTestUtils.checkCanTestDocker(); + DockerTestUtils.checkCanUseResourceLimits(); DockerTestUtils.buildJdkContainerImage(imageName); try { diff --git a/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java b/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java index ee9e7f41ab0e..a34245002d68 100644 --- a/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java +++ b/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2023, Red Hat, Inc. - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved. * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -48,17 +48,19 @@ import jdk.test.lib.containers.docker.DockerRunOptions; import jdk.test.lib.containers.docker.DockerTestUtils; import jdk.test.lib.process.OutputAnalyzer; +import jtreg.SkippedException; public class TestLimitsUpdating { private static final long M = 1024 * 1024; + private static final int CPU_PERIOD = 100_000; + private static final int INITIAL_CPU_COUNT = 1; + private static final int UPDATED_CPU_COUNT = 2; private static final String TARGET_CONTAINER = "limitsUpdatingJDK_" + Runtime.getRuntime().version().major(); private static final String imageName = Common.imageName("limitsUpdatingJDK"); public static void main(String[] args) throws Exception { - if (!DockerTestUtils.canTestDocker()) { - return; - } - + DockerTestUtils.checkCanTestDocker(); + DockerTestUtils.checkCanUseResourceLimits(); DockerTestUtils.buildJdkContainerImage(imageName); try { @@ -69,6 +71,10 @@ public static void main(String[] args) throws Exception { } private static void testLimitUpdates() throws Exception { + if (Runtime.getRuntime().availableProcessors() < UPDATED_CPU_COUNT) { + throw new SkippedException("Need at least " + UPDATED_CPU_COUNT + + " available CPUs to test CPU limit updates"); + } File sharedtmpdir = new File("jdk-sharedtmp"); File flag = new File(sharedtmpdir, "limitsUpdated"); // shared with LimitUpdateChecker File started = new File(sharedtmpdir, "started"); // shared with LimitUpdateChecker @@ -78,8 +84,8 @@ private static void testLimitUpdates() throws Exception { DockerRunOptions opts = new DockerRunOptions(imageName, "/jdk/bin/java", "LimitUpdateChecker"); opts.addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/"); opts.addDockerOpts("--volume", sharedtmpdir.getAbsolutePath() + ":/tmp"); - opts.addDockerOpts("--cpu-period", "100000"); - opts.addDockerOpts("--cpu-quota", "200000"); + opts.addDockerOpts("--cpu-period", Integer.toString(CPU_PERIOD)); + opts.addDockerOpts("--cpu-quota", Integer.toString(INITIAL_CPU_COUNT * CPU_PERIOD)); opts.addDockerOpts("--memory", "500m"); opts.addDockerOpts("--memory-swap", "500m"); opts.addDockerOpts("--name", TARGET_CONTAINER); @@ -108,7 +114,7 @@ public void run() { Thread.sleep(100); } - final List containerCommand = getContainerUpdate(300_000, 100_000, "300m"); + final List containerCommand = getContainerUpdate(UPDATED_CPU_COUNT * CPU_PERIOD, CPU_PERIOD, "300m"); // Run the update command so as to increase resources once the container signaled it has started. Thread t2 = new Thread() { public void run() { @@ -131,10 +137,10 @@ public void run() { // Do assertions based on the output in target container OutputAnalyzer targetOut = out[0]; - targetOut.shouldContain("Runtime.availableProcessors: 2"); // initial value - targetOut.shouldContain("OperatingSystemMXBean.getAvailableProcessors: 2"); // initial value - targetOut.shouldContain("Runtime.availableProcessors: 3"); // updated value - targetOut.shouldContain("OperatingSystemMXBean.getAvailableProcessors: 3"); // updated value + targetOut.shouldContain("Runtime.availableProcessors: 1"); // initial value + targetOut.shouldContain("OperatingSystemMXBean.getAvailableProcessors: 1"); // initial value + targetOut.shouldContain("Runtime.availableProcessors: 2"); // updated value + targetOut.shouldContain("OperatingSystemMXBean.getAvailableProcessors: 2"); // updated value long memoryInBytes = 500 * M; targetOut.shouldContain("Metrics.getMemoryLimit() == " + memoryInBytes); // initial value targetOut.shouldContain("OperatingSystemMXBean.getTotalMemorySize: " + memoryInBytes); // initial value diff --git a/test/jdk/jdk/internal/platform/docker/TestPidsLimit.java b/test/jdk/jdk/internal/platform/docker/TestPidsLimit.java index 04c172b13b8f..683eb28a069d 100644 --- a/test/jdk/jdk/internal/platform/docker/TestPidsLimit.java +++ b/test/jdk/jdk/internal/platform/docker/TestPidsLimit.java @@ -30,6 +30,7 @@ * @requires container.support * @requires !vm.asan * @library /test/lib + * @modules java.base/jdk.internal.platform * @build TestPidsLimit * @run driver TestPidsLimit */ @@ -49,10 +50,8 @@ public class TestPidsLimit { private static final int UNLIMITED_PIDS_DOCKER = -1; public static void main(String[] args) throws Exception { - if (!DockerTestUtils.canTestDocker()) { - return; - } - + DockerTestUtils.checkCanTestDocker(); + DockerTestUtils.checkCanUseResourceLimits(); DockerTestUtils.buildJdkContainerImage(imageName); try { diff --git a/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java b/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java index 49ec56634787..e6e78bd5cd8d 100644 --- a/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java +++ b/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java @@ -42,10 +42,7 @@ public class TestSystemMetrics { private static final String imageName = Common.imageName("metrics"); public static void main(String[] args) throws Exception { - if (!DockerTestUtils.canTestDocker()) { - return; - } - + DockerTestUtils.checkCanTestDocker(); DockerTestUtils.buildJdkContainerImage(imageName); try { diff --git a/test/jdk/jdk/internal/platform/docker/TestUseContainerSupport.java b/test/jdk/jdk/internal/platform/docker/TestUseContainerSupport.java index d8d300401a0c..e77783f395bc 100644 --- a/test/jdk/jdk/internal/platform/docker/TestUseContainerSupport.java +++ b/test/jdk/jdk/internal/platform/docker/TestUseContainerSupport.java @@ -42,10 +42,7 @@ public class TestUseContainerSupport { private static final String imageName = Common.imageName("useContainerSupport"); public static void main(String[] args) throws Exception { - if (!DockerTestUtils.canTestDocker()) { - return; - } - + DockerTestUtils.checkCanTestDocker(); DockerTestUtils.buildJdkContainerImage(imageName); try { diff --git a/test/jdk/jdk/jfr/event/gc/collection/TestGarbageCollectionEventWithZMinor.java b/test/jdk/jdk/jfr/event/gc/collection/TestGarbageCollectionEventWithZMinor.java index e7e94cf9ff04..74e994a75b96 100644 --- a/test/jdk/jdk/jfr/event/gc/collection/TestGarbageCollectionEventWithZMinor.java +++ b/test/jdk/jdk/jfr/event/gc/collection/TestGarbageCollectionEventWithZMinor.java @@ -41,7 +41,6 @@ * @test * @key jfr * @requires vm.hasJFR & vm.gc.ZGenerational - * @key jfr * @library /test/lib /test/jdk * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox diff --git a/test/jdk/jdk/jfr/event/os/TestCPULoad.java b/test/jdk/jdk/jfr/event/os/TestCPULoad.java index 1edb16396995..63d41e995b97 100644 --- a/test/jdk/jdk/jfr/event/os/TestCPULoad.java +++ b/test/jdk/jdk/jfr/event/os/TestCPULoad.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,10 +23,12 @@ package jdk.jfr.event.os; -import java.util.List; +import java.time.Duration; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; -import jdk.jfr.Recording; import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.consumer.RecordingStream; import jdk.test.lib.jfr.EventNames; import jdk.test.lib.jfr.Events; @@ -40,56 +42,18 @@ public class TestCPULoad { private final static String EVENT_NAME = EventNames.CPULoad; - public static boolean isPrime(int num) { - if (num <= 1) return false; - for (int i = 2; i <= Math.sqrt(num); i++) { - if (num % i == 0) return false; + public static void main(String... args) throws Exception { + try (RecordingStream rs = new RecordingStream()) { + BlockingQueue cpuEvent = new ArrayBlockingQueue<>(1); + rs.setReuse(false); + rs.enable(EVENT_NAME).withPeriod(Duration.ofMillis(100)); + rs.onEvent(cpuEvent::offer); + rs.startAsync(); + RecordedEvent event = cpuEvent.take(); + System.out.println(event); + Events.assertField(event, "jvmUser").atLeast(0.0f).atMost(1.0f); + Events.assertField(event, "jvmSystem").atLeast(0.0f).atMost(1.0f); + Events.assertField(event, "machineTotal").atLeast(0.0f).atMost(1.0f); } - return true; } - - public static int burnCpuCycles(int limit) { - int primeCount = 0; - for (int i = 2; i < limit; i++) { - if (isPrime(i)) { - primeCount++; - } - } - return primeCount; - } - - public static void main(String[] args) throws Throwable { - Recording recording = new Recording(); - recording.enable(EVENT_NAME); - recording.start(); - // burn some cycles to check increase of CPU related counters - int pn = burnCpuCycles(2500000); - recording.stop(); - System.out.println("Found " + pn + " primes while burning cycles"); - - List events = Events.fromRecording(recording); - if (events.isEmpty()) { - // CPU Load events are unreliable on Windows because - // the way processes are identified with perf. counters. - // See BUG 8010378. - // Workaround is to detect Windows and allow - // test to pass if events are missing. - if (isWindows()) { - return; - } - throw new AssertionError("Expected at least one event"); - } - for (RecordedEvent event : events) { - System.out.println("Event: " + event); - for (String loadName : loadNames) { - Events.assertField(event, loadName).atLeast(0.0f).atMost(1.0f); - } - } - } - - private static final String[] loadNames = {"jvmUser", "jvmSystem", "machineTotal"}; - - private static boolean isWindows() { - return System.getProperty("os.name").startsWith("Windows"); - } -} +} \ No newline at end of file diff --git a/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java b/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java index e2581683aed9..7247bb39f19c 100644 --- a/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java +++ b/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java @@ -290,9 +290,8 @@ * @summary Interoperability tests with Microsoft TLS root CAs * @library /test/lib * @build jtreg.SkippedException ValidatePathWithURL CAInterop - * @run main/othervm/manual -Djava.security.debug=certpath,ocsp CAInterop microsoftrsa2017 OCSP - * @run main/othervm/manual -Djava.security.debug=certpath,ocsp -Dcom.sun.security.ocsp.useget=false CAInterop microsoftrsa2017 OCSP - * @run main/othervm/manual -Djava.security.debug=certpath CAInterop microsoftrsa2017 CRL + * @run main/othervm/manual -Djava.security.debug=certpath,ocsp CAInterop microsoftrsa2017 DEFAULT + * @run main/othervm/manual -Djava.security.debug=certpath,ocsp -Dcom.sun.security.ocsp.useget=false CAInterop microsoftrsa2017 DEFAULT */ /* @@ -607,8 +606,8 @@ private CATestURLs getTestURLs(String alias) { new CATestURLs("https://valid.business.ca22.ssl.buypass.no", "https://revoked.business.ca22.ssl.buypass.no"); case "buypassclass3ca" -> - new CATestURLs("https://valid.qcevident.ca23.ssl.buypass.no", - "https://revoked.qcevident.ca23.ssl.buypass.no"); + new CATestURLs("https://valid.evident.ca23.ssl.buypass.no", + "https://revoked.evident.ca23.ssl.buypass.no"); case "comodorsaca" -> new CATestURLs("https://comodorsacertificationauthority-ev.comodoca.com", diff --git a/test/jdk/sun/security/ec/ed/TestEdOps.java b/test/jdk/sun/security/ec/ed/TestEdOps.java index 79502be45e0c..3dab620d3814 100644 --- a/test/jdk/sun/security/ec/ed/TestEdOps.java +++ b/test/jdk/sun/security/ec/ed/TestEdOps.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ import java.util.Arrays; import java.util.HexFormat; -import sun.security.provider.SHAKE256; +import sun.security.provider.SHA3.SHAKE256; public class TestEdOps { diff --git a/test/jdk/sun/security/provider/MessageDigest/SHAKEsqueeze.java b/test/jdk/sun/security/provider/MessageDigest/SHAKEsqueeze.java new file mode 100644 index 000000000000..5cdcce00e357 --- /dev/null +++ b/test/jdk/sun/security/provider/MessageDigest/SHAKEsqueeze.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8338587 + * @summary Ensure squeeze and digest always have the same output + * @library /test/lib + * @modules java.base/sun.security.provider + */ + +import jdk.test.lib.Asserts; +import jdk.test.lib.security.SeededSecureRandom; +import sun.security.provider.SHA3; + +import java.io.ByteArrayOutputStream; +import java.util.Arrays; + +public class SHAKEsqueeze { + public static void main(String[] args) throws Exception { + var r = SeededSecureRandom.one(); + var atlast = 0; + // Random test on SHAKE + for (var i = 0; i < 1_000_000; i++) { + var s = new SHA3.SHAKE256(0); + var in = new ByteArrayOutputStream(); + while (r.nextBoolean()) { + var b = r.nBytes(r.nextInt(200)); + if (b.length > 0 && r.nextBoolean()) { + // Test update(b) + s.update(b[0]); + in.write(b[0]); + } else if (r.nextBoolean()) { + // Test update(byte[]) + s.update(b); + in.write(b); + } else { + // Test update(byte[], offset, len) + var prepend = r.nextInt(100); + var append = r.nextInt(100); + var bb = new byte[prepend + b.length + append]; + r.nextBytes(bb); + System.arraycopy(b, 0, bb, prepend, b.length); + s.update(bb, prepend, b.length); + in.write(b); + } + } + + // Squeeze for multiple times + var out = new ByteArrayOutputStream(); + do { + var n = r.nextInt(200); + out.write(s.squeeze(n)); + } while (out.size() == 0 || r.nextBoolean()); + var b1 = out.toByteArray(); + + // Digest for one time + var s2 = new SHA3.SHAKE256(b1.length); + s2.update(in.toByteArray()); + var b2 = s2.digest(); + + atlast = Arrays.hashCode(b2) * 17 + atlast; + Asserts.assertEqualsByteArray(b1, b2); + } + // Just to provide a visual clue to show that the same + // SeededSecureRandom seed results in same final result + // so that the test can be exactly reproduced. + System.out.println("Final hash: " + atlast); + } +} diff --git a/test/jdk/sun/security/provider/NamedEdDSA.java b/test/jdk/sun/security/provider/NamedEdDSA.java new file mode 100644 index 000000000000..2a59c2d68f93 --- /dev/null +++ b/test/jdk/sun/security/provider/NamedEdDSA.java @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8340327 + * @modules jdk.crypto.ec/sun.security.ec.ed + * jdk.crypto.ec/sun.security.ec.point + * java.base/sun.security.jca + * java.base/sun.security.provider + * @library /test/lib + */ + +import jdk.test.lib.Asserts; +import jdk.test.lib.Utils; +import sun.security.ec.ed.EdDSAOperations; +import sun.security.ec.ed.EdDSAParameters; +import sun.security.ec.point.AffinePoint; +import sun.security.jca.JCAUtil; +import sun.security.provider.NamedKeyFactory; +import sun.security.provider.NamedKeyPairGenerator; +import sun.security.provider.NamedSignature; + +import java.security.*; +import java.security.spec.EdDSAParameterSpec; +import java.security.spec.NamedParameterSpec; +import java.util.Arrays; +import java.util.List; + +public class NamedEdDSA { + + public static class ProviderImpl extends Provider { + public ProviderImpl() { + super("Named", "0", ""); + put("KeyPairGenerator.EdDSA", EdDSAKeyPairGenerator.class.getName()); + put("KeyPairGenerator.Ed25519", EdDSAKeyPairGenerator.Ed25519.class.getName()); + put("KeyPairGenerator.Ed448", EdDSAKeyPairGenerator.Ed448.class.getName()); + put("KeyFactory.EdDSA", EdDSAKeyFactory.class.getName()); + put("KeyFactory.Ed25519", EdDSAKeyFactory.Ed25519.class.getName()); + put("KeyFactory.Ed448", EdDSAKeyFactory.Ed448.class.getName()); + put("Signature.EdDSA", EdDSASignature.class.getName()); + put("Signature.Ed25519", EdDSASignature.Ed25519.class.getName()); + put("Signature.Ed448", EdDSASignature.Ed448.class.getName()); + } + } + + public static class EdDSASignature extends NamedSignature { + public EdDSASignature() { + super("EdDSA", "Ed25519", "Ed448"); + } + + protected EdDSASignature(String pname) { + super("EdDSA", pname); + } + + public static class Ed25519 extends EdDSASignature { + public Ed25519() { + super("Ed25519"); + } + } + + public static class Ed448 extends EdDSASignature { + public Ed448() { + super("Ed448"); + } + } + + @Override + public byte[] implSign(String name, byte[] sk, Object sk2, byte[] msg, SecureRandom sr) throws SignatureException { + return getOps(name).sign(plain, sk, msg); + } + + @Override + public boolean implVerify(String name, byte[] pk, Object pk2, byte[] msg, byte[] sig) throws SignatureException { + return getOps(name).verify(plain, (AffinePoint) pk2, pk, msg, sig); + } + + @Override + public Object implCheckPublicKey(String name, byte[] pk) throws InvalidKeyException { + return getOps(name).decodeAffinePoint(InvalidKeyException::new, pk); + } + } + + public static class EdDSAKeyFactory extends NamedKeyFactory { + public EdDSAKeyFactory() { + super("EdDSA", "Ed25519", "Ed448"); + } + + protected EdDSAKeyFactory(String pname) { + super("EdDSA", pname); + } + + public static class Ed25519 extends EdDSAKeyFactory { + public Ed25519() { + super("Ed25519"); + } + } + + public static class Ed448 extends EdDSAKeyFactory { + public Ed448() { + super("Ed448"); + } + } + } + + public static class EdDSAKeyPairGenerator extends NamedKeyPairGenerator { + public EdDSAKeyPairGenerator() { + super("EdDSA", "Ed25519", "Ed448"); + } + + protected EdDSAKeyPairGenerator(String pname) { + super("EdDSA", pname); + } + + public static class Ed25519 extends EdDSAKeyPairGenerator { + public Ed25519() { + super("Ed25519"); + } + } + + public static class Ed448 extends EdDSAKeyPairGenerator { + public Ed448() { + super("Ed448"); + } + } + + @Override + public byte[][] implGenerateKeyPair(String pname, SecureRandom sr) { + sr = sr == null ? JCAUtil.getDefSecureRandom() : sr; + var op = getOps(pname); + var sk = op.generatePrivate(sr); + var point = op.computePublic(sk); + byte[] encodedPoint = point.getY().toByteArray(); + reverse(encodedPoint); + // array may be too large or too small, depending on the value + encodedPoint = Arrays.copyOf(encodedPoint, op.getParameters().getKeyLength()); + // set the high-order bit of the encoded point + byte msb = (byte) (point.isXOdd() ? 0x80 : 0); + encodedPoint[encodedPoint.length - 1] |= msb; + return new byte[][] { encodedPoint, sk }; + } + + private static void swap(byte[] arr, int i, int j) { + byte tmp = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp; + } + + private static void reverse(byte [] arr) { + int i = 0; + int j = arr.length - 1; + + while (i < j) { + swap(arr, i, j); + i++; + j--; + } + } + } + + private static EdDSAOperations getOps(String pname) { + var op = switch (pname) { + case "Ed25519" -> e2; + case "Ed448" -> e4; + default -> throw new AssertionError("unknown pname " + pname); + }; + return op; + } + + static final EdDSAParameterSpec plain = new EdDSAParameterSpec(false); + static final EdDSAOperations e2, e4; + static { + try { + e2 = new EdDSAOperations(EdDSAParameters.getBySize(AssertionError::new, 255)); + e4 = new EdDSAOperations(EdDSAParameters.getBySize(AssertionError::new, 448)); + } catch (Exception e) { + throw new AssertionError(e); + } + } + + public static void main(String[] args) throws Exception { + var ps = List.of(new ProviderImpl(), Security.getProvider("SunEC")); + for (var p1 : ps) { + for (var p2 : ps) { + for (var p3 : ps) { + test(p1, p2, p3); + } + } + } + } + + static void test(Provider p1, Provider p2, Provider p3) throws Exception { + System.out.println(p1.getName() + " " + p2.getName() + " " + p3.getName()); + var g = KeyPairGenerator.getInstance("EdDSA", p1); + g.initialize(NamedParameterSpec.ED448); + var kp = g.generateKeyPair(); + var s1 = Signature.getInstance("EdDSA", p2); + var s2 = Signature.getInstance("EdDSA", p3); + var f1 = KeyFactory.getInstance("EdDSA", p2); + var f2 = KeyFactory.getInstance("EdDSA", p3); + var sk = (PrivateKey) f1.translateKey(kp.getPrivate()); + var pk = (PublicKey) f2.translateKey(kp.getPublic()); + // sign and verify twice to make sure the key is intact + s1.initSign(sk); + var sig1 = s1.sign(); + s1.initSign(sk); + var sig2 = s1.sign(); + // EdDSA signing is deterministic + Asserts.assertEqualsByteArray(sig1, sig2); + s2.initVerify(pk); + Asserts.assertTrue(s2.verify(sig1)); + s2.initVerify(pk); + Asserts.assertTrue(s2.verify(sig2)); + // No parameters defined + s1.setParameter(null); + Utils.runAndCheckException(() -> s1.setParameter(NamedParameterSpec.ED448), + InvalidAlgorithmParameterException.class); + } +} diff --git a/test/jdk/sun/security/provider/NamedKeyFactoryTest.java b/test/jdk/sun/security/provider/NamedKeyFactoryTest.java new file mode 100644 index 000000000000..6192493e560f --- /dev/null +++ b/test/jdk/sun/security/provider/NamedKeyFactoryTest.java @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test id=plainTest + * @bug 8340327 + * @modules java.base/sun.security.x509 + * java.base/sun.security.pkcs + * java.base/sun.security.provider + * java.base/sun.security.util + * @library /test/lib + */ + +/* + * @test id=securityManager + * @bug 8340327 + * @modules java.base/sun.security.x509 + * java.base/sun.security.pkcs + * java.base/sun.security.provider + * java.base/sun.security.util + * @library /test/lib + * @run main/othervm/policy=namedKeyFactoryTest.policy NamedKeyFactoryTest + */ + +import jdk.test.lib.Asserts; +import jdk.test.lib.Utils; +import jdk.test.lib.security.SeededSecureRandom; +import sun.security.pkcs.NamedPKCS8Key; +import sun.security.provider.NamedKeyFactory; +import sun.security.provider.NamedKeyPairGenerator; +import sun.security.util.KeyUtil; +import sun.security.util.RawKeySpec; +import sun.security.x509.NamedX509Key; + +import java.security.*; +import java.security.spec.*; + +public class NamedKeyFactoryTest { + + private static final SeededSecureRandom RAND = SeededSecureRandom.one(); + + public static void main(String[] args) throws Exception { + Security.addProvider(new ProviderImpl()); + + var g = KeyPairGenerator.getInstance("sHA"); + var g2 = KeyPairGenerator.getInstance("ShA-256"); + var g5 = KeyPairGenerator.getInstance("SHa-512"); + var kf = KeyFactory.getInstance("ShA"); + var kf2 = KeyFactory.getInstance("Sha-256"); + var kf5 = KeyFactory.getInstance("Sha-512"); + + checkKeyPair(g.generateKeyPair(), "SHA", "SHA-256"); + checkKeyPair(g2.generateKeyPair(), "SHA", "SHA-256"); + checkKeyPair(g5.generateKeyPair(), "SHA", "SHA-512"); + + checkKeyPair(g.generateKeyPair(), "SHA", "SHA-256"); + checkKeyPair(g2.generateKeyPair(), "SHA", "SHA-256"); + checkKeyPair(g5.generateKeyPair(), "SHA", "SHA-512"); + + Utils.runAndCheckException(() -> g.initialize(NamedParameterSpec.ED448), + InvalidAlgorithmParameterException.class); // wrong pname + Utils.runAndCheckException(() -> g.initialize(new NamedParameterSpec("SHA-384")), + InvalidAlgorithmParameterException.class); // wrong pname + + Utils.runAndCheckException(() -> g5.initialize(new NamedParameterSpec("SHA-256")), + InvalidAlgorithmParameterException.class); // diff pname + g5.initialize(new NamedParameterSpec("SHA-512")); + + g.initialize(new NamedParameterSpec("sHA-512")); + checkKeyPair(g.generateKeyPair(), "SHA", "SHA-512"); + g.initialize(new NamedParameterSpec("ShA-256")); + checkKeyPair(g.generateKeyPair(), "SHA", "SHA-256"); + + var pk = new NamedX509Key("sHa", "ShA-256", RAND.nBytes(2)); + var sk = new NamedPKCS8Key("sHa", "SHa-256", RAND.nBytes(2)); + checkKey(pk, "sHa", "ShA-256"); + checkKey(sk, "sHa", "SHa-256"); + + Asserts.assertEquals("X.509", pk.getFormat()); + Asserts.assertEquals("PKCS#8", sk.getFormat()); + + var pkSpec = kf.getKeySpec(pk, X509EncodedKeySpec.class); + var skSpec = kf.getKeySpec(sk, PKCS8EncodedKeySpec.class); + + kf2.getKeySpec(pk, X509EncodedKeySpec.class); + kf2.getKeySpec(sk, PKCS8EncodedKeySpec.class); + Utils.runAndCheckException(() -> kf5.getKeySpec(pk, X509EncodedKeySpec.class), + InvalidKeySpecException.class); // wrong KF + Utils.runAndCheckException(() -> kf5.getKeySpec(sk, PKCS8EncodedKeySpec.class), + InvalidKeySpecException.class); + Utils.runAndCheckException(() -> kf.getKeySpec(pk, PKCS8EncodedKeySpec.class), + InvalidKeySpecException.class); // wrong KeySpec + Utils.runAndCheckException(() -> kf.getKeySpec(sk, X509EncodedKeySpec.class), + InvalidKeySpecException.class); + + checkKey(kf.generatePublic(pkSpec), "SHA", "SHA-256"); + Utils.runAndCheckException(() -> kf.generatePrivate(pkSpec), + InvalidKeySpecException.class); + + checkKey(kf.generatePrivate(skSpec), "SHA", "SHA-256"); + Utils.runAndCheckException(() -> kf.generatePublic(skSpec), + InvalidKeySpecException.class); + + checkKey(kf2.generatePrivate(skSpec), "SHA", "SHA-256"); + checkKey(kf2.generatePublic(pkSpec), "SHA", "SHA-256"); + + Utils.runAndCheckException(() -> kf5.generatePublic(pkSpec), + InvalidKeySpecException.class); // wrong KF + Utils.runAndCheckException(() -> kf5.generatePublic(skSpec), + InvalidKeySpecException.class); + + // The private RawKeySpec and unnamed RAW EncodedKeySpec + var prk = kf.getKeySpec(pk, RawKeySpec.class); + Asserts.assertEqualsByteArray(prk.getKeyArr(), pk.getRawBytes()); + var prk2 = kf.getKeySpec(pk, EncodedKeySpec.class); + Asserts.assertEquals("RAW", prk2.getFormat()); + Asserts.assertEqualsByteArray(prk.getKeyArr(), prk2.getEncoded()); + + Asserts.assertEqualsByteArray(kf2.generatePublic(prk).getEncoded(), pk.getEncoded()); + Utils.runAndCheckException(() -> kf.generatePublic(prk), InvalidKeySpecException.class); // no pname + Asserts.assertEqualsByteArray(kf2.generatePublic(prk2).getEncoded(), pk.getEncoded()); + Utils.runAndCheckException(() -> kf.generatePublic(prk2), InvalidKeySpecException.class); // no pname + + var srk = kf.getKeySpec(sk, RawKeySpec.class); + Asserts.assertEqualsByteArray(srk.getKeyArr(), sk.getRawBytes()); + var srk2 = kf.getKeySpec(sk, EncodedKeySpec.class); + Asserts.assertEquals("RAW", srk2.getFormat()); + Asserts.assertEqualsByteArray(srk2.getEncoded(), sk.getRawBytes()); + + Asserts.assertEqualsByteArray(kf2.generatePrivate(srk).getEncoded(), sk.getEncoded()); + Utils.runAndCheckException(() -> kf.generatePrivate(srk), InvalidKeySpecException.class); // no pname + Asserts.assertEqualsByteArray(kf2.generatePrivate(srk2).getEncoded(), sk.getEncoded()); + Utils.runAndCheckException(() -> kf.generatePrivate(srk2), InvalidKeySpecException.class); // no pname + + var pk1 = new PublicKey() { + public String getAlgorithm() { return "SHA"; } + public String getFormat() { return "RAW"; } + public byte[] getEncoded() { return RAND.nBytes(2); } + }; + var pk2 = new PublicKey() { + public String getAlgorithm() { return "sHA-256"; } + public String getFormat() { return "RAW"; } + public byte[] getEncoded() { return RAND.nBytes(2); } + }; + var pk3 = new PublicKey() { + public String getAlgorithm() { return "SHA"; } + public String getFormat() { return "RAW"; } + public byte[] getEncoded() { return RAND.nBytes(2); } + public AlgorithmParameterSpec getParams() { return new NamedParameterSpec("sHA-256"); } + }; + + checkKey(kf2.translateKey(pk1), "SHA", "SHA-256"); + checkKey(kf.translateKey(pk2), "SHA", "SHA-256"); + checkKey(kf.translateKey(pk3), "SHA", "SHA-256"); + + Utils.runAndCheckException(() -> kf.translateKey(pk1), InvalidKeyException.class); + Utils.runAndCheckException(() -> kf5.translateKey(pk2), InvalidKeyException.class); + Utils.runAndCheckException(() -> kf5.translateKey(pk3), InvalidKeyException.class); + + var sk1 = new PrivateKey() { + public String getAlgorithm() { return "SHA"; } + public String getFormat() { return "RAW"; } + public byte[] getEncoded() { return RAND.nBytes(2); } + }; + var sk2 = new PrivateKey() { + public String getAlgorithm() { return "sHA-256"; } + public String getFormat() { return "RAW"; } + public byte[] getEncoded() { return RAND.nBytes(2); } + }; + var sk3 = new PrivateKey() { + public String getAlgorithm() { return "SHA"; } + public String getFormat() { return "RAW"; } + public byte[] getEncoded() { return RAND.nBytes(2); } + public AlgorithmParameterSpec getParams() { return new NamedParameterSpec("sHA-256"); } + }; + + checkKey(kf2.translateKey(sk1), "SHA", "SHA-256"); + checkKey(kf.translateKey(sk2), "SHA", "SHA-256"); + checkKey(kf.translateKey(sk3), "SHA", "SHA-256"); + + Utils.runAndCheckException(() -> kf.translateKey(sk1), InvalidKeyException.class); + Utils.runAndCheckException(() -> kf5.translateKey(sk2), InvalidKeyException.class); + Utils.runAndCheckException(() -> kf5.translateKey(sk3), InvalidKeyException.class); + } + + static void checkKeyPair(KeyPair kp, String algName, String toString) { + checkKey(kp.getPrivate(), algName, toString); + checkKey(kp.getPublic(), algName, toString); + } + + static void checkKey(Key k, String algName, String pname) { + Asserts.assertEquals(algName, k.getAlgorithm()); + Asserts.assertTrue(k.toString().contains(pname)); + if ((k instanceof PrivateKey || k instanceof PublicKey) && KeyUtil.getParams(k) instanceof NamedParameterSpec nps) { + Asserts.assertEquals(pname, nps.getName()); + } + } + + // Provider + + public static class ProviderImpl extends Provider { + public ProviderImpl() { + super("P", "1", "..."); + put("KeyFactory.SHA", KF.class.getName()); + put("KeyFactory.SHA-256", KF1.class.getName()); + put("KeyFactory.SHA-512", KF2.class.getName()); + put("KeyPairGenerator.SHA", KPG.class.getName()); + put("KeyPairGenerator.SHA-256", KPG1.class.getName()); + put("KeyPairGenerator.SHA-512", KPG2.class.getName()); + } + } + public static class KF extends NamedKeyFactory { + public KF() { + super("SHA", "SHA-256", "SHA-512"); + } + } + public static class KF1 extends NamedKeyFactory { + public KF1() { + super("SHA", "SHA-256"); + } + } + public static class KF2 extends NamedKeyFactory { + public KF2() { + super("SHA", "SHA-512"); + } + } + public static class KPG extends NamedKeyPairGenerator { + public KPG() { + super("SHA", "SHA-256", "SHA-512"); + } + + public KPG(String pname) { + super("SHA", pname); + } + + @Override + public byte[][] implGenerateKeyPair(String name, SecureRandom sr) { + var out = new byte[2][]; + out[0] = RAND.nBytes(name.endsWith("256") ? 2 : 4); + out[1] = RAND.nBytes(name.endsWith("256") ? 2 : 4); + return out; + } + } + public static class KPG1 extends KPG { + public KPG1() { + super("SHA-256"); + } + } + public static class KPG2 extends KPG { + public KPG2() { + super("SHA-512"); + } + } +} diff --git a/test/jdk/sun/security/provider/acvp/Launcher.java b/test/jdk/sun/security/provider/acvp/Launcher.java new file mode 100644 index 000000000000..1405847de5d1 --- /dev/null +++ b/test/jdk/sun/security/provider/acvp/Launcher.java @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import jdk.test.lib.artifacts.Artifact; +import jdk.test.lib.artifacts.ArtifactResolver; +import jdk.test.lib.artifacts.ArtifactResolverException; +import jdk.test.lib.json.JSONValue; +import jtreg.SkippedException; + +import java.io.InputStream; +import java.nio.file.Path; +import java.security.Provider; +import java.security.Security; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +/* + * @test + * @bug 8342442 8345057 + * @library /test/lib + * @modules java.base/sun.security.provider + */ + +/// This test runs on `internalProjection.json`-style files generated by NIST's +/// ACVP Server ([GitHub repository](https://github.com/usnistgov/ACVP-Server)). +/// These files are included in ZIP archives available under the +/// [tags section](https://github.com/usnistgov/ACVP-Server/tags) +/// of the repository. +/// +/// The zip archive is either hosted on artifactory server or +/// specified with local path to the test. +/// The test looks for test data files in the archive listed with `TEST_FILES`. +/// +/// These tests are currently compatible with ACVP version 1.1.0.38. +/// +/// By default, the test uses system-preferred implementations. +/// If you want to test a specific provider, set the +/// `test.acvp.provider` test property. The provider must be +/// registered. +/// +/// Tests for each algorithm must be compliant to its specification linked from +/// [https://github.com/usnistgov/ACVP?tab=readme-ov-file#supported-algorithms]. +/// +/// Example: +/// +/// Run locally with ArtifactResolver +/// ``` +/// jtreg -Djdk.test.lib.artifacts.ACVP-Server= +/// ``` +/// OR host the zip archive on artifactory server. +/// + +public class Launcher { + + private static final Provider PROVIDER; + + private static final String ACVP_BUNDLE_LOC = "jpg.tests.jdk"; + private static final String ACVP_BUNDLE_NAME = "ACVP-Server"; + private static final String ACVP_BUNDLE_VERSION = "1.1.0.38"; + // Zip archive entry name, do not update to use File.separator + private static final String[] TEST_FILES = { + "gen-val/json-files/ML-DSA-keyGen-FIPS204/internalProjection.json", + "gen-val/json-files/ML-DSA-sigGen-FIPS204/internalProjection.json", + "gen-val/json-files/ML-DSA-sigVer-FIPS204/internalProjection.json", + "gen-val/json-files/ML-KEM-encapDecap-FIPS203/internalProjection.json", + "gen-val/json-files/ML-KEM-keyGen-FIPS203/internalProjection.json" + }; + + private static int count = 0; + private static int invalidTest = 0; + private static int unsupportedTest = 0; + + static { + var provProp = System.getProperty("test.acvp.provider"); + if (provProp != null) { + var p = Security.getProvider(provProp); + if (p == null) { + System.err.println(provProp + " is not a registered provider name"); + throw new RuntimeException(provProp + " is not a registered provider name"); + } + PROVIDER = p; + } else { + PROVIDER = null; + } + } + + public static void main(String[] args) throws Exception { + + Path archivePath = fetchACVPServerTests(ACVP_SERVER_TESTS.class); + System.out.println("Data path: " + archivePath); + + if (PROVIDER != null) { + System.out.println("Provider: " + PROVIDER.getName()); + } + + // Read test data files from zip archive + try (ZipFile zf = new ZipFile(archivePath.toFile())) { + for (String testFile : TEST_FILES) { + // Zip archive entry name, do not update to use File.separator + String fullEntryName = ACVP_BUNDLE_NAME + "-" + ACVP_BUNDLE_VERSION + "/" + testFile; + System.out.println("Find and test with: " + fullEntryName); + ZipEntry ze = zf.getEntry(fullEntryName); + if (ze != null) { + run(zf.getInputStream(ze)); + } else { + throw new RuntimeException("Entry not found: " + fullEntryName); + } + } + } + + if (count > 0) { + System.out.println(); + System.out.println("Test completed: " + count); + System.out.println("Invalid tests: " + invalidTest); + System.out.println("Unsupported tests: " + unsupportedTest); + } else { + throw new RuntimeException("No supported test found"); + } + + if (invalidTest != 0 || unsupportedTest != 0){ + throw new RuntimeException("Invalid or Unsupported tests found"); + } + } + + static void run(InputStream test) { + try { + JSONValue kat; + try (test) { + kat = JSONValue.parse(new String(test.readAllBytes())); + } catch (Exception e) { + System.out.println("Warning: cannot parse " + test + ". Skipped"); + invalidTest++; + return; + } + var alg = kat.get("algorithm").asString(); + switch (alg) { + case "ML-DSA" -> { + ML_DSA_Test.run(kat, PROVIDER); + count++; + } + case "ML-KEM" -> { + ML_KEM_Test.run(kat, PROVIDER); + count++; + } + case "SHA2-256", "SHA2-224", "SHA3-256", "SHA3-224" -> { + SHA_Test.run(kat, PROVIDER); + count++; + } + default -> { + System.out.println("Skipped unsupported algorithm: " + alg); + unsupportedTest++; + } + } + } catch (RuntimeException re) { + throw re; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static Path fetchACVPServerTests(Class clazz) { + try { + return ArtifactResolver.resolve(clazz).entrySet().stream() + .findAny().get().getValue(); + } catch (ArtifactResolverException e) { + Throwable cause = e.getCause(); + if (cause == null) { + throw new SkippedException("Cannot resolve artifact, " + + "please check if JIB jar is present in classpath.", e); + } + + throw new SkippedException("Fetch artifact failed: " + clazz, e); + } + } + + @Artifact( + organization = ACVP_BUNDLE_LOC, + name = ACVP_BUNDLE_NAME, + revision = ACVP_BUNDLE_VERSION, + extension = "zip", + unpack = false) + private static class ACVP_SERVER_TESTS { + } +} diff --git a/test/jdk/sun/security/provider/acvp/ML_DSA_Test.java b/test/jdk/sun/security/provider/acvp/ML_DSA_Test.java new file mode 100644 index 000000000000..ab6072eaa414 --- /dev/null +++ b/test/jdk/sun/security/provider/acvp/ML_DSA_Test.java @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import jdk.test.lib.Asserts; +import jdk.test.lib.json.JSONValue; +import jdk.test.lib.security.FixedSecureRandom; +import sun.security.provider.ML_DSA_Impls; + +import java.security.*; +import java.security.spec.EncodedKeySpec; +import java.security.spec.NamedParameterSpec; + +import static jdk.test.lib.Utils.toByteArray; + +// JSON spec at https://pages.nist.gov/ACVP/draft-celi-acvp-ml-dsa.html +public class ML_DSA_Test { + + public static void run(JSONValue kat, Provider provider) throws Exception { + + var mode = kat.get("mode").asString(); + switch (mode) { + case "keyGen" -> keyGenTest(kat, provider); + case "sigGen" -> sigGenTest(kat, provider); + case "sigVer" -> sigVerTest(kat, provider); + default -> throw new UnsupportedOperationException("Unknown mode: " + mode); + } + } + + static NamedParameterSpec genParams(String pname) { + return switch (pname) { + case "ML-DSA-44" -> new NamedParameterSpec(pname); + case "ML-DSA-65" -> new NamedParameterSpec(pname); + case "ML-DSA-87" -> new NamedParameterSpec(pname); + default -> throw new RuntimeException("Unknown params: " + pname); + + }; + } + + static void keyGenTest(JSONValue kat, Provider p) throws Exception { + var g = p == null + ? KeyPairGenerator.getInstance("ML-DSA") + : KeyPairGenerator.getInstance("ML-DSA", p); + var f = p == null + ? KeyFactory.getInstance("ML-DSA") + : KeyFactory.getInstance("ML-DSA", p); + for (var t : kat.get("testGroups").asArray()) { + var pname = t.get("parameterSet").asString(); + var np = genParams(pname); + System.out.println(">> " + pname); + for (var c : t.get("tests").asArray()) { + System.out.print(c.get("tcId").asString() + " "); + g.initialize(np, new FixedSecureRandom(toByteArray(c.get("seed").asString()))); + var kp = g.generateKeyPair(); + var pk = f.getKeySpec(kp.getPublic(), EncodedKeySpec.class).getEncoded(); + var sk = f.getKeySpec(kp.getPrivate(), EncodedKeySpec.class).getEncoded(); + Asserts.assertEqualsByteArray(pk, toByteArray(c.get("pk").asString())); + Asserts.assertEqualsByteArray(sk, toByteArray(c.get("sk").asString())); + } + System.out.println(); + } + } + + static void sigGenTest(JSONValue kat, Provider p) throws Exception { + var s = p == null + ? Signature.getInstance("ML-DSA") + : Signature.getInstance("ML-DSA", p); + for (var t : kat.get("testGroups").asArray()) { + var pname = t.get("parameterSet").asString(); + System.out.println(">> " + pname + " sign"); + var det = Boolean.parseBoolean(t.get("deterministic").asString()); + if (t.get("signatureInterface").asString().equals("internal")) { + ML_DSA_Impls.version = ML_DSA_Impls.Version.DRAFT; + } else { + ML_DSA_Impls.version = ML_DSA_Impls.Version.FINAL; + } + if (t.get("externalMu").asString().equals("true")) { + continue; // Not supported + } + for (var c : t.get("tests").asArray()) { + var cstr = c.get("context"); + var ctxt = cstr == null ? new byte[0] : toByteArray(cstr.asString()); + var hashAlg = c.get("hashAlg").asString(); + if (!hashAlg.equals("none") || ctxt.length != 0) { + continue; // Not supported + } + System.out.print(Integer.parseInt(c.get("tcId").asString()) + " "); + var sk = new PrivateKey() { + public String getAlgorithm() { return pname; } + public String getFormat() { return "RAW"; } + public byte[] getEncoded() { return toByteArray(c.get("sk").asString()); } + }; + var sr = new FixedSecureRandom( + det ? new byte[32] : toByteArray(c.get("rnd").asString())); + s.initSign(sk, sr); + s.update(toByteArray(c.get("message").asString())); + var sig = s.sign(); + Asserts.assertEqualsByteArray( + sig, toByteArray(c.get("signature").asString())); + } + System.out.println(); + } + } + + static void sigVerTest(JSONValue kat, Provider p) throws Exception { + var s = p == null + ? Signature.getInstance("ML-DSA") + : Signature.getInstance("ML-DSA", p); + for (var t : kat.get("testGroups").asArray()) { + var pname = t.get("parameterSet").asString(); + System.out.println(">> " + pname + " verify"); + + if (t.get("signatureInterface").asString().equals("internal")) { + ML_DSA_Impls.version = ML_DSA_Impls.Version.DRAFT; + } else { + ML_DSA_Impls.version = ML_DSA_Impls.Version.FINAL; + } + + if (t.get("externalMu").asString().equals("true")) { + continue; // Not supported + } + + for (var c : t.get("tests").asArray()) { + var cstr = c.get("context"); + var ctxt = cstr == null ? new byte[0] : toByteArray(cstr.asString()); + var hashAlg = c.get("hashAlg").asString(); + if (!hashAlg.equals("none") || ctxt.length != 0) { + continue; // Not supported + } + System.out.print(c.get("tcId").asString() + " "); + var pk = new PublicKey() { + public String getAlgorithm() { return pname; } + public String getFormat() { return "RAW"; } + public byte[] getEncoded() { return toByteArray(c.get("pk").asString()); } + }; + // Only ML-DSA sigVer has negative tests + var expected = Boolean.parseBoolean(c.get("testPassed").asString()); + var actual = true; + try { + s.initVerify(pk); + s.update(toByteArray(c.get("message").asString())); + actual = s.verify(toByteArray(c.get("signature").asString())); + } catch (InvalidKeyException | SignatureException e) { + actual = false; + } + Asserts.assertEQ(expected, actual); + } + System.out.println(); + } + } +} diff --git a/test/jdk/sun/security/provider/acvp/ML_KEM_Test.java b/test/jdk/sun/security/provider/acvp/ML_KEM_Test.java new file mode 100644 index 000000000000..49c9c4ecb9fe --- /dev/null +++ b/test/jdk/sun/security/provider/acvp/ML_KEM_Test.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import jdk.test.lib.Asserts; +import jdk.test.lib.json.JSONValue; +import jdk.test.lib.security.FixedSecureRandom; + +import javax.crypto.KEM; +import java.security.*; +import java.security.spec.EncodedKeySpec; +import java.security.spec.NamedParameterSpec; + +import static jdk.test.lib.Utils.toByteArray; + +// JSON spec at https://pages.nist.gov/ACVP/draft-celi-acvp-ml-kem.html +public class ML_KEM_Test { + + public static void run(JSONValue kat, Provider provider) throws Exception { + var mode = kat.get("mode").asString(); + switch (mode) { + case "keyGen" -> keyGenTest(kat, provider); + case "encapDecap" -> encapDecapTest(kat, provider); + default -> throw new UnsupportedOperationException("Unknown mode: " + mode); + } + } + + static NamedParameterSpec genParams(String pname) { + return switch (pname) { + case "ML-KEM-512" -> new NamedParameterSpec(pname); + case "ML-KEM-768" -> new NamedParameterSpec(pname); + case "ML-KEM-1024" -> new NamedParameterSpec(pname); + default -> throw new RuntimeException("Unknown params: " + pname); + }; + } + + static void keyGenTest(JSONValue kat, Provider p) throws Exception { + var g = p == null + ? KeyPairGenerator.getInstance("ML-KEM") + : KeyPairGenerator.getInstance("ML-KEM", p); + var f = p == null + ? KeyFactory.getInstance("ML-KEM") + : KeyFactory.getInstance("ML-KEM", p); + for (var t : kat.get("testGroups").asArray()) { + var pname = t.get("parameterSet").asString(); + var np = genParams(pname); + System.out.println(">> " + pname); + for (var c : t.get("tests").asArray()) { + System.out.print(c.get("tcId").asString() + " "); + g.initialize(np, new FixedSecureRandom( + toByteArray(c.get("d").asString()), toByteArray(c.get("z").asString()))); + var kp = g.generateKeyPair(); + var pk = f.getKeySpec(kp.getPublic(), EncodedKeySpec.class).getEncoded(); + var sk = f.getKeySpec(kp.getPrivate(), EncodedKeySpec.class).getEncoded(); + Asserts.assertEqualsByteArray(pk, toByteArray(c.get("ek").asString())); + Asserts.assertEqualsByteArray(sk, toByteArray(c.get("dk").asString())); + } + System.out.println(); + } + } + + static void encapDecapTest(JSONValue kat, Provider p) throws Exception { + var g = p == null + ? KEM.getInstance("ML-KEM") + : KEM.getInstance("ML-KEM", p); + for (var t : kat.get("testGroups").asArray()) { + var pname = t.get("parameterSet").asString(); + var function = t.get("function").asString(); + System.out.println(">> " + pname + " " + function); + if (function.equals("encapsulation")) { + for (var c : t.get("tests").asArray()) { + System.out.print(c.get("tcId").asString() + " "); + var ek = new PublicKey() { + public String getAlgorithm() { return pname; } + public String getFormat() { return "RAW"; } + public byte[] getEncoded() { return toByteArray(c.get("ek").asString()); } + }; + var e = g.newEncapsulator( + ek, new FixedSecureRandom(toByteArray(c.get("m").asString()))); + var enc = e.encapsulate(); + Asserts.assertEqualsByteArray( + enc.encapsulation(), toByteArray(c.get("c").asString())); + Asserts.assertEqualsByteArray( + enc.key().getEncoded(), toByteArray(c.get("k").asString())); + } + System.out.println(); + } else if (function.equals("decapsulation")) { + var dk = new PrivateKey() { + public String getAlgorithm() { return pname; } + public String getFormat() { return "RAW"; } + public byte[] getEncoded() { return toByteArray(t.get("dk").asString()); } + }; + for (var c : t.get("tests").asArray()) { + System.out.print(c.get("tcId").asString() + " "); + var d = g.newDecapsulator(dk); + var k = d.decapsulate(toByteArray(c.get("c").asString())); + Asserts.assertEqualsByteArray(k.getEncoded(), toByteArray(c.get("k").asString())); + } + System.out.println(); + } + } + } +} diff --git a/test/jdk/sun/security/provider/acvp/SHA_Test.java b/test/jdk/sun/security/provider/acvp/SHA_Test.java new file mode 100644 index 000000000000..3e5d4bb25214 --- /dev/null +++ b/test/jdk/sun/security/provider/acvp/SHA_Test.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import jdk.test.lib.Asserts; +import jdk.test.lib.json.JSONValue; + +import java.security.*; +import java.util.Arrays; + +import static jdk.test.lib.Utils.toByteArray; + +// JSON spec at https://pages.nist.gov/ACVP/draft-celi-acvp-sha.html +// and https://pages.nist.gov/ACVP/draft-celi-acvp-sha3.html +public class SHA_Test { + + public static void run(JSONValue kat, Provider provider) throws Exception { + var alg = kat.get("algorithm").asString(); + if (alg.startsWith("SHA2-")) alg = "SHA-" + alg.substring(5); + var md = provider == null ? MessageDigest.getInstance(alg) + : MessageDigest.getInstance(alg, provider); + for (var t : kat.get("testGroups").asArray()) { + var testType = t.get("testType").asString(); + switch (testType) { + case "AFT" -> { + for (var c : t.get("tests").asArray()) { + System.out.print(c.get("tcId").asString() + " "); + var msg = toByteArray(c.get("msg").asString()); + var len = Integer.parseInt(c.get("len").asString()); + if (msg.length * 8 == len) { + Asserts.assertEqualsByteArray(md.digest(msg), + toByteArray(c.get("md").asString())); + } else { + System.out.print("bits "); + } + } + } + case "MCT" -> { + var mctVersion = t.get("mctVersion").asString(); + var trunc = mctVersion.equals("alternate"); + for (var c : t.get("tests").asArray()) { + System.out.print(c.get("tcId").asString() + " "); + var SEED = toByteArray(c.get("msg").asString()); + var INITIAL_SEED_LENGTH = Integer.parseInt(c.get("len").asString()); + if (SEED.length * 8 == INITIAL_SEED_LENGTH) { + for (var r : c.get("resultsArray").asArray()) { + if (alg.startsWith("SHA3-")) { + var MD = SEED; + for (var i = 0; i < 1000; i++) { + if (trunc) { + MD = Arrays.copyOf(MD, INITIAL_SEED_LENGTH / 8); + } + MD = md.digest(MD); + } + Asserts.assertEqualsByteArray(MD, + toByteArray(r.get("md").asString())); + SEED = MD; + } else { + var A = SEED; + var B = SEED; + var C = SEED; + byte[] MD = null; + for (var i = 0; i < 1000; i++) { + var MSG = concat(A, B, C); + if (trunc) { + MSG = Arrays.copyOf(MSG, INITIAL_SEED_LENGTH / 8); + } + MD = md.digest(MSG); + A = B; + B = C; + C = MD; + } + Asserts.assertEqualsByteArray(MD, + toByteArray(r.get("md").asString())); + SEED = MD; + } + } + } else { + System.out.print("bits "); + } + } + } + case "LDT" -> { + for (var c : t.get("tests").asArray()) { + System.out.print(c.get("tcId").asString() + " "); + var lm = c.get("largeMsg"); + var ct = toByteArray(lm.get("content").asString()); + var flen = Long.parseLong(lm.get("fullLength").asString()); + var clen = Long.parseLong(lm.get("contentLength").asString()); + var cc = 0L; + while (cc < flen) { + md.update(ct); + cc += clen; + } + Asserts.assertEqualsByteArray(md.digest(), + toByteArray(c.get("md").asString())); + } + } + default -> throw new UnsupportedOperationException( + "Unknown testType: " + testType); + } + System.out.println(); + } + } + + ///////////// + + static byte[] concat(byte[]... input) { + var sum = 0; + for (var i : input) { + sum += i.length; + } + var out = new byte[sum]; + sum = 0; + for (var i : input) { + System.arraycopy(i, 0, out, sum, i.length); + sum += i.length; + } + return out; + } +} diff --git a/test/jdk/sun/security/provider/all/Deterministic.java b/test/jdk/sun/security/provider/all/Deterministic.java index 2a2f5d888532..6db6c3692626 100644 --- a/test/jdk/sun/security/provider/all/Deterministic.java +++ b/test/jdk/sun/security/provider/all/Deterministic.java @@ -212,6 +212,8 @@ static KeyPair generateKeyPair(String alg, int offset) throws Exception { case "EC" -> 256; case "EdDSA", "Ed25519", "XDH", "X25519" -> 255; case "Ed448", "X448" -> 448; + case "ML-KEM", "ML-KEM-768", "ML-KEM-512", "ML-KEM-1024", + "ML-DSA", "ML-DSA-44", "ML-DSA-65", "ML-DSA-87" -> -1; default -> throw new UnsupportedOperationException(alg); }; g.initialize(size, new SeededSecureRandom(SEED + offset)); diff --git a/test/jdk/sun/security/provider/namedKeyFactoryTest.policy b/test/jdk/sun/security/provider/namedKeyFactoryTest.policy new file mode 100644 index 000000000000..1ce5e72a62d3 --- /dev/null +++ b/test/jdk/sun/security/provider/namedKeyFactoryTest.policy @@ -0,0 +1,11 @@ +grant { + + permission java.util.PropertyPermission "*", "read"; + permission java.security.SecurityPermission "putProviderProperty.P"; + permission java.security.SecurityPermission "insertProvider"; + permission java.lang.RuntimePermission "accessClassInPackage.sun.security.x509"; + permission java.lang.RuntimePermission "accessClassInPackage.sun.security.pkcs"; + permission java.lang.RuntimePermission "accessClassInPackage.sun.security.util"; + permission java.lang.RuntimePermission "accessClassInPackage.sun.security.provider"; + +}; diff --git a/test/jdk/sun/security/tools/keytool/GenKeyPairSigner.java b/test/jdk/sun/security/tools/keytool/GenKeyPairSigner.java index 52ca1ead82c5..84cfcd7cb17d 100644 --- a/test/jdk/sun/security/tools/keytool/GenKeyPairSigner.java +++ b/test/jdk/sun/security/tools/keytool/GenKeyPairSigner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -84,7 +84,7 @@ static void testSignerPKCS12() throws Exception { System.out.println("Generating an XDH cert with -signer option"); SecurityTools.keytool("-keystore ks -storepass changeit " + "-genkeypair -keyalg XDH -alias e1 -dname CN=E1 -signer ca") - .shouldContain("Generating 255 bit XDH key pair and a certificate (Ed25519) issued by with a validity of 90 days") + .shouldContain("Generating 255 bit X25519 key pair and a certificate (Ed25519) issued by with a validity of 90 days") .shouldContain("for: CN=E1") .shouldHaveExitValue(0); @@ -118,7 +118,7 @@ static void testSignerPKCS12() throws Exception { .shouldContain("Alias name: e1") .shouldContain("Certificate chain length: 2") .shouldContain("Signature algorithm name: Ed25519") - .shouldContain("Subject Public Key Algorithm: 255-bit XDH key") + .shouldContain("Subject Public Key Algorithm: 255-bit X25519 key") .shouldHaveExitValue(0); // check to make sure that cert's AKID is created from the SKID of the signing cert @@ -150,7 +150,7 @@ static void testSignerPKCS12() throws Exception { System.out.println("Generating an X448 cert with -signer option"); SecurityTools.keytool("-keystore ks -storepass changeit " + "-genkeypair -keyalg X448 -alias e2 -dname CN=E2 -sigalg SHA384withRSA -signer ca2") - .shouldContain("Generating 448 bit XDH key pair and a certificate (SHA384withRSA) issued by with a validity of 90 days") + .shouldContain("Generating 448 bit X448 key pair and a certificate (SHA384withRSA) issued by with a validity of 90 days") .shouldContain("for: CN=E2") .shouldHaveExitValue(0); @@ -177,7 +177,7 @@ static void testSignerPKCS12() throws Exception { "-list -v") .shouldContain("Alias name: e2") .shouldContain("Signature algorithm name: SHA384withRSA") - .shouldContain("Subject Public Key Algorithm: 448-bit XDH key") + .shouldContain("Subject Public Key Algorithm: 448-bit X448 key") .shouldHaveExitValue(0); kt("-genkeypair -keyalg DSA -alias ca3 -dname CN=CA3 -ext bc:c ", @@ -249,7 +249,7 @@ static void testSignerJKS() throws Exception { SecurityTools.keytool("-keystore ksjks -storepass changeit -storetype jks " + "-genkeypair -keyalg XDH -alias e1 -dname CN=E1 " + "-keypass e1keypass -signer ca1 -signerkeypass ca1keypass") - .shouldContain("Generating 255 bit XDH key pair and a certificate (SHA256withDSA) issued by with a validity of 90 days") + .shouldContain("Generating 255 bit X25519 key pair and a certificate (SHA256withDSA) issued by with a validity of 90 days") .shouldContain("for: CN=E1") .shouldContain("The generated certificate #2 of 3 uses a 1024-bit DSA key which is considered a security risk") .shouldContain("The generated certificate #3 of 3 uses a 1024-bit RSA key which is considered a security risk") @@ -285,7 +285,7 @@ static void testSignerJKS() throws Exception { .shouldContain("Alias name: e1") .shouldContain("Certificate chain length: 3") .shouldContain("Signature algorithm name: SHA256withDSA") - .shouldContain("Subject Public Key Algorithm: 255-bit XDH key") + .shouldContain("Subject Public Key Algorithm: 255-bit X25519 key") .shouldHaveExitValue(0); } diff --git a/test/jdk/sun/security/x509/GeneralName/DNSNameTest.java b/test/jdk/sun/security/x509/GeneralName/DNSNameTest.java index c4905cd5eb1c..8b3a23985726 100644 --- a/test/jdk/sun/security/x509/GeneralName/DNSNameTest.java +++ b/test/jdk/sun/security/x509/GeneralName/DNSNameTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,132 +21,126 @@ * questions. */ -/** +import static jdk.test.lib.Asserts.fail; + +import java.io.IOException; +import java.net.IDN; +import java.util.List; +import java.util.stream.Stream; +import sun.security.x509.DNSName; + +/* * @test * @summary DNSName parsing tests - * @bug 8213952 8186143 + * @bug 8213952 8186143 8381771 + * @library /test/lib * @modules java.base/sun.security.x509 - * @run testng DNSNameTest + * @run main DNSNameTest */ -import java.io.IOException; -import sun.security.x509.DNSName; +public class DNSNameTest { -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; + private static final List GOOD_NAMES = List.of( + "abc", + String.join(".", "a".repeat(63), "b".repeat(63), + "c".repeat(63), "d".repeat(61)), + "abc.com", + "tesT.Abc.com", + "ABC.COM", + "a12.com", + "a1b2c3.com", + "1abc.com", + "123.com", + "a-b-c.com", // hyphens + IDN.toASCII("公司.江利子") // IDN punycode + ); -import static org.testng.Assert.*; + private static final List GOOD_SAN_NAMES = Stream.concat( + Stream.of( + "*.domain.com", // wildcard in 1st level subdomain + "*.com"), + GOOD_NAMES.stream()) + .toList(); -public class DNSNameTest { - @DataProvider(name = "goodNames") - public Object[][] goodNames() { - Object[][] data = { - {"abc.com"}, - {"ABC.COM"}, - {"a12.com"}, - {"a1b2c3.com"}, - {"1abc.com"}, - {"123.com"}, - {"abc.com-"}, // end with hyphen - {"a-b-c.com"}, // hyphens - }; - return data; - } + private static final List BAD_NAMES = List.of( + // DNSName too long + String.join(".", "a".repeat(63), "b".repeat(63), + "c".repeat(63), "d".repeat(62)), + // DNSName label too long + "a".repeat(64), + " 1abc.com", // begin with space + "1abc.com ", // end with space + "1a bc.com ", // no space allowed + "-abc.com", // name begins with a hyphen + "abc.com-", // name ends with a hyphen + "abc.-com", // label begins with a hyphen + "abc-.com", // label ends with a hyphen + "a..b", // .. + ".a", // begin with . + "a.", // end with . + "", // empty + " ", // space only + "*.domain.com", // wildcard not allowed + "a*.com" // only allow letter, digit, or hyphen + ); - @DataProvider(name = "goodSanNames") - public Object[][] goodSanNames() { - Object[][] data = { - {"abc.com"}, - {"ABC.COM"}, - {"a12.com"}, - {"a1b2c3.com"}, - {"1abc.com"}, - {"123.com"}, - {"abc.com-"}, // end with hyphen - {"a-b-c.com"}, // hyphens - {"*.domain.com"}, // wildcard in 1st level subdomain - {"*.com"}, - }; - return data; - } + private static final List BAD_SAN_NAMES = Stream.concat( + Stream.of( + "*", // wildcard only + "*.", // wildcard with a period + "*a.com", // partial wildcard disallowed + "abc.*.com", // wildcard not allowed in 2nd level + "**.domain.com", // double wildcard not allowed + "*.domain.com*", // can't end with wildcard + "a*.com"), // only allow letter, digit, or hyphen + BAD_NAMES.stream().filter(n -> !n.contains("*"))) + .toList(); - @DataProvider(name = "badNames") - public Object[][] badNames() { - Object[][] data = { - {" 1abc.com"}, // begin with space - {"1abc.com "}, // end with space - {"1a bc.com "}, // no space allowed - {"-abc.com"}, // begin with hyphen - {"a..b"}, // .. - {".a"}, // begin with . - {"a."}, // end with . - {""}, // empty - {" "}, // space only - {"*.domain.com"}, // wildcard not allowed - {"a*.com"}, // only allow letter, digit, or hyphen - }; - return data; - } - @DataProvider(name = "badSanNames") - public Object[][] badSanNames() { - Object[][] data = { - {" 1abc.com"}, // begin with space - {"1abc.com "}, // end with space - {"1a bc.com "}, // no space allowed - {"-abc.com"}, // begin with hyphen - {"a..b"}, // .. - {".a"}, // begin with . - {"a."}, // end with . - {""}, // empty - {" "}, // space only - {"*"}, // wildcard only - {"*a.com"}, // partial wildcard disallowed - {"abc.*.com"}, // wildcard not allowed in 2nd level - {"*.*.domain.com"}, // double wildcard not allowed - {"a*.com"}, // only allow letter, digit, or hyphen - }; - return data; + public static void main(String[] args) { + GOOD_NAMES.forEach(DNSNameTest::testGoodDNSName); + GOOD_SAN_NAMES.forEach(DNSNameTest::testGoodSanDNSName); + BAD_NAMES.forEach(DNSNameTest::testBadDNSName); + BAD_SAN_NAMES.forEach(DNSNameTest::testBadSanDNSName); } - - @Test(dataProvider = "goodNames") - public void testGoodDNSName(String dnsNameString) { + private static void testGoodDNSName(String dnsNameString) { try { DNSName dn = new DNSName(dnsNameString); } catch (IOException e) { - fail("Unexpected IOException"); + fail("Unexpected IOException with input " + dnsNameString + ": " + + e.getMessage()); } } - @Test(dataProvider = "goodSanNames") - public void testGoodSanDNSName(String dnsNameString) { + private static void testGoodSanDNSName(String dnsNameString) { try { DNSName dn = new DNSName(dnsNameString, true); } catch (IOException e) { - fail("Unexpected IOException"); + fail("Unexpected IOException with input " + dnsNameString + ": " + + e.getMessage()); } } - @Test(dataProvider = "badNames") - public void testBadDNSName(String dnsNameString) { + private static void testBadDNSName(String dnsNameString) { try { DNSName dn = new DNSName(dnsNameString); - fail("IOException expected"); + fail("IOException expected with input " + dnsNameString); } catch (IOException e) { - if (!e.getMessage().contains("DNSName")) + if (!e.getMessage().contains("DNSName")) { fail("Unexpected message: " + e); + } } } - @Test(dataProvider = "badSanNames") - public void testBadSanDNSName(String dnsNameString) { + private static void testBadSanDNSName(String dnsNameString) { try { DNSName dn = new DNSName(dnsNameString, true); - fail("IOException expected"); + fail("IOException expected with input " + dnsNameString); } catch (IOException e) { - if (!e.getMessage().contains("DNSName")) + if (!e.getMessage().contains("DNSName")) { fail("Unexpected message: " + e); + } } } } diff --git a/test/jdk/sun/tools/jstat/jstatGcCapacityOutput1.sh b/test/jdk/sun/tools/jstat/jstatGcCapacityOutput1.sh index c1908855ea76..6e184e9dc310 100644 --- a/test/jdk/sun/tools/jstat/jstatGcCapacityOutput1.sh +++ b/test/jdk/sun/tools/jstat/jstatGcCapacityOutput1.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ # @test # @bug 4990825 +# @requires vm.gc.Parallel # @run shell jstatGcCapacityOutput1.sh # @summary Test that output of 'jstat -gccapacity 0' has expected line counts diff --git a/test/jdk/sun/tools/jstat/jstatGcMetaCapacityOutput1.sh b/test/jdk/sun/tools/jstat/jstatGcMetaCapacityOutput1.sh index b16d0e38d02c..b5caccb17681 100644 --- a/test/jdk/sun/tools/jstat/jstatGcMetaCapacityOutput1.sh +++ b/test/jdk/sun/tools/jstat/jstatGcMetaCapacityOutput1.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2013, 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ # @test # @bug 4990825 +# @requires vm.gc.Parallel # @run shell jstatGcMetaCapacityOutput1.sh # @summary Test that output of 'jstat -gcmetacapacity 0' has expected line counts diff --git a/test/jdk/sun/tools/jstat/jstatGcNewCapacityOutput1.sh b/test/jdk/sun/tools/jstat/jstatGcNewCapacityOutput1.sh index 64ce2efd455e..96f0722a9e13 100644 --- a/test/jdk/sun/tools/jstat/jstatGcNewCapacityOutput1.sh +++ b/test/jdk/sun/tools/jstat/jstatGcNewCapacityOutput1.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ # @test # @bug 4990825 +# @requires vm.gc.Parallel # @run shell jstatGcNewCapacityOutput1.sh # @summary Test that output of 'jstat -gcnewcapacity 0' has expected line counts diff --git a/test/jdk/sun/tools/jstat/jstatGcNewOutput1.sh b/test/jdk/sun/tools/jstat/jstatGcNewOutput1.sh index b15ec02d2b0a..96e2db61488e 100644 --- a/test/jdk/sun/tools/jstat/jstatGcNewOutput1.sh +++ b/test/jdk/sun/tools/jstat/jstatGcNewOutput1.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ # @test # @bug 4990825 +# @requires vm.gc.Parallel # @run shell jstatGcNewOutput1.sh # @summary Test that output of 'jstat -gcnew 0' has expected line counts diff --git a/test/jdk/sun/tools/jstat/jstatGcOldCapacityOutput1.sh b/test/jdk/sun/tools/jstat/jstatGcOldCapacityOutput1.sh index 1c13d6f916d3..0c5e2e198945 100644 --- a/test/jdk/sun/tools/jstat/jstatGcOldCapacityOutput1.sh +++ b/test/jdk/sun/tools/jstat/jstatGcOldCapacityOutput1.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,8 +23,9 @@ # @test # @bug 4990825 +# @requires vm.gc.Parallel # @run shell jstatGcOldCapacityOutput1.sh -# @summary Test that output of 'jstat -gcoldcapcaity 0' has expected line counts +# @summary Test that output of 'jstat -gcoldcapacity 0' has expected line counts . ${TESTSRC-.}/../../jvmstat/testlibrary/utils.sh diff --git a/test/jdk/sun/tools/jstat/jstatGcOldOutput1.sh b/test/jdk/sun/tools/jstat/jstatGcOldOutput1.sh index 7f505228b12a..0f857ccb1e68 100644 --- a/test/jdk/sun/tools/jstat/jstatGcOldOutput1.sh +++ b/test/jdk/sun/tools/jstat/jstatGcOldOutput1.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ # @test # @bug 4990825 +# @requires vm.gc.Parallel # @run shell jstatGcOldOutput1.sh # @summary Test that output of 'jstat -gcold 0' has expected line counts diff --git a/test/jdk/sun/tools/jstat/jstatGcOutput1.sh b/test/jdk/sun/tools/jstat/jstatGcOutput1.sh index dfffa2d1a550..5862fda3fd78 100644 --- a/test/jdk/sun/tools/jstat/jstatGcOutput1.sh +++ b/test/jdk/sun/tools/jstat/jstatGcOutput1.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ # @test # @bug 4990825 +# @requires vm.gc.Parallel # @run shell jstatGcOutput1.sh # @summary Test that output of 'jstat -gc 0' has expected line counts diff --git a/test/jdk/sun/tools/jstat/jstatLineCounts1.sh b/test/jdk/sun/tools/jstat/jstatLineCounts1.sh index 97338b8e793d..ca6adce96a5c 100644 --- a/test/jdk/sun/tools/jstat/jstatLineCounts1.sh +++ b/test/jdk/sun/tools/jstat/jstatLineCounts1.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ # @test # @bug 4990825 +# @requires vm.gc.Parallel # @run shell jstatLineCounts1.sh # @summary Test that output of 'jstat -gcutil 0 250 5' has expected line counts diff --git a/test/jdk/sun/tools/jstat/jstatLineCounts2.sh b/test/jdk/sun/tools/jstat/jstatLineCounts2.sh index eab19f3931e8..a668df72e0ec 100644 --- a/test/jdk/sun/tools/jstat/jstatLineCounts2.sh +++ b/test/jdk/sun/tools/jstat/jstatLineCounts2.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ # @test # @bug 4990825 +# @requires vm.gc.Parallel # @run shell jstatLineCounts2.sh # @summary Test that output of 'jstat -gcutil 0' has expected line counts diff --git a/test/jdk/sun/tools/jstat/jstatLineCounts3.sh b/test/jdk/sun/tools/jstat/jstatLineCounts3.sh index 9a769a924648..bffffc8a38e3 100644 --- a/test/jdk/sun/tools/jstat/jstatLineCounts3.sh +++ b/test/jdk/sun/tools/jstat/jstatLineCounts3.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ # @test # @bug 4990825 +# @requires vm.gc.Parallel # @run shell jstatLineCounts3.sh # @summary Test that output of 'jstat -gcutil -h 10 250 10' has expected line counts diff --git a/test/jdk/sun/tools/jstat/jstatLineCounts4.sh b/test/jdk/sun/tools/jstat/jstatLineCounts4.sh index 817c3b14f621..9ad1f57a5d50 100644 --- a/test/jdk/sun/tools/jstat/jstatLineCounts4.sh +++ b/test/jdk/sun/tools/jstat/jstatLineCounts4.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ # @test # @bug 4990825 +# @requires vm.gc.Parallel # @run shell jstatLineCounts4.sh # @summary Test that output of 'jstat -gcutil -h 10 250 11' has expected line counts diff --git a/test/jdk/sun/tools/jstat/jstatTimeStamp1.sh b/test/jdk/sun/tools/jstat/jstatTimeStamp1.sh index db71314fcf95..4e4cb8df4266 100644 --- a/test/jdk/sun/tools/jstat/jstatTimeStamp1.sh +++ b/test/jdk/sun/tools/jstat/jstatTimeStamp1.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ # @test # @bug 4990825 +# @requires vm.gc.Parallel # @run shell jstatTimeStamp1.sh # @summary Test that output of 'jstat -gcutil -t 0' has expected format diff --git a/test/langtools/TEST.ROOT b/test/langtools/TEST.ROOT index 0abad0ce02d8..5c2ca2ce08fd 100644 --- a/test/langtools/TEST.ROOT +++ b/test/langtools/TEST.ROOT @@ -15,7 +15,7 @@ keys=intermittent randomness needs-src needs-src-jdk_javadoc groups=TEST.groups # Minimum jtreg version -requiredVersion=7.5.2+1 +requiredVersion=8.2.1+1 # Use new module options useNewOptions=true diff --git a/test/lib-test/TEST.ROOT b/test/lib-test/TEST.ROOT index 2483eee4fbd2..393e99db56e7 100644 --- a/test/lib-test/TEST.ROOT +++ b/test/lib-test/TEST.ROOT @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,7 @@ keys=randomness # Minimum jtreg version -requiredVersion=7.5.2+1 +requiredVersion=8.2.1+1 # Path to libraries in the topmost test directory. This is needed so @library # does not need ../../ notation to reach them diff --git a/test/lib-test/jdk/test/lib/security/FixedSecureRandomTest.java b/test/lib-test/jdk/test/lib/security/FixedSecureRandomTest.java new file mode 100644 index 000000000000..bdebc9e0a8c8 --- /dev/null +++ b/test/lib-test/jdk/test/lib/security/FixedSecureRandomTest.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import jdk.test.lib.Asserts; +import jdk.test.lib.Utils; +import jdk.test.lib.security.FixedSecureRandom; + +/* + * @test + * @library /test/lib + * @summary ensure FixedSecureRandom works as expected + */ +public class FixedSecureRandomTest { + public static void main(String[] args) throws Exception { + var fsr = new FixedSecureRandom(new byte[] {1, 2, 3}, + new byte[] {4, 5, 6}); + var b1 = new byte[2]; + fsr.nextBytes(b1); + Asserts.assertEqualsByteArray(b1, new byte[] {1, 2}); + Asserts.assertTrue(fsr.hasRemaining()); + fsr.nextBytes(b1); + Asserts.assertEqualsByteArray(b1, new byte[] {3, 4}); + Asserts.assertTrue(fsr.hasRemaining()); + fsr.nextBytes(b1); + Asserts.assertEqualsByteArray(b1, new byte[] {5, 6}); + Asserts.assertFalse(fsr.hasRemaining()); + Utils.runAndCheckException(() -> fsr.nextBytes(b1), + IllegalStateException.class); + } +} diff --git a/test/lib/jdk/test/lib/Utils.java b/test/lib/jdk/test/lib/Utils.java index c4a42dc61ba2..7daac4f74202 100644 --- a/test/lib/jdk/test/lib/Utils.java +++ b/test/lib/jdk/test/lib/Utils.java @@ -45,9 +45,11 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.attribute.AclEntry; +import java.nio.file.attribute.AclEntryPermission; import java.nio.file.attribute.AclEntryType; import java.nio.file.attribute.AclFileAttributeView; import java.nio.file.attribute.FileAttribute; +import java.nio.file.attribute.UserPrincipal; import java.nio.channels.SocketChannel; import java.nio.file.attribute.PosixFilePermissions; import java.security.MessageDigest; @@ -56,6 +58,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.EnumSet; import java.util.HexFormat; import java.util.Iterator; import java.util.Map; @@ -1033,25 +1036,18 @@ public static void grantFileAccess(Path file, boolean userOnly) } else if (attr.contains("acl")) { AclFileAttributeView view = Files.getFileAttributeView(file, AclFileAttributeView.class); + UserPrincipal everyone = file.getFileSystem() + .getUserPrincipalLookupService() + .lookupPrincipalByName("Everyone"); + UserPrincipal principal = userOnly ? view.getOwner() : everyone; + EnumSet allPermissions = EnumSet.allOf(AclEntryPermission.class); + List acl = new ArrayList<>(); - for (AclEntry thisEntry : view.getAcl()) { - if (userOnly) { - if (thisEntry.principal().getName() - .equals(view.getOwner().getName())) { - acl.add(allowAccess(thisEntry)); - } else if (thisEntry.type() == AclEntryType.ALLOW) { - acl.add(revokeAccess(thisEntry)); - } else { - acl.add(thisEntry); - } - } else { - if (thisEntry.type() != AclEntryType.ALLOW) { - acl.add(allowAccess(thisEntry)); - } else { - acl.add(thisEntry); - } - } - } + acl.add(AclEntry.newBuilder() + .setType(AclEntryType.ALLOW) + .setPrincipal(principal) + .setPermissions(allPermissions) + .build()); view.setAcl(acl); } else { throw new RuntimeException("Unsupported file attributes: " + attr); diff --git a/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java b/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java index 886412190674..178559036b12 100644 --- a/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java +++ b/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,6 +38,7 @@ import java.util.Collections; import java.util.EnumSet; import java.util.List; +import jdk.internal.platform.Metrics; import jdk.test.lib.Container; import jdk.test.lib.Utils; import jdk.test.lib.process.OutputAnalyzer; @@ -47,6 +48,7 @@ public class DockerTestUtils { private static boolean isDockerEngineAvailable = false; private static boolean wasDockerEngineChecked = false; + private static final Metrics metrics = Metrics.systemMetrics(); // Specifies how many lines to copy from child STDOUT to main test output. // Having too many lines in the main test output will result @@ -93,16 +95,12 @@ public static boolean isPodman() { } /** - * Convenience method, will check if docker engine is available and usable; - * will print the appropriate message when not available. + * Checks if the docker engine is available and usable, throws an exception if not. * - * @return true if docker engine is available * @throws Exception */ - public static boolean canTestDocker() throws Exception { - if (isDockerEngineAvailable()) { - return true; - } else { + public static void checkCanTestDocker() throws Exception { + if (!isDockerEngineAvailable()) { throw new SkippedException("Docker engine is not available on this system"); } } @@ -133,6 +131,17 @@ private static String getEngineInfo(String format) throws Exception { return execute(Container.ENGINE_COMMAND, "info", "-f", format).getStdout(); } + /** + * Checks if the engine can use resource limits, throws an exception if not. + * + * @throws Exception + */ + public static void checkCanUseResourceLimits() throws Exception { + if (isRootless() && "cgroupv1".equals(metrics.getProvider())) { + throw new SkippedException("Resource limits are not available on this system"); + } + } + /** * Determine if the engine is running in root-less mode. * diff --git a/test/lib/jdk/test/lib/security/FixedSecureRandom.java b/test/lib/jdk/test/lib/security/FixedSecureRandom.java new file mode 100644 index 000000000000..cfe8ccc212f4 --- /dev/null +++ b/test/lib/jdk/test/lib/security/FixedSecureRandom.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.test.lib.security; + +import java.io.ByteArrayOutputStream; +import java.security.SecureRandom; + +/// A custom implementation of `SecureRandom` that outputs a +/// predefined sequence of bytes. +/// +/// The `FixedSecureRandom` class is designed for testing and +/// controlled environments where predictable output is required. +/// Upon creation, the class is initialized with a fixed byte array. +/// Each call to `nextBytes()` will return these bytes in sequence, +/// ensuring that the output matches the provided input exactly. +/// An `IllegalStateException` will be thrown when the predefined +/// bytes are exhausted. +public class FixedSecureRandom extends SecureRandom { + + private byte[] buffer; + private int offset; + + // Multiple segments of ordered predefined bytes can be + // provided for convenience. For example, ML-KEM.KeyGen + // requires 2 blocks of 32-byte random data. + public FixedSecureRandom(byte[]... data) { + var os = new ByteArrayOutputStream(); + for (byte[] b : data) { + os.writeBytes(b); + } + buffer = os.toByteArray(); + offset = 0; + } + + @Override + public void nextBytes(byte[] bytes) { + if (bytes.length > buffer.length - offset) { + throw new IllegalStateException("Not enough bytes"); + } + System.arraycopy(buffer, offset, bytes, 0, bytes.length); + offset += bytes.length; + } + + /// {@return whether there are remaining used bytes} + /// + /// This method is useful to detect whether an algorithm + /// implementation has indeed consumed the required number + /// of bytes correctly. + public boolean hasRemaining() { + return offset != buffer.length; + } +} diff --git a/test/lib/jdk/test/lib/security/SeededSecureRandom.java b/test/lib/jdk/test/lib/security/SeededSecureRandom.java index f897677390ea..305a91c41d22 100644 --- a/test/lib/jdk/test/lib/security/SeededSecureRandom.java +++ b/test/lib/jdk/test/lib/security/SeededSecureRandom.java @@ -65,4 +65,10 @@ public byte[] generateSeed(int numBytes) { rnd.nextBytes(out); return out; } + + public byte[] nBytes(int n) { + var out = new byte[n]; + nextBytes(out); + return out; + } } diff --git a/test/micro/org/openjdk/bench/java/security/MLDSA.java b/test/micro/org/openjdk/bench/java/security/MLDSA.java new file mode 100644 index 000000000000..2dc33e2b2985 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/security/MLDSA.java @@ -0,0 +1,833 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.openjdk.bench.java.security; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.InterruptedException; +import java.security.DigestException; +import java.security.NoSuchAlgorithmException; +import java.security.KeyPair; +import java.util.Arrays; +import java.util.HexFormat; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@State(Scope.Thread) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@Fork(value = 3, jvmArgsAppend = {"--add-opens", "java.base/sun.security.provider=ALL-UNNAMED"}) + +public class MLDSA { + @Param({"ML-DSA-44", "ML-DSA-65", "ML-DSA-87"} ) + private static String algorithm; + + @State(Scope.Thread) + public static class MyState { + + Object mldsa44; + Object mldsa65; + Object mldsa87; + + MethodHandle keygen, siggen, sigver; + + @Setup(Level.Trial) + public void setup() throws Throwable, Exception { + + MethodHandles.Lookup lookup = MethodHandles.lookup(); + Class kClazz = Class.forName("sun.security.provider.ML_DSA"); + Constructor constructor = kClazz.getDeclaredConstructor( + int.class); + constructor.setAccessible(true); + + Method m = kClazz.getDeclaredMethod("generateKeyPairInternal", + byte[].class); + m.setAccessible(true); + keygen = lookup.unreflect(m); + + m = kClazz.getDeclaredMethod("signInternal", + byte[].class, byte[].class, byte[].class); + m.setAccessible(true); + siggen = lookup.unreflect(m); + + m = kClazz.getDeclaredMethod("verifyInternal", + byte[].class, byte[].class, byte[].class); + m.setAccessible(true); + sigver = lookup.unreflect(m); + + mldsa44 = constructor.newInstance(2); + mldsa65 = constructor.newInstance(3); + mldsa87 = constructor.newInstance(5); + } + } + + @Benchmark + public void keygen(MyState myState) throws Throwable { + switch (algorithm) { + case "ML-DSA-44": + for (KeyGenTestCase testCase : KeyGenTestCases44) { + myState.keygen.invoke(myState.mldsa44, testCase.seed); + } + break; + case "ML-DSA-65": + for (KeyGenTestCase testCase : KeyGenTestCases65) { + myState.keygen.invoke(myState.mldsa65, testCase.seed); + } + break; + case "ML-DSA-87": + for (KeyGenTestCase testCase : KeyGenTestCases87) { + myState.keygen.invoke(myState.mldsa87, testCase.seed); + } + break; + } + } + + @Benchmark + public void siggen(MyState myState) throws Throwable { + byte[] rnd = new byte[32]; + switch (algorithm) { + case "ML-DSA-44": + for (SigGenTestCase testCase : SigGenTestCases44) { + myState.siggen.invoke(myState.mldsa44, testCase.msg, + rnd, testCase.sk); + } + break; + case "ML-DSA-65": + for (SigGenTestCase testCase : SigGenTestCases65) { + myState.siggen.invoke(myState.mldsa65, testCase.msg, + rnd, testCase.sk); + } + break; + case "ML-DSA-87": + for (SigGenTestCase testCase : SigGenTestCases87) { + myState.siggen.invoke(myState.mldsa87, testCase.msg, + rnd, testCase.sk); + } + } + } + + @Benchmark + public void sigver(MyState myState) throws Throwable { + switch (algorithm) { + case "ML-DSA-44": + for (SigVerTestCase testCase : SigVerTestCases44) { + myState.sigver.invoke(myState.mldsa44, testCase.pk, + testCase.msg, testCase.sig); + } + break; + case "ML-DSA-65": + for (SigVerTestCase testCase : SigVerTestCases65) { + myState.sigver.invoke(myState.mldsa65, testCase.pk, + testCase.msg, testCase.sig); + } + break; + case "ML-DSA-87": + for (SigVerTestCase testCase : SigVerTestCases87) { + myState.sigver.invoke(myState.mldsa87, testCase.pk, + testCase.msg, testCase.sig); + } + } + } + + static class TestUtils { + static void printHex(String s, byte[] h) { + System.out.println(HexFormat.of().formatHex(h)); + } + static byte[] hexDecode(String s) { + return HexFormat.of().parseHex(s); + } + } + + record KeyGenTestCase( + byte[] seed) { + } + record SigGenTestCase( + byte[] sk, + byte[] msg, + byte[] sig) { + } + record SigVerTestCase( + byte[] pk, + byte[] msg, + byte[] sig) { + } + + static KeyGenTestCase[] KeyGenTestCases44 = new KeyGenTestCase[] { + new KeyGenTestCase( + TestUtils.hexDecode(""" +93EF2E6EF1FB08999D142ABE0295482370D3F43BDB254A78E2B0D5168ECA065F""") + ), + new KeyGenTestCase( + TestUtils.hexDecode(""" +D6A5D2325B94CA1B993A0151E24AB95B396F415831DC14A08404820AE58A2AD1""") + ), + new KeyGenTestCase( + TestUtils.hexDecode(""" +8A5E79B82DC81553BBE821EE367F0ADFA54F59A3E8A71CA626F873F638636DD7""") + ), + new KeyGenTestCase( + TestUtils.hexDecode(""" +6137CAB1DBF57A5CFCD0079BA87FAF2C7141EBB92DABBD45FD8B478D24AB8946""") + ), + new KeyGenTestCase( + TestUtils.hexDecode(""" +B9E2F48349350D30A5342783C915A608C905E0DA4BEBE2067FB62C714207C62B""") + ), + new KeyGenTestCase( + TestUtils.hexDecode(""" +2241FB7005D1B26A1735FFEA5186D08950B4B12CD4FF51BD263C6B8A2A2A18D0""") + ), + new KeyGenTestCase( + TestUtils.hexDecode(""" +32BA0BCE82AC978E5932BD14B1AC1A9319BA20412538191E2C7B1E0BD1D01CBE""") + ), + new KeyGenTestCase( + TestUtils.hexDecode(""" +0BE86B084CD4B31D855EBDED6DE39326516D4BA6770B76B1D4398FB2C9C75196""") + ), + new KeyGenTestCase( + TestUtils.hexDecode(""" +68E203AD881ECE7B354F6A760C87CE3C2F7A62EF1E12C71DC2A965517F0E196D""") + ), + new KeyGenTestCase( + TestUtils.hexDecode(""" +F09E23ABE72DF75EE36DC1C952F56564FA4213A987A0656FF758F3991BF4E1B3""") + ) + }; + + static SigGenTestCase[] SigGenTestCases44 = new SigGenTestCase[] { + new SigGenTestCase( + TestUtils.hexDecode(""" +C1623CC91C677078CAC1FE857F7DC40809F390BA0D51BE7BFBAD9B55306FB2E1C5B3DE04C3E7FE3E3B24A41F45F5FDD3E73A72EAED3B3F57356483D7CC102953873F519C79E445456157FDE4EA5F64D613E5ECB8C6258484AFA36AC4D31AF313FC17A5835184087F04CBCB7AE63D41AB1685FA02D1A64F5D0F844F6FB5213DB1C0444190B48DDC04111AB824DC342C19164CCB242803018284C2416206650A280D2020900A83314CC62DE1824C128489E0844518A22D141628D19290D01805490010E284500CB409E11429D2220118A30D10B561249449C2201213B525CBA020DB148DC3280853B0498B34262045919A424910098C89200553A00C12430060C060E33869C4428CD984648C8009C3C844E1886520478060264601140EC1046ACC4045E444921921921AA15023074A022444903470C33250C9384D824249444042809060842811021660C242251C102EC034060BA74D81224C5C286C50A861009388534062A32671524268D42225D9106C08314C231385994608CCA265E222685C804904080013236994864C23A03014184DC0063114488C5AB0850922080A396DD29045242588890286CC18858886700B474CD02461DC86511B932CA38031033764092446811802503671E44624A41632C9868CC236700CC489038910601670428811414042A0A224D92831E344451A2548A30281C024701348224BA06003C38DE1184C59A64954A46810348D4B34815A00215C24018442685B088E920002DB42508A3071A39881811871E4A069A0180603203022C68C8212824A180561A4311402301494691840619A482919868051308414A30C01350D94362DCC220820368624280E623200531045A2388C1039498004465AA86C892682E2C601CA14652340704A246502882520B56508025124248EA42408018270D036804940211834681C862490241018239023406841384D1028718C4226D1B04099249214219140362C0B216689A268A23280014545A0320C89806492466DDA0802D0326E9BC808D2A249E0006D5A226A93B42020364E413669A1124C10A2901CC66D99B26C92442600004A1AC36C9C4221E2B66C58120409850420884D19A930D3347159128D024271C0140603A790D1806C00296D58B8011A29441A308124A58C82B070D2B60021270E48A809248709192585593462A4460C13160E8B844C4AC07154946D22235003244AD0808D83B644CB066289C250C8486811407242C409138268D0B66980B46D52097202586725A9DD16DFD951EFB6F6FE3231A2C471231B53057FD316DB0876691543D51B66FE1CD1ADF7A9A73C97CB74056DEB19AAAE8DAEC4EE2D512F19B5521DF260609A5F1DD23CA4EEBFECAEBC9CB0DD9D612D0AF491655C6B22A2AB52C6BDF09B8C05784D2BE8832EE184F7D7EEC0C15F06052258A5DD658C74DE50D9F351979A1B0E5D4C94832DEB34A09F08422C53BE60568F81F379B76F5C1F85A0E74434942DC524D85C26A8489C273643CDBE8662EE0D7EBE56C7E4AC93D84016D99C0C180D24B6B3A9234E60A01A83DD64446DE5DBF8AA770BDC66097BAD4261AC8878450653F21EC34CD3E6F1303C44A4D29C9E801D6E87DEF63D4D35F7516A992B788913829191A09E9526F8CBC361D6530EDA7EC9013AAC629177CCB744CAAA8ADAC376F0222B97997F273BF7098FC39A63B899CF35D2E9D397F0D2A49D320B03A9FFF21D98D307DFA94A328E04BEE9D58B77C53303779973495E3EDEE49BAB18E3634E23E363E1F46F087D8CFBBBA8A210661C6E790A6A6449E0CC2738DE05A034BFEDD377C0AB454D4F39FA6F4E91FDFCBE621D0AF8F84197B4762CAF6D5992643A16BE5626E52CC0ED24895F629B02D3CFC92E98BEFDB1DC80475FC9EA7A40EFBEF650355B03B76E7887BDBC2D4EF8FBCDD6D95E260FE6561F17C44E1E01F6712DD0E5F7EB89766AF3FC9370A7C168F64746FB8F744D146CA781C6C708A963EB90858930875223CA379428A71D8008C70264C87E420ECF17DC963D3D7E3C8F280A8716EB636FFB857E8AB92847CEAE7C77FD2970DA98D08E001AC9605BDD6A07885B330F04AF2DDDA3EE6E9314C012E3FB14358D67070014A728B6ED5006622052EB43B77EA3E5DDAA0BB1C1C6A973C8A455786A76A673B5F4BDD339258A7218F4A210F0BFA65B4A07EDBB199EE755B8F60CC001026107163EFCEFA41DF85065D46FBA9471513268517F06B5914F0C625F3C40DCFE428853BB58B10FC19C2685007AE56F42CD6730CB4A6283BA4AC4B40AD9D9B2FEA1C2916111C39BAF1430612E569227E2C6AEB11E0451AF81E308F3BD59CBE29D940E2CA1653F6D6C70CB1D3358392F2A97A34FB9BF05203FF507DA2041AFD85E4643A77CFA441963E282B7B2A5A2B8D293D036CB5143F3E01722E589840DFF12186B7D9799A3D74E99288FBCDB6D2CBAD2E5FD4B449AABE16A12924AEBD33AE5F61856EC66F44C0B09FAF4D0C20CD0C59D760368B335CDA9422C695653E06C0E839EA7FE946237B222F61F9F02B3AC916D030560B8ACD07A41E7D54C402FA7CF6983F09D3E46EE6A7F786FA39DC369E0EC4A30BF734C636DAE26D756AA781E40BD1530A0BDD4040AC17329DD6B90534491CB2AE4D179C2215CEB1F466E7D871D42FB21106834D72BBD656D836F09FDFF875B0029D9F3B50BE25BF05D6A2B0EE322E969247609E16D321CC928C3C7F9CAC3C9F53358D066EE23B52837FFDA6CE77D6235DA4FC06869BFFF3FBA209E8255EB6DE7DC40D0C89969DE0D33B5E54151378BD3021C2A8879BBACEF98AC7F542CEF27F8C639FDD3BF0A0194BCA92E46D6AB5C44C7CD960B1409A088304D807AE67442712E3F72171E06FBA8CE1CE2A6A15562F6BD6968D15339233C5BDD9A5A9796C1DF657F08BD90D1EB5126314B16324A63ED2E8486716B38DFDEC3B14BFE21B2D710BC4DF2ED5A45993DFA197E5B190BC11275E5D9B2BBDAD69E819E4FB4EC859B8C6D32D6F21A7CB35E62ABAC2892E0C6C76D6A416FE3E5CE80361204CDD30C584344C3E61BF91A239B626D8C57750CE0FC4BEAB5743F93083BA01FCF2A9B4CE04BB80AD8B3652C28F4A81D96ABF4716E8EB090817710AB2D052366391F1897C7512F221221B2EEAE39D36C24B919CEA2EA7EFC42CA4FD6FEF946BC241106F12FB82B12D947527723E32BF5029EF8E6C6EEC47C54FFA329D8832F43811EF85FF1B2133FB6240849D7435EA99DFA76EC12ACD6E7AD590889441FBAF7278F019849872D9F4A281764005CC34951CA11C2CD1CE31E51CD2C9EA8E4185274188718D56780DA3F7D234FF14422697B3B4B3936BB1607BB9F048A69A293C7C9DF377E380C9EF8B39990E6D7FFCD4FEAD58C1E5249EA58F9ACE95BEFC1A904B6BDC284577D8FB618278D1F132DE15E55A09FA1A558999298A02B3787C5E53B34EE7D017599CEAEFEF80AAE2953E1CEC97E880349C2AEDF507B3AC853EDD5C0D8081500DAA684A20CE3462E1338917748A2869C9708C5A282FB7D66CA0AADA519FC56874D158D8951BC66EDF57EAF987044C7349CAB7C91BEC1655F22006182084F1A65C356CA2AE8AEACE36D3C5EA966C23F047EA10F1681B679"""), + TestUtils.hexDecode(""" +430B1F46E87DDE9A3D055A7D4D6AB1277B2DA6EDA642896412126391AA2B29AFD81C246EC839929F5C06749491DC4D81D58CC989D8500B6879E8807B1C3AA0B199EB599AEB86B344B77E3DB1AA034C938D80CB4BDCC29B31B710F57C7E491D99B71E97DD6FDA01A0D8A54C7481C2786F64FFC53AD358CF31C9C875ED278CEA03F2BF732372B19252BB9FA4ABF465FA2CFD1C08684D10582B410A8E012DBD407C5140D97CEE768C6D68124B2C84113B58C9A2AA67093B44CC3B6199FF1EFA6506CC28BD30BEC4CEA88411A491DD948DDB09ADFB92C40CA50E709840BC1F107E0CA428C111EC4505C5346E74AE4AB5647C1EB80F9C07092F8D39A975C4890317F9C0EF474110AB941949029BF39ADFB8E65CCAC0360A3EFCEB69D2BD805E4FC8D0620F8E039BC046DFEF1ADB03F5995FF62AD41352D479084EF3E302578B83332506918CFAD6E3BA701C94B0138DF0CF6C2948049274CE61EE0A64E756306273A02D68F3C405883F2F668820356812B2DA3A32B9FF23608DFA559183151221F83DCA18253FCA099FE24728F302C8B7808D7AF978299F3EB853A8BECDA46B8657598BE9ECE8A02DD4B25C593DDCB436B82335EF9C6A7B8426B701C66C9EBBFB3C8405A73881DAB57D1664F3AEC6F5BA19155D89A0A80B5D01C46BC79E1D4338A50B203397CD4B16ACD597A7C77C49917E9FE4B0D761065CB89C758498868B14BE2B6FF758745AFDC535EAA605C3F97648034D2A320264150278A7F1CB114B977C9D6BC1F29295CCCA16B23B7709D5608E4095E41D08B22AEC6289ED402414787062B0DA2387B6DEE76B32E42C51788B65E815E089BCF92D778F49A9707D37FCFBDF8CEF953A48A4201FA0173529BA360BFA6A77200F57FD5245146C2CD7FE8882670EE6878386D06036F0E1BA4B728CFB75806F05BA6409C514731B0BA8DA11015A63A8B5B5AB8C69703185191D12C5611F1407E8FFE3E50FC39C3310EF4091BC09FECC11D3AC107C696EE89F74CD6147830B4B3A971A0027747B62C528F6D858D1F9E67F59496C6B4E9E03FF0A598B26625B06C79863B5F07E265A40175E1A6D6EF3F900F3C4A28AD3E49D4D0B7E4ECEBB79244264474CCBFADA43FCD33F4FEBEB0F7E5928479F869D6A0FE52EB0CAC1232D7F674A057DEC4C2248934A40F5E2C9CBFDD53F71FC3BE06E48E13398ED426D8D3CC82118B7E8E5BDCA248380F4E64C427D1BF2384F60F6A07F01EE62AA1746CB143F26412547E7EF0E8FD1F2DC606F3643DEAF330D81CD6309465F9ED7F34D9B175FE1641D90212D4FFFB91CC300E7DFA0C555F7B35D2AF6A343D1467436EEC7AB95F2C34010FC99D66391377770A7DB8CD4D5C6BBF931092322741929F790E037318D6ADB74B4768C11F0E4674D18185DFB3D051725F93800CD38F58688AAC747F885908804D6CADAEDECB43131D75B18FBA2D4BED8D9BCC2156FB23F8F6378C622153EA8301300D0FCDEF1E2BB4E6F807784EA0171E95C372EC19B05A6C7B8DECE7080A057D29CE5A445A83410EB83B174590647424736A3B6967BCDF8A416A51202CE3F00E4D97DCC2C48A78D12CDA98E94A9BD6CCBE09DAF8085304F6911ECED3547DE9512461E16721322E4E6233BC7CA360A9004DA5AE064514603EFF0DF4E2D8EB04E9574C59F3AC14726C10100C688203F4960197CE696730AD7E558D7B939E3E6E7EAC4E70A7F6AAA80C1F1546E282B5CC7AA193213769B137C7F450AE5410817166F29F2E4E7E962932DF282A9F08A1DEF3E19C251F95611DDA9CFF4E2FED873439B45F8451B9AE06C6B2C698778BC4C742708BDB54CB35B686F0E7FC856CDBF977AFB663DFE44F7FCCE0E0555BE81EB28984BAFBD6FED3F0182F78A1396AF7B7081280864E5E4BFD7C52DA28BB5DE5FFA211678D13D41BF825F4B21BE1CBD29719ABA341E7B0C3F101CEDFE2F709E4DA4B5A6D0C021152AB546837024F4DCC4C45C132A038315A0F1D69AE768F70606D070169AE0818685C4BDB7341BFE15AA0455F535766FBEBB50875246A6DAE86C7B9F6F3A9FE01AB9928A99C13E6628431D41C1506381A63FAAB57BFB3B180F5D7FF59A434233EBC5A659B71CAE6970CC838D5FB638676216E3B16E8BA6C01349A7482AAF32ABD17DF7FAB8C69789F0194022BC4E62B6A6AAA4CDEF13B1E3BF5E1F4FA69F82B1EE3FDCC16DDE1106E3D2C41F6E661E33984DE7AD6021EAAD3E64D8C9CD7B5CB538AF88DB82FA048E5705EFDAC0EF479827EDCA0255BA60771A5EBC716C690CD3AC840FB6FF462063503D68C199050BFBD64533D94E093A47658822A25D54CBBFC689DFCBEB1DDD5BC6190B8F02C6FF3D001AC63729D35C8C50FAD3DCA2E67C5CCC6A8799420B159C7C5CACAB958B423964C489DAB1982A4E2222D700BA5AB772C4A11A44FF64018AF477D054217EAE28FB8E37595941FEE7AF87FD44960A144DB0CE2A44B33DC79B1EE31CAF80DAD620666D0ACEA76841EEE6CE81C6FF1F6D1027502EF89F1595065CDEC19B30E4B5314EFD64031B3B9DDFC6C95A4943247ADF7E4C93350C241ECA71260A454707B84017C5EB7AFFEB5DBB863A1CBDE0062C662308A2E824CDF6397863EF78F62319E2873B506F8A9EE82135B803025D962E609E006961EA3F7B67347518E70D9273893D79530F67CB678D6A8D28A0342BAF904BFC0A69AD575CDA4AB73AF22B52AE5D58372E0C26795CA96A16B8461AC61E6F68433ABCEFCBC16B857A89C475D1A322D34266539A17D485B8FA356EC3E154D37BAFC4CE75829FBE8BC823FAFF15A49F847C286F999A1F2C12B03E8F8A4C34A97588D91971279FFCB100EDB943E636F78ABFBAF88BCA5C55C935F6147E51BF798267E1350D2F5E3F74B339F6EFE86208C5BDE149C5B71056BEE748D06614AFEAF6DDA2A6EFFBB56B0880AF9B201B3C12055D292E3BB556240DD031C29A67BF244F59112BFB6865EEEC1DFE1CDB1E27F0A9E3372638FE4407099D0E54E9A188079C8BB9470BE6F63C83612D80BD60C21B251B64236E5CAF09A11C12F1A5E94F199DBC7C9E394C0B0E07A583E707E5241B8FB33E39BB26C31929F39316F4FDE206493566E17B51CE635420493176D8FD353206EF87F0994F039DF8F008AF602F50D7F9C0051B56227F3A2ED20B29611219FC4376234EB900093A81389ED00991272B739389F1F978A92A3E41F0A28985D697C01240875AC46A82B2FE94004CBD7B1E7594AE38A9DA0E84FE7E122482BB391538EB8E85AF9DC022CB32CC08FDA7A95165725EC29A0F824F97F0251BE636B57E0791A7F50EE190D45749472B29A674239AF95B373A40A6E0E09C674071186B125EF5AF72CB434AC0AA990341F063EBFE30963451491474B603733959A23A6D5B8A378F15A5A5B9CE4BA44BAEF6AA531AF5097ADE73F64AED0A541784119665F548FAEB447DE108AB74A74893017F0A1AF84AEF0730B555767B0CF6AE502E7693374D2E01C54C64E411AA93C96DC5FA010267B387299D4376FBB190E1C51A560871B559FC800D82ABD119A5732B50270BEDBCC8A636E7499149AE0E47F736FDB71EBF1995D1E8BDCB0EE96E732E8C2509F98717C3D174C78A4A2BE43DD89195408CD300505A219305809A1BFE7294BC2EECE6D98C768A8A1E0F74B665EE3D652AE8E008EBBB11F0D2148E4E5C93D7FE0190D27B3EBB7D2194BFBB624AF3A894CEF7AED571954D006824950A981F4ADA72BEAA0D820C5DD9BD519D39BB7915681F266DA66D49BDAB9E55879B953A7332F877DC5F5CC7BB3C9E1C1F2E41EB55EFC02A450B5142514F1E06D43E48FBF5DC80DF241169D5936432BFE9BE99DCB17293CF968A17F3111C884635EF2BEDFC87DBB80BF25EE9BF57B55CFE635FD99554F5FF2B4482D1948BD282FA282C48C0302348982E30A772BF14195CAC7FE39F836E6238EB1E1FD074E63B9AD0A8D37111087E47FE5D04B62DEB496353457BC76C53A2FC9D5AC9AE6A47F632E6D45E08786DA128464FF2266BFF92B5CD89176A19226F2EB14CDEB331C497F1836FB6C0A117ED6BAF95E9DB8254487B0DFA7301397AA29D95FF2065D851BD302B747AB47BA0AF408B51E4BBBF042ED1B2B604EEF4C266FE243261515778BC9451A8DFB025FA3212E868C3A078C7CFF65077DE94E50ED90A259FAFAEB398A94FF15C838EFA7F49904BEAFCCECD8C9ED4E014EA00C7AEF1D437DA306E8B7DFCE536912C169BAF0A3B78A643D6E210E5550E3B2BAF7EDFE01E721E3D05BAC1378EC1DFDEB2E2AC0F0BC368E0A8CC64F375DFEA2FC20CBDC515440FC2ABBBCEA3584E103BD686C5403EFE376D44F5242D35C9F9D35E1A869FFCB6657823EA0D4331ADD5CCFA99BD6EB3494A48ABBA7B7ABC32ACB8FF00512E1B0AD493F579898847E328C06FE05FE282F8D4AF48A1AAD0495AF1AC7354275A6D45AD5A7B3F6787F893EA558BC5D4ADDE1F0D265ABF73C86550D25C00821C3138B385448E3E02901E2E6EBC6A0F211CB6F22F8F865F0DF3893B987DD086B6674F5464ACE18B9F0EAE948667B2FC04FECEA3E2B7EA6B869D5F66D02D4DB124A59621B96E0DEFBF99A91AFA0CFD6D5A5968E62EF42B4C8908C3719BA0254929A9A183D50C566CE4FC970E047474490FFB07F576765AC5286B2E0FDBF1EC56A8AE8E6F560C69614FDF5C89BA53B8B7189E6388F7CDF7B819F78F3E6EA54C40865262BD2C8CE87284FEC36E2E73BDB8AA9CB5283272A90A6BBBFC3F7FED5F124E8BFD770B6254CDC695FBA0D8627315370E2CCDB89BCC84C96E20805AAF087F9E9BD1A189F4C6D66A6DC3FEF773788B3B57EF876CFEAE1F2C876CD239BE3B8A94F21350EDAE6C269698CC66BAF90B3641593F96399C71B2ECBE50F61B5D6F37D47DF702A9B9E47BED2824DEB19ADE7D7D8830A8F610088CF4BD0AD22A5A4FBA767D01987688BE710235A74129666FF7917B506A18E6B5D6166E8B682BE6B1946A4D4420926FF8CDF2488EABE71EFA7F2536B9DBEFBA08BB9E94086F55B1B991E18E6023E6952D4A563F2420A1536A1EDDE119E5779223CB712AB5C0BA4F0C176830FE523DD8603F1B316E128579E65454C2BE62C922C1DFE09DFB47D4497CC552AA9987A8BFE19C44E207397204686C718A0936145FC102B8A7111F74A421226AE016EDE658DE5DF9D3C28A247A87F2BC6FECF66CE7A6699880E0871CDB6F066D2CB3F9F625DC5E80751DBBC85982982E2EFAE3AB8F4F1EDA0D13C3B65FD2178E8AE4A712B521B7539785BB058176AB4396E6EFF2FD9052D4C6AF17DC30F50630233C3F05C62E151EECE13CE124E58A25F0F3AB65033ACAC9EA6E41CB3FA435D367DFEB0B9C9B37414CF32DC85A3C43087A578165C86D100E47DBA1FE7061111AAA961E67ED057C715974D3144912A58B6DB22D51BEDF6A8646D810190D91B61F0776DA00C8B0BAA7A83F4433F357E758F5AE8F278119908497E717A7AD25B09EA7C76B306A9A3AFCD9AE6B4F64016D5E80BD3FBE2F5EE673A7459B03AD9356148EA83461B66716346DBE85678C37C932EBC53B033A3F46DC28219880CFA8BB5E15F8862D345923BBC179FD763A0F943FC56BAB69F26C0C15D668BAD923D7AE6B35C07621768F9D972E2D6F46551D45E3FBBB577D13F01E8C1AFDBDD2F052E931C0529380F290FA1DE8BF5A11F82612943BAA2C0D086EBEC84069B271AC8656883F686C67B1808E27C860ECD1B95FF6CC6E6A5846DA29992CBA450081B8C37DD4911470EFF281FE94F10636A29B790E41EA6A342A5BE79CAF575FE9B0147F2EFE02874BC8A0E136A395B42E77D9F18CA4F61501E6C1805CDCDC10D0292593481F7E0F93281D0456EB51F6ABB7C379C028890F445D9FAC0D96AF68CDF6CC879A406CF2F0991916B33A72A193CF170B45AA079DB1BFD4B4126FA9AD3ED13FC98CE4C6C3C30923C8C53BCE1812B21BB644ED3A0CC0596C60032FFB1462DF5182528553AE865BF87FB7C7F61D1FD8E40D830B8D8F54924EDF934D1EBB88DA90BC59EEF1F6BF9FC2D17D8E9E0E39FFAD22EB84EFF39BAA70447B124E492D760E55D6301DCDFBCF9173FE293AC4D6CAF2E1964B32973067EC76BBECC65113C1FAB85375D92CE1436E1D1B205A88202B304264620B282E62CAAF5CFE1169EDAD9459B15BF0060C5744A17460F9FB164974CC55B3FFA71AAC13437BE58325E5E27E151C71D195F886F5630925D441A54695DF23F64C6BC3B0CA83F0E88D01BA4DC748A29F42AC2997C2A21EC258E430032C09E73E73AC2B21B55E1DFB2DBA281426620A0545D2507D1E96A3778C780FE77F1DA3B615E1B0D14DE8729229472E6619AB3B67CCAF21CFBFFD1F237E780927F147425B2142BF62CAD6B467A10F7B3DB922F095A0012EC179C4F8D5437AA8024F13A2A485E8890940DB69FB719B94B7D2629D277B593B94ECC744AA4CFF3D33D2250236C74DA057496BEFDB961B89BD6F44D581AD7A28524A6AF2253FD27530B7FF16FB5804FCA7E44BA2A3AB85FEDEED837DC130F533E8215B3AC3F584A2EC0E9B6194F97741EC050576E16349AD852DE8AAE2BF83CB1894107299F101AD5A2C05EC590B2CC698663C44FC0DC7F893F42BC5A2DECFF2FAF46CC1C00FA7294A0184A85CDDA2B1F38A89B1B17EC08555D082411A4CAEDED562C9FBBC1F512118EEC3BC931CC91636461151BDA454C4F029E01231BF170EBE17C526F3D8F705DC46560642B1AF36E3B401325A6CF59B88BCD4B3242D676FF4066E4252ADCA37786CBDB340DD81C5DD0540992F0B142C5A18D3BD1070719AF996E3C3768C3B234D303E6E9850B35C7AE52496C76106D7CAE4CF8ED01767B6DB5603F339FBAA019B08FA35E3DE1129A6A4D578264CF1FC8A1DBF218DD72B4865214DAA795A00505D4AE2B85E90F589065D65FC60CDD828007D4D3A4C084C7EC159C5D86817860CA03545FF74F17AD8570B2ADA55ECA12BFAB5C10067A086A34A57AAD8694C953137BBE901F8D3DEC27DB5DAD2AC96D56C312E25FE48BDC889373ED252B4F88D32DED6702B58D35A1FB40ABE2F2ABDE21CAA5FD0F67E7407A8"""), + TestUtils.hexDecode(""" +8C94308B9CAEA02AAFC29AB18EC01929A029D49F06F3BB4EA3110B1A9A415C77DF646A68302FFB4D853F8B9AFDD4D46B30ADA30213D763551A2FB98F690296DA77F08B3A1C2363EABE33DB1A891C331932EA22902277F44D68A0001D339C1108C3815A68DD0F7396119FB1DC888E10E3A95182E5A185E9CFB0F76CE84ABC199F7D58C7DE375F74EBC6B3338E3F6C51070336A1D513B3BF6FF4250313A52282D32DC616EA4B2B83A1861024AF9ABA17FE0159544800AEE0534511D9359415A66A6D79C2B3173B6281BFC3C96F07F944CEA0841DDEC3BA1ED9B337ECCBA219C675A13A1466463C128FF79E5C8F1BCE22220E1EBD1A071AEAA32E5506B553176309E1EF15AE7C15BD361EF6676046996132716B5391E9C0350C248A70A3552540963858FDDD3456FDA6707B99C120AFD925A47E4DA492DE65DD041E58A881A8E4125C3CAB474ED7D172F05FFAD0655FB7729AAC1C951AB05892198D713657936808A2E9795488F3F6E3183D0AB6B69B3484AC7B9F3C2AD65AAB9901992FAE9DC1E585D9CF7C71B4C7CEBB47EA07D534F9C869B114E3B0BF29ACC2CA60B91055E98643E7F16D3B4FB0477E3AF62C9BC5535565BAE2B8B276B33DFC50C3A14A62891435DB43DA2861154C654A4429ED865A373C28FF41F0C0ED11A1AB963838FF975EC9754C5FCAE3BAACB9ECDD920E365964DC321147A39653FE4B2F2D1EFBAF8D82B2198376C814FBCAEE96411B9E2D958D64AA731BBC1D6174D6EC139FDC73C9F3AB2886A92E0E82C700DD5A83F5EF0912ABE4CD30E0E3E9C8639C4B329B639DE189D8AAED2250F3BA74C381D6A4D333EDBEC2D1511B20A8144B42F0B5F674F4004F39CE1091BD431ABA3719D994893F4CF798F3CDFAEA9ED0AD5A3BF7DF0BF7E9E716CF2D3C72B17870780C724A0A0A2EED8E5CB4E8D15597DA311A4923BC8F6FDB64B9CCEF2C95BC026994ABA7C743F2FE83D5E771ACC2B6F8AEFCF6E1C7360767B9BF995778F95390C303C88FB81447EE993DDA266F031B9E4907811E3868F883AE4175D95C0B4C61092FDAFD2A41514408811828B3FF30150239C28C1E3E65631B178FA56D019BA08822C038F718BAA7A12FEF65C08A84E2E9D6E292774859574686AB024E2DAA6DEF1BED248EEAA02E0D28C73ECF803A250123636E6B8C642A10C3B8B3DA55706E17ED5EA96B80AA9D99E450513E16ACFE6A587896BF17254B4F420EED062775BD74CBC09ED7F925D10D34FBFB9EEBBEF6DC29ED87BDF01DD57EE8909BC0889BDA2AE430D8CF80E211EEA8C41DFCCE7DCD197352F60CAB92363FE4681DAA0C8F62ADD5FB1874151E1EBD8BC025A8341C46D335DED5293F012E7E9C2A8CA2234E1E5970E6C51C6711ED16494472205878ACCEEFC98850E3AEB99F10B6A07CC3A31CA742F1F93B4104496EEE8DBF0480AB395310ED09D8C7A117AD8A9F5C4A3050807A600613723555189F22ECB98F01ED8E69D113A03923B9C0C8889F094B30BC16792565F3CCF427EE9F0BF24AD436DB5C40E6FB66BC416009DF2F4D422A9C719585D47B95BF274063B64540B672A373073FF87291A62C7B9838446321B71356E7BB5EB096E9EB13B51A50EE891A2412E2117A5275DB0265889D74D9AB9FEE8AD1B039A0EF471F1410AAC97323E30DA2F91FF22D33DC9C8379211A404E32EB01786EA0CBD618821F710F093DD276F52A10416648E52879ED2A7FF6821EC49768D687984397D532C20B7050ADCB4330037D1EA1108B3A98ADFBB5457B05C8027E1E9433BCD89ACA8A84B802634C0759BA1AC6C144097E0EEB0A8E1A3A64E3E66A09D443E49ED53FA8FA8A295AEECB459D4CC32109EB999A4BC3CDD4D744EE7D9A73F07D763B8F80F4BFC63002CA3EAB87319EB69DF4A25FF1A7CDB72A74CDCD2E49B5A9D780ADDF902B9FC31F90AE788AFC954074E010B495885153DA0CDD15B26C6436D077A040165B6454A24B2E2162F9FF31B9C4B9199934A7A1FC78C68704B9BB784B0FA15A84AEA9E70D51000D7F335E450A026AA935533DF695F471739D9924D452B3C3D84DC597442A92E9A5C950C72B80138BD6154214720D8F19EA7E99328770A48069506F22869FC67129656E26E8E85242FB6E93B466B5277E8FB8B235A221A86A1191801B6B2EF236DCF910CE2FA399F8CEF28F148E977B762C8A828D57ED48C95711A479090255308196CD168B3C6C49777FF0E4D2319B1C44954E9A20C07E23F79CF1096DAF01ECEF4D47BA517554FCC1C6D139CD2F9F5754B61963DED55FA7638FE20041D4E689E6256A305AE0BF096EE9ADB9A76EBA46F5183575E8CF70CC6F69E5AD1DE54159E5339D818EDD92A2B9345AD759DB829C6BAB42398922788DAE97AF3F12A4354014F147A27E267495208978D736C632A5F0270C561353B27BE23CEAB57AD68D02F9AA94F301D3FCEF3E6E234BACE92F5D8BB1F975400D0D6B22F1347DB350CDBC71DB4519BBA4FB5C243A91BD0DA06C1155514E45184581815C7229AB66C921F2BC95655CED4A32D128FBB6B8BAFF83708CB49F69502D90BCEB6BD55DBDE19732098D1D1C1A26C74FE56DB0470C5E76BC6F4927A34D6BD84E57233E37127146295E5F19AABB77F9A6F90D702A58CB0EC0648AA54753AFE9140A9A60EF9814E43A916F07043819F09BA02A7A84525C34D3492C67ACA7C5489B72084CA7D1D5CF2A061394FAC77DCA111DAEBB9CF6C1B270A027F8D2EE04E0BB68D6BFA136640D04366864213F9EB3406A747B81EAD497416880A0CFF50F95784C044E58BC0839E6D36FCA9A45374A4059C812EC2B47AF8FC3A99540A62EF1C4B6D75FED8AFE7DCAF37832A02B3BC0339CF41A6F42733A584DA80A8CB328A5E6E59848DC23A0C0332F529853B138ABD0D3F2A8D2FEBC1D71E249E1FFED726E4664FC3020566BB769D4F3CBC8A735FC7309AFF545C3F87560BBE3D5016FC99CCBA9F5410030A86858F320DA5058DB5A188E68164E2349EE036B6904E5229920A7580206D3B75E89A8EED7ABF650D69494A13E83F37F841A4FB2A7F1BA538D40F84F25DBC0EC78DEC1B5F29F1A27198291365257819922F1A42104C721ABC95B2D610B0DB4576401E70B1760184DBC285EDDDD0788DEB108E824A21B8E98F0CD8A60557D183D16162F32C3D7C7353C3DC402A8B96EE8C5408A4D525517F76EF11238DA98E8069402FAA2A9A64350C4AE80F033A52209E66FC36F1802552292F706BB6B703C8E1FD66DF7DE25B4167EBF2E6F8189D8AE114460A1B0C0398CEE7BCE10D022833BEEFCA70D5BD174446CEA2C23DA0426303D45535C5F7E81838F93979DA4BFE71729373C426366787E899CA1ADB1C8D1E5EBED05315F646A798795ADBDDDE5EAFC1A4D6F7884929ADFE4E8EC0000000000000000000000000000000000001225333E""") + ), + + new SigGenTestCase( + TestUtils.hexDecode(""" +D9C4374117AAD1691D8CF8789E3E9544C379C5021B04E4BAEDF25FB2BF7225CC5530437B7D76D449CF4749DDDD18BED539BE7661D0803A4D7F379DFA3FB293A0B1A5F48C7818986FB379E41A921DF4726396F2DF788606A8C8C5B4E973968545A66B1467245A5A9140C7ADD5083090B658C7654630272C9A25C1CDAB4DB6521DD49641491664C1A06192B68420970153A825DB263249429018088C13289121236A0C022912276604194109360D52948812C93004209092142E22B52C24900DA086248C940D01A62D1B948D84A8300B868541902C00316D8A306203C47003B4440BA6201382515CA42489884403204A00338403B72498142A5888681C12611B116A18C16D5C8248A316815C1630898464C4320403A731892289602424A1464A490868E2B64101146E8B884012270A4A242C020522C320411028124A868C04358902B6259A244A8C008D0820882202320A3442E2308E9094900CA730C44046911261191708D0126A81308DA2204CA2165221134498063264046E23B461A1162A1383710323421C042A1C840D840886921070C0160E03198AD4A2811A484C53200919079080C49009400198A885583682931882A4184C530805D8C648E12272C3C80944348ECBC650523610D3A481D2244121412C8C028D52B4210A244C44B8641109099C440AC2380E9036082016645C30314220725C48440B3306A2C24CC0B689CB26801CC388D3306E1C9261223108E282680A1852639224E3322A093260C8C2842085485B240603830511850903246E61880509A851011500120592DAC8419B826D4832660C2121C3166882084221359059389020C20801824951808D101406010431938201CAA8858C44504B4680A3265022470ED028500CA60520928113232A409449103865DA808DE1208E40B401C844261B808501294651922403490452124090B48914294E21858500A565DC2012193584C02668544608DA82451346055BA808894090A346708C4410DC349049A86D110742242288DA388094364181188C4C086C09150E0BC4290C070083422841342D122508C40865C8B004121631C43430A044900C4822D8086EC918815420214C8821A49088CA320E209361C8B8605C04529228900045501C0829CB0646C0180A03232542004C11276E0B448D02A7110489005CA021881071D9A201D0028CA3B08C01252064102652946401116E8A002E0C05465A186D1418405C464C1A0732CCB820D28420C224710000628A1088DDBE8BE20BD3D9163E7CD8E081F70C5EA00959FDAC57B0D8DC10873C27E22EE17981C4E689700036D682BDBA68454F9B7C394C50CAC4DE6A8CC734850F95764B228134B9AF1E0BCE16A593EB6CFBE451620DBBBE3666E3B248FEB4E5306609AEAFC331E92965C0479F86FA1AD47F1C4A793B2904949ADC0B4FE939DBBCF05066CD0E230A8E485C26F41533BD744AC8E442CD1358991B0C11A90CA17697CA7130FBF44DDF626B7F4D2FEB954FDC64B1D3EC0B72AE26B90B5100C649BCC89172FCCE6558F28EC5B764DB91EBE971C7E881D879956210BE220D6607BD9EAE2C72C4B413D8DCEB01F386C0EB8A1F8EBCB4053B6BCC383303DA64635B9CE7892662F8680905429617EAE18C58DE9380FB69F558FA1B706733A1B7B324B92FCDAB07438F020F0449A70B8F602B5A9702C771B2B3A4A906B2D27CBD824AC5A207A2FFFF1FF1FAC38EB85DC30F3F17C799A1B8E71D7A69D1D5046C73AFC04DA3D1F6487D1CD41C4075E7A6BAA11048273A416B86578047057C6027F89E695C66A6880AC8053D5FC6360353F336F282281C32484840B3D7779A2B59DF42467C42100D382530A74613E147EF863FAC5CEE1522871427739EDD9E089C1327E10F39ABA9F27E66E074200DDCBD31C7CAEE7D4967D8DAF612AA0B5123A1FFD4F8EB379CB8097C3A49E7F45ED5872AC1A579F41D1A8B9AB4F1D0946A9AD6C2FF429385DBFAAF002E96D85DCC93978115CF1BBD5F69A54B3AEC88FA74EBB175ED930A5E47EF09138C0986811946388D4452AF4A07A1E8983333340F9FAF033A87C56855C8975471DEA335CE0E0A57D36E43E1FF5DAF699A5258DD22FBEA92C7F7D7DA258D250717A6EDC2082DDA972A36CFA6552F4397F502BA040145207F874D4E5B07222581646132A5CF5D5DE59F347056F5A52BD89C75B7EB3D48E2326C02AFA1822716A4B4D109F0DA405380BCAE4C7C673ABEB898DD21936195D3F3ADB1B3F042016ABFAB2670A977D1729A605F201DB816606DB7D73B1906C9C4A49C1687460E2093B51ED68F7C548F84C01372CB97FA557B2D7514355E4D0F77D22C0F245B6DEE89982F7C2DF3EE89AECAD428C9C6CE962BCF6DC898EA7AF0A0065EB4477771E97DD30DECF8F41B1B0BCB5DD84C20F502D894710F97B8E93A6ED694AC69A43B6E20F7FA885997D23DB912F1C5336EE2050A96EF1F4CBE9BB50F977C9035FDA05E063928069394C18393E988F715E64F02CE6C3A70AFD2403E3606721EBCA72E9D4A63E3E11707604587301CFC4D461EE07D337A9A1C74870B67457C22D9E4EFB60A5F6D405A184F972BA07CA8D702160BB598104B35F0C0DBC4105E3714A32A789C3C19E3CE8D19AB71FF69514F2CD7C488D6F999625405E9702C38EB3C5B50F53766BF51BA14015FFA2EDAF83B13CAA06060A30C9D3D44BDA226905C357384D027E05B3C0837C246629A070AECBE608E743E330ED18BA3F8DEB7F09F61808C527C5695C4F3FB8DD5F376EF656EC4AADBB21234E85C39CBB37910ED7A9E12D04AF813D3D87A7FCA55CE6F86A53C6432F9C99DD23AC297B217DE1079EE21F467EF700965A326C82CDC548084EBC5F9D0C3B48F75771ACC1C3C45A70388A0C65764829274062989F7A209B71D4051F26897C8FEB6AC847763463A0858B0B2F9CEC93454C35ECD5CCB9AB987B1957849E1EB610D2636FA7BBD08193A69227A34FF2BBAE787DE0F9EC719A3DD04018D3F4DAA2047C569C6B5BA52785FB44F24DC548BEFF25B3E51C24880469BB9D0749121C039BD7FB831D098B8DDF213023476DABCBBC778393F02B4077B57D392AFFA2215587D934025D148F435C1B49998C937BA3D0E7463C526D08DA8C67A2C305934E82B648D4A8CC3EC162E56A42575E944CB711C3AB0474EBECD829CA8E678C10782A284485F3D96A1DB852FEB36BC1748EAD20A342436FE63124C161183DB1BF5CDDC1436999764010C2F57E55BAE6788A7D653ABD03989A6F515DB7A76A77CF3E282E83FEBAA8326B9ADFA176685FFA1C6F9ECFEEF97953685EF2DBE311BA25E2D76F3950E005E4117585709447FEF5F1ED198B98DBA256B4BD2A430D7CDE4052A36D87905A8124AD317ED4DF338CBD1CF26BD02680944226BFAB3DE9149CF19C2519F639F9068825C0BEC1A7572C70B948BBCC290B95B0BF5106A8B2CA8FBF9CE34599E633EBA37254C250438218AB1D2A3EAA0C148AF2CBA48DCEDB11FA3B5D873BD161D24C65CF7DA109D1B8CA296071FF706E5666D66ED10E5B1FD78D2F993F76DA41EE8A9299D33C2ADC8303EC322449EEDA11FF245D03048E5701C7763D545EBCF540CC2CB0E3A06265F380C622FECEE4E"""), + TestUtils.hexDecode(""" +8F69A33C4CB9627BF27401D4A1BC131D28AD0E2E5A317CE983BA2CC7465861A414FB72745E4DA31C0E04576DFE0D0EE834A1EE323D5A0901DD0189EFD6718049E2FFE1AFA548BE16E04B8963325AEB0CA90238C7A243A3F6AA17BC1D63836898688AC8E919B8EB6D689075E050B4189A1FEC723E0AE8D4AAE9FB6790B527A7552CDA174BF40BF91C4142B076ED8CF112A871450AD994737FD5BCF513D42DB01906636D42C6C10B64F74BD37D68A966DE0F3BBE6541AEB9991DDD0C0070F16715C01820546A014E66D786B8922E905DE2BC65053C42703227B7D8431427E3EBB0DD010DC58C2343147700D673D5707160F234E35BA24516CEDEAC77AE15C667AEFA8E029FF14F169FC0A781593E11D42E8659DA8E91E53EE0A1FF15A3C203BBF9591584A99FF8BACDC37541E126B8CDF3503AB2D1BFC0C37F38A298AB1DDA150288A8110C052469382A9A4F5565778339AB327DD80644A26B218ACE0830E56813CAA658A9F17826CD12B815612BE40906ABC89185EDDFA8E05102842CF27BF040FC7B396E7E2E023CB86AB7AE25F36DA6B6C0842126658E0315D6D8F4B5DF38CA663B55998ABFC72FE9B7EB7CE3BEB72AF73A0B2A45577C5215C42E465EECF4A4E69B6DDC1E65E0C1EBCA"""), + TestUtils.hexDecode(""" +3639297077C2F61950A09D4AE55408D1822CBA6133C788347C1881F8E02400B683B012EF2D9EEBDB65029BCC9EECAD9881BDD4FFBCE8FB50242D9081E2C8C791577C800986BD7A03A3817A06E4D6609E288B3849AEFA840EB7B69C589AACF26B6332DF4210F3AB0E8DF14F918848B907FE9B09CFB91F32871B0ACDE0ECAB8915A0621CEDB4A591B1A6EC4B4B9F83F432A9B576D9E5D40AA57D24D408135E72C77281515A3783C8F3397C9E7D26B4543A528BFC1FE91965142D52FFFD2A26470EB821435914D346EC8765539D39083D743320FEDDBE31E08EA0E4ECCF74B231934B5757D460E5B79D16758F4A56E59C166C7F9F1BF6C1DEAF5478E97C8F55000475D523456724390D94AE9F5C4B3F96E86F1932412D740D04D1851560476D50D7B97B080BBDBDB7A347197F2ECE6603B0296C8833B5DDB95BDE239245F1BF27A7584F5B9243D906E4880CDAE82E5A7F1A71A7DF8AF9FC41C0FB4B63CD356CF5F36F94D20592BA58D1FCA9D354B358AE5423D7D5FCCEB05B831024EDC7DB64D6C9E45454790F8B4239BEA02983C5827E4D08E8DF3F795D46CBDE5D4955A6AF2A6E0D101CDF43F43D7F5DCB829A5A79881EC903C1B8522CCA5D8D4722FE29B36BA0C571DADDBAAABFD48DAC4D2603D768A92D8ECFAD5264A9081A74A2F7FD635220EC8A95695F2264075DCC05F69084EB8336588CDBD58CA028E02A2756C8A3081E720F281172F43194D8ACAD2F61F2DD4F01C235694FC20921EDCAFB9AFAC8FFB1A234FF35E68AD90086CDEF922C47C84ABB31112C6AD6CFFE0DA11C1999483609EA98573217C28B512ABDBA6F7A7E69FB8944D0B0C4B9CE7AAB52BB558A5411671385FE36903D148D11DE00A9007929094C54ADE5E9BA60AEE35D5014C7293FAD0158D69FA08E2CCFFBE2AD99C66A2FD2382E6D1C355481248F53A5130EB4743DF24EC048196CE056A7EB032FBF6FD07D12C153D06BFAC06C1AB23147F8139DDE1C00F9A9C6347456C148245E3C94F2C012284190CC3EB04ED006AAC3DD2F08D6D0AD54EF507D7E80671F12A3E4DE2136B6ECF02EDD28E75B985F73841F600EEB64F8E5CC101756AD7794DC14D187237BC82CF6531583DE7B0F60275E63976296A0A02E67298C20FC64A1A8B1CCECAD1DFEAD996A47E9B6DA0079AEB435FA40A53A4C0D565AF713DCDC8D4F16CAB00263058A9CA1F276A39172FABE34FD75422E64F23B2715B395C73F2335B6E4EE7E5BA8E2DE18EFA39FF1B0CD8C0C6F5618C971213E94BF2B9B18E05BDFDFD9DFD88CE24B392BE1ECAB51B95C0BBD9513F881DA789C57B1EEC8C53EE9CD4FAD5E7526B1F1462AD88F180243774B91A9CB219D4CF9730E682E2C6C8EB160131D3AED3D3B3E64EF6A1AD7ADE7048A0CCCB67852971330A62223A89733E06615508029823D397EFE221B35896C18E9BB08140C464F8466190CFD8B0F09E6EF46BC14753974AFA2CE926EB6B02F4EB25CFAE70C77A865CCAE8FF2415C0D81A82F3807A4BF61F6EFA9BA4A16D14E3169C2ED86B50059880D07897A67C882E9B10450DE3978ECD78EE2A3C2B2BD51544FE65ABB7909FE439355530D44244052F2154279B6395E77FF1B288103357C5F83177794D517B0D8A368C9B008838AA4139F1BD10E3ECAD45748804F45122F3384A1A2D541BB8B9FE3C478EC0AFD81EF69FB2A42CC9059CBBEF42633139C342627A604AD07D09AB962E7C1CD2E1F1FBAA633E00AC1EECD29B5324DDA5F273154E7E9D0AD3F78C6AA08E92C77BBA7CF202B94377872146C60E9384830DA573CD7E3BE362267CB74BCDE63FA708E15F5933E27117037F6C35F91D03DA285222FD3F29C440DE820C89F6F37C250F82F0B20E69D728A680095B59AF058A06E46CA75B6BB1E2B0E14D2C9C4705A080B9B826E2F1F96CAC70A902894B416C68171B7388F4FD6BFC4BCF7A6745F3AC83B8A31F869C64F67C5600F35202D3F45E697F46DB1991AEA695443C79810796CF0C0150A83E24B2DA00DC72364CD34C2BF6A9F1EC4C39BE42F8A7E9DCC3BB6D0BB6198FC08C9743335262D996C489C460DA87FF75D4B75367C17A466AE08D24D736EA63A6B0087041426C03BC94BA143264086C94B4C8A3F6B7914CE40EB7FEB876CF16A2F12C66AE3EC3B57A93866F63E56666AC7B59D3C78536D77F73E9E9BEF9899EF390E8BDA6E2AD5CAC671153C348C804F65408309A08B2E78FE79F014ACD99766B383E5869F3A3562B4A312CEFB3D8F5B90FE769365E1640520C817B6A3A26734F406D104CB7AC9B6DCE371AE3D7D10E265EA370C0C78D0685F9BE4B3E9E097A334F53E47C016215719A5A25EAFCA799BD13F5B23C63CF372972F5588B8A125AAC58A0ADF961A6D0A2646F9520DF6699B67293ACE799C784CFF813CD508317ECF90726D638A13AFE574BAF3D2E9F39103DC199510AE4B28FED016993FB16CBA627C820F4B76227044F39AF0B8222E1D387C7005080E5CC216E22AFB8F591074938A3510AEF62D18D8CBC9978A8284DDEC00F7BD3C75F724540174416CFEF71D5BE602FEAAC4EDABCB72F7252471F4A3D01A5D1BD82F98A7BAF66CD6193E17499741810B68B1B066C827FF18763CC557946FE1B60C706606F7CE607047F18D93593A7859BD669642FA74EF569C31F811AFEA327962E02FED620011AC0B96C6CA3AD9120EF1C3DB3C9EC43E7C4E1A255C822EBDBD71080C103EAFF847973B30AD88C40CDEA8E19750BAD8E298D8B0569CF6D3F99DCA585B418355ED039B585F9F829DFD4460A748083ED38C6DD9A93C34447AF47B339C5621D908838469326D318C41ECF288B16C62040EC628DEA4C29DE18F6BD3793BE057B52BD0AE44EC5AB575383FCF35EA91E74ED011792C415934B16CE8D4E9C2416C1C79C1C8B09DC94E005DE0D9B8BFDD07552140D3EAC45EBBBE9E164BFA885940702281DC14142E236AB3307EED9A2F4A88AF5FB61D771ACC92B2306B08F5D8F740C3F10BFD5368A744BB6590AC29295085EC4DA93C508AE62AB59E2390C1EB5B2D5976C55DB166B9D1FCA8A91FCD234EA2B5895DC5228CA981C630195FB832938ED7BD73353EA9771ADD724BAB7AAB17CA622F4B9FFFD6878E7759DC98C0F5F57A5F59132AC552FF4575104CDAF00FC6B73F460AB4F3E06861EFDF5DB48345F35A00F5DFDEE36A49C2150547036544F0DBCA21FC5B41D36D4823B2917432366F97BC0B0AE524715293C6FFF6DC57FCC9A7806C7ACEA749193CA1FD24266CCF42402C565F488CDD0794CA7BE9A78E9DCF4A2BC2C83024C0C58876B2921A1A5203152E4F73757A9AA4E4E9EEF103273C44454D5069737892B4C8D1111E313637445D7C8292A1B4B7D8EC060B3B444D646B6D85888A969BA0DAE1F20000000000000000000000000000000000000000000D1B2A3B""") + ), + + new SigGenTestCase( + TestUtils.hexDecode(""" +B7682E0C424BE42ED48F21AB5AB57FD47BED455A6853B3C166D2AECE055EAAD23EA1D186FD4F24BF1F8D910CFABA719AAF8714606159023E27B81BFDE79B4C21F2E28722215C01B06BE6835163253464EFAA9CDD2150EC59085A32C2BD5D840DE568E12A825CAB4E5CC6CA768D632BD6780CB532522953FA3D774AEE03E2D76748206C49384D81406A9B82201334601346214CB0419C228089C88C5C16690A10022006715A308510102210B44C0A042A8802425B202064042D1BB2850B3292C93461634488D900111C092ED42884CC484D5440440A318AC0B08D1B024D04164DD9B44CE1B01124A72004A671E3106514A74581062C193786E04291600242CAC40C93124E981010A3226262982990806099C88418398019018A2140828C066D13B929C384659B82451405910B114058484A00210663942911358AC1420DC8A484D8344404908921C408123160809000494010CBC4911C041223384E14364D633806032720A006524924850A410693A804E4968CA284510492609482242214640AB20D89A44821294A8C246D511666048949D02685D38688A2100E0CB028DC3889C3C88913B540401012E3C48992081241A608E43425E31645603022E312691A824011412684286DD1A6811239825028692200249908401B124908056D0AC58111352A04A1909224095B34281A2408DC984DD300300222724C145182C8241AB040D1B849CBC26DDB9411D8020E0B2708A4266490A624C28085140726C342819842068A0092D91600CC224A21B20C53067100A37121C14C98B42021818C99004242086E8C964C03086D23017100004CD0B61049385191A6040941261B2891C396704C0646E03421A398010C3784C31248D1C44DA22029E0366E54846D230862608404C3A88CC34021C9A8605C94518B16309BA0499310891B87856394854A24918C228CE4388802434424346910A948C80288E0A68D613081E00269E0440A2187919A082809A165DBB24852080E2180711B16250A338802368004138CC018415A020591B8699B3250989611D406525B820D50B46DDC884809102EA0284D0300242031640C382042180D91925103C5291145109C98315CC80D60108C10220511B12CDC366492383183444DD1802521055153185141328499444C2390505494201B830DC3168A48A29064880019A18CD42208520644992245E2360AE404851C4648C2B8814C2822CB38218124084188884802409CA624C184699B360E58B64181046501E3E9D13414F71537E2AB58DE666A17ECB001FF8EAAB0141BEBDA328E8C7EC44F552DC00A1261A83DAB59F8CC4392EF5F14BD88386694EF93223BBA9EC78A67D5FC9A01AAFB16F4E1C80BA31229514DC1637CD43ECBDF85BDE63F6A2A17E6A1BEBEFA27EAFF596624B30DDF797120E52ED396371C1B143C27EA83BE66C9C2BAB70EB1FFA60CB818B9D159C0C7B02734A91200C2282403D316F6136B0BD3E6FFD328DAD5F257B316BB76D6B3317FC3D7808CA0A8C3A7BDE19A2988B994CC13C13D1E3C9790BA3239FF91081CA6F21AC9684D4189BCD387B0E70EFBCF09B8924C5D9385E1006CA7E153B7CE207B920671065FF7A9AFAEA91DC64484A857563C9E90D74237DC453A554D7ED88CAD9EA30F0A49E0B835560B4D7741FD1B96EB6EDC6BB7201DAF2499623683B672956FDD51E14EA62504421AEDAA2C3527BF7AE8DB52D35D673F5E45918C833FAC8482DB27001C766DA36B3E8B0B24616E749E38807F3E646761E4C998E04D53FC98B7D636871D5719EEAA6BE67D20565D7C120E210A67C12B03571B9BB450A710CF6986D961BAA5A9F92FB33E61D605CF0E4FF4C689D535DF5FEECC5D5BABBC22975256B9834143A5DCB903308B18D7503A2EA8CB8B8ECAFA6BE70BE6779B9FCBF3984830B72C513CB150C5529ABE6EEF29E24291756BE46DE9796714A940BCF0AD21721247EA5449946D987DF5E70326B15CBE2C439388E64480CE84EB9063A4213B58C7223FC06A5B618C3BFCA18A4E46205DD963CA8E2C86712D75A4582668E955D821AC4A7C136D7F31C7CA4E7B8AF187B2C6F4366CD11996BE298D71B9E6C3D6C9DC47826F58935CC8EC353C27B3827C3065165B3645032D3013036690D9232FBEA4FDF57D035D99FA9CDD8697BEBE97D2B9DA476BCFA7BF167A1FC66BB1C5F2348E86F3F61432600D231A593AF2FA3CEEDF7F4417CC0E75023054E21841DD19D53D3547D3481D76401E66FE238D68A5381F98E0F6C455B852CF09A1B17343336FE25DF426A0FD29CDC00F207402C7F96668881EECBE43A4C1DA9B86AC50FC6B3E2C74D244848FABF414BD7B3BAECDC750BF2E58033010B8944991D6CBE7E5468C168FEA69B167B566078673BB06A035BFDE64F66C50616E9B3419394E71F8AAAA636634F51F588D3E012A40E1C9A787044596C51A82D77EBAE4FEB448C919601A183E6A847E605CE142B5D56A0417F20356E7E1A35FE18E94188155E3867BBDC7CD04069D1DC4B3EB8C9AA64F7F955C7251667441E77D7C818A8F49496F1141E829C51074D3D38AF41FAF4C77A56D05296B034913A253536702A21B77DCD3137BA26C413461CDCD413296C9291F1CA056EC0DF02FB888654DC54192EA30631F8F9C8B4921A1DC2AFF4CA8C350DAB4234D9151078DB0EB340CC3754E48012E8C21C84B410FBAB3134DBEC37805E723E5C08F1AB371624AEC29A1885AAA7915497220DA11EADDFC7D9FCFD51D0765515C16273F978BE26CD6D7F8627587F82F3BF4EC25C4263DE24B3D4A0839F7AFF0C4D16A3DA89D1F23678FBC23F475B18B523F115CEC9D59928ACDC7772FB39B0F44A77E15C7D786317CFF38DFA9222FD53470AA15061EC8A9D6CFEFA5C32A60B29FD1265B10C78625B2634158C3131727688D7837AC25BCD90FA8EB272B7B3B232E8259FDE162813ABE082BB0BA76B62DECB230310DE5AD36BF3F1AF145660FBAC027D58D86B03E2E1B5ACCF81B6252B90E1B9E85FF41FCAF60E308E5FD114B63CC26262B4A5031E654B673B23464318FB55785C5B707D901E2BE7A3C7E2CC4BE5EAD3CCEA165A577680183A1E05A2FBAC4EABA9022F9A43A53CFC61E3236652842ACE2C8B4249523BF57D6404EA8B247B0058FF1AE98CDD79164B6445A80F31C427EE1BA04256F0833E752DEE5B5224317919242A7E8CFD0791637D3D3873768FACBA6DA65BD8B4177E6F634CBAD83A94F2CC6500A0A5829C9BDB3849FBCFD517A80CE0D8411948791D0E5927BD13EEC09C4FA2B2453D9CE1BA10769B067D8D92547E8BA2F6103D066792655BE8C05AF1628099D2617BF2BBC2324DC6E3E36C9F32597A13FC45C1E974B00FC53009716EAC9FF0FAC4C6B87DC59B4908631A6A21FD5E156D476E438872D93FE112AABAF99A6952959FD9FFD7C3C25E11AA011333FAED86DA99A6BCEF75E4F341BBDC0E181B5A2A22E9CA06BD4F9EDB955CC44F11C6D2E23378B94BAF0509DF55E8D05C4F8DE0B4FDA82AFE7450A0A3E5D8DE82368F1390D5696FF19D1C4F265EF051CAA0E68E336DAF98698FCE2472A6B580E1F30BFA7B385D8F4DBF063FA79E412756ED83668D5C3EFB0FF4A59FE6189D1B70EC45C7B"""), + TestUtils.hexDecode(""" +5DE75924D05BBEF6B34CEB195AE3349EB621187051B1EF95A779B99A3E0F729994BD19C7D1172418BBD3E015B20699DD09D8BFB0A343F477AE2A3BF5737AC994619D1FF3C13E7676D1BCB446289DBFE36E2D1508A3D437B4B0DA06478DF6D4701909B272E9070B1FE06385DBF8A552B471C8EB48EAE39D141009FBCC5D57D95697ACEB7B5231AB5976FFEC41E947BEACA7639F664C6C1D058505A49561811ECDA46E23B651F918112F38B407E82219B49E5C4E7C247DC4BA633C746B42DB912B07D56302FC5C08F5E0C3E311268041F970E670F3AD26A207701F1359EEF9D4134ADB882A1C899B0E4FFBA2C68535D97796636417EEDC0790FF808C976B57F0838A694700F8D75DD4FE5ECFB4B6A188FCB77FB1DF7C5F7C91DC81017A5E9A6D1EAF59680D3291F74743E1776A6DE31101FAEA31D876A0DDF3777A91EF1EA0B575C83C97C7A283E7E958287F5A52F30B6E70201A1410355B47210B911A7A4F6FC23BC95D7951822115FE410ED2E7FEFE08940B3F8E63F13F26B6E949C498E62A66FA675850FB9F7AAFAF7D054F5C12306ACF2900A5B66A29931A5919CB31D19304916AE41869CE3294B0F5F88D845A7FCFB57B952BEABCD1DF7FC11E2D342AA5A70A8AA9DBE1E6E66555EA618849A95439864DF6D7789D8E3B46C6FE4F33877F127D4136D993061DAB530EC979F818A57E1052B5B33D22E941643DE2FF9239741F6459A0EE28658C3C0033FA62DFF37928C59189A7A7E36B1E305F3E1F421EDF4D71A96C71406A0F9AFA5C96A9411AA1A35D241D7186E5C8D0CAE15938FF869897DC3B7D8196D64DE202108D6FB436FF89983EA6DBB5BC88EE2A02488E4D12AA87CC4BDF41A339E10300D32E0FD4F3D3136FA64BA90D64E2BC7C20BA77DA4DB5311F616288496F2FE3E7B3409879050FE57A23DB0344CAE82ED329B0D31DC9B7406CA715E3D84E364BA98F73F693B6E62DF4D741928D21D934453BD67FBBD9725BAAD34E5F3204BDBBB569251DFE2D69A9A96BAD90256213BB0747E7950AEBB4CEAC7224FD5F8F99A16866F5A1DCE07C2CD1E06B70A81FCECED0AEEECBA62521AA0A01FD7B5A3A8A14DB55AFF331E469F5138DBB2B96BFD0AAEE7F38EAA375F71759268546D590BA8C0C022F78CABC4E089992409D3D7BD19048D30B15C796170BCD7AAF7FED0387542BF8A6674F197EF994FF81BB80C59208A572495DE4E584B36A7E9149B5E2081A4DC162CF8376029231EFFB4B4981895FC36562F51DD5158DC82ADE52ABB0E98F4BCB3C0A24566D07686732FA734CDD48D03DF99F7253E589CB8725F17E6BF964E96F9827CA5A9DBD04D448025EE014EE1B5DBDA514D3FEE4F20664C11371DCB16991DA883BF9A68EE30D727137D7902F4839635B1C63F6C4F7D42070E880CA774680DAEF105D277EB8D9090A98F6B813774D42DEE922314480EBE562775F68ED180B67EFEB077D8B174C7D4DA877B0DD3698CF506EE382AE6FC6F68EE93ECA3627B28248D3EEAC469EB0C26BD1A10A7779CEA142958F9F9A533BDE974E1B3CD9B74FEEB2EE29ACD7DB65E00D7ED6E94E5E44A925188285166570727FC687AC7EBE4042BAEF68BC23F4B9C51BA5040BC6BBA41FFA9AFB1AFA09DE1BAA4DA091A08086128A9CA5F27D3F4420327C8FF4801BBF2057282D05D1CBDE60E1E6FB6715EC41AA9A852686DCFC47279FCCE5D86ABF02A6B5B57DE22B2097B12381EEC567E4ED1855F9B482C174D6D40A5825687C02E1D0AB634C020497A44E07E8FBB2D05280C53562DB4C90AE0901B88179D06F9F991E33BF17E7A9227A30454430CB768F56842995081520158FC34BF5257EC8EA9338B3714126D6A95A3D77FB61207154F6DD0041BB03D84D8F75E6EE910460F22CA765A2206D6C56C6E498E063B08B76B1DDF98571F492F9DBD3DEAE7D9C8EF21EDBABED962331F06371364DFCB3216E24638A20F77FCDD894FCC5525DD0C8FC329494841EAFD93CFDF0053FCC27F5A1263C7F4599C186B35FCA9C6F5F2FE169B00275F15447AAA3A823E27E322CA2316B25823F3A79FFA785E9CBC953815FE06F376B6F5860C6A87CB9BE98690C9C2A93EFF1BF1050A01C72CD521BEF265D66BC4B8ACE5736215DE59290DA957175D704BBEFB0E81C2CF906C3A579BEAC3A0C945409DEE4A1E683A0DADB3C4AA7E0174710C72A33F1BBC62A6E6F3EB9C138C0CEDA817688BCE8CCE523A2A4E2566775015F3BF66C09E716CA929BCC6DCBA7427EBD93B21CE276820734331B078558C63ADD096004B67E618D9E58FF3FEF00183EAA293A1DA2520BC03FADEB6A74B52292DBBC6EE4E5ECA8F8B0556FED36C2B41F9D8FBDA8EAA1F74BED46F05E7712E20E463502A420B6CE67D125BE999EF906300C627C57C468C8DD608F9AB354791E6FEF0EE63DF3C1821AE78111B27E57DA88FA44D89581D11C2C72F565A3D0B5E8E2D83DF178810075E5F8FD29E1953BD2C6326B693C5CF6ACE086673D69A67A181062A6ED511E0CF36381358C2DB2A394B05E0C1EE9C54B89C68E10857463F71A842BDB8429EB31D250542F88E6BD3BF10BDCA160C0FF44EBE7D0D982F15C4892091B4A69A3AE7051BECD1D2DB132599F1101E2BCF60136CE947F339A3DEF9F6D81E1BA3F5D4CF2ED989861F7CED86B1A6A167291CACA74C45BA7B5969C09EA20C4EB061D4CC4B68392AC866AC591764A16D0A42710645988FE070314D0859A1F022789442381EA0E3E83F5245272CB5FBB861C3729EC484D2F299F37D2F50688D1D8DD91F131D03207CD1459B289B19E3ED609D70D6BF8E0B97A75F4B4F1DB52DCA7AD03100A36C45D2AA221CD01C8A51D5328AE47E3307EDCEE9B27F62E5DA9EEE15B7A2FCFF1678551BB3DEAD4CE54A16C22119BCA343822DCD20271BB1518688CF69B566A123F65C4787C1C525BAFF00CE20C46C536E47DB1E4410E572BFECDD7904583BF61847868D7D1AEB1EA071EE15A9CB9E3EFF8D17A5BB7EE8BA83C95272E065979904AA99CF036BE085ED869D3CCB694C025FBDEE9BE140A0A21689F95D90D8A54DAEA98EE5DDFDFCEE2908E65C210F347D26F35B95B34642939067CCF04A098ED3E2CE3C0FE66305BB5391E223E43119D38A33672FBC980BEAB96558D3A940700B3CCA9D3AD2CEA08E23082DBF30FC08E94B6640CA04BBAE80091ECE96F128B37141131FED2A5549CAFD7BEB5B180509880C49FC6CB1C11E4CB7C7901C89ADFA0E5335C43A74053347D3028B23085647993B5844FB2716B7154D93E25DAD1CCD889EF3B16FAE34D04145237378D66BD09A254D395736990204A5627F5446787B467B619EE8F06CE664BF7B94392B5C77BCE828D6186348EA2DECA1CC84999FCCD95C9EC55E28C8C2FB559C9020C6EEB661F708E40351D7E530BFB7B1C3683BF15FAC5B17D1CE7EC5CC3C27E04889A9E59E6534C08AEF6934747083CCEE84FF2345D519CABC7D2BA6B783D36C864C65C47CA636B28B71D6797717950D652659AFA8BE3CAE4E269BD527C0425168D04C097DE8F34834A7D1728367F148524366F9E53C4CC255D3BD6FEE7B5A6CF459E1685FE740CC203EDBF58082820B967A40822D36BB4A489BF0CEB51387009D5205056387C292D584309076956E56926283657BF7CF096F54E0128A265050DF528AEED9247E19EFCC79EC301A9F38BE7AE5057456631840EE39E191B25F4F7070BB15CE2CC18777F7CBEF100FE7993681D4E965D0C19A68591BAAABE601BBAB89FC27B3C5BA83545AD645F0DB716C98D5C7A37E0AD97C986EDB88B025D25E3DCCCA816C707F0E2542E44F4D69F943E1DBD08E344F88661B68A822C3EFD648AA23AFFA2F533879540BE2F670F4D53091AF68867E7C71EDB6E9E494E9D30A1839653422AA8AE34A525EFAA62D3F5FF00D91F5DDF80FBDDE464A8502AD9AC85EB21025C0E4E2C2877D50962C5AB8283BFC823FB221CC285F3629056D1260AAF87B556E556B4C723D44279A106EE4075BB79773588333B42065811D671016AF177105106203EFC36FDAB2F5E5EC8DE043902583C1782BFD8BB772353EBC5CF03A0D869E5F3797713B58EB7480CF7B92AACFC9C41040BC9E1F5447F9852B2C5B5F33B5517F28A01D5435C47E063B41D3B0F7605B07AC33FF6F05C6FF44EBB70FD6E1AFC2A32C9A0B1AC17044401B93D6439CE53C3B033CFF06688E1933CAEEC48A04999A01956096339B5E44AB3A57FD1F0ACA23A03114708BB16803C2CDA679061B8E9808A2E11DB0957D4F73C8A06E6C50D6DA43E4D008ACA23CE2A3213BA0DAD20D5BA8B44DE5D50E188039C112B8A40B250E7E815B1367375C5698B61BD915A70096815479916F455B9EF837300908C5A8BEFA5157EB688EA02245AD3B309D10C769CA1B8E5CCA2F5FC66CC3920759A203C3F6B8E9ED10CAB20FA143B0BF0BC8529A4E89AB0C99AF77E43E68B61A9E4176066C4708FFAB05F3652817FC42039E2F22DE2058CFA8701AFFA894F3143FDA27AD85C45D3AEB30CA9759537CA4AF2079317CE5F4B5EEFBCAB981E42065AD5CB8A4CC9B628CCFAC18D2E637CB73399CE3D90A9060F88EF438E8511CE6F403A0CF14C6B641830983C1EDDE73BA27E41BD678E834167C718F5B1E2E6C109199F756905FAF9F0005CC1D110CE277DA02675461AE70EB6A412EC455B6575F16A4DEC0565DBC8F387D84F9D3AE67AB35E511657D82B5606A4DB45CEEE81C94FFAFCB88B8185CFB67E4D7171EEB391E9E1DAC625B56FED22D86E8A34924740F94A3D50CBD05B8E2476CBC7C54D2F742F0FD7162E7A138D4AC788E710AA45824513BEA162E2A1C1F709413942BAB5AABF7E347A148D53B8EBA0336D91539766AF0E827BF8EFF36389ECA38232FF2D7E341A3AA710F590C78EB69156462BAE9B8B73386F38EAC4FA26456FA555E26E7DF679983FEF23DAE87DBA66BCEA19A9F991F864A17C23F7CD592ACAEADE0E82F4737B70F0243F94F015B59330B71E25F1304DB3D8D7E2F96669BD7F8313EF9E10EB1EDB0F0BD94745D03C83768A618AD9ADDEDA7C1E6E134F8B7BC96B84652C982B1D9242F8D2CF0ACAD146EA3185E2332904E84088CA2D7D60D3E2DAE411171726B5FB6C95B3DE961E62474CEC73226E55AE7D9C7C534E278927F5D669EE6D111E325D54F338E2A6A06493D6F1B7A556A94CC9512235498409EEA477597EFAB239380491C9CCBA1F00A0D1C5D758162E9F4F5464A1A64A22C32721AE57E246722A6B2E07E544A5FEB06AF86C580DAB2B9DFB5AA0F0251E6840EAD66FCB6B89F80C2AD38383B329F9EF4589BF0E8A0C9996EC19E1DA539CFDEFB2BB0F3D9544392A06F765A74218B7DC34F38D230D1AFCF9130410A4B4FE038F7AC59B6B062EE2D2ACCD288606AD9AFDBE95D9572B78B54D26166C7817E6F72F7E6C55DD1576720E4AB99CC26722107F7C278BAC2D82FBD0A3B0E1793C2D8B498F90A9172D17244A4107D9274958FE078FA8A5A33087BF278383F439C0B41523E0E51A662A9F2822CBBB34EDA97F5398EAA12D52506C2EAAF6D4B75639EF0676F482A69DF0E8A9BDFBF6105E32B6FB3ADA2E29C62A0AA687820B4ED35C2418DB1A67A3A5B92DC61368585CF7F3B1B644A8137A52CA21DD982760CAB7FB111558ED0310E9FBA34E5480F4E707A2CEE74DC24AE5717C06DE2B509E4807824707505FFFC5DBFF798E8D85F758A94C2D3770674DFE03627457B2DF10628A31D44BD89D3435D93E4F9BC14D47E6D4B9BD3BB2287ADBCE1FA58495D9032A9A3ADCD56CCB116787E060EA431C1EA9E60A30B609AA9C66064017EA05BC16392992B7DFF62EF1046FC7E64F8F811CE50AAB40AC122CBD5119D3045ED0812F6E30EF6B6001285427B643E3C6FCB6390A9FE76B342A462994F2B9074B56A848538DE205C98BBBCC75DF6BF23CC1AF0B201E5A0618D4BC5035B9F71BCE9D3493A97FA47607D65865A5FF3FF17A7CE28C0E87A57FE951C8F804EADC21F161CCB5D1E66F1E4DBE92C69D4358E0CCC13A12DBE87C9B530579189EF2359A9DF5A8FDE00CB2B58EBD748B23F884626A66EA39847917995EADC1839BFEDCC24AB6BF22A5C247B6FABE8CF382DB48148915167BB47F505C184EC027C3AC741BB0F6676B0D0E7781E19FB8D4D630E71ED4843010198DB9B122CC301D432856B393632369FA1C99BA252F086E317229486C034F1960087ED4606288A7C89DB0EA0DE94700785322249E901897611913AA74F8BBF412639DDB639CBD1C41374A3EC66A87451D9E4127F7627DFDE4E1701D7FC9DE13DC7754952F659EBA7B1A861B8DFC78D1379274530B976C66F9CC4002563837C852D83B3F3BBFD892F14DBF64C976C924E3C656B69131EC17B7905507F78F073A7E509157215C988D490685F8AF23F64ED338915E72B518E4305C9CD44C219876456E87C0C59C5D7524C86CAA161C745364A12890064CA9061056F37ED1BD56B5B09B1423775BF0FCC898AB1BBC283B23DB6E91A3D749125992FF1BB598260DCFE428D2524050C1F545FFDA18A63B052C0C8CA4DF8C3BDE83EE5474395135FCA2B05157C25548B0804D1EDE"""), + TestUtils.hexDecode(""" +CDBC27DDFC61E219B3448514C2DDD3D8A8199E8F4B49C7E4E73178708F40D30FD66E7873D6BF716588C97559C6C4998B2E43A58575F4854C6637784055A0C147AB1CC54787C73A49FB8BED952D2679DCA79EABB65926DEBC4C7D25D441C56ADF09C409C9FF12D2C43468CA67E45AD07E58CEAAB0F35ABB7F3D236DB2849DC0EAC34448643D7183055623A7B9BC8A08033D3B5939958E90DDDF6C9A7602A44F8516C78386905270FB047C354303AFA6E2A387A8832DC8B436BB178F713C70ECC12E98FEC4D5B28A3E072116B9D2F0BB95BED447861C56E6160170DA93030C32E41288C1C06794F7E6341DC4D6031051E51A18B1D7A9FD1A84A5DB0A1F1FFC93E0976F7077A83FEDB7B085CD366B67820EA9FE232C77B54BB368FC6A530DA21605249B3CEAD87C3E8B4CCCDC776F0092069679FA63DD91C802A368C5158718BFC115BBF9D45B7A87D4B03040A1E4DE2CD0343A318A04092EBFC0CA2BA1B94552DB961D42B1E638234617DBD18B4EBDA761CD35D12C30683428C83754D8FCA43DBCFD3B3D486D234A21D3563C8396E8AADFA89D1D79F01E6A139504441BEF37209F8D5C5495146A8A1951EBF17F7317D3594A54FAA220E3A73DD7EA3D193801C0640D6BCE9FD57F16C2F749B3E96B2071F5A36ED9D038F97616EFE62C383E69C3D70AAFC5FE4890D827D26CECFC0AE1C8BC96841652628D318F424F50915EC65E9DC9DC43E19C08CB4011818C53301CE8A292165DD6249A8D796B257481089780C8895995F7672F1B2124AE77D38E825F72EA07E0B7515AD8DC615735268A417C25944B33513BACD93C3502688130862E2307BA77BB74986819A152A3DE627401B268587FE1FD45B373CDDAB5C4D6B593D07A8421394D97C564F7F373C2D90DB689500E67D9C7FD52B14F7F1B20F27CD97BDB06E04E13D702B92B640F6E20DB82F0455DDB9C2420E7A51E063A00962C29B4273030A01EB60690C48660F552D41D7EC955B70379EE13E390D421F032EDFBCFD3E958085EFAA573E60A55961C2E390B50F85992864EE654007CA0DC6B2CC7485A558F5909C58D701F91895DCE90FDAB1069B87BAF2DDD822DCB61ED44DDEBA48BD257827F0D1045FC7B482F462ED3ADC794C2974EACACBE3577353586955ABF65538C942CE46A3B5C9A3255BE71DD5C8A572A86095BF4A1FC36BBD3E65E7AA536FDE6A31069BFFB676158664B1BB87144D3E129156E8A22CD757BEB1495A5C9740B0F0B271C920EDBDABB208BD544AE20B1813198605042A38B40969B0D6D044D4804061561ECF8AF816B7EF6B4ECA3AC0EDFA4C8699C76080CE3EAA5E2CABACE5FAA150E5D233BB694BAFF02D6825FCE4412725DDE05DB5F521B9E17DE3C719FCCFF0CE174F369C2DC497062991B157FB2FF36772C084A226D577E9E451BCE364E0EA32FAF6B366CD5E02C74D8907ED3DC54925EE10B3E97CC96DCDA7067DA790409F2B422616C65CF3CB26A7C6C8E9240C9235BA9B7A67BD21ADC729B102FCDF7329ECDB2EFF495122E265D0F749EE7414312532EEACF600C62A15A18172FECFA2BFA62BCA47CE794835EBE25557A61B61F6977BB7ACD04BDE30C2425F68785B3E227106FAD9E5ACB26BAD47FE1AD461EB2445560904CD6DEC4DB091BDE4CC2ABD72CAE258BE07CA0A8634C72DDF75A06B4AA84DD16F9E9FA2D2DA81B5553C598E10E9FFA7E80AEA8131C16775C1DF3E45950AFD77E9045A419A7B52D3F3B1C1309EEFC00B53060FDA34B95FA6347305DC91F477F4D99BF4A1BC5418CBEDB316FC83B090B0015BB6D0EB1AF1EB32EC962D2AC089D92BA915A8F5693D04876D2ABCDBDF675B8A871B837FAB190CC47D93C2E00DBEC028A26860DC39678B188C27E8E776C7C8C72CA22FEE2861725C7340D4B5B6D8D0FF63A5C439A1CC12137DBD14AA540C10EF6993CDB9D5F6D1C6A8980F48818AF7FF6DC75A2AA1987E689EB10BA40F2255BA2BFD9A36C629F02A8CBD4A862D9D6B0E6D7C25327CB87F47799ABED84BD3B4BA60422B5491FE512B0A689E49FC2D037B8D7B9FD5895C13A40C14525A6A1AFB1DB0A6747A3FA1E7CE023F290757BE19309154477176011100160232AF0C5BC2CD425AC5AED3955CD7E1A700FEB09ADE5BF281EDA1DE0FD91B072F78AB77EDDF7C7E47343B5184FE540DBDF6BD617719550B8658C29A276A704E500C379D03F60A2A977676F04B0249AF27FF58F09275AB99C1201702EC1B5AB7CE4F08096C561CE2AF0A373B2C797DE10C017D1D65821312989519173A8F901E9832C210729A48A58DE10E7F4F09453A02E656B629366846C5AF57CE17C889C1CF30FAAAF091EC80A831991519580F80770037F1775B534612F5B7D1FE5D161BD3E38CF00726779792C17E51ABD013D7A9989EB9A136EC7059B8BBD5E3013D03110326299134B2CC96CADC3995FAE8EAF9466D7E502AD3755058612C083685F9355DAAC4B43AD138C6CFCD100E463D17ACF63C830A899C2187E85C2BAC006D9CAD1276C2154FE264EC6E607E178BACB3290DEB1FA077FB3843DDC0FD44707096CC54BBB17F1238A975A536BC00BE8BD625C930147EEF5F110D5B2B3B3E303D44B57289A00D1E047314BD3A206B55AB72AC676C4B26D004E23E590396B52AE35E3ABAFF7E5C965404714D1ABE9D69CB6F780EBBE4027B8AFBCE253EA7D7503887262673AC0132A0E4689DD45553AEB1660A72D3AF71D85E94EE92E478BE68253B48F2CB40F88C35828274F04676CD22996D6A7F92175C733C06E0B71F077F0B7E122314B771A28786DE8D2DABC94F720BDA3980F0C97BA6849919F469A3C6B0FC12263B5BA87B8BB5F01BEC53A68E5A1CDE4749223CE118CD17EA6F2743B9ECA60DB616BF30C4FC3B15F3F43352D72B8094C47064EC5E6869BB45EF803B51DB512DE5AE26A90C3EDD184751F9179B14D8363B7EA74A27463EB85846EDF89D38CED01BE910883239B51D20C60664A70156C89D7031DD2BB0E51E1A520DCBFE8F5099490F3C1477BE812D0EA2AF032F1E628067998A671AF4AA84B694EC2C6193359E8B43404597F4C3900979EDC4CD7435E95A66DDFC704CB918CDA3541FE63355C1CAFB19E9277C7B843AE4FBA7B7AD8873BD54E4324714D80D906E8BDEB17272B722681A2BF2467CAB68C5DA699CD1EE5F1DF3849F7AA1F2321F6D34DA719E2A93860EEFD441F25442B01081511401648C778F3E081ADAF247FF8BA3F2DD2E70294B094D8C4F73292F0A28936273710E6BFAD532ECF02EACFB6572C0EAE5B5A258E12A112E1A22AC086938857D189DE0912313E53757B80A3A8C2D3D4DFE4060E1D23263A3C63727C95BBC4CDD0ECED0B1D334349858A96AADBE00F1A3D3F6B849AC4C5D4D5DADDE100000000000000000000000000000000000000000000000F202B39""") + ), + + new SigGenTestCase( + TestUtils.hexDecode(""" +ABCEC4A46E695FC6EBE64A191389F0D0AE180F911D5B824F4ED9111728FF4F9493EF3A7512DACF766D576898D33C4C8F4001B777EE5EC2E2DC1A8E3E181B43418AF45100B92A3835D02B9892E609B2AA8C6AF7661CE0BC8362AE0DA172A79E84FF4CDAD8607E4924FF41DB6EC28DCCD09B8D1F5657BA17C848BABC71BB242A50C44069A0200101914D130822C114288436508B0422D83004E23848032532CA902509A0009A848440004CC3304D04C0601CC84889340950B68918C81103410D631870DB444AE4224D8B96491B0224C2802904365290222D424626E0060613B12DE1187203B18442228144027159186C22092C012751083160DC48061045089AC444601609240224DA006623945149C200182232CA462A0BA16D22B2215028700AC108D1828C00B24014083221B5810C4501240225E44291984622C90826532650DBA8495B226294B049603050242382DC0429D2260254262CC3A868001546089168CC067184B86C518285DA221110402494149044B8102220299AB40190824D523050229668101072913411CCC625D2880D1B1951C3888C222509DA20322003209106028C188000B02D92421111B92DA10890A228700B4464A1B01153966800B925423860884688630800C3C2910BA9511A1902C2B229532052D9906DD9C080192400249589E004914180600022440908012435624C48864BB46123C900588869C1001251248960B64844322513C5318B909118A8691A850449B800A3B02598A2052293455342701B3722590860911248939221D9024E2042601439410937318346851A836D192751C93686111749A0B4649BB285CCC049C0C4611A066203C304A032248CB861A34408CB4852484866244610A1068909280C01810C028531232102E4442C0A988C19C54192187223B168D844862295405824408C322222C27110170A910668D438529B025212086458185208078DD388240C1092C2C60D549640031989093530988425D104524C146E62A06C5AA004CC126AC3284490268A43468021454460B249A390681A4745D2965188220E6032249AA6280A034A9CB6888B180CC1021012B70D0340480CB3444C0010011549E2B23094064504378441B2401AA3884AA885112229D2402550B0048C2621180872912851481842499020C9126D1A1289A4404C4A82710301228920449C48624006920813819CA670D0C808D938721A118A1BB589111150C3C6695386851A0204D2426D19116419A38152C861403A93CB8575520D2A3A7317CAE1963E2705B7596C8E5DBF0DAEAF8755DF38A5DF16297CFC84097B480D9729E4CC62170739A1A8A2057EA7FEFB06275344ADB6934E1C2DA7E7F3E831FA35E6A4B8D8DEF435235CE957DF5FA1D842962711443BEADE91070833C84264B45E2380B094202E079A0A7C6058A54E6F552F202760230F6D95F5EA873709BE4D7603AC010CFBADAFE229CADA1F2BC717F877856D8B930D0E215C4BA2212D66E21A2D1F09B1F1A9BC8C298CFD65B318FE91847279F204201203E0922E82BD298D9BF18B8FBCF72070F7C7C51D5480E60674341CF263FD179862F37D5665FE35ED0B2A86B7115C90093F5785309CD56C48BBC50570A0C2D066BD0ECCD3C86E2A6C8B098AFD9C0E235CEB920D58F0B913BFB633BFE21BB1668D9C45638F5CE9650CAAA83DB2D9B4B24B1F518B19226ABDA06239698A90F30A50AF69AE1D20FA00E3D88FF6F2C2466E45A39A1C946FB695888383CB6A59A7C8395082134A82DEA3DA7FE6D9E6F76C7E86A50CA04990C70DD5F9AF062ED14CC661F453BF309DA08056E19F2F7B34A15235230C15EC6859D7DCF0ED892DDFF4E5096B36B406A10CB35AA81F72827C5982E3C5BFBB989E062CB4A7F0F76B008AB8CA5EC1CEBDABCAA1E97809B44C5F49281415337978184811ADB8131D2DFA2477D27532E92409493D46C597A6886250593FD58D305D0760CE8F772337D42B0F7DBFC483A941E8CDF32CE3E97309C3C404B6E4101678F123438853FC8A71C835D1AD0C7712460DBE83C1ABC6BB0834C0271A6627E7DCB93EFC25F78417BBC801488E5A051455343757F6BFAF923867C45ED5BF37304B11E012EE63A3B8D84DCE7A15D5AB940D87FE1181EABA3C97BCA702F5DE4DF74848A99D2B1F34FE2B03633D6AAC900A09C278556172DF5D9CDE361A8ACD779465CBAF50DE5C8F4CA0D15DF3F74347C6DDF7D9B3E3E5E197BFE0AA170949FB42B78364A72B1B106156EC09A6E4EC72F3F814781D3CE7B7AA2B02E49CAA25AC36DAADE0FD570A61589553A0CAE582BA2894C82C0380A713B0B74924E006A6B341F21AE2AAEC2016D2687F1AB696337F5A268B3B6F3730F507D6122DC92CAB36107E864BB3EDEEA6FC1C5309A9B51582CDFCC1A899929AD7CDBECBCBF9D38121D58C3B3E6D9BE001B117E4A7F762816174B761EFCF291A1CC5DA354029962EB8B0F6166A9C9EAF26921D1777E621C50C41614300605B1EE2A0CC41BC666CE90A15733C69A82451FD41F23EFAA73A2482C4E3D476CCBBFB59B25140FFA0C1CECEABD3B036F2611C83AA834E6CFE03963941BDAD4AEFB11D01EC43293BCD22ECB8784EF5CE2A6042F200F1B9D6C595EF920C3CACD1C1C3CB61B6B46454A3B28A472AE0203038A5602CB9B001620C98BC09BC2DB5621C8DB085D88561058AEA691AFD199C6D4BB1511137ED2800722A81670B44FAC51DFA6683675BF34C52F6EB7EBA35D22C907A207AE5CE6C3C40AB0A26B88DAE777E10B4FC33AB38C308CA2532032A7F306E9ECA723B58119C3BE662817A1EAB6069FA05C3B0ED31060D5794121A83FBB152C7FC05BB753C9D29BC329E745D7C7D493372C26C0336AAB37B884FB41741B344EE4D247D6B5D049E5E322CC97EC6647EC7551824C6AA9CD249F49FE1652ECFD01C3E7EB026FDCE7320D21EC9E4D460E50D6440C7364A15AE3C107CE8EE1E8A33EBC9D2B5585B8F69771F687EB6940C21F45750079D68D3DD6CE1CD7CA8D91A64D093A25A96628169B675CDA9F14FADA4AF3D11B6524465B89DD4EF93A9A159F8DF2A134FEA301110EB77E1ECA51166D26CB036BF92F1655167BD32D12BE04A91FF0B3C52C69DE376856FAB9B4E14524E5858717ECBD0865719BF1DDEDDF8CC141396F9F0B4ED38B0CAADA08B64451AD8BD38557660CFEF46EC0059B4AEA6A7534A3DB767C537E60210A1AF84EC939413FD7EBBF14FE96D6EE82A0C632EDC63715C0C6654AA4FE298F43ED5B47AF7350C32C8D7F696F9A96B81E9832F486A66D9B304A6531139561FE5A967061BDFFA4793EA986C3A2693C21DAD4428FE98F168EB928FCBEB8FE0A611049C1F430CCD80F9181D276AFEDAEA40261FE1B038F5677AD507EB48B9768964BAEC928197AC26ACB1A89CDDAF51C4336B6F49985C13926E76AA7D69F5F0844F23E7B2B977565587718903B39173F7F18AF84264370BD61020F2A76ED281687419E334443159BF6A21533F41E030654F6876AABB21025B6D2312304FF8BEFFB7AD2E225BF79F1B6F8C33AA90D9DC18B369846FA06548E72EFB2EC4FD6BD833F1872DF9659F62AF040345CB5B8399A4836F7F5A9F920F0484009C1F6871D2"""), + TestUtils.hexDecode(""" +22AA98C685E1552B525B4302C943037F668279C224B6270DCAF2B06C4F4AB1254C48DE253829FE6DFFA9CB6BB294F054711BAE3FBACFB900CFD1F0844E55D51EC6F697B998759B14C13392DDB6F7DEBA77FFC22468781CE402"""), + TestUtils.hexDecode(""" +0313B5DD1E344BF95EB5D825837F570922337633494F8F2EE3618AEB906DF766F5ADDCCB8EC1C5CC51AAE0B9FAD876FCFF5D6814357E8C63FE59FD72DB3CE4D1650660A0CF64339D8B7C6DDB7A7A3C8EC6C88F2F0F70B377D9D5E21F0D40E17573F07C94CDF844CB6794CE2CB8E4A11254FF0012D562DCF4D9FBBD18348D13E1B69395C69DCCBF618D7A38EA6A51B9F1F8CC70CD36D087682A558A1EA9BF9DE6ACE5B350B6EB977F435CC46FD43F155B29822D68D1CA9603BA43F1DB28BF4D3CE284523BB440D1E2C124CF92DC74F19B74CBC177DE9B08377B0E363401D23E97AE967E13AB77E9B7C7488E49B45E835136EC2874A24CC79059DE5B0A67C842F2E09B37B3039DC186427F760CE60790A9FB58AA388880EC720A783EFEB4E11ABD817A7EA884E5EFC279AD9E8AC2C58A41020C7468A749933348EBF78A0F0597B29B00A126050FA40F532B0F4411B733BAA5C80CA1B52828CB236268989EA2641431A359E6595F49B4FEABFA85ED4BA85443E2D7B82DC7523FF627D336DA1551897438100C20F0184A963D0B9AF7F7CC9FD64A2878D8FC5ADE2D0D928445EEBED286F2B280AF573EE62E70F698BA0C14381A5B4E001C53C49A77E9F181EC65B49E6CD8BBE30B5F309686F7DC80176F654771DF17FDF136D6C05498CC00C476E71608A39CB29A19A986297CB9C1E3FFB4BA08ED42AD12908287F018D49A0E1AE89A9BB3F932DF98CA91E691AB5F3BFADEA9A233350A9EDE63CFC45427CAD109468FCE4ABF7FDB83C6EC83865134380D3FFCA4D94C5604DD9DAFFAC204C14009FE06311B81310940C43FBFCF049F99F5DEEA649A333F6A3AE6232EC7CDE62C95338C23085D776B9B8F4454E03BD0FB28046618C33A7CCB409BE7BCBC0906B5A9424B41998A3A1E65E5EC667A14339E3BB44354047A2868D64B78FE5FAEDDDFFDE497368C3CC130D0821C1DEB2C43119195C6C4CFF1D5A778965FF97685DD93775837EA0852284C670DD418DC9FDC9C44DB7EDA60E58030D8FBDF86D48B98230E6AD19E97D21D7358510E20EE374B8486341302EFA590B96C1DC253226A12CAFDB3B4A31EE2270F764B74F17BF9C5681B6578777739FF767D4E094CE80AD9804261767097BDB163430332C428CB3CCD9AA881316B51556C718A95816797CD5C8A2A640B85DFDA520D1A0129F0E9DE772724EE8B74B4DF6793EBC0A801B6F77A2647CA2A5F564D336BC23ECF591327A8DC4214953D99EA3A9ED9943F07809B4C36A8BFF093721949A2AEF2CDD9687934849CA35BA1F38743AC663E48B39A2A32122B6951CF6F1BE17FA96628D8DEE8760CF7F2699045DF30484722601E7A45DEB277CBEB749F5CB4383C8643241158EF13D8723B9B00C98F8BC68C5F42DFC4A1B8D95F4652AEF67798A8B3C0C2AD40CB7A2B88A23650147E32CB605324A99370BDB640EDAC9CE57EC22689DD45D1922811584B01685615520DBB0FFBB028E43B77B54AF4A3EBC6B9F857E9100FD9C64028867999BB9C7FF05D37704D41C94CD63DFD1A7673F817931A4F2C42CE572B24FB5E779897FA4E6E2191524783C710A099D1A6BB9EAE47E849187432A2039BBE1D37D0E7C797907F99BDB8E7FB33C3B2FC9E06708312BEEEF2935D443F29B646FB5AD52C99EB71559571781A4C86250D262329FF3DAACA18A5E7B77C3CE593CF3A92B12B9AE86CA3AF05EBBBD75B6BEFC368982D96F2E5FBC128B6A8D65FDB0B0F7859689F0B6F0A3D1EFCBF1915DC61C7FEEBD077F71122E77775B4279F4F57ABA521BE4682DAA5B836B5B4D44CDB726DFF3AC9CDDA9F0D1CF4E79BC9E90DFF7562CF206E756C38E708BD30820A14C595288730F42C8ED99A7C1F2FA6CA9759CD31B8F28FD35B9E0980ACC3432F462CD9CB4C594AB63FD250DDD4877269056677EA7E3B0AACD4757AEBA398688423015D952D0CF67E5027BA4B6B376F6380B5823717D64513EFB35015FBD20FB2284E1E340C9B94F87CFBA24310325D7597AB34BACA6753215AB994390C2E5A82EEB06F338293E72C5D0FF786666FF2EE2D429461F1112551AD0928844D7698D3AB0C4054881A623525D728E514E12550AAB227389E5F0C2341A6AA34BAB5472BC9E465DC24E9910175B2B968F2E7883CD22CC07B3D203CFDCDD877CBB28368DBE668F561E3FA1C5D3391D4A408A71E0BF0C32C1FD6494DEF7678E58B829AB428509C33F2491725959485928B2E7FA96EC7AFF12BA3196087D3C83DC242E5EC95BF95C8581693FC0B744E758E1E85959AB63E9B4B0A4547BE5ABD7D29BF9DA2D192B4BCA491D1DC856EC80AD6C3C738FB775F95A217D76093852AEE0CC203DB1316C6253BB75CE2D92906B47A5B733E4A8B0C28B1283419249B5A05F6302CE110F85790EB46DED7109B0DAC58A4D25255B6950F3B2C3421140E4825B6AC968091EA7AE9790BC8D03F3F8F4C1BF1006E821E5DA2C65C542183F4230CEC934ACB81FEA94D959FB6A21C7AB20652C9B247EDEF72674FE915858795A9A00564F602136C364A6D9638CB1BBD8A705B90429D13A19DE93520229282D5122EE112A32A68E23577E358FB28EC45478D05F64513A9E814A5F1FC7CDE4D03EC51ED41D29ABBC0F60292E2F7D0AA4490C38B583329E2D5A1E61C73D6033CB73A7A4F75ABBB29A31E52CD1EEDC3DC4F0B9152FAE6B29DD1F9739456AC5B1890B3BB00415027C634F1E6374F310C95E680086862B8BDEA0833997746814FC602F97999A2309D4CC05362303F72BBE2EEAD04D566579A00A8265E238FC578FDB2A63C57250B5714F2C6485BC6247752853F75ABF066637645A5A6AC0E85459EC2E24D704ED7DA4BA0FD23748D1D853BCF84D4D00EB4B6DA6D036B8F29797882EF5400F2F7D6EFCDA0418CBC5752AE5431B59D2D518FD752467B7EE13F699CEE1581AA1A305B2ADACA12647FA8FF00B427F28AA33FC094A374521437E3B4A109113E1AD8AD23E2AEBD69EDECEDDFEF0B5AA0A484AE32BFB2B05F8F7F65077F5B35C99B61EC28060437D9CB982AFA28FFE8AD4C02BFBFB071CA8E9EEA15CCEED97D47BE2313E3C344793D40B45F709C8A2C639C09662A81F117839AB62135B6715FD57F7B0368C6EE1E3234655EAE94213D24D92989A46CBD5C7EF116243A085462C5454949D41D2D570AC810B54C727FA5E187D0D9F7FA7DB3682D99460F5077AED0A90D513C0D833E5F5A91A5A26CF47AD134C074D658AC0164ACBAAE8FAE161E00C7F8B043FFF46FC5C900C9ED14C44C98ADDEDCD5F3BB7038868F8460EE12472DE2A24BCD0A611D9E039D60000D131D242E3C436E808FCDD3E2F55667698D91929DA3A4F0F72D4B58636C6D9CC9D9EFF0141C233B3F4A53595F696B6F848AC2F7FE00000000000000000000000000000000000000000000000000000F1A2536""") + ), + + new SigGenTestCase( + TestUtils.hexDecode(""" +3820A7CA1DDF6D374E8053628E628D142C4305EC1F3F05C66908FD5A1720C7F02EDD55DC8D2252C7E3FB5C91BBA1C615E23C16AD39B4FF5BF62EC0E22F081573D22DFC983A88CDB217F422AE9FEA6F82BF0E72EA8E6193E9DEFA584C29A9873CD76741016481CCB01ADA6063BC8BE27A5887FABA7F701DAD4114DBF31357508E54982900B391C1A42822330C82485114330A14A3601BA310D2344D63368904368293100840B42991C2405C22290C492C52084208A788CC266682148180300E10C330928021E214499C904812A169A13009A4908518882420926919A44D2448612217821A358019B2891245619A342A2132665B362994220E942812CAB6300A9251C910295B160848486E9A90641A238D0CC52022B9318A3266A2B82902440463380A0C373022B22C0B3152D40410DB100011265150C245424622103792882691D8207221088C8C246623044E1845698AB8886192004A244C0CA46518206C8A342C12498A1034455B200D02184E98420D09A30DD94028CCC821200150E4B02981466821434880C46DD0480E14884152829052C08CA4B26DA2C401540850A3828CA0A248A33240044032231041A3C680D3042DC9884DD1302A93202A0C250A991408E3160548464C64A2319818122308865A926814B7219A2071C214640028509C806413996D99002C1008909B925018266AD4020453026001950500953113A385829820C43651C30004E010269824660B920109362E500889E0326C14378C181589DCB864993271A00260C1A425A3C8718B8829CC946558243080C204583465D1B01088A82422120219244A02388D1A295244446E10320514488C13814544427052129182308A1BA14C1AA3119A163200B53049322AA14061801885D822520BA091D02422222112D94409D944215C84811416641BC40940088A61C40DE0162120842CE19000E024654110721B364A511085E398719A448223016C12A12121C4240A346520A850A332815A2051A288500319421B2831D4346C24A06082140C0211889BB009C424001034525A482AD91252CA96090101611892604016040B91214BB66910024840C40D00828D081161A142310BA424522612C3328820300D18C705243505D4320E94C8841C406253364811A061214669589611132001D8A430400431DB18120294281CB0291C374564A88811824810236C01C2500A24094A842D9936688086284330719A280E04A24C091312D124718298100C297123324843368E17AE9DBEF07C60FC5C871DAC487C6EEA46F0FB8B88470DE3D6C3F2B75C615689DFAA98540F2A9D1A3F8448947B6AC7D535DE9F3019C60901BECBADC594124FB4C677CF4341088FF2085957DF9F3837121DF75F92D40EB77D6F4B0AF61B2577E432316D09DECD949F1A31EBB1E4B51E3D412B5CC66BC65D4B399EE83AE52F558994F5C0C9D15617E43E9AB83A34C16D097A3690677B35119EB33D80A88F1A8A77C2343A29EDBC9B3D77E52CCCDC1977E09BD3EC6C8E05085D23C063F785B518E49EC3BA8AA156F16C760DA4787259398A9D343E5B37602A5318DCEB6F27BDAB8C143FF882993E80FAEE6707B26263EAC39E22980BFD23C61ABADE42C22549D493B23BFB6449FE242EB61986E5AB99832B161EF32CFDFEF5221C2710F1D316D12B170F4C9EC71DDE912EC7572DC0B25BE911DD536CFE6C6EFE9B7ECAE861E5D3DD28E68FFC7BFAF7CB38810DD8DE12B23DFCE3A69337FC423BD82764263669295023F3BBE4E48DC7A3F17337C7BFAABA2F7B57459C3572881EA0BD39DA3C2CF160B6C032F81A6AB8FCD5B94A7F2014F0AE904B4346994CD4C54EE678E23AF95BEB21A3BA062E1A9DECC2A983475641A66550FB2892F732437302F19F1B80F034208F6E4250822868ECC32F43446028DBAF1A910B923ACD44CDBEF856098EC10171A53B89DEB2488F6D4CC4EBBD024668EC570C00E335CA9AC4C031A3BDE783B093DEADCB5D6DEC107CC35591AEC160549D7263D1D3B6CADEC6D6DD874CE9C73E61804173F07E4F20F5B7A5C3698799C30E9489D1805F3A5DD6C36C70D38A573CD425FB89A928061ACE86F065F04D2C14AF0B8C9D8CB4F7640DC5AFBA3EA426FDA628B72A4CC276BE9DF0844ADC526BE701BED18843F001A88570BAD4181BB66E37C35230E2DCE7DE953D1C4C8F7CB7C46E1C57FB7F32BE90F65ED059ABB9250B8D8046AB35CD9098A49F81B5957B830FA47184DC5D10B5176142C956098C7410F3EF6B0CC092CF5B0FBF73060FFC9FC612767B95D1FDF018216F8CBC1FDFCB5A97B21019C0694231C34783D519346BE304BF1217BC6BEB5B2126CA975725328ED5CD6542B8E41AEED52FC50D1F99C35C755E207BE22A7C5904A10204BF0B583F486CE7BFB5D6CEC33370CC02654A6837F4A88E6CBE64C1930DCA4905DAD35DDEE0F8D4BEBC17A04BCB086D3C44BCFB68394384AEDF39D27471C422371FDD80BC72FBAD6C392285EDDA04A0EF4CE9742C020DA2F528E183E634ABEAE41785EF3C69FC8527F7334B6C7278960364AADFA66D58D8F7AF4183ACF3323EBB3505BDB84FB4A76B2CE0B768CC8BBAAE17FC2B637DE77E107ED1C6314F94677A4462DC03B60DE122E5AB843893944E6902724A8C4CA0C00D88C3D08D6314B4B07DB39C4EA413BE9E0DA58270EF6A949AEE60804A78EDFB0D4FC989C02CD7E48D116DDA1E91E72FBCBC9E90172501871A7E444449EF65F639BFBA5D4F297FDBD2A6295B67499FD853B4E26A82B62975B07945CCF29BFED8BAD16E67D95B8A485B9756CABCC8C99A11A577C50FB6D39C49B53B309907213D9E60983EB820276B2416C8CF8CA98D9A9FDC6CF3F122A81901988DE195DDF69D9CC38B36BF74BE8D4DA4C1345A5FDBEECAC4DF62B2146AA5BBA74AF45D2B736BE08593466E85AAF96FAF3FE9E5E6FCEDF7E3C80D1D16BF761B73B5C5EEB5F01AEA31153A5618404AFDCF85C2FE38E370B844FF850E1EFBE759779211CA7C219E2425B2510C00A653D32A1238CF423067A309E5839200F6C5AF42BF7EAB25A685D9965037C61047155A7B33BCA049ABB15DD4E869B7C9E525B607861EFBF250C83F95ECF3593484FEF1D49FCA407088A3B1B9CB6EC4FBD9CF8F2C1A5C98E667A8027C38F51299B6442B6188963262B14BB71F6824189FE8E372C6BE319147B719FE723C6861DE89A95FB61BD23A61BA04A6751033C5372E840B29C6F04951D3FF7FC559A3387DE0D582FB059E43FC5C230B8352A563E05CAA7DDCE8E068E5910F490706E8E6F58C6AEC45C6BE781AEEE0FB9AD868036E5314C44D2BE4DF0D4E47278BA9FF6418317088AF48347602D58B8F4CE43324CC9A053FA1AFB622664E8DD5020E4A6333EC1418E57C26CC3C45EA61600DEEAC5A93854D39F60315E99357BA88F58BD6136E96DA043825C7C17BD246054DCB99438E24DBAEA048666F15158D71C1543C2A550B9D24C5A24A9B78BFDBCBD3495D25449DCD76E8BEC2A65513C8EA9E729D7E1AF990D323A6ECF88E206C94A685DD3A4A9BBA3DDF153B7D98912B130C2A1C1DAA0262ECD8E43B5B1AEC483BE373EDEE376A866D51A3A6662C0AB3A062CF645FEF874E97CCD2D6C5"""), + TestUtils.hexDecode(""" +0B0F604B53752973C4A72EF940C3FBA910AA9AF2916D673D69C4AE4DE92A237F271E84921C309B59B92E795BD26C5C015EC5176155DDAE8FA17D7BEFCEE3A23E0201669CC55A6F270CF0D03FFC09BBE4B47D318B6926808EBB49EC8B57A849896E76648D51117E8F518088D66B69D88E09D298186C10B5678EB8AE43E9C0A794C63CA9D597C4B74C959E9C1E8E0F46698CD64CFF3C0FC6174CFC51095E142DED9F16E5B2D3656555D2D42832280164E0C10C5817AE47ABACEE7C3BFD198A21BDD1C420F2EF0776E5EEFA46E8BCB49388FA6B937FD1FEB2BF09D5B9494A534F19BDE4E7BB8A5E4C558C2A166006B481A7C5865069A3DEA2B880AA503B5C020F045A4D9C3E5C590E4AD5375E74B732695A11164B5A57AA665922431498A9218CEB9ECD92700E92BD11E0A8140938C4FB9543FA5DE8EDADD1EDBDAAD11A6AEFF2EA409638B2C7AD546EFE390729982304F35D7F889C0CCC81D67F5A1D6201BC4BE8D1AD2D3CB85815CB9669B56F845148DA0DD2D6B5D7C4986DD3F10BDC78EAD8B4A88B7AE1FE11C634355F60A43A55C88B37954CDA71F4744C8E2B4D7F8D4A2BF60EF0C44CDC7F7059AC48A94B10279921709827A3E1E7A46DD857616E6B737CDFAB71CBD47639245E392DC116614CA3F099B8F2092AD667DAC43B8501DEA9876E5E0B98B41733DA63A2517A49C169A95E583F18F2E1DAEB4425E307509CC6B0B376827F0BAAFC2FB2ABD4E4151A8DBDCB8C22C78F5DFEF0DD1743B047E58537866795D67E35358020CF75F0D2B80287D62AECD6D34D18494D01B4412B1CFF279CA69C18A263E7B862F514A7A64BF192586ECD460D22DD2280373A66ED987635761C3CC34A5BF6A370F9F8B16F98808767A2D9A1517544D869E674980758B15BA7844027D3593432101FBC51FA4709F4D041BE9FF31DB9B7430F1D7F8E06C22C4BF3F8798D50C92641CDBF0B2C88E88666029FC985FD4E9FFDCD779C7F7600D02AE8D9E3CE6FF76F0B449C41BDB785BBAC9CF58ED7ED1525D7C7E885C0D46ADD0F7CC3B14394235B9176B69A222567E6533870EA540F4DED9A1D78F2CB89E6C1DEBE67249ED8F31C87499E24DAB0434FB9B40EA695499C76A1618A37B1AAA5309A914B6574209A61DE0633F086EE4F2455299C70B981532A23DC453939D223BA3A25122AD498795624C727E973C052E69AC40AD465DF55ADBB20FEEE76BF2906EFA7B0D9D5EAE860FE02500E2E0F4A21CABCF963D91262EAFEE814BDF9775874D656F8BDE11DA29327E3E7C7C95395D0DDF766CF34005CE86592F6787D1044E5CA1962C4DF2719308B2D6335FAC77DF46092CD3D5D228E381BD7E5FB4D2EC18B19E18E4748F662AB34C3F2C33877BF4A8D43A63F9B5DC75861AABB42D34EF37EF19CADBA110A3807D1699B247BEFE3D61AB84941ACB227C79CA05180FD3415D0E76EB31B4DD903D78553F2C22563F9B22BB876E81EDAECA4B8FB9415E2BD5AC32CC08775A20E8F90A1681C9957DFC330B6343E58F841906EE3562ADD6AA53FA1EC4AA2E894AFE769116E29AF49D0FBE2D8FEBA215E470ECEA81B258977A0FFCB17666953C29B2F70559DA00610398A08E0A17D69705707569D6484C4203C06B17439E9D4D9DB8456682A79659DAB332DDF45C67E527304013A422E46F2989BCF033DB143676A4EA720D0DD75584298CBAA765CBB0B09EF267D503F2782A427459FD2A83676DEA43C01D288429A82527A69B1EB19DD3BA1AB7428220BA74F79A81377F7ABBC027D96903AF6ADB4644E9F5CE676FC4D3ABD977D6438F4743476F77F3DA6E822AE61E0AD38549BD21E0FAC1C963F1D47F9E6BA6019591DE22BCEE5D5C9CBC4106A369C04BDF633F41EB1D6821B1F43194CC14B02B753584A659EA46C49B983F592C83BD959690845E872B471A38381CF3B2E8F4DC157D9A60FF56EC63B1C66D2227A069CEE7E48DB0E0D5991F96740D364DF89B08BA67098652958A14516534103ADD9E457E6AFC4DE1AF332EF3ECF6897B3DC8E5D6980FC5E5D829D4326F6023F48CFC9D0D787416EE61A0BA3CFF5E7C69BC83B18928AD277AABBDE271EABF8269701E526960460EEF521E83CF7A61A3CAABBEE1F1C99402EF55FD438753790CF56034AEA3292828AE858B2D3B9C8D77FF4545FAE7B4F2AE1EB17B8198F4846A8F4A105CE250F900969696E477B2C46AE786481BCDF85715BD270F9C29BECF4579F2DFFFF7750E375113E33ECABFC52E4DA5405849FE5D5F4A17C1F0984A1479D561943CD1120037EE821A2B57A12D7F1797E64E38A4B71E2FB10207ACECB96B3F3ADFF82EDCB633E388FCF11C8D105C1F6EDD41B553B4B559C3199745F3B0EB7326B867FD4CEDF4E9ABA1FD6A10E1494847FB5DC83C91F7A2DD351CD1AFDF95865701FDC658A41ACCA58E574B67929EEFEB371589374285148EB09157AA9A67F2FD54FCAFC1248F6D84951AB1A676637E9CB76C17C282DB53B1BEFAD8019F51B0400DC1CB012B97575ED81C129636C38998A2E6FC5AB7F0BF1FFDDB588BDE4590A7A0F879FFFC1183A3C6CFB341FB518D0786A6473FF9614877B1B722AF4B2E1E9B5E0DE7C3DB004EFA16F5CBF07870D7208A93A9FCE0EEB598CC54F04B1BAAA992C02BB2D27217AB20A3381EBEFA04CCB1F23E59E4B0DEC700E069DB7620E22235A4C5F54522D96ED4785ADBA7FF95F2A7DB212D3DD05E58C560E5ABD0EC238B7ED01E54ECACA7D32F7C2A3309A437E68C3AC7A9BC51025409A2A1ED05F8DB0EBB647FEFE6222D6F74DD8E4034580B675DEBA4BBFADEFFEECFF4771A0C1CB0ADCC6E9B050B85D230F6B288AC3FC24880CCBDF9C6A6976D46797B75B8532411FD89BE027CD8C81547B24B535825695A35BCDA4E2E0A3A6BCEDB73DD10DD847C4A0AAE059A07F56B0ADC0401026648BA469C534CDF6E2CAB8F581A7233D2F15BB35DC990EFBFE688F9B9AC5AA5C9B3E95DA7B0122947DA03AB9DB58090FF14B736B9CAC65F966206AE7C84B971D83944D8AB61589A28058E14193751B685058E632E32EF1E8C94BF005A3A2EC5EE2CE2FF6C05A67D87E56998E952E4557250E8AB5A979ECB28B0EE41DEE07F919E67670D9CC4077DB0D90ACCFE17CF6AE69DE0C9DBCD3D552A7FB37383574692A267B0A8BDCAF3532AB47887FCC94AEC3461A9257322095F1024C880273222295107864903F3DC8FB353FBE51C4D89F30FEAA5A570979A38B0B4AC9A4AB6B7169984C576BC4AD6DA1719CD0D5ABA03BCBF1336DE48CBBE167E4293DADDE3997061469F200A391646C8FE712EBE087B448F7A7DE437186D38A4CFBFC2919FC888487B15C60E93373D076DF6A60452E62E05256AA66BD1FB771CADB331661DB4BFA47581A4367069FA20E9C6229F79D6680125D0464F7CFDCA1F5C46688D5816CD90862FDABAE753E56BAA1369AC1AD3530630998CEB4545C4404C8B9A65D5A43443624D62DCEC989AA2CB8B85414E06AAE6BC4E219C5A3FDDF8FCC75381F6A0F73F54A7A2B5BA0F546235E71B233EC107900D8116CCD398FB14F32CEC310AC089D6BEC40255A6A877C30B05355544D115E8F85E428087A5F3670D596E31D25F676B3C6FF444AA0FFE5011AE62D6FFF86E615EBE80622BB646A318BC65950889616DEC254DB332649788C07E46CE590C2362EE66BB33BD43807A1336B94198BECE586CBBE3136B5CC809F24DB5BC3069E9C1FDFE53C6D1DE29DF48A9000A7E89D6862A773832DE2151423D9D11D722D923233137DB6F34F8DFA4EEC134BC9EF5A70424D895638D1B09D95D98CFA17308908D65AF00259DFB5ECFEAC55DD7FAAEEAFD4E94EFB36698D2315D795A93B8BA6A3CA93F6B79F2E599149BFBFC6F5C5742A83C886BDD4539BCC128F30B370FFABBE724AA3F3D571785AA6234FD2359FB3468A06A8E74918EE6E87CB29178900B49891F565A80BFF302BAFD0D5C2C123973BA7B9B425973CB3D7F2AFF3059D272A7CE611F5CDDB5AFF3E2B4024FDF0E01D7AD1C63FB47D9BA986C341030B3E5C6CD3CDC6A3DF9D6901E76D31C141C37619F5BB316209FAF8428AF19236DD426D70EC81E77309D5D9AC33CF3AACC0259A19F91E4579AE49EEBA41CF79B9499CD1211AF1E6DCDC70383A35E0ABF7B53A1203AADCD3AE638862D35EC4E441100E8CDEC7F0E6D22845F6CDCDA801111C4C7F261189C7D67B981101C40F21D33D05E336F1C7443560238C72B34E47758927E37F972247F4457EA60B2546F6B5B7A91B151E8B3800CC1748587E0D5421A43648BBC5D87C591B01C229C8104CA87C0B7F0770ECABD1E2A858147B62F607A86E1C71EF73C036B18C01CA5C1BA8242BC4BB7414FC90C0A8372F860F2EE51DCC1E457135776C377F940400AC5309112E6742617FC226EDDF51E95CAB40CAB58CAE1E662DD78C6E253B373BE970129193DAC7DAE372CBEA847248C2E69273B7CFEE70BEE59DECF64126D44BACAB5F2813CFEE1EF89AA3FD6D030319CDCE94FA86E4E64998266082F8BF74877038ED888C16907A8DF99BB53809E54520E4B5B6AD44849A33EC3FA44A7B179350DB07524823FE8384413F0A7E1936D8CAAAFE1052C462778B36AB8A9A14BCCC0319CF6EE2AFF01EF5077A10BC0FD0DF76D9B806481BAD1F49EA013942F38BFE52FB194EF8ACB283B1462BFFE4AC618D6FEE7E25130EC71D68C81A9532A16520075EBC1E9C3FCDF5FFCC150F3815E8647F34DAA814935D0E1AB68EC6A1B14FC7566415CC11E0C14A9693B8711DE2D3F78EBC468269BC851D2ACDFF5E8A6388B73E33F20C0C7621C6B644649AB088DC191418292A698EFA4871224232A7788EFA2D69F9F9FBE80FB8E6B0106405F6406D00A6D6185EB521372CEDF51C2E0876C7A86A90F1F5DCC0EB3187DF8BC62736663F713A1D403665BD5AEFD6BCD3413FC63CD68B3C5C7FDE3AC4164FC3737C2703AAC85E6ECEB29E34A6ED70D4178402814B5207ED2AE12E9DE009D0DE6A0BABCBC4ED41D5C28B1943C4B61D8B1DBF4395F5BACE1E47ECF0EB9E21F9E7F663EAC3788E935A1AF73B19714ED91BCCCDBEDAF1C74155CF235A58485BCDFEA58A929ED1E959DC99345C36109E42A14438466B1F9E728801BCADD16B2D8F762E4BB8B3F01E531339DE79634F43117DF5C585D7D2FB4A5D3E82BC25FD92BB1298AC79211B3866CA1019666AFCB10BBEE1AB63263F2823A86DD3EC57E8632C9F4975155A01F22859EBC400F5A3B8302ADAA5892A320487AD077B144392528F100F0A222DDCE5636AD5962AC6D62A2382167EA977743CAA6BA2F140655DFDEF168BD620C73A47A8831DFD66DC6F2A9F47E0724081681BE62FD15C74846980683B729AF1757203F457FF12925B6B7BC81775A9E5C53862B07D4B93CB2E9FA896AF58D258384115F1C63779E4189832C29C8B142DFF30C00DCAD2328A63C92CD1E42B2A8D2E18542BA3A81686452C83AFD5F6955A708CC1DAE500718C6DB89ADCBEBF119C4707B931E685BAC00AA60E3B5F9F42FDA6EA90F5C77295E84A3AB05D69212C5368E24F18F43B450181884D7AE8BBC61E1603FDEB13797F9620AD6C2B863C495821F7F726BD5801A3D5A36F4609B595B7653799B3794E4A60090D71F5DE1AA5F0CF562F7E722C55AFB676395ED988A491A34B462B2D18AF517569531308B8190F0148CFAD463802AC62C6CB289FC0C95C207AADF82AA7399E0476B774D9B876829ED91EA3E5C40B504370D266B7B3C72DDE2CCB7F3AB8E820ECB5715289451D352D83DB67EEA889EBF9E8B012C8265376C841BAF6EDA4067A400D4C6FB00539F3839A8D0B29906F9923B9244132282E38242257C339A0D0BA8F05F75D41ADA51E29E33BF65F78981F04F397BD5F9580376A8D1C552363D6BE90EC83C2AF748CBB7783D6B26098C641777A260F5F60A712C7A7D1CE681CA1FF969B8F25B90F9A2B03F71E06A848DF3C5C8571C5626D5A1F123DD14A9F90B3958A7EFB3FD522C7E83F897CBA80B95099F1705E1CB22C7E91DB644880F7DAB480B29FC0F8E1D0ADBAA123F1E1FE36835ABEC924531065354B77DC1082DD690B316A7BF104140F6316C46E81E777F56EECE625EA030C1FFBA3A4D40745E77129230A69D76C226A80A8CD31720B08D9207F22F8F3068C169B41E7136F94B73047377A8AC0987490E4DA2B7619A760E3B61369BF762FA9A3ADCB014CFD0644AB1FE6D8D3EFBFEC893E98289DA93AE19D8DE41AB33FD717200B6949AD21B3290C77D5B1FA44EEC7D0C6A9978D50B40DF77823FF2613BC80D0E11DC2B790B332D5267851B6315AC08D0A2D6FC0A8F93DCD20DA6054894F84C88CE254057CD2FE36693F868D812DD1D978897597840CB336223F8A8EEA9C15AC05D3E40333391680C4F4CD5C2F600CAA684BF09EFC8A9B71E6883E9353C22B379BB6ED8ED83A2468287121207D9ABF61D2DD5116D3B163F262BD3D57A23EF2E6154BF6EEC1DF88B961C4505F7CFD2E23E0E0D245A9418292A5AE6E60F3852D78D19E1EACBE9F42A522FA57554308A1D01E31DDCFB7C38534F7B48E0384AAB4B81A93681ECE4C55BEB089092E757A4633B2F30BA83E470B3ABDEDF9135DF22E2B29CCD0893C54C329DA1B16C2FE4221F1C7EBF6B3D6DE84EA1DA57392762FD9C64C0771966B0E1FA9A6E286C23128DF317F704237B97A339A623C985BFD6A0C60DE48EBDD73A0610A22B02D0978E626B50171FC8390B80F37E5E536CC184259D4ECFFA958DEE1A27CF3D2EFC9B218809909B19D573EF86087A1C9BE161C54DD1279E022F98030669FC93A7BF03FB101A3FB5321F654D2B40EF8298844806BB66EC32F7AB3BC7BED2AA7F22AF20759B12A0E3F82D3C3A141F393DE746D5A0D91F32D8249F0DB0FE37D27E49795C648EC6D96E352115FE4F10D1F56C39FF9140E3E87F13AF3C6480D6150E1B7B4AE614A577D6E81694C19E468761039E970335FDE9945F6119F6ADC184C9F2A434C681D593F34D258F2A8847E02DA5EA2605A007B25031DCCBA8A8C50C77411D197E742D4B3994471AE84E2B612B09B2BBAA38C5E71C22A8E3DD1F284A681DDD45E962F9D061846EDB9713D4F925A9DAC0E32D2A4496F68C68448EDFA87FDE3ECD47411AF5DA95D8C48D5CED988AFD72BCB7A81896EB1496F468D4664A58EC3874BC6FF6A85692790BB405592DFAF53CBAC93884A842EB2D3DE9619843919CD9D68AD89DC7A84BE54C406B8208428066011807D722C2B34D4A279EE43BDEB967360D9BAE50F654B2A06B576B803544DCDDAD670CF8D2D7723929842C6AFC4093BBFBB75D1F5E03682500AA0A34FC66CE4409D08C726552ED5ABB0C646E89B35A659C67F6F398D6BE39D9725BB0322D458DE2A62E46B62013F2BAE5E60C3D41975C6A4C6231F4B0EA2827329279459840911891B0111FB4B1FE99FBB482FED56C7BFBA15882CE5E2FA2C73E0B682EADEE6F68E4E1A9CD92FDC2CF30902453A16622AAB1273407B985FA4B7DB40D87812F2A10183464F8173D22D5603C44586B107B4B82E94DD80E87AD49E9C0FAB5C3330B74E89F742CA1A5940F0F329F56DFD40C6869D0BA8CA412AF9C5116ADBB3C22080F93142C7778D52C4D75F1EABE13FE50877C26D7DB429E991506ECF1DDF30A00F9E0B355306B889F41BBFD1B4D27B67952E4A0B53D1BF8B2E84497F00826D84A913F02649D5145383163F3C3F586EDAD06F518B64D9B300C4540A67593B9F3358FF2A22AC4BD7E7B9AEE507D184E039ECA3BBA0B5C584D3359D7121BCCE01691E11C120925A7D8B100751E8ADE99D3676C7355BA4BE451920BC7D2AD6E8EF0A9693F16FBB570122FE5F5FFBDFA490B3C84809ACD898FC0F807C77937C7CEB6F03308D3E9C657F80730EF3A1CEC6959850FAA6C158F23B23D28ED53BD77531F1012DC1753CE1AD6E0A629E14BCCE9D56B74E09AD6EEC9DC4A5C92049D48AE21222AF706B1C4DE65AA814AEF5B7E1EDF2D8A9C5B98853A17199DDC3233C5583B95756F5A9C175FF7D0891010F5D36A268ED5C9F58433A69185931E11BCBEEECAA240C2C5A4ADB4E770109F3F16CFAA37AF98E1228FFA7C584B13F850FED0187FB836E0A01B19CF700849EFF09BE1A57DE41CE1D52EA6F182E0DDDF741DBD2150113B10CC3D9E44917E0FD9717D6D361A88060E202039AAD8F31E4E6FBB4D7FD1BB5D6DC20C3D83F23D120EC98FF4912F3D9AB18D8EECBD7EFD1CF9B19081B38CD959660E8C63A539939D0CEDA897F5ECDFDEE16ECA492B216BEA35A167178F4A0FB76175D160FE2EF97BD6BA0E296922CE60D91FCBB3343ADF477F8A92AEB56A471B0711CAC45DA8EEBD21FE83FA68EB74C8502C81C65506C92C4A3F19ECDC2B7A5AB47704DDFB2E8D5AE620CA0D67197699677EDA3FC4FB821BFFB5F2DB03D4DDEC0BEB13EF84EC372A5C56C1E712C8D23D1A2DB1BA077645C85689CA2258E9B1B807DCC6394680B72938E1B61AC3E8A5B9E84BB4B58CE5C8C2246A604C05701C026185CFB872BA78CEE33EAFD0486A22C6D5CF9264EC134DD79548F3CF5FAA67D8B1FE74F6AF7B897AB0A0D8CABD5E1B2829CFE66D58CE00E68C6F23FC35397FBBF96D2E63825C96BC3CEB22FCF9CA46C93538F8DF566145D06207533627B665E39DD284F4275051229F3CCE9E9E62EDDFA55BB2AB1D1D8E8E6145B3E38F35F90B89C15FE799EC14F7E415FCE4EFA72615EAD26C10C1FFA4FDBA2EE04C4845489C21BE45C478D8B2116C84AAC21B48BD4181FC28C7C21AC9CF95D8B04C0D817C8ED8083D9CF8B81213AA2E3B8BBF4AD66A7AFDCDC4C420945F5B3E8C8AEC5C4F98005A0CE1B3283F5FC0FCF8567A150E12639CA85D298CE8E4F9E0C53817D3009284A5A0BD5D3A07234AF751AD059E301076946DECFED43DB1176A2BBA4B8A571299FDE4AA3574B6C189A721674E004F259B00B26EF5AA90794FD622040B80CA6C5E9FBD44B3DB21290353878F4D8D87496E374B05E6A5B25742A885569DBA2501367EF4C549BD5CE6169914A7F1D311D52CCFBE2091F0DB436506F210C137C2180B89626F52B4192C67ED06C1F9175E44B9468E6FC2208A98DE577962D9B4C31D5B0DCF4017DB1BBB2F80512C89B9AADE69DBD584452D25CAC97A4A7E6F48BCB909907B93F5B8108EDAD38CF7FB541328C5E8AB867DDCADD6A1B5083869E68EBC785C80ACD260C715624360F2F3D78FC1B2A464FE0525059A3D5E04BCCD72D23BC680CF7B25C5CD2AD6A0BB8366DB24B671D5BB3C12554D37C7A662AF9B9DB61DC6C7DE288DF1976DE08743426CDD30AFFDA05A8390A8F3A4A94D7CCD33BDB229E32850A77B2256CC595BE515F9E6854463966D4DB7A946276F594AD4BDF0B9C59D4D38E211A4465AEE023CE6C062FDF4123ACDED834F672C1A724BC17D44DE9632A588E7EAA77F3183E09D2ED55099BB1AC8198C96EC7B1635139980D5CA4B8B3102375A2E08BC3BC754D9FE659C3FA403218BC8C00FA87A0FA6F096E336865DDF02BB05049CDC9680E99C4F567ACD25AA7CC76C182A8DFC174BF6FAAF4D2553A4207922C1EA10CA8DA3E35DFBBFB5F6919FD4088A3A8E48358CEF25576A3A6447980F1C716EB58E755196A672C378F6615E54E9A16CEBA33CEA918768961C244A561164B61754F679856575DDCB32C70447BB738E84CA590CB523C6553F13EAC77461A58A7D4E1CC1E36E7BC5E85860B0E6B67C70D398AC0BABE1F42426D9E7F12B5E362BF3BDBAC42C572730C5F4EEA957FD3F17050625BA9D9938380249290AAF31BAC"""), + TestUtils.hexDecode(""" +7C6B47263ADC85F69B12955F66743C08E52EA89E18EEF82D6ADFCF8CC1B1A13D386305F13956EF20C02C65C64BA0AE526CE9EAFFDCD44DBA07600C4563EDE57CC7BE708C057BB3716AE33D09FAEEBA0E9B71A8E24D03DB2ED26C85754A25856F054410E286BD70A176095540559340F1CCABD50EC5E89B36F97783D35EEF716A910E6ED934332083F0B49B9B7995489BAD905E86D54576447BA6254C382732320D1ADEC8B75C85EFD00217DBE6F386C0C02CE4822AD52B72AAD0FD00F74BDFE62F2182FA1AEAD069074255883B08434E20886923086D3083864DD22EA3469D56A8A7F4384DCBB04B819274399346544F08A14E5E5E7DE0788854702775DCD8C6A32CCC85C1CFD78D5D27BC651FEE0E3EF0082DAD5ED0399F33C179AC987A2B933268A07BECB62CFBF4425609161E1AF5E706CED78857F3D1561A4615A058635C6D4F73E60ADC5E5567528A63B60D26AD8C8607BF09F4C8C96A6183AFA07C63CC19C25EF43AF3A21FF390185B5EE30904988DDD853F7F3DD4E09F145385FE52358CE2C69E3B14F7A2872AB7455EDC06A5C448298813D7E0A2605EA911A03D6670D08631BA4E11EC4CF9959C38071A959DF07610C3DE964D82FA9C5C37821E4A3FF7E0EA642370DCC4EDA58F2CF264A8A87E21260B4C0B84C5D5CB5633AB0AF0A40F9E4BB3D5A05DCC5FEE2D6C1BE45EF44099F740D35E5A515C6CA1D578E1A0C57BCCCADCEF80FA42089C055F13FFA1CFA8163B0C338244EAD2F473831640ECBFC4F7E244BA5A00FB366C87646A8453F44BE68BF5EB96DEC1B1428AE0C224F82A0CE6FCBD5225F1C0EDB502344066B191B81069ECF87088A81F8CC6710976C65C9C12CD4FDC0964B77A7D79A055A907AAD424F6D0B951086C3583963D823A2F2244741277B15171AEA99A691AC76EAD489F25FA84A1EE6DBFEB3E1827E828B8A04A87B8174F5AD43D0B59D39E88321D301B6506724042FC1229F60BC0D3CB2E923AD72D4F6F1B416D6E83106B042055C9F92C79C97FEDF1DDEE892C080521FA69AB735F91F369595F5DB09F03CC917F4AC29EC03E893D3EF6D536923B9DDA78C04489F020C4EA18A144E2BBE1B5686A1D8C8864AFCDC681632BCA685F5F391F07192F51FC9A18F0A05ACB47F818A12F3BF654A892D396D3BC54BCB09D877FD0D98ABC76BBB3F184BCC3BB294D7BF6F548720C6B8BDDE604476A876E7789D6584B2BB9EFF13FE32113250B6B15EED1C6BD48F54D2353E15766CF4AD88921E66BB2B17AFD3D8C0CC18A2DA69443F3F4CA9109BDACAB0CDC704B835F6992B96D088BB3C7D86F072675EA1C259A4A11DB96B9557F60461F33C06264E3EF6A405BE4640710A36835AD44CDA5BE55F0720313A5BD39CAD155F33261076C1211930D23D2202E8DA8130505E1B18032A743F293111DB0ABEE58CBE2D5FF413CEBCFAA1BC10EEF60477B2ABE50D598247D00917F0FD2C9122DD7EED52403364B14640EBD6525DBEF7AF9EF7051D85C7F80BFF2CDBCB61E0708AF53B2FBA4B6D5D3751D07115E693D68F4C6A0E41270EFCE43D9A888E83A6006703BED0622F5CADB57F6DE5F3E5DB74AF934CDC70B31ECA0751540F255EE3D29DA18069330CCAC2E49BD2E85BAD2B43CD6F39F6601FCCB84A5F47B94BFCBED53536FC7DB0666E0D50A9A567D78C2F6FCA01D94923A6373743C00BE3FA1A1A62C24CEDB2440AD7645475DD6D7D7D616D30EE0E35E5912ED4055A895848094895329F07AE1E201568061E27ECCCBD78D564C38F1681E7AEBE51C02F563DCF77FDC4F32819FEDA21F0812067FAF1FDBA95ADAC178B92A4762551C669057A483453B49209A20A52DCB6F5266E1A8012580B65707BE63DD5619413B56644BA6B5036C68E2E66245BFF8D6A84D55B37A497EB16D01724BF3790931AC164DEA3CE1952912A938924F5D4DFCD5FE398E0727A79C0EA11DA7CF1DD406AF37D91638ED36D8C03404359BA719889C8DAD452A98AF1538CF1316CE669AB2468BA3CBDFB76470525214D177DD0BFFDDCAB4C82E2B1D1764CE850209E37EA76E8CAA553BFC42CE5D2DD483A34502E73B0F04F497B8AF26A188FB68902A8B2F5DD8387D71350C77E7FA50F541E45EF0F68D623298A88DCE27547F83150C2E679A5F8A3D28EF96C229253BBD5B60F2BD7845E354B3D7329179C1DF91626E7549FFECEE116AB6A7EFB4C8B49424B68BE363AAA794BCC68E751B3A3F203E5A9495B440649F9E3DE6A8AE4817CFB738875FFA75CEEB6ECFEC6EB555B65493234EFC90C5203C6312B7EC954B444D706F4A572342059B765DF362FD07C3B48150476D5DC08D3409A79BEE44634D0AA92C6B70EE7DAFCB38252D91EEC63164EF7555786437A7F8A282E56BCC13511D71142FFFE35E6F3219555766A0A08207B2DA4C894CF35206485C2B0EE6B28662A64A37C5C1A9D4C0B366CC6D99E92ADA28792CC10E5AF605FBFC638C0A657054A0E8760118307EDCC7384C9DF458C3C64150925B22EC3E1A1720BFC967ECB4EC5BFBC314852CC17A2269479F1AACD60DFCB1E415EB40136B7A6A027C782FE7D7F7C6D19507D8C2D0F6C250106DC0A72E4448D0585225F9E735A8F126FDEB81192DA13BD806DE1482AD570BF016DAE36928EE49D735F91F059EDD2750D785BB14A44019916BB8BBA2B4F818637BA312D54AC37257FC9E2853C086E95EEC0066782713C98C82F582C0431C531FEAB552E1C1AF0B82D6034F04C85171FBE7BC0818E8BE09C5033DB552FDDBBDF5DA0A048F920B7FA61B7D5B38D1C85F3CDF837D90F64D31FC5EE79209C45A4670849C70C82BA98A7EE2030DDFA50E6952BC73C71A8CC49BDFCB0F10C1304B291221D56895D47C9FFC80FA25DCD12B40C96EE3177E9B6B78A2D9F59D2C2481143D3C70605830E3634931A3027A8FA3FF22EAFDEBBEE16AEDE4D8712EACFB58EADE2E5DB35CF01BE532C2631A1EABF4B5F373E230BC8765737D1F1DD529F10D2FBA8882E62C74937DDF93CF6B769F84872F779D974AC8ED13A55A076790C032D8367AAC64C944426D661A87BB24A5E4861D0EE60D07A600D4D15404EE920573F2F5A3AF5D31209548624B52D1001D2477097A25A0D480C1A1A04E7E1FAF0754E4DF5EDBC0E5BFBF152F23B54B90C55A8900F4091BC9C7CEAA1C7200C017D5F99DFD5FF5D7DC33168C4BB834AF29F3F651C9657D3E1653A7DB02D7E61BC48A13EC743F3107240F53FEF424B864577BC4E6D78E8634AF636333063B366F0AF833949B0770B3E545C563E3B3354D87993940A47128185D74EBE823EE752375264143555E6D7F8897A7C2CFDAE2013641586A91AAB6BAC1D2F3FE292A4C51595B6A7985999CC0E0ECFE0B181E2E3046477D8B9AA5A6D6000000000000000000000000000000000000000000000000000E1B2A37""") + ), + + new SigGenTestCase( + TestUtils.hexDecode(""" +0672A2BA2653D9EFAADFB90DFBAC95F77BE8540FFAA866671AF76F7CE585A21A5EE3BC98E969B2DF5F910F15A109DC09B91579F8761F4145771C80666362EAFE59CE336D877D8C724953C5738F65F3E1C551C1FFD9DC7E627DBE0BCA5174F200E8CDCBB1D8B0F84569DDB324562C66B5692C9069EFF52A7E4ACA9E293B26C1BAC3162A43808DDC4248A286401248649AB208E020462106815128900A984C94988C4CA82090926888B44D4924495A426E83B6050038500BA38D00B96902436E9BA484D1B88CD8A42D043208CB4089E12032613210D144491148258B08694BB00CDB280003C70C98883041A40CC20612982402DA06498C362C822209643089A34624129690818270A3108554206DC2B66001426A212222198204D1248660A065D0482214372662384C809808248040C1A44C1A4692133430C88808DAA650D812920230518B244CE302300A114CC4246A4CC44523B044D0B80C633800CB062EA4304E103051CA084D1BA349DB4828D1464D9BC484D0042CC9B60103A64443941080C66999100181142403050293264C9B028E53180D8A16411BC0290C47259C482553A405538401CC8868012882E1980C42440208A32008836D042292882800608408040289820812D0B609D992248C022C0C482A13920D1400244B380081188C0A9328220808E1460682386120196059441151A80D8C12321A07881144116338255C340050A064C0266DA232308CC684A224710CC72D5B323111246D944011C2B87108054C48184E49A6910B451014816CA0480A222588E2203050A80551366E234820242932D2C40C9008081A9750221345A1304D14A088CB06111104095B928891A001C48848E4264C0BA2499B022523160100924DA006908AA481A312481C9281121842040152892846D0840513374419B9911B010D19912C42386559466D802428E3068A24952411C38D0A1491498400C082655C448C23476889308253300224186E08414202248210846594288C1BC1210A246693A8011C041204308C9C486A0C47460AB50D8B288C58162100354E4C024E14B05112C80D80C40CD1484A1A36720B372419440962048D48424E91028103B405134082184520DB4288E338019B460299B860D8106D13240AD0B08818996503022A00372012079082B04559A485D0266290822D0B324E218291212006C90270803681544092D034640903011A90510CA2085120229BA009D8120452028820315184804C5492000403810A4809FB030EB7ADE0094AF6D6A78EF4A30D8A22BD35A79B413822D86A8ABF9BBC04D838EC1F2150FD86A245498E76DF32DE661DE605C76757DA5FFDA3082DA464400EFB1393D92A3A53270E0F144D255B5825B05BC72C287634A16EDAB6AB4422CE3AB84E45DB798151B1697FBB7CBBF0FA370D1F57D887E5026226CDCFABB2D502F7A82E983B03BA41D643DA93BFA387620265DFA80DF45E82C74C14963392199609CC59065A7D4C26646A87C04C31B34B2A70E029C24EF993B30EB53EDECBB4FBD6FAD614C581B3C04A15AC777006B0293183CA9DCD587960E736F780B1BE219928BEAB8EF5DE4B8A03449F33A65B2B08DB13F4B7DA0B756153A322282AD8F8D8F64EBCC6D322D519D6CF1A8F684CE469B9B9269759944CD1A863E236C856441F6C2198B73999AF6EF8140C9D23095847D3DB2518113BA8C96D6871C4BEA7067C0BF6947FE69B3FE12081BF58DE113C2B487759511CCE1FA48D814FAB7F0AB1B1323827A8DA71454578F1046CFD395E3683C332DAA81867B112E8865B6E2405D5AD2E57E8EDD695C3DEC48A52BB39E590ECC8F32B5F80382F1D444CBAC5FC7378C4D8EDB275CAE3DEB4C298EF20E6E4E25DFD2996769361ECB2C86AC0D28287685219F60213722CD172A2A2ADE055B515955E2D982FFBC13C2EB17CBC96371EB69C35BFBDA0DED49E6DD63021F38BA0C7E30A655401B6B8A9796A675FBD5044E64F6289C69248AFBFA217B68A5499E605E1487A07CCD60EC743F053731CAB8A2EA92C4BCEB56560FE3F55B21FDD604E6AED8F2511F0562B6F1AEB40B70C116BCD8DB842E26EA0B325246F4B6580559F26D6817D6BB4FBAFE4B144B26DFBC52D45C3DE758999834A642E871AF54DA2C86D7D4E3DC6BA54F5ACCC8B6D74EF7AE1BBD0C82D76A8E837F47BD53B8DA621FFD51A05F17FA88CC3D7143DD4B36F0674548FB886ED228BCC53B33998C3094258ADC3E05E24C5A8BEEBC588ECF45178D246D20757C287FF45149371931C75A7C59955F5BD1834B6738DA57D4FD28CBB11ADBCC6A11692021D5AEC5D36D6A992E7321C9FEBEB0A8544ABD8DB5CDBFB40889219F893FB4F543C22CA29ACA96B8E4C48E3FDDD763D5AF7C4A69AE763926F6F687130CCF2A2EE5EA746C3F1AC9772306A01E378845F568D3D885D4C267708B2C352C45905C7523A3C390B89F3E034D4EDAD9327785975D7286B755CCC9D9D4874B5A9DBDF90544421D7C6B2CD2876C4301FA891A2836E1C078EB7E4C31837DE4B8A38D270024F121DA31F48021CA533ED61FAB4B5C08CF3CE5DD5300722CBC6D1A11D068C604967D525394E88A0920EBC56AEF47FF4807DC5245345CC7CC13F5BD929EDDC183D10F83E5AF32DB1F7D87B2B27110B4A6D0B3AB5252079D4FA1E5FB3D667189ACC70193C1CFD4D7E3FA9BC93CBB834DD3C8854EEEF5FB471D73B3A35689C8E04A1367FD191DCEA35A661D0AF567DDDEECFA8AC62C34DDEF14BF848B35C9D97BE3978B055CF895477902B40CC35F3A7DEE7900F5717073486E8C995192619F7BAEE5EABCA9B314B4D0F3F602CDEDC8084CE573A6C7BB59E4E0048EE367D7FC40419199E0B104DEB93B9E36BB510B8E40A00AB9AECE27D5FEBCAC6134A303CA9B07F332DB85A8A03A56995876A74699A8170EB695F77395341355AA8AECFD30443824F7BA6A07034AC1638F4C6B602C48A0F11EFCF4CF765F886DDF128D16518F2E7EF3B4E6BF799D0FA82C152832FEFE7BDA434EBBD1C81128ADD704A749D46B8D5A4BECCEB7AD6E4959F8F4F191002A43FA609299667292332BED76228613EB5AA536F15BF7C2DBD73A002B133E7E780DE1F0A3F49FFA1E32DEC1DC496A0080CE85130FF9622882A61CB392D3233AB3AE81458517ED1A65AE45C6577308FC98B31D74B008056B666E70423816151EF5881812AADAF241B299222AB9F6F0C0178196846958E2C1B4536E2110029F1E2D7B8796B049EF697EBECD35E467704AE9248836634194BCB51E4F8474FA7699A1125CCE9FB62F16BF5CE11E422DDE6323CA490086F2F9D41B7659943D455C90BC978726707CBAF0224613828281276672CBA3FD13CF37609CCB8027FB026A8211DF8E13252AFB9DF7F13423BD9477A0518D581326181498DFE98D30248DA71F1DEC92E7453DAB2CAA2DEC15E1F73A249D9A8DB45D503780C94DF2985E339612AE8D9AF07E96E3B54F233636E180867619700CEB0DA7C2362496013D14F904C30594D6DCC3FC5424AAB9A4605B34808E22C697DE85453D4E9E55E0B7C04E5CBBD8F3530676B09ED3A0D5870042940C900514D9361CB3E3C5FDD687FA90F51C0A21A0E27CB420CA68356807DD24F"""), + TestUtils.hexDecode(""" +0C39B65F4C2094AC626652CD33CFE44EDB2667CF722443514CAB443DC398A8EA009277BE397E1C1E7ADCD1B24376AF0F19EA50E56C90D683F8EFDE693F0F8834199544E2DEFE392B0BD46048A83C412A14834C4BCDC180457456BC72AA28F2DB247AEE84A1C49266361DA7EDD54BD9B562889131EAADAE071AE5A671646F49B2C1359382F1A3B2A6B437F87CC99A2A1BC821E1F3DBB311B8FCDF28546A479E2F9970870066A2D6447B6CE4FB65ABE7423910B9039EE3234836F924C8E82E1299335E27B0DD642B812480D6FEFC47B121A710827DE1D18DC12064649224FBC4526AE14317CC8E53BC8E9BD42BA444AD9B8B48C3AC807D7A7675F43E3021BA1DF9AC7A42A9E23D696BBD03FB5C4702B55F95854C41F470CDAD8A255436F910C089F71C2E59A44221D78AB81D4E2B059CC92A3841E1431415DAD4E6EB0315F423DA512661E4CCE098D6678F560A4BA19475296A2A1DEB12AF5900FA3A3C188867E0C268EFBF7AC53455552DF4F36E16D50E23048C7DD4E64341E6DCAA0036EE045B82C42121B0B779B5E7FF032F549536ABFB702B1CE4EAA5E389A077F47B1B55595D4888A4C1D17F4E21706779C9CDE25DD1261C8B4761A40B69E2F22F069A264E79CDFD36F307D117FC737D88F50EC67CD07D8FA269CF265A7E7CAC93E97BC29EF95C88904AB2DB61C8865A6EBB23871576DBABC83920AA015D47E8CE699A9E57E139AB7D233C577B46C9C314D084A1674A152D87D2A3D8A5D9ABCDA22E212B8C9A2BF25D8AD22AA3627E6C12C684AD2BE917F094263982D396364F4DE0BAFAB2DB89997DAF8B7E3AA953C055776FDC29F8AE5C28D4071534A9A2E9090CD3F723D3E381A2ADA6D9463FC49B3C6D2B76803F5C21D8DDCE965D2C472389D2BEFF448F2D81EDEF1C851A863AF66B64417BCC2CBBC70C18875055D171BE32C06081362FFF7DE8F8A23B076839602E2368CEEB79E4EA53F42F440D167A902A23ED53E6691AD3332DF5B0160EBC3B5C9567CF619BE2201447EA500332ABDEA9B849C3A395F596F2C96ACD9AF8313E453277B9F4234874E791E9DCFF0C9D9DFA8FA9474C026DD34E5CF3AA10CAB1FD23EA5DA0D0A66E520096C6116944F2E5747A974BF55428A3D2475F6276490AADA25220F2F2111892DB9E9C75A5401BADBF69F31B77535044DC50B1E93849F19C0B6C5184F1B14F68960F9F469805F3843198AC68E51619F3D712A34279AEA27BE4357A99C44C456BD2D9319147285680922B98DBC4D6D2860515D1371D2141C7A1E76EEF8586AFC973713EB89C1F09A84AC064BB7644625224FF1F7316B9DD1091CEB151D1A040F7E60F202728F7862589E7F1FA32D39653383F90C67D96D9949967AF234592903CBB968E0D979B92B5C69D09EF4E767741F1F6E361DCFC8D751CB8C3BAAC4CC393D63F71AA1488491CA06CC20B0BF54C5C225B6F0825677C2C40A395E1B7322288A815E59AD2999D61FE09C95828CE18B2997AEDCED56CA8BCDA4343B1E948256AC5EBDA23A8E6D7102A4474CE23567084547F2ADD9DE77483398D81A9A9C7A573D7EDAF99536D31C3588BB649EFE1495CEDED788EBBFD5775842D91DAAA2F9BE08D63B06DB35E72CD0EE5DBF45DF9B0CA682BD944A733D6875A62F8C53A3FA9337F13429FACB288C73220C29285B2D87DF2CB1A54631AF3D0035C1F3B26A5EDD07760A63576A395827F3D5F9B03D9E47A9E1E6A271021942648B8424234080492BBC56C692C769B5DF32A75F7403C88469E54432A37A895E3CAD3AB110089ACF534A0D78C2083CFE149A2D0A5055EF9F4C943CBE1FD393292518CECFC57E4FFC4D07A563A30528A6A3540636A3BE770B7CF03F5004D7C6F8ADA08DEAAED0422AC0C0C8D7515C9F8BF44195D6DC30D9B3036DA007A910BD05DF06B032812CE8393AE2777D717A691D07E860C1EDA60F6DE31F0787097D0D483E3A51CA7997646503738CDBAEBCC21AE4B984B668FB4020C139D9F581EBACB7BE263A33955DD68C9ED9BD2DD6C0A7BD049972B624CB7E787DE7184023F33EC0A1539C4679D6B4677FB971D763BE17D989FDF8C0AC4E0B5A6CB40A49B5464610A110EBEE9A21BB0D6A2F043015EB2C8820DD966A13EFD18D32367834D41E8673E997B2803638A710580CA08DDB4D90E4E8EE584BCA2FB853A122274142130A1ABCDF7DA6C0056689195099CC3382AF6987BA47EE294353674E7295ACC1C070F1D8E4107AA7189F20CC818F1D86F6D646CEE911B304E2FECD5A14CF5F36331AA86E10C319C96E52996D4CC12810AD7C1DD1DBDFDC78DF029BFDE9E8F9B1FC7D9DA99FBB0304A8129EC58A82177EECB7330E715BB3C0B4482923C7B1EC0D1823FF643014C7D08A8F2D9F9090B0F83663AFC5E601E5FBE1DDBE678B9D93C5A23F564B8A4DD29C8D19106747959E72AFA4B16B879E3C6E7F79A212A144F9AAF665253F1360ACF7DF37642270656583E06FAC85389A3AD76E69BC2735B1C3E13B80CCBD298EE25C29F9F5C275AAD83BA0E7C47526253BB3125EBDF5CCD6E1C4F9D9CD4891167BB4E4D2AA644D5D362C6F790E2776BDBAF8D96DC3A543C72ED46E431FABD737B4BF0F4B32E12E0520E60401CCEBBB40180985948045C58B0017C3D8797E433A2E2C64B9679EC7409D59B3992053EEF2ACD7B152E5F564196876EA0A31CB6ED47F2455BBEE6827D96C6B99E46F3DF1FA21F593E842B26E83D843118F6833BC273E12C7224E00E840B0041544893C6C8A06523DEDE2ACE7365693BCC6A8D7DD81B01310CBB8084C5FD3868539F8B5179519CA6745B56C4A5EEE8F2A8A60CBC7453E1E0990D176446D97F34A2D0BD5C5712E2D82601D0B9FC9A3F2420C65E4532DB3810FBE3635B2AC3A84415535FE41208B907EB3E97AD63DDC4FD694127EF1E948801B5CF651119CE17BEAE3396C098A86548B67DDABADCEEDF60F57D2941815778AC14F78C78516F84C5F9749B433DB97A9283A94697419CF94248B6819D9310324977D47A133AE9F1FC141B56D6302817761BBD52B4A1EF808E0AC761426C99E0504ACB6B552F9550D55DE787C12A0409A9F9EE3674617D15E229AAA98BBF4FE49CDC81DA3AD110645132B332B6D2AA38B35320925135BDD225053D6594E78389909E596C63B85DCA8B3F6C3233A31A1F8F3E900E49DF83F649E592979C9CA4BE65E7D6D1F23A7744626972D52B07B7B89CD90238A5E871666F4CA6DAFCBF34FE15983AEA5BB7F9917736F7BA46F342F0C08F56D19AB9569FD23288EBCBEE7B5924B8C86EF77748F3AA9CF2FB884398F83772C9771958B6DD063162A3AAA42E6A3280FEDEEB7A628A07702950975CD135D6338FF959ADDA2296B3E85A024F63D4ED8A5859786E2BC76C2325F37B4D91EE8B64F30E781BF48ADA774C1641CFAD2D63A59E294B5D99C94108154E38B499E3CA2A29AF7CC77A8BB3A3B712376CD081715EA715305C18B51470D5F3A6A82E9189848311511E8B0ABACF856312AE3916FBBCF6664523684D3C7ACE08D2345A3907C9C07183CB3E68C5EC3899A95430E278A72701E2355A4AF606DD8F8750F7F3682FB84290B2BE23BED99CA06D5E54190A5558C927C369C00C512342EFFC41618CA6F8FE6E3A38D1714FC44BF5679C1A49CD8BC8B28499602E277DC8832F738225920709799DE6961E0B4EC12397E7891AA772627F66F494AF719C55D056DCBF10E8E3DDF1B6C1BB2F0B2FA61949D1CA7D4E1F60EF836B086FF8C03A5916A14EB2670AF56264D7390761E6EB6F638D6FACF56B72A48F271ADE4541C8EFC91D15F69E0AA6B97EC0E9C0C3EF169E4A4DB1C1AF04762B98ECBD0DC374224D98FDF7788435BC154E1FB06C970A914C34DE52678F61ECC1969A2C5B1FF4D82E2C80CB543B4B7C9DB541229CC50CC6C448DC029CA24ECE635233C401D3715671BC75785DCFD929377AF5B65EC43EF45A9B00CC766695A4A5DE9A2E6582F7936B9FE7DBBA6762C41453683146F4ACFD809847F866DDF559972FE0C093EE7C9FAB3CAB0BC2BF8DA19466A96BBF2DD4859E2D1CE122A3CF16AAAA9A4708F72BBEBE285E1B794B2B9C7A699B36F39F033277E8B7BEAC3BC70A572556EE5C070A309D9D0BC35F4B6E55ECC91CE9AD273B0098F64E1327C85CCAEBBE67E8A118669653495D2FA09C29C6FCDF870905B2C8BE0DF806C29D5E7AFACDAC5F89116A3474D2229C76E649F99EB9EC71A2C229764A477853D68C39B8F0BF4378993AE2B26E814A337CFC103760CE92FB564E3A3E4546996CC4D8B6BE069E99861DA9C731B543BFDC006FBDE3B33D2C8C4A3F5789466122616C98F52E5E4BA239E0C3758C5BDD3BAED8809F67A70504BA061409A9D87A499236230EF0F1985DA0D765E9B7F733A154E8300490F458847A89E7C6BBEB7A9ECA7B6CBFFC3124DEDC1093C02C808DA1CDCFF5237745C5FFF51F3F15CF746D3397916A45990070490CA74A55F34EA4BA9EB73A281F123035C005BF6C7B30852665860ED13A2B5808F81435A77A8504B58CBA45559BD3BAA663A571F108685E414FC4DBF8033075E30CD6FCD9B893DA32F7C8D5D971D5EB417F1201B00F65DEF4EEED3B55B7FC7E6194B72A861439B865558157E65D4C2F8A1A93F48192099B375D111370F830B34EAF3225A16006D4749494B9AB9D3B05015E34866A4A2D94B9588A8DE8AD4CF90F2CF422634E8DBFA0FE3FAF27C3F3C2EAF9C1BDF23FDF43D196732E1FA6D2B343BB7D9F5F26FFC31B26C64A8EFE2B2D86AA34BB618FB58CCB54486211A8E66648CEAE52F07A6C1EB5234DA7CCAA971AF984D6050D1A81F10E6D19CC44B5E668CE92F4251924B25DAF41D5E381C3FAE4208D18F710B5F93CF3C776A3D81C608B06CE6BC68FB8A8117CE7BA065675B88510F2E8A440EC363A5983DDC1352E446A482C593A490AD6093258E447EF52BFD189ACD11C87A8B75F08B5D166C1DA69602EAA5916474131E20F704DF84C3FEF2AE99F9B9E8F7315A143A07C7AEDE5797F503086DF7DA971244A61909C4AFB00842FBF4C3A59B991B58AD6C0B8667C449F0D97F34CC41FE935D9F55821299F780359E2F631858617437D4AFE67DE4A1AA382B93CC3FF596726F0D1C071FD0E00883E9E03811FC659495AF2A62B45DA079A66552F2928B6A25C6416F8DECF723623764441E5E581F9B2E36479A1B6CB3DE9B090E3343277CD7F84E80219793CAED4945DF782C4B72B498A62A1F5362745662F711A7E47CB816EC7069D10CA8314845AB0C9FC326C5BCA0E2AFFB4E6948522F8CD9C8DC008855E592AEF1F8239748916878ABC493E33CCFFDB86CC2ADB99B6251F493F0D2A0BE56D133B66395AA695F6298F7F4BAB41420CA9B8CCEDF2719590287928CF6BB3A506D6678B814076B7A774BE9B7029DF9F4719AAC1D012BBD49EBCA6AF124D0AB5C5FFA92B4A895CB76B88DEA9C7105136D78B76D92079A5B001B214DDF7E140861D86ACC260B72ABEF2CB3A75C2BC87B39A9D9052D4283B71C10AE275474E82A5FEA1654EC3ECD468DE4A015CEB67BAE3275C2C79863E2883D46FAE351F0908F42825DC7D9FAE0FC7171791FCAB10E16F3F027E5043AACBDB1F05FCD2B3EC7F6F46AD6DCCD6F9E6A6AC702451194788D14261219F794EA195F2B3778654BB373C68AB4333E224D161A1F89FE440BD8E968B518EEA28E81B89E04FF1A85B879E4B54650FA8DD1322D14B4A87"""), + TestUtils.hexDecode(""" +947B02936A53FABF0009C0ED2E82970B33714BD4F15DDF7BC3A895DCEB96F9304811F783F8CC627B5B80868E23EE36CB98E6A5F9AF020BC5DA891E898BFF4A5AE003268A74BA6088E920511F5EEA54A5338D03356EE19C79E7BEA43AF809BD763EDED9D639DB0CDC790BACEF8983CB91F1087682A4E707E94B7D00EA8EDF04B57D5117F84589FA045A7B4A75C62FF9A344035E8B771D66D82156E28EED855DE1861023D5C1CD356C225AE03EA0A11BB1231B784CE9BE0D54DD6C4EF3128C7E14928CC0DB36DA5F81CCEE1924064403E964D375B071FD36CE9595509DA0BFFFA4E4C2DE1DAE201A55EA124C86F9B963221631AF131D2C4DA034A7798817D2734AE44282DA3BF2803D4DF90B718329F31317E5D585E323DB512D2036B74812C11B219729214B485D05917C913E742402ACA2127782534EB2DF176C5C25C484ABEF24A969EA2EB524FCB54A7CAFF7E6F464D8E716689810A2A02EC899685A1E28C2FA215572D188D3F39184D09EB93AB30D507DEDA6D6049E5345F989E071D26D909170D7AB1BD6CC35AC198EC7C0B48FA5679D24912E9EAB38FE594F1FFF5F2D97ECC84D8C81B81B2AD476CA93E050E550887D017E55B2B5D15700542E90A4639F55A63EACB727CF1F6C76D1DC7B6C0FFCDCC1086B7D8EE1C6624DDEF545082B4A4BA6637F8B77214914693DEDEFA7E62F5342548C0264206C30B631486CF5522D3BFEC6936AA961719984B84C43C49F2399EFAC02020613E97E16640EDFBA2D74ADFF5357A064FA43BEF8CC7D03AE781859942111E4C14CFEC01C47DD9FFF9D3D97EF92B4AB04C571A0C58DCE3BF45CDC01A7E09F7C89C81BFC06B5A4A46C88FF95B7FAAF3576D53346D18A0C179E73C4DE8501FF6B49963E2683951FA7E55B49056CCB0BB6759494AFC8A14A1D5823074E0C17DC279540D29C2329635189397DB8EC9F8327958BB00DDBDA507E1B54C226E7C02A680FA84E935588A435AA1CC029EC15CBFFF5B3AEC29034332C917882709A95266ECFA14D4459D5F7C60AB739AB428CD967CAE7D1D925BA66365A522F4F9D559D3268913CE7F0F228ABC49D4CA872878D7902F7A202A58FFC7D54FD7AEF88E31FA605840E510C639D0D568D7BCB1A72268162576717A238CD3416E89B3A77163529A816D613928C2CA18D2B2C6728FD622432E54A9085185042034D4DC8EA8E9F100BA7629201636CB87B2E5DF1F95FDEB407DC330716AD0D6ECC93BE38E497E1B38B94DB5DB6A5C067C6D0E1345AFBD7D2AB9646B16C531A96D4B3EAC2E540D479118F448780E15A3C17FC34051B4137C8E52C84495CAB2CD93420FE657743180C93337E39306874F8D54DCE702D5729F82710ECA144F040DB9A0907A3CC4DE9A12DD3958047C157F826F9C054CAC044567CB71A727CC9FD94DD0A388DF0A167DB6F9F16FB00DFE96968C463CAD7617587E5698DE7AC658E954D94AD94A1A3E6A5FFDF9B7E49429C00212839005E29803DC4CC4FF778CC331DC060E69279263005685494F686838DA7930805AD839437056C62510081D276EF676739C0D689B2415D3EC4C0BF67BF52C9A2845E7361BEA53111D6DE6F5EF65A22A62396BDE531886D71B925D91AB1F916AAC97201CFC477B694E898AA52AFDB46787BB85F01917B06E34342D2977E78A5A82CDA3C93F34BF9A99F7AE9ACA24D4BFB2C57485934EDFB7123BAC3DB085DB5B0F2FECD29AA6BBA2EF2C2B04F66605678BEAF90F448B19ACD4918A337FC9ABC098FCC804AA1E37E22C9EF010A9FC40CA42CD270ABD9E56D31B12663A984513AFE3917F3982F32E42FA9D67BA2E5C149FC2E6562E7EBC24DE2E1C475D05028E69AEE688EEA60155346843F71F1F99B3D4BA69DF71ECC4AD75FAAE1921EB47EAC6C4B73F31220F1993665ABA88F5C504CD7F6D0789B1166E4CDE2CDFEB140356CA5FF1B5074661A90958E940B8A7F80CF298B8366D81C4EA232DB4A8A4153028F9BC9B9758BF1BF27B7A4887D48A09C453E3F81A8D7D92ED7DA35B3828463C4F2AC5BFBDADB70FED3E73BEE26CF0B973FC6C00922C2BFAFF53842BC71294122CDF7E057931E46790356856930EE6D653A70F68E107D86CC521232ACB62F86626DD626E1D5745EB26B91917D11E68A6BAB09B6BB0BAAC327A37504E3B10037871BC8D92466D2EF236552C1F3E80102F8FEB03BBCFC4C51039F17D5490FD61A6E5BCB4BEDA507013CEA1C810E933CC805E67C1AAC6DBD9D9B7204FB5560D691148F7369996B48D370F32739ABD5E1DAB98BDE86FDCCEEE4459E3396C8ED7137BF5326322AA7A41B2AB74CA5D76ED91DFB678C66874E7C6B4C6367A5BF256DDBA53BBA20AAC90C4855CF1C608774896A974DF5B1840A83B2FEDC619D707AE30B186F9FB75BEA7531035207AB889B92FEFA6D9802E6D44598F534390178F14E1F629629F6E120C1DC8F5C14C392C117A239E539A602E521360CCE81F3E70D94FE371A13B7A42CCDB29709428D3EDD96CAC31BA34B91BB2A92C9208B7C81AD8300905BADFB91DE8632C7E62C4D4E4C32616F712BC4A50858FDB651AB486B6D0D16A0BA10D128D539E3729F364E628A93DF73DB954C5D8A1CB6935E1D5D3AC2F905DF189736539298F7A20B3C705453CBB0E991ACE069DE62A2C89CB956E8E0110083C344D971C61101DBB2978E1831885EE7C27A6CDEE29402552D701663E5579F450C4788D46AD794217926CAB7EB351E93CC7D3771975A969A3A06E789EFB410FC829123BC00776E6940D8C15CC8773992C0FAB5CDC59EC4AC6A8889EE8087C26AD7702A8672F711859A179CDEDE22D1A77D8693395575ED4E023B903C6F14FF4A2191E49D4C21398E484B3189F50853B0B20B2BBAD0EBFB75528B4B6FD5C7B7B71CA9D4DF36E67ADDBD7305839E7FB2A25AC53AA1622F13B3B4C4E8CC8198269065717451CBE58B8DBB1F448C96D5940EB94460618036398172A2F22CCFE2B31DB2DB562EEA7415AEDB81D65EBADD8D2CF04C69D870C898D05353D8C5CCB2E37A6EA9EB3E5E9DF32175888E07F4472A80DBEC699210A1E6B8F4BC7968C3FCD9666AC9D1CC81C3428A26A3A94C96292F3A8341FB90350FC79DA7E0D947751C6E1E17770B980EC325E0E87D8A283F0BD853F221873853DB22213BFD7A7D621F64BFFD73115B48C4B06DC11F307538CC86B351CB23E199E15733A2B5E3E2360B42A203F632A8243B1557C64773D72EE1D3E3E25AE943AE3E9F984D116938D39005D4556B76A793AEAF0A6397691AF7386F509668B435DCF7B10A8B810FA55190D56DB430E0061026292D3E494C707C85E1ECFF151D1F243063646C7D8D909CA2B2BFD3DFEDFC08173649595D667C8598C5CBF10A37456575839BA2A3A7BBC0C2F6F9000000000000000000000000000000000000000E212E3D""") + ), + + new SigGenTestCase( + TestUtils.hexDecode(""" +A7DFE40E0A335C3B287EB94E97BB6875F589EFCF7FD841EC88F9D03248BF26C9EC8E7F8DC376270F7112B52DB67CEBFB8A5FCBEB0A2273FC3CB8FF1CA1DEB5C581335B8F6C53E0F8513C42D5AE82B193BCB8BBE9298446ED79D278DFEA201D0B2667E3806972F34278B83138432AAA10065DE34B24303A4E5BF1A5E3DB90825684A0205948885094459C3840C916061A284A8AA40CE0A828123369E2208254C66C91A06C64426AA1B44508418220379218170803406C5B384ED3224A48A2519A840DDC420294A82C14C105118070592009D00405C8B08DD2222920B8880A39511086805084910A098AC3A84C5824080912698A486401182C489804CC14051912250832855A202942382252B8880A814119032D1BA5214A448492366A91B84C1AA528513669DA240E14820C08A0244A444E83B48C22224212C985D014690422824B882913298918A1201293306400201806451C8051D2A870D1444D13268A1C376D84186024C6081A262D011621C3048E02A06C832446C2C20599826418B86459B0618B240422B58CE3080A0231229C244DD4C88448202202868063B68543A68D1A132E51862911B929918868D9C828D4320C0149498844105842269CC265D1165064A27049A029C12641D1403100262A51828DDC2401C14670D3C0484C962909A18CA4A485889410D00030C9808C8814501C234E91287218490248828D890005D4222D0BB26C21020018A00098248960A88D8B921062B251224282D8B02853A090A24268CC0651048940102229140988D1322A12C95023C68401068889B62819180E10468D03A7500028051286248B9880D3242C0B172111176D5C048991888C183388D2268DDC42450208300B302253148CCA888D89B665111482D1A029E428315B462952B221DB126A01B90C0A3361A3420D1A3528A232498898802011285C200EC3284EDB283120264550C04903298021004A1C347098360E11A04914390CD9046408100D09202904A52D524400D01488E4084823B4110B907103440C20425021085212994CD1A8290B4229DB1229D3360513256162340814B24450068002C20C22C98D4B968520962480402C51B26C0922424B8041984809E3346E24829024930C0A1348533440843004223826A2042C1C9484001860DA864D14331204118E030144E3240263C029E288291291019AB22183B29153222051380400A244D4066E19160E08183120388C14B88420152C19A02C22192E448468D3B048D310612181EF7DB8F0B9A7828845B0CEDCBA94F60B86C183E48327BF5CDF316E9A8F55571B452EF600C2A1AFC57A159F501016FCA48627C1FA9D7C3DDA58BB4D41EBBB6B7F9DCBA591719CC4B9ECAC146BF8788B48C911600FEAA5683EF2D12C45A3C14A0A5A62839944B427439881DBCE4481DA951B10D81FC7711D64CEB088DB4A70B5804ED577C30356BFDA58D5426DFDEACC6F7CAD7C30E718E7FFF4AE006BD98232417ACA13359A05F8B389FCBB29E9B670B28CD8AC24F3ED55F70D8BACDE3F144E79312D8298FE6AF01996E00C5E8D940A408D532CFBA872B461F538E0C7583A73D8C93E9889E251EBB4C7B1DCE6FE013DAB5AE565DC3EF4F4F5429930F1A6DED98A66932BE3B985E4DEF769609E5EEFE6EBFCB6FC56E9542FE4ED8A121ADFE9E19B8F9EBC4B9C1F4AEFB351C2D3840499D0D2227B157DB138EE62860F2963D6F3D6458F457057E4A03A72ECC52589B74E12F4EA37D8E0D9797EEDB246B88744602332EE0886AC9630D876BE34D9FFF286B5CB06498C60CE53A558CAC63DC5626DAEF14F702CA476E4C08A569DBEC1763DB6C5910B8D2352C6A648B2A6F27F9E248FA4C42FD48E7E9CBF37F318A8D4362C1B53741B41E4231680A6F91122520306325C2621EB87A1736FB79098006E83E17E7E22637688CEE4BA8A399EB1583CB8EC9DF3B8C284A230AB6622D73F590D19331783CC2C921EBAE23DC5605F4707CCC96A18924BC17952916A97408B4715FF3F9ACEF8FC4943BFF6C9F7F5E7DE18B93E679D49D04366A658AB913EA5209D22D72B62992383C7EAE704259B5932FC09F76A12FFAC12605D8715366167DBE45B272EE7EE27817128EC94E1C1299DA8F58E4206D477AAEB8BAA8634107E14059E75C90926189D3FC06C9D38799F3E00BCB87637EE24705551A797899C9EF7FA41F61342E9B2480508D9D3401EFBFD12776EAD4CEBB815F505E1347609AE7527C81AE892C841F0D21C7F97003D5F9F3843DBDB89A4E55E52BF915B92F0F2CF0345FBEDA99C322FE7BE34E0E08034078FADADFBF0661AE573EE9B664C9F05A8AD3F02B1866D24B8230D20FDFCD358BDD88AAA4C3E458CEBFCCAE2D65C64F6066C7495B571814F714545E6423D322848459DCCCC2120D8BA7CF672F37C5343085045FE3037070310E851508A0D5605249AF5D911560D308C81C7E2F2538A0A7EDD6DE341424ADD8249D628599953F857913F5767584A7420A669AF08AD060281D536C170F383C450CE8C61DCCD534AE64B91AFAEBA4742808733AA718A13BF0A55B1BD4AD618A932F84F8039754E1E316C560AFE646D98E928C28D39F5BF2F0D0E079C6BBCDBC5843A5FE72E99642B0E297F11AB5B9C629BB4601230F33837975AA2C81664825216D8821B79802C0C3812D1C0140AC676860C565E7775ADCD2D41865B23DC61BC5BFD3A80F56561DCE6F2A79D37E85629FA6EA952289FA3AAE5DA7D4E9238942684EA932F89AC0AEB15263AB2D5FA4D3D181851E38BB2B3B5702E6E8DA5CA981D2DF3A0A7371A75EC897A46205D9F05594DC169333158F929E3421220EFF6204BDFA75E41481A3E70BD4EC1D4502D902698C4FF7FA6D69CAC4A8F67EDB414FE5EFBEE8A6B695B218AF6FCCA45CF900550681B124CE36D2D9CBE8B2F179B4A4009281A559A6C5B30D4B6DEE9BDABEFFCA70446166CD353D8905641EF072F00571CEFBEEF7A296E7F49F5B112F6F0A6F1576468C75942609484DAA448F4508EAFBF2E9DFD2F83860831D6EAB17B8FA73E493E3D8B71530719209FD2D24637D6323FB03E3CAD1FD601F1FBC7B408D3AA6B90C053BAEAEDDDAFCBEDEB3CE0C6A70FB83AA450A9968CC458C18CC9571F74FFE1ECA182ACA2C4EA57A60BAA4D922AB6B006EEA433CF69448AE44A807846361F5E09D565D89410C3CACBC284DA15BA53860450E28843A662BD38E89C0AFF23ECB50B85C7069E44E211DF89CB12E6CC211036B0ED7EC5C098027A8C11EEF0898B785DE421C8212EC9CFEBDE72463F3856831FA209B8C21E63CADDBCFCE247F0D831373B7AAF82B676FE9C7E3CE70752AD0C45FBC3C11B157834103B74597644E095C386C6FDD7C9DB072EF20AC511DB9D4CDCEF85330E1372512336D5CC951A7424A8EF7FA4CFE956B6926DB9E1969747B814EC682659DC28A088A37B62D9E84485FB3B33B6F69BDAE3DA0C7D734713632B9926421B7941BB44D141AE72819281CC405F667772D68837B58156BEB2E2EDA6A51D9B9A5DD972E70F3F2B9DFE660884250CBF8E539EA6E637A693AA3B7E34467ABB697AAC4FB376048621F2DEBBD94E1DA4C9A1D2AD21DEB16A94BE1B0DBF0B5DA2C38B618CB3323D9F"""), + TestUtils.hexDecode(""" +214BC54C508E63F77B261DC59588A87CF95C233C22A339E7158C47931C1EFEF775EB3C91A32C56E888214F9F68D7CD2525B23F695871CF5EDC6979A677EC19CBC5859C63ADCE2E38C67CAEF20116508F33BE8035E9C47D124EEA5FD1651D64371451B6B96601E4A6E8292ED6841E483C3ADFC3DB242D1D7B3F036492741661F45232104A528B6FF79AA4630740BD16B37CD3E7C711B76A259C0845D6F87E4A4B306E939AD1C41022A7D5938E52B98485D95D11BE629263E6CDE20F63AE16CC2E32B6C1C442EF108D92495A759D3707AB6CF3ECC5AD7C02F133D689E252A26C014A31C65A65F079C622BE3B648496BC57C462051B17175FF81126B5BBB5324CCEAEDE0B5A8ECC0D710F04DC0C751318E8913F149E701AE0568B5426736288CAFECAB1779C7F4E96D9007635F76DEB4D379918447F30167F257B8BA825A50EE845FC4AF7C34AB200D5BF45B5F0405BE2347ACC814BCDC648C274C24F8024561FB66676534F1FC8041B63114679D9F4E8CB0BCD7BC4C54FBB4F9A178B4FCE64E705BF8FE42826EE01F691479A8815E2DA00111DE40B5CDE464A9F7A3D21BE9562FD9A5C5CB3F4F9E8F0D8D8A20B9A5AC9D7394AE4316181621B43D8220FDEDACE345234E3DFBA134BF54E458DBEF98923C1891CFB8DC9B5317E3B16C740EF373666969C95BD1C53F435D7ADE792FF9E310A191246154064D0E8F20032AF4823A335D88D5C2A943CD4CF313CF2999E237F6EC50F63936D0FF3F2C729FAF0232671C94785B67E0CF71A7CA5B32434579711EDF155D5BAEDEBBB8F0C6922AEB9798356714931AF1070C49BCA507E289F005BE9D8B46AA67CE2137935C7EFD192E4CC24DBC434B381E9A15CFC529D0064F057FC3AB592869E5F1AA5FCB299B2CCC0ED6750E318F6FC969E6A3A08059788102CCE79BC92804B1D08F3BA30492054DB6401EA251191BED1B8CD35DEA3A653D5D546D2EE8D31C2D88D6275D6C7B463D449DDAF586D5E57FFBC07ED5558D87F7DCA82E4ADF49EB9135A578468907BD8A6228EB723241D58BAF3C78C46451D2F11CA0552A05A85620001D376C6194AC6494E337388EA49821C233F32579FBAE6D11E9DB257C426D99516A16DA63A7BFA261F2B012CEE4EAF7C5C16C6331B79A26E79B1421371E574505F61D699C6DF33EA734ED14129608260B1233C387638F7ED3A34866D656D74F06C2B8D70AE60A0994F3D6C1267DCA2001EA781E5D6E17BECD284F967788227E060381ECC60A10832091319F225C972349BFEF08D4DD5298BF7EE11B693AAAC682F91DCDA113EFE0F35CFBAFF6C73DAE43B8C1124EB57713C122F0A5FB03D02C4128565FFAEADC0AC23DBE5BF123CBA024DC2F3956EBEEE95918B87D2EB22EB1A8ECC3B267528A62F2280E3DAEC02C89A01F5829B5891914DAC"""), + TestUtils.hexDecode(""" +7D337573A06A3698B8631704D2D6A1E529B45BBE47236936D0BC13A6DA8E09ADAC5E60E2D0D2D5100ACE99EA411D50C77CAE43BDCB50B330412EFD99959E562100822C5F2B932F7D43EB8015878C49D182EB968F3B12313F6EDF5056FD9518FE09EA1CEF89411D126346924C0B4EEC9D7447083482C12D6B98F0EF74913E66A018319143A5DFBCC3C21D1AE52FA19FCFF12E4730E4510B90EE9F9727C240A145CF34A01A5BA058CFCD26611D7F729F742610AC81B94E931A47039027F81377C84CF225763F68A446B63D64A3D375E1EDF67C1EB3E997A43BA77F108CA3D16BCCDB6CC451308146348C33C9485F4320E8A7ECF3758128B929D4E8CE07B3E84999515A0E5CD7D7D6C5B3EE0E712966D91666AE5C2FE8E30F22A83A1A7DA0FFAE83531C30B3A0B49029239409F36D384C888AA82F86B6D00C0D6D02FB75BC49831489161BE918EF91AF79D031DACC7CFCEC51467F5FE59095C1E8FFFDA2970D4D5EF2B72D519AB0F9919BF046A19BA279F64A084627315938EC50A5B1ADE46A4A2E3D382BE747D895E0AC6926EB6ADBA0E845FA49903B83BB56520B809B034DC7A4B7F292CC7167C51969C2C8E78CFA42BD342B78104512AA4003C48FD059AE0735F78F4837802E6711B35BE35DE93B86D9EC82C9303B732CBE1B16BFC3E718C65288810A5510410CA87DA489A71DEA594F993C7B45FC00CA68BEECCA107FF4723339E15C49F7839725AE5643BFCDB2B98C443DCB6CDD5169465740FB9959F2B17B4BF31D0704FA48ECAB5BD0F4CAB954AB132D4BB0014E558083F1ADCC81B9B5ACC2987F57A3CB069187325D5F5BF5128185608C464CF9534755EDAA7404E35F6182BC83D016C8892E63A7ECA6406EB369FFA55AC37963946038E3F74D9E18F3F40FD190DD510B07D2FDD244D74342A2DF22CBA0835B5A5183A4A9ADE24D82D7C988723031FE07BAB95F4BF96CA393BD58E74CFF56F916B8D3835F833EE658C788E9AC56E408A5A4E98F05C2379F75A82514AD1A42D9A90742C7F92D982B9C789A862259953D9D88F1BBFB1BDB345E966577226C87C6AD8DEA26F75F0C3715225B5297FA7C5D375C1BD8B5D6DEFBBBEA757E6A504E83B0F2FB3A80CBE2FE526CE76D799135497C498A721AF6EA8443934E0D76266ADB52ABE212AE58D7F52458901AB3CFB8A1EBE9AFAD9203EEDC9D1BA66ECCA41D8C268541A83CB49243FFC534C9EE8E0279139989FAA602B668669AEEE6E00EDE80F60CD41929A6BE3800E53677056C7D0ED1AC4D80AD357D96B7B2C2F1B35EA9B9CA397D23A2928245F7A9A0BB4AE0569F16C4445EA9CEA3094364A40E8CB5D06E1F624DF1929782CC33FC322201525CD181CFCD4A5D4201693D0EB249E9967095F73A35F4ADCAB9279C93E0F62E533E121F3396767D409CA80447A4208BB1D83BF7688A007B5402B5F0BCE4ED4EF51847B9F036C3BE81EEC6A6FBC6980D5505BBEDB99FEA87140EEB4B3AEC965108B48C6C808414512F04B5DB3D27FF450D54D6CF5CEF9F9B80D60C0C9A2F2E33129411013599A1ADC3B7CEB410CD007E413B463C1E08EFD1AD51B08B21A08163080450812D6B020A299BD8BF3C8B5E6AA69BD5ACA973C625D995EAC71A81B31E75B4BE92A773E9C10E7686EAA978791E0A68C0C5371D6FD12DE5A370B09F90CF140B7D1B63E381919EF326D0F58A21F04BC24B5623713C0F42E56F4727278C1AACBA51CA553CA46F7B4A3651584897B5EB99BDAAB90966D971AAB0768C96CBAA0D87EEE1DC0E8578B2A8416157BB7BE74F1D815EDFBC169D2D848AD00CED03966DA2E6BD5F98B230D26C3979EAFB099A07CD5495E623238EB46C62F62B748CD97491F0CA8C9A91FFCF617649951C6C61EFBA868E240A2B754C4C920B025BC51278E5239A7EE1F1223F4B8574AAA9E8EECA6B65356820F8290D336EF57A7E6F84280BB7179C6B919B2D89450DEE63BB4DB6AC77BEBC00D0D4407B8D6018C3D878DD74D27D3C01F555B7768859E499EF742251CE86E7ADDF7745C4C2931FC872DAE54060CB6B930F9483D0634613DF19F9AC589C39A666E00F8627B234B95BD77A88C93572FAA2CB38374414E56BFCB9FE30E55F85F476D08C6C6680468F6E23378795435E6B974BEAF4EC6FBFC49A3C0F23277C29EA4822D36A081EE3AF75438A99811AFBF54BF9DEF686F26FAB9A8618F6AD361486209CA84ECDFC3960F47C61BA603E09BC3AD5048AA4D52842C3B9A9C79B49AF43AA952A972B86C485CAFCF2DAA0D0D1050F66E4D8DE1F1732D9C88C0837A83EC78F033C762E950E25BACC1DD6B89C1D4C05728D6EB03E7435523CFDDA3AED8FBB4E131A494D11C951D88490625800E35E594924D84864DB441CF17C5A5E70E0A338D2F5774FA6DD8E3DA2478D6860D032C54A95990FDF5BEC5083552A386A45A81245EB75ADF99A1A6163DFA3729308F310C8C212322F96B08BBDA9ECB239CDE74E75D324F61CBAF7F1A40657B86E83E896706624E51B3730680C574872AF46BD84D5761105CEDCAF29ADB1DC24A1C8B74E6F762292BC03FA07CEBBAA430648BA27E9023ED7C7A2B61BBF1620514CEB508742328AEE012939543D69E0D705BC57903A4E8183286CAD8579734FE35811285CAAEC8BC0EC14F126B10022E0EEE54766B221B6682854EE9B16E53EACB6BCDC989E47190275BF19B3D894C8AF56A4D34D61CC6C078A04B70A69DB3019A5BB0D3E349DD21C101AE2B42EA29950FA164FBB86871597F2E64A84BDD281F1B3538F51F01C0E87ED962640F18DD3C429CEE89B017AD485F188A3A1803D053E7D8F22A47B6A04D558ED17BF0101EB7E1D7D0FB1A1B6082D12398F500B2F65363912B8D8D94FF8F73F1246FDD4C3E6F7C4E372842301583AE8CBD5EA185FFA685E21AF074E3C2883774534D8B449A5DCB07C46F36FFCE4F56222073806CE59EE5BFED172E5A252D214ED2642207DF742AE7A62F8D9A4EDBE70182DC277E09F6826C8DE5B103AB17A892DAC844EE7B2019881DA549200B76AAFE5B9E92711BBC36A3EEDE9B24E44AB42883E2BC7B9109B70EDA772642317B50A4D307592120485F6C1C7B29A0271D571C7DF5F0438C8B725FA98AE2147556D38A295C373B627B732333A0961A45A20EED30B4AF3A95890A12E932B1BF934754A0994154C814E114E9D671306FA257AA8D2FAC90C5920D2E20FB35C5AF0259F7F69607C29075B8DF9B7DE0C4059D62BAF1660E05EFAEED41091D3B6323E32538CAC3D88225B9C683B69C415003CBB0A770A0530F2738FB14ADFBF48459AF82D5D43C7ED0F1E2131535C6266757B9398A6CADDE9EA000621252D373C4352767A7B939EA0ABB1B20E17717E8098B5B8BCC3D3DF152A2D3855565F606682889DE2E7EB00000000000000000000000000000000000011232F3E""") + ), + + new SigGenTestCase( + TestUtils.hexDecode(""" +55FDD4E2E182AC68535720F7EE49C2C48266568EA967FEA7CD50AC62663043EA16FCBC7BECCCFD1E71594F6608124EA79CAADB039A303FD25C820B2186E801CBB5E715431F30363F908858E6927537FB74E7EF9D094790AFF50F5E88AF6139E20933274A7D4F3EEFEFBD08ECC4AB77DBCD0CCCCC17BCA0357DB699BC2424F1A99A08128B20486334062116120441525C3001E206460BA77082262A18314D63106E5AA669D12229083746129584DB30001132049CA45058046E144021982228510681C1C831A39244212162CB200CCC444A200529D23860D8288441024D44188D1B39460BB391088010091790C222491B378619384000126A5B828C24B600D1C4091C3750E39681A24031C1A28104344060C8691AB88D01150C24375260C44114274152462ED3B29124278198244920838198C250C1906D1B0788114885533890624871C01291024902D104729A26521B2012D124051B146C4C382D23465261442423C451C1388508480D14428E9B304D239330CA266A2385050192040A826819030824069061A469512845A2044841122819A9688B34664B8471A3808C844031D030460A31018B102D98A249440821018281009585D80430133288DBC04C6132820AC645CA240018384EC1048A0CC72911294940262941205202B430638090081685432689C324821A0850212149814031C8485212028404106522240810450D001830431081E4281048B850008545D188108286658C04252445044A204584863113460851260DD0260923A7911C4761103861DC226423C96492C03110B40C22B3012023648A0480A302601001509AA86050180C442270D1184DC49231DA464619438C84226293C685E2260420084E53240C5AB605CCC44110B951898628DB96216006011A4045C84448108601621461C2106904140050284AA2946123834801C64D981068118409C9C8446186445006100A26264182714138720C43091CA90851A40518418090B610CB429103B724E1800C63060022908953244D0A094962B80894208D54A46C09C09064B084002205A38689182905E12065138551214648191362989881C42428C330618C386CCC186A89A0891C246E5B489108262CD1242D6086645122855B1441DA105083006109088613868921B5480CA131A420319446408A060C480008D09029CB06255B1852C496109B442508260158B60C924229DB248504A840D4326C443080E44810C9A260DB060E91841009468C5B2249232425B4DEEA430C8E4E98CCD4D270BD4B96248155DF82B14BDADB0241D93D57742771D73368AC1C839621783F161524178734CABF900B0AFF404E4242826FF4FDA48FC5D09CF0C54110C688430DE63F1A16560D4A4F36363C00C8865616B178243B4282879D0E90576D18C4ABCFC821CCF87DD19DF99D8C341C3A7E6AD9B1D936D83EC1C2756616439D59688709FA7C6ABB3783963F1DA6A5BD3F3C391A3D50B65EAA6C1547B3C8CBD9F3D9BBF2D828E18756A35933D217682E527F68E0935BE2EA5CB8F74DBA51EB3A9BD4DE3294B962E74D76BE40ADA71B8B5D30DAFDC34490A91D1A7302097EB7C1A9B75FD018CCB0FA8FE4AA8C95261C837922A08FFCEB669D7A4C4D97F5C657080FEA40933DB7EEE691FA496D015799B72A2C6D48BFD8D43A5AC1D4035AC92860D3C58E52134179D459A9E7D34A069E99C702A7E3683AE83B6EC19C322C5D794DC1977C7F8C75C3B1477AA4553E7CCB49D17A6DC6418ABE9EBB80D1329E4471DE21D2944B4041A6DEC0B3A7C38EE411946B9FB552DEEEB4C1BA2F6279BD1DF088C3F5B24412AF02F8F28FA8BE2C5D8098C8BFE4008F53448C28420CFF19DD3B9CDE0AFFE43293EED189CFBF2CBF141EC1DF9AFB5C3678B36DFED40868C8C73D0BFA7BB6B6C6141A9226FBD5DF9D8CF485EAC66803932D2487BE19E5F48F8D34E175D0A24EEE880B4C6EAA0E093691E7A6BFC912F89AE07A4613D1A5136EDDF15A3DAB94626C36143FE16558867BD43E5EAE022011B0DFE75610CA7B6F220AEB7BA46BE1A6F1CDE340EE5C6D915AFB49223CC34D183142AB7E82A922D6669E15BA4A316B9282FB6FE5A1F310B294910B04174A955F40D82CD5517437642E91C41451051F2D063E492AF13EFB411454F90BFF85BBB8B0666233CB19C2DAD4A192AAE440344A9CA97F26D504886030BCACDFE72C87EA5785AF2BC55C54C641BFE7861ED3F5AF1F1B430B63C872FADB6C5FE4B446C4823B7AB7BCCFB20652358611DFA20466A176CEB3CE1D7336C34889A6EE4BEB96563801AE9DADAB2DA8AD03A256FF5BFCDD8BF0F65AB942678391862DF6B3EC81385DE7721B6B650C8A3B6C59CDA6B2A799383309D4176DBD7F9A91952298600349690A6FA57B02196BB2483E57907FB8C027849228B884BC33D0D0B3D49C6FFD11EE219D6379592AFF909862ABA39C0B0E4B2CE259C4C77F51E7C7833A6FAC2FF2AB30F34A54522EEB3EE52F0DD3FFC1FC3E0EB51311CA66D47C4160918BE13CE1946F27F56A0AE6B647A1AC04E1148608C4D35E60E95DD3FC887C812710920004B55027EDFD5D77396BCE2E43D696574DB561E4FF9F475609898E32650E9A18B7E22692ADEF2848E1A0B26F3990A5CE03305EB6D90228D4735F97D008AD96C019C79186B1994D8210052C432FC145D280C6F8AFA51B7D52E1F0151E266EB86CCF02144C4073FC01C32DC69234250953718CE1CAB03DD64E5AE07B3BE21BD208B5A76E2A990987AF5DF07DE6AA059DA7AD6FD1186B99223EAF0E8096EE716705D0033E8BD8172A732DB465284850B41A7C3303116AB487D03999615CF0B43AB8070364B7E0A50364947C92F48422C4EA043D33A31248D4ED643BA3314B9F42C380A1319E18BF300B3F247F334DCD78D1E917553318DCCEEC91D1CEC4A9AAA0685EAA32BE2F214F7CBEE8CD3CC60AF330187F7F688AA009D453E21FB0D1879D39C6444FBEFD02C6547BB6EF70E61F7D3F0A3337C157ABBC4CB598B8A750ECDD2DDBC1DF4CE5E1CF6F2A7657BCE25377F46CAFFB9FC0DAB2D42C590DBABD7147DBF56C619479598F62FB5DD0769AB4F915990BB524385AB946C3266C95870F199073A81B172F23F7DCA7B2A9A9B3B6EDCF5DF718340EB4C10CA61FF4FB969F736028372795EF6AF711FE9AE752231C3F9C6CC789B6DB5EF2086D91FE6A22027C83B5719DC6FC87FFB8F0113DB674F4E23B4EBC7F984136C79EF8881E0478B8EDD289237044D7FC11188C753AFE34664C680902A2066A2BF8BD48ECD2ADC23389288ACB70117EF8031D332CFEAD3ABA3B3A8C8115762AA9E8F8B46DFF5D97B6441489CD8A5F53E0FEC9A105FA7AABE36F1219469717C510F5090BAFE13506BF7E82BD30E5CAAD3D64537B047268CE62C325B89184D55B92A5788B2D09C1E7F9B7E1D5708A0C2D47FF9C79CDDB958F7AB25FADB4078B1E4C45093B8674E1E605DCAD367D2CB72D7009B9FCA95C55B91081F0A689D7CC3A7616BCEB070D49DC25AAB7F7F53C0CEE24E12F97327DD511B21DCFC004B123B2D8BE604D1F57A490D7B2A7A6E3CC3270D41DA5E2C02FC1920BCA7F1C2689D20C4F0310081E3B3D7BA8D67489E00A285561"""), + TestUtils.hexDecode(""" +E742D452F392CD3CE405908EB380CB0225A4725065AFCB0C91C5E4823471376E6424AB24D57FC4265B24DEF6CA73E28FE20468B6E26BCC9267AAD2B7B82960C3FB5A01960FAE078D5A54BB324232B6647C9DAB943533C865BABBD3DC0D1E7A1756212980D75F2C8E999DE9ABD1874E3A86DFD53340B6E424DAD9F53C3CA02B44FF8DB9906D3D4352D0EC4B1A57A33FAFF7107D38637AA410B196BD1BB1FD7AE4B7414E1037454A031839AEE4C796BA98F4A739B785E3854E9EF0D5B7415C8B7ED012B0123C335730C7021CE8C94200874EFE783D7C4BF768538A448E76120635217727C81D08976CE4B5027D4BD9D9E27E4BCA4791ADF6F8DACD1BD3A03BE5CA7F68C2A2247FD3184609EB7243D2366E5EE4C95CDD869DE41A4B47F021DE76CF27464F814837C648A7A7CE2F91104322BE3CB1160A0D10CFE90ADAEBC87BBF14387C8387F4F5AA10FBD469ED5587EEF537106CE0F3AF4CABCD4476F248C21D119523B680067B332A1CA4C657B9DE1360FD23ADE58C5538EFFC8902281FC7B5C12C22CC69E7EB18E5F6F8352B9E4935D06C96BAFD834934618D9E6B1F60292352D064A0EEAE80F7B721312FC1B6C58D68A96351431A8626CC117BE9DFA33A1625BAECF12CB1DE33BEDAD584A91546DC767D0E59764FDE3FC29052CCE23ED28CA5DA4507933C0A7702D9A1225A48B71FDE5D27B12FDFF16AC2802E3629E10D5FFC2FCC6135243A9E2F3E3867BAA0C0F0C77BAEEF9DCFBC723C7A2BCEDA39B53B415BC21A397F9A8C4DC580EC512DE4EE4E0870DF1C4FBABF4906E0CFB08863AF2A89949F8E0FF9385ACA3F588E05781C49DC563EE9E0C5D6FA512932B7F5568C1E0FF1C9492ECAA5465ABFE125B511723998C4071481BF1C53DECD59B440931AAC640D9F78B1B40EE46AC0A8FD18B4C8AADD734B0F03F02CAF6A7BFE3DAF100703BDFADA7DBB50ACE3D40A05AE6E87CEDC0B08C44796D7A63E8B5BC95D97E3EF706E1684E791D3B3A2BAE1E7A92FB70A33D896219E80751A41E16B506FF266C4BCB4346578BAA7732CA745BCB01988AADBCBBCC45C9FA3A5D38F3F8E04005AE777910032D992D5EF9DF2C0422548A980707050CAD9DE56BCE60EF74EAA4465EDE96B055999F81A2C9596A2B35C8AB3CBDDE9D26AED44527DEB9A2AF3BF6A853FA51DCCD913876A43DA3E0E2C5B42571101B7B930840B0AB64419E1043CF56AA3C2FEF5B39CB582971A5776F8FA9696CD9F67E9290E483E9BD1698E961E849A513608C3F20FF678EBE0C778C2A6DC1FD3AFFF89D646A1AB85F005AA14A0635E92191CD41A6A46CC283D2FCABACD2FA07B7E2FF97D17B36E0B222D39DC1EB61BAB8146F147579D02A87DA08AB4ACCEB32AE1C8CBBB0EE0D90A642BB76DEF4AC8C7E477888159824349EB075DF0BED236DA9B2826E67EFF220AC84AC99BE6EEB0DA904887E3A84E5208AF49BB31EAA1552EC79E5BA02458106B5A31D0AC8AF392A63947911400FE78F6C94B3F8E6B7C3B98F6548E7894EA22215C87E121441C53EED726AE26394C825517EF8A477A6DF33B5315C8DEE16ACCE76ECA60835390E65392B9FC5EB88EADBF336FE361D190ECBD0B35B22A6FE6A8D48466B5E70BB6C5FA515CD8672BFE70054038C5893E514E23B16C39198B37B06B21275C2994EDF7F9F921B320B39E29444E3D621F52C9FCE19049D403AFBF1C047C8B065543BF43A25817533A33DE6C866FE9D8A73B2CF7277CA0E8D78F4F104C5CE6FE2025992E26E49D4C49F0798278216453C00C78EA7BAC2BEE71E5273FA46044B4B5578EEBC2A9E42025A8A3526B11CEFFCFF47191109C56AE105CD70A04C3F4EC43E49346203347319D8986D15B3C4A49F02C02994D8798499DAF1E0ADB81A9AC79FE8EB55ABE2BD18EBE18A9E5F35D2F66B38CAD6F6EEBD29AEE054C05D6F0B5326CC5B86BB0FC7CDA720838593238A2FB24E0CC36DB193FB7FA66573B064497F771DB1D965953477FC28989AEA2CC004640524A6DE8270E8A5B12BFF87B3F63FBB7DA25337EE34E6E4EB45DE9A39BC9B95ED37A6A404ED2970F9C79A7C2953420732C496B855F19BBBC8ABCBABE1D26D5BA828EB060D7280046AB93979E0BF90B6F1C07CA70833BEC83DB41684F1842A23417B3BBA0A33D7AF7BAEEC14C9C96FDF30BD201C05AEC6D3D2F539D511FBB356DDF333409EC16411DC7255DF0791BD67892880A4DB082684BBCA8B7E55B421C17DF3B68720E907C1620B142C3382AE6E738F8943CD214A847A6439A682D62CF0AE8961B5F020E7126C5DD6258CA0E8F5711E5472A4C05ADFA9A6B8180B741F382090CD1C781F7CC7F23E041800F42B228C351AA21E4D916BA5D9C56CF8E9507065D729B7C3653A8BB062C0463BF0B97F13A1016BE4851F5A489081A2AB3D2AC2744008BA734ED38DA10F372D97EA0C278C709A23ABD4B07E91ACF6A6F2DB9AF7806820381845FFBDC4BD30A503A0F74F37748E3624BB2AA478210072FCA83AD1A43ACE9F2943AC1AB6CEDED67938AF921FF34F2DAD4F224EF7498BC450A67CA383A9DDA333073286A22B85570A11FE03F55119794BBE8B81EDF1966BCA5E363C15E8E8673C94E3396C9AEC28D110408DA5561296E2928C6C111A4826309F119E5456675AAF935A17E80C0BD82A9CAC2627D6FAEBEC9A928D33980A86ACDB35686306B57D466864A0320F21751FB0041BA0F4F1660774A519D3ADB304438C1709711B982EA84D1B193D026081A4663AE69C5E12C3E4A683FB356DCA618191B29290C5DB4AA6A069C3B8D61C8B7FDA779E1F34A5F62EB7DF5C563ECF1200D3FF499DD06C2BF44A2B4254318BC402EA3A047FDB3570EB40630CF1DF84D1E2BDF5449A1F65A9DEF76954B5814691C4C12BEB10A1C006189968F37A4B236D9EE0D39AC340852EC54AA64FE15E1A4433ED48153D23B2B648C8852F3E3AE485474AB2DFD58A7F0CE6691ED36818DEADC8973E6ED06AB841B0A915425D7B87E41E1E68B00BE2EB725C287FE575736F6E1AD2AAC61F02A3A00ABEB2C0FCDB35564E8446C776E980636D5D61740AB2F0736A021D82C1D66864E5DFA98C4648CFBD9C7AA865F6C97038656C9C8767898FB43B0919BC98C1D0F6FA4D90F711E5D009D4C8FD8A773B7C73CEA654A2CD52A276C6CB62265294869A052FA1634D3EDEBA1F69DA09F0568F9D2F6C511F6BD6169BA0DE25F09FFF63AED2FDD0F6D89BD01FC5B088D3EE5344FCCC0215B6436987D6167A0F2D5EA47A984DC86D45534BAF35129488F3BC2D05BFFB84A51A87A1774033244277D0F2B45EA43500F4034081711CAD67BAA9CB0A58E1D01013032EDD5EBC7095D4BCCBD28A5F32BEB685F7901BA7A839650023B0C908FF33B37D038162FB96EBA35C2919560267EE5A94035825938D168481D8E59813E20DD611E4E23D8D42C9DE1D2398CE3CCB3DE5CBC4BB16D555985F411EB5B56508C6F4E75621304DBA2F4F1A2D8B2BEC5793478E5AA0DAE6F52C43253FE7BC91D3FBA84F8525D002CC307CAFA20BF198BD8F28CB579960A1168A1D26340C8E26CEF1261F23E97B806E9F27BB51F16102527721BE0E8B930A1ACC38F0A63EA1F3FBCEA1031E441FEF4D3746EAA37B7D4F8AB354D5F079E56FF4446333C8B8B7B589CB36DF40EBC5A75D2237F3FB874E7E0FF1B96DE43BCF229DE1FED3FB6D01752B3271E1F98D4134114911BFAC8351E3186E90DA3DE2E7FBBD305C822FE6F06ED1D4774D7A66DCA0CBF740DC277C62FA641ECAFBCBE359A28FEC48D62E1D3B6215392C0F8DB601E35A6CBD978567E806168A9F5B4915A80DE405038C4A370D898ED6441F727985037A040163F14DA78378931D3B96BA486958AE8902C98BE75BD0AED53CFB609923C63615917EF0BC6D07CD183192DE3854133F701B9D4B499F958064ADAABF4080C4A019DF1E5B98C8CA265E031B8CEC355C8FFC3BE16DC3D01533ED17C9769365D023CE7F0384D40F7B6179612B5EC382982E244E2510B4831F2D53F26B142A33877961EF1F845370CE115CA5F0D2FD6926482BF3BA1AEF3212DDF36705A210D8076A4428C7F9CAC411DE590452C761028469947BEC31ADCBA229D8EA58755F2715AF6D51E581D2CAC4182557E6815BFBB84BDC54C9368764CC29AA9AB49EEC37364F85AEB3295E60CE6DB2639669F55CC49D7934BC8566AB5E207B33F29128868BCBC1DBDE1089317088EA3FE1D595376DAD3BDD156802F82B63CF4C5ADEF9A89D94493BA152F9F07A9E9CBF8D821F1D6CD602EC49B61AC4F7633EC810F3D01D4867B1F0F3021D70897593303CFA6B5A3BD0303AEC32105F854C3DBED373760DDEC9B9E8EC4AFDAD00FF2E5A05A0113522024B86F1AEE6F250AE3BF0AF1E6FB7DFA8E04E3F9D5C876731D9C33460FDC13CDCDD433B45A6BF17E98638C264DEDAC262BB03714E020F4576DCA85DFEEBD6D70E557DF9321A8AAC519C419CA20E33DA37C22047D4CF925AD67545D04300A42B22DAC098A912848302D830E06CE5BACCACEB6E9316F9B1DEEE271BC6AD9D74927CAE725CCAD0C596653731869E8071E23BF"""), + TestUtils.hexDecode(""" +39F0B36E2780F8D81EE231CF85B28930B0876F344B4EA32F8CEF086931EE1E6B9382AA19FB650AC81A2BFF86453BEFB33BF8F0FD8E0FDA5737D7C56E4D9427BD1E802930F500594396F98A2C574073FD570D30666F5C067EAA3C88610A52FB0F6826CD12BCE739EB685B3800B3B4E3833DD2886CBF4587CF0704B2E72B128E43183F5A5613E8A5342C123AA38FEDD3AAC513432A96AEAA598AB9DA0789B440A4F4AE37EC090144670E8E876D83A39E0569A1F38159B8128317216ABAE8C5988A396F2964B6BAC4521E1E35B4C1BE3A4AD1745F718A1C74B260F462567146394C5190A3B6F724BE2804C3E8BB3FE3587B09F22F3227A2E69B651F52A32F62693E212B502A5F7917D17BEBF20BB261D554C966418273C6BDFC51C8947BE2704116BFB1D1657D5D82E676DDE05A580F048F7E111A3D632205FA52911721CB22F937E6241E1248F1A6E10A71C34932DB75A4878BEDF3EA3E6EF5508E5CD691114192DD4C44E6620EABF1DEE4D09448680D84C6117773D240DDACE06A2D925920F61A0AF12B6E64DB0FEEB2274EA1238E22BE017579792F2EF95BB55F6A23D18CCE1D3AD209B6463370CFF1F8278E779A9A943B5779A99C971F8A3794CDB3B04773C9875D82D9B72C39368B1FD4FB0A661BCD31821ABDCF4CAFEE9FD959285FF15B9FF8211619638EF4EFA138E44E4EA9F1FADB550C13EAEE9828A34BA911D4027F38FC0B9D0A1E788A6B8648C63A9E4D6AF974F87170333BF82233C199598D7A7CA1F90816CFC72621DC36FE881F25BB86C67B9B59DBB02D78A1ED003193ABB5470A89C8F958FAD2D6491ED121AB9A02EF470099D42FA37174052E231D4D988707567F319D964B4F0551EAC4CAB4EE069EB8FAD6BBC4A9F1D98DD8BD73A5647F64D4535E8FAE71B53902C917A9D286E014474E4B126AB17C29DE31ABBD58CEB1C12669FC2EE50042CF30BA29F08E97FBEBB6059A458A90EA6613C7F76A5AAA9DDA66D266CE0514B0B0442694252AEA4ECEA14CF5C90A8BB60FDC56F865447BF29769F49E79751E8AEDA70CD78E29154D688558D1F831096C660FAEF3EB1850DA01F2E929A6432CFE9DBD342D1CC234551D6301B6B61819CC487EACDDEA62C2CB8766E2C7066698305CA924419C8E83CB1D68527E923700EF7C5A05DDB511DF15AF11F5BCBA557C815B95001E0F57E6A7B8798133ED1AAC2819B10A8E2E4BA69606BB148881A2C23D3EE0E981551E02EB1ECE320B6BC15AD1EB0EB2FF3FEAE63DB0AB4C2F315E54F047734833CD380DCA1ED68FF1838B09495083457B07D93B8607217913D678D409C1ADCA9C7F496FCDCE029F2F4D254CDFFBA036CEB59D15BB40B4215397DA55B5480EC2DCAA221D4CED195DC440BD0B84EE2BA5108F46B7E24148EFAA6C2AA728F6CFF1391B46C36DE741C7C546A0EC22776B9830C3165D2ADA141F97C05D03D93557BDB24012C336CDACCF8CA3630064460C12251ABC89AAD06478610B8A2BAE5380E65A2C449632EF9A79CD9AD8857BECA18552DB913C0C79CAAC8AB166A1ADD7DE272A796E72EA53E23582DD8A00F554849B9EB9D77390CA41B04F6A0C9BE3C3D0E94F9E3DC39BF1AAEE34E910204DE1A2B3A92557A67089B912B676F93884D4A6411B89740953E1F79ACE3407B2252DFDDBAB75276C10EDD534A9F398E51CE9E36469C1DF0526ECDB84B07308A0D5D5C520D028A8E30A193DF746F0402D160A4E9515CEBA20655979124B1D6F5EAD8892D9F1F92A0E1A1DB0B4BB90892F569194E088E98C0C5FB93A108F05507B29A595CDA161BF4D97680D6B0D4428D6A74B016509CED3B635B02183222B79598B6342A20DF2269E881C7B121889C0751462D76C5ADB628D26359D56F8876CF14A71D330D03361F63E90C85CBB275AA78C15293EDA0356E9DE2474ECE7C49419E15ECC5EB8233DC8377D88316AE846BD464D292B91FA8B3319A28EEF4D678F0DBC04687C7C59CD98B694BB15DB7E18F4599D4F2806D0D78E80984C4136EF605FBC268221E7608ACD24004CAD8F533DC1BDE1D3CBE0605A69E828AA13210A07001D60B8EE2DF19D5AB8D792F3899C39C9AA1B82F1FDF9222264F7C3EC8B756DEF951F20D1622B23CAE013DE6CC95B0F39721FD46A64B7134A602E0D9B6B19299A5521148AB61ACBB878686C2020663EDF3652CDB93CF4E24C8FD2AF8D0167573333A7DAFA1CDE08C253D523AF9F944680B97BD7BE2196870A754894334A029A870F8FB342E53BD3F080657A4C5A2DB603C9F0F3BB341AE936A2B9356A73DA67AB54AFAE131C8FB0CB73EA10832D2094D014C01107FDC06177FC3884E7F788384E8AC89C689B2A2BCE8D6852C8B5BE520671DBD8447E4D78049E1EE50663A609DA79725A3822DC899CC87224C115D129702C7573B45ED58188D422C510381BA3C77DB099B87C028C895DDC6F60C148CB1CBC60CF56C15455048AEC096CE78B0E70F8C8F1694CEB365DB8FDA1F01897247E632B30FEA0F888EB49D5487482B367ECB413856E8630841F811BB1AF14CD26DF29DFE7238AFF1D169804445A74BA5F9F96D9EED27BA70AA516C1BE7DC46C015704E1BFB42F0CC44456CAD7FFE48B62BB8BBFFE5C97027BDDBA1E83C027DEBE20A908486A351F077E627464F6BBEA0AFE9230FACED923DD9DF215AF123D8089B467FBDEF42C4174156687ECE49D87C0F9711592D2469BA2100A5286B086C2FBF47A60B864FC9628CD1977D7D8D72B411D2494BFDBB77543DF4B39664F7B22451B8C7244008A3D24DEEED0C9CA67DAD2D56F1987313B4AD33A72CB4973B6125257BE3295682A3D0418A2251D71510F858F65840149C8335BD999C55E51181914DAF055DA97746FA5A80A7019D9424EF0087F38EF1491A3861A19C87452E05BCDAA61CF148A84507B043AE4A42FBAE9359842B0CFE70FC17DA78A754E3D7A768469C170DE3AAD692101422C00C0F8315BEF3BBDF887E75E5DF7101317CA4F8C4D365B56A63A1D833B5D79BBA1812F3659C377BF9CB4A913CFA504E0CFDD1FEA0B87BABC132F81E9A2C7FE0C6E6D8467BE84EC5E21E0A46E4759A5267E6EEE4266A4EA8718F8D40A1594CADC835306F88E2100AC444379E9EFA4B3FA0E690550CAC00EE4633687DD1FFA748DA3882ACC6CBBB2EFDC0513A25B31361DDBECF5ACB3C488AAB788E63A48D556ADD74B607CDB8DE11C7448DED000E8665EB75BE788AAB14C3E958CC969FE353C0137924941951BEE553FA392DDD5D7FBFB8A2A8DB5FB0EE58D08FB5ADF617EAC526044962C599523981AC06B60E1A6A34ED97B80949DABB6C9D6D8F1F4FB11222632456068798995B5B9E4E9F1F4F8FF10161D2B5D636E9395A1B2D0EBFB1419202A2B383A424B578592A0B4C2CCCFE9EBEE000000000000000000000000000000000C1E2C40""") + ), + + new SigGenTestCase( + TestUtils.hexDecode(""" +382FE71D7DCA3DA9138076E84FD5601E999042CBEF87ED4A8B5200087B61564E433A8E49F18104C7A7158AB1D83044AAA46F6511B361326218771C3F99094F9624AD27D16068D01BC7BBCD0B5448338C2A81FB3F83B2799A81EE2610C5534CFAF09100FEB0913F2DE35DD5C21DE040A2E8B6FD99848AF401BE6EAC45DCDAB38AE1442E88B24C2233621A187061C4606390801B272A133450042331A4300994204D11464404242051C48DA14649DB4428C0084C84304DCB8244CCA84C13B39018150DE3C04122160400A6252384511A28221B136E2049715A04222112724B4889993210E3A42C02147004B06920110918352EC8B681614400E320324124321CB47083C60D0B970451B8101A3268E2A84951C06C20926824B448C9902922122101252C13B70099B02519A6410AA049149069089751C8006A1A233142168A620428D3C6900BA544A234251484605C48324B384E19296661286450A409DA162A9C10100306019088410A0006C9283020A44808C04920B78DE2886809A64C1A030ADA180DC1088962384D61842C91180D61A649033672C2A24DC2B02449260540006948226512C50C08C36D54224D244368418230D3402114285050366C4A446D989604CA90605A162ED2422241129048827013A2815C8025DC12264396499292281A042D8C800100262C93025192A288C2B29183080E12382262406D14436923112E521480A4187280304961863182224C92486C60B84808C30104280152084A1041520939664A328A99960C14430E1AB46C44C00801C60C128024A390104C0046048069E2C260D2360EC9C82963962D53C870203311021568E3222453466C410891E0883008266E5B386510A991A1B88454888152444118A81093004581122C10224E1BC909C04406A4A00414C401DC0286CBC645CBB889800885244945100871990804CB382512359244067011406550483240A009E0C20020244D82A20C81360514460E21C1494A442D9B343120C85004256502B59084B445542489C4A224122225643862D8B02584A005024828E1C625E03462E19221E03452DAC2219B38311C113293C80D612466C4024DC8026E240582630248D1140A51342960A82C2093891B496C519010E102654CB0251C096C4B18860B35421829658028696080296012250A417081222990A00950C041C0884448804D1A182820A82C22806D099501088670C9120803272DDB208C1BC92C62128ED98681CB067010C7498B386D9C8005F34E25F7A1DA3F630CCC7317F25ECDDF9ED98A9E07707DED49B04D35168D0ACD1EC48A4A92EE0A9B2AB5B84F7F3FD38F399E54FE65FE2EA64CDB121AEEB6EBA1C0D52580543B76E82C799F8ECDCEA58DEE9CF8E24C1B08C271B805BB729C7060608B6564F93CF8DFA6FDAB6F7B6F483E81C9F35E07C061F88585B86F7DD9E62CB027AA2DAE58ACB5C095B23661FABE88C717A46223395B94A972E3CCA2FD131EF052F7C8C75EA9B93784893E354BE0E4DB252C36AD03285A7FCB33A3D53269D20EEE2C3E6C0D74C91A2F1B35510AB2E7C4D12F0C564FE96090081A76B9163DFF22815EEC4B7AF398DCAF4AC6A39D31EB3C4674F7D007D6C04C95AC37C4E62182B0448CF3D10CC25823463A9808F97640E378BDB17EC0A2972F5F70812625EABBF6F1F93B566E36D2CB3FCFDDF94B3DEFC1AB168DAC4371398DE157EFA4B1998D2E19B4E9536038DECFB279770CF87FEB7C0904DDDFCBEC1721AC33D837AC7689676033D6D556DC70CDFCE1940CE25D69A961C6BCFB4E16CF42636B5DCE6C0F736DB467C39D0E4BBD0577F3535E7A47D3A80010A5A96CCDBA9C89CDF7894C43B19EEEE86D7B248E6FE89F84D73F76DDEBEDF18BF3AB9F5D0E69BDFB35AC1AEFD64E64488711C95D132029440D3573F1DE86EA10B9CB85241735112D992319FE5C28EFD072D2808BEBB97A75607F2BD0D62CA3223819F2FF26F047A5E1283C39317C1244CB95CA3C91C752DA2B1B36D185FF6B6FA6E779860DF82DF8450A2B131459E5C437B0FC44E49A9C613F8CCFFA188850E520E166F73BE0F978C8E770E88312F8DEB9FC4F93962AE579B2371484A6A7E09C68DAF0E00DE46749AB332791745294C3AD193FBC533E56A723D230BA35DCD4308728014FA998C4036066238B50D5A4381A1E46BB6CC2EB3C4AE4A43BA3712462D7A842598A1E5A7076320194C57BADC732197DF4A8A1E9455201AF865FCCAA674E2B427F7B3D35F9E66D1FB56CC690D61C7EAB983D3F31EE3066D0CAF61455B185902DB44CD2A85D6BA2D4B97DB516AE75CAFC855829E24160ABA921528CE718E10023D84EDAB83D42CA84E4E3B078218C44BFBA356F1815F927D61F2EF8C46C4B5521D0F8971D54E81BEE1FBE150F3B303D8668C9328B61D68ADF26AE20B4A38C4A0DD62A5B432ED1A3DB945003FFFD37870B5A514FED603B5EC54668FFD29D6DCB5A593DE0852CBBE4376B161BD7FCD8CCB8F60D453B68510E5705549E25149A1271A8093F6084759F47AA3B5D32ADAE32173B7B0DB4DEFF645D172BB02F5D2BB776906E1118167F3DCF7CB8C0AE2866344A59A9F6C3687CA3ECF74884E632CD63B6AA193DC56E087A67782B69699525C53A35DAB992F9BAB1CB098723BA2F1027E72BD20076AECCCA2BCEF8EE76ACD195380A34B934B44E642BAE00DA4C1ABF7174CF0C0A353F96F27CCC2B6281B7CBB29222E9F7067646F0D915AF86F90ECB3E9AF2B1D7FA2A233A5EC015C6268981942E0DB8E1F3667DBCE020907148E61B353D505A3077626E56B8FB108D90A5922E5259387CDCC49D03D1D47E3CEBE87A752C7562C219C25F502A8716722EF7CC7B4AF8C33DB33EFCF2B31A076DEB28A410B8162A9D3F1042E1AFCD5A9DA472393CEE28810C853DCD94F5590F2F5D9888ACDDF1FC78DC26221CFEB3EBA97D0AC4B2B2CABE0BA52E6D7BC29738837B7DFE5A2236AE31CF61A449186080519DE388F1211F6BC81663D2AC7A4BFAE83E9E64BE6EA7DAFCFA7C1DEEF73DC6F9F9714626B9F67F292DA66D19B6A5CB4DEF0E870AD09CADEE4DF12C873722521D191EDAB644CE9EF6AD93CBC951B8AE64F741B6497645E92A916605137CF73C5E30CCBAE5DBDECAF908C16543310C592529819C926885DD3C8DE66480FAF7DB079BAFB47BB99341EB9091AB9E9A0CA721A8144882154C3D4DF29427042F41810DF2BB8D59C5FCE38468AA8328A740068843F7E2C911990C9B2CC9C8E3597F03502ED2813587980918E69D4C482F040A8B7A09733BAB73E581E7DE74899A5EC59369EC1C112EEE0073E1320B189058ECF06DA8E1B74A7F4FAB3C77E2CB93066DA683BF9C6DBDF4E673F11F446DB7AADDCABCCB6AD68BFE43F5AB8EAA5F8C737AB144E33ADA994E5F38E1184A4CF2EF21734DB0CE019F114D02316703CC86BC12550C1CFB863C1249D9624591ABC9661DA47E2972231378F57D27F5C1A6B0ED2303DBCF69A8E98C6317929C6B092E1C0973AE4DEC65C3F3B59EBF6AFAA60C5121500EE6B4027480BBDFABBAD8FBA8ACF4A23AFDF667EF95B6B60DCA6A39C688BADB1DE6F3795DB7D4D31E882D001087E81A0B7846C7D0B383D6E85DD516E37409"""), + TestUtils.hexDecode(""" +7EBAAFA6D04129716131907EAD0832AD490D09E97D865B4AFC5D6B0FFF4EDE6A52E961ED88DB60A325AFF2675DFCD6A87984884AFB8680DFA7378130E44F205398ED7B83B1AC32D2580570FD6603827E8E4F5E20A27758CE6D1299BAADB8A895AD586BDF7B64F8D7A52BC15455EEF240F22FE98CE4CEAC03CDF7E8A983D7FD1A59C5EC594474AE77DC43EE4E7B25C556BC1D91ABD2015B99B1AF5329DCD41B93793D791A44AF5D83DABB8E40675EB32120C57D9E6B7757D3E03008A2F788336B8355AD2E47E61B39BBFC2229D53BC9BA514BB20F3F9EE9266BC0015FE81980FDE5637B3018046DD3D4BC3D549EC394E190F1BB788619CFFF86C532B4B9F0F6F951C0ED691C59AB0CC438290E9D6FEC9E75BA4FDF12D2BED2CD988AC411310BFECBDAC48A61099CE0D0CE4B44EC9C97108A44E5C5EEC1D3154B4E72B8397CDB0F7D15AA358076E25B7F3EA1E6E80A214051C440EC4189137610450144641B1E71B5334F0DDCE9D5CA30274E0237E45B4D92D7D458ED9142CC23871E56411382CE40D9CA4358B417261C2E7E845637FD2E9B4357E7EA5F4A8076A7C2F40FF1F8AFABA5393512F690EABEBFB73811B974E57C2D473AC22E747A0EDD39E99FD6E5D3668F3DCA1C795CE27D1A155ED9595EAF9061CAF5C55F3EE97056AF6ED90E05D41E90926F69044746230C990118E4D0BE4C12F7A4AA0464F8FFA7CF64C07FEF171B2E43A917AAC2880675F929583E9040BA6FEEC8262002613AA91A2B8D4DBC1D36F23FA9248A2D3ADB1DC5AD669EA219D35DB17C9C25095AD7673445E59DA6CB2260C8FA57639D6BEC8AEE307BD9C96EEF00C93318DF7DFEED970DC1F61AC5C94D4086300D91199C90C95C1A24F7F1E4292A60AB67F30BA990D58C71002D3548A412276DBEF3984FAB312723880ED479080EEE2B636ADC75AD4423A6E0C5CEB7EDE528F871FAF21855C3164469B9EEB47B6D37CFE4222DCD0B9867B00BEE12C27590DD77C24FE640DDD34E9138E70D15F52E94F3874447CA5CEB48573ACFECA3554E2B76CEE4E31060BF132CED8AB953F0A280F7916810A107AB5BA66047FFF0003B1CF13BFEB77526265B98E54E76B891A89F3AC0ECDF71406674865A0936BC57F87B64424BFC8FDC41E471D951077C32B5AF960457E97CA05F3C378D94B60A9735E9EDCAA96E413FA391AA687FD07D9D021B1014CDF241E5460DB08D3B336DEB4CF0AACEA57E4DC6C464F698CFC2AD10CA72C102A25787E0B89249F63406A39A2A792B2DE04710C41DB36B55D2FA789004E593DECE9865771D8B16B5436A792FBAC9934852B1F55D518F9A07CFA56BCF488D61AE355D63BDC27DDED6A56154B8BA3AFA3EC9C01D6593C83C315527F5FC61BB169723346AB4075D09701789268EC1F02EC4A1CD8A5F2584E29F126B1ACBEEF660CBEF16A8E9FF9C0B542042EA76684F9D70F2E3F3C18606ADCB1D695112B129B301008EDD5E6121A8948E1165D350FF09647DCCF4A1F8605ACC750A0AA8319A6685153A7672B31A3DE785EB22E1D223D6271282AC18AEC83C760190799F082D7FB0F238F627271BE62AE5A36A34D65B5DEEAA12D6B14B59BD0C619D8D9A44238AEF1FF83C30118039E834F7716CD59E138E2ABEC2921D9FA92F6808A760031B2157103FD2EAE988AD6CA4F350F488261409FE91B5667A9A2EF1E226B8BFEDDEDB84ECF993E9A71220E0253D2C4B918C5521C7953FDFA00D50A32879FC0A68D2AAD13EE181DD47DB9E3D715574CB3D566BDF30209297B01A666DD7DBC5464F913599086AA2FC6C8541592CEFFA067B287EEDBF4C9B9D6CB23CE1DEED628935CB2D6B5CEFF3BC442B2BCBBEFE4AECFC455A3A64FA117CFD9289FC27E6289750005877DBF64CD562E2E7D1C99830F5AE63C70685B3898D420862A8C4569F2CFDF564EEF4F94FC34CDFEDED8854855F3A4E52C612258DB5EE4D702BBA98B450D070264FF86A440129DA2C126978DAB3341C4079A66F9C23445C5938FA799E78F157656208BA7C7BC7F936AF49D11148856BA55910A6A736D32E0974E50BFA608975E37AC0601FDA7551204EA66F524DD03F44F5DA28EED5D126C32794F1CCE747DC1E9B1FE287CA607F81FE7C795C96569E66B2F3413DA810035D472B7F5AF74F9CC70306A8EC36F1383617D0FFD92F6DEFA7EFE91C840EDF24430B197802979752FD55A8CA85FD8D4FCE774F1CCC540F77C02E16F1494DF170CD8BA57A86BFB086349D53E8A62E1DBDE03369757EADB0E985A038B31DCBEF513D4FF9A3BA6E8338EDCECA7C3E9417F9E133BC399F2EC0C72E60E809F79D55FE1A917CBE28FEF19D6D08A43F74DF496EA9305072C90AE3BA0D21A1AC0BF040920D3F5B8703C12A32A6864382E9CEE8D00CF4F93830623E76197F7F52309824B08B8E0D5DAF5662A36981D50880FD3A8D73D24430A1CB201A9D0BDE656593B37B8EC47F235B5CA251249A04507DDB81F8E5E4E5E414B3750AB168BA51A8873E6ED153E302F61F7159B658E316D6D183575D87ECA30185CF72C67543CDB658AA07B1DB220032DF80D287E769E3253C80F43570AA538EEF49F45316E176F1F9411F3C085257C6B8C708DA7B924B792389A7EC34C7F778E6100333E8B9FAE75A4D1A32E306AEE36D29FC6823399FF37CDD0D11C8D03F14740342B736C4EFB5302C141A86C857309A70BD74DB6C7C29C839F8D86F2A136F67A0FB3A3749542A9DD8D4A062672C75B67D3BDC3FA6B56F3E79008AEF8D8E04CC7781B23D0DAED64CFD1A91DBBAA2C9C4E765FE2FDFE6E8533848E51FA027B86AB05A0530F15C1B7B6BBB268F09A7865E202B1645F8B4267CB1A49A2929410823AA9B834101E9EFFEAAF6E406639AF7D2710E60A84B6205339B0719E05BC6724FC2892A017AF86D80D361A7FEE8C284CB84F5F09B90CAADD49CFD396E6AC36052F5CCC8E7667CC762A9F173F837A231D57584A3BB19671B8B71907E415A1672475ADFA11998F94F28B00903AC551E651A3F9485DC0ABA3297E561E0B5A5786BAD9EC8169CBD706AFA60AE764BFE01EC514623BAC6C4100F707C5E8A02F4B0D6265502AE4170AC3EF95B49ED1A2BAEF56F63D5667C9FC0AF4C0A8648FB6AC5444EC8A1FAF4715027AC9F5987735D1AF7C55AF4C838FE9FC84FF71F929758DD52E2BD4A34237350642C0E641B6710A66C9C1EA1D9BDA80198FCC56D45D67C3511BAC0971AC9B6166633B1713A969B8DBC3CF60FCD6998137AD713EA3ADA84169D49FBB7F5CDE362ABEB0B71D022D9ACE7FF48C9EC1A7E0C72B564FD2C620272A482941443838D0506E2294B760AC9DED5404D3C4D2898315D3E3A82D2E944D537817B9901AFEC343B95F2844CDC4AAC3836E7713739F4201B95C42FB7C99AF8667628C1B60115BCB185754148B3C7226DF14B6DE1AB4C6043329B176C9DB9B1D73B3814FEB89E84A4C91C84993752B7AD30CC707A71339E8A277A5586BA85CD090F799A6B75523A62C6DF1549D787BD8722D1F26BC2C150D6A38951F3014B83DE665B21F5D9D97F2237333CC10A4114796D56D13D643364306E7445F475729602A11F8BEB002BDDF30E579E26F2BE4AE87DC666974E24FEF2462120B6CD8E79D65A2E80542A9240D4EE1F616326AA528E2A1282EF49F0312174B67D40FFCB1370BAC5D1444D75FBFFB6B0887F4573A8C4622082E1FE349B2C73CDC92592F684769FA7D7CE6FB5AEADF38023E51DA4EE3EDB10368442B218919341FAFB22EE80DA96A52434B184D499A4C49317C62F6D6DC9EC1413D01A1CC3DC8853444E52718798EA158A12B72AF023079E5E76F41AE685494E947618C4AB3036ECDC74F7A043230A0BE116F2B617818A2C94C54CFAC964C73BEF969591A3CB2B7DC9CFAC7B4F9B64AB70BD7FAEC138E42908BC90D6ADFFBC88EF473CA8CE7BC960C4B3EFFCAB92E8259CFAFA85EDB7832B3E630D6D2CF031B8CB570E38C101A56B426C654464228D152ABCC6DEB888DFFD7FFDA974E60CCC2AF7531F38A813E263D9B20DCCB50229E7D8F379F81A280CEB90B64BA3657F1E50381B468D0A6608A4B5E107C4736FB4CAA10FF3045C05453EE12A9FB0B79845E077803C69CDCBF7CCF7D6FE6067ED152F67023CAA6095D1748414580232007AB3426FB2889E1BCDDDBA539A2D79CA523A2CD1B1314C87502909DA849BA9B11F9104772BBA27410018348832B0BFDA4F09AF02B351927F2B6D29D9CA9F330266EC035908C9D4023CDF2343B177F57903D37AB89D0F9E23EB0C4100BC6421235CE5FF2729C2ADCAC24D1151757D8C6D6DE53DEBC38FE866142D1BB593974F4D3198C03DE4625F41BE3D488575B25007C2D5970BB152BC1C23E48A88036C070BD38604C5844E4205F1EF3D7FAC0B4B9FB51F229BA322D3355E458C27685130FCBDF591C0520626E5703A2E85871A62AF0CF2DA3468C401644656CCAB33B2402074C59A0EBB57928F548B5FA4871A8B2AF0BFD9A871A5C257044C17E4967B70D0DFB59F1345526FE59B4BD92A1C06B15E3A6226A4821FD614D8DF612A3D2DDB2DB67BAA3878C68C16645CC747BA9B366677541171A9264B89EE18D9D169D341629393C5526C28B24CD4CFCACEA9C42DB2B1CAFD7F906FC17CCE16612B1261E62E2A700CE74DE73174D3A1E06AA31AA05044EC324F026CD39F7B13399D9D86EEB53A6DE84914719EE31AFFEB630F3D8F08B4FFB10016209C13BA2158ECCB4B74BF04EFA73222554FF5EC49709F7F8DC1D40005E91245F3A5E2A00B9F64678B2D8A9E6BF1D011900D9D12F7F3BB023D1E5985BF78F8D6132AF5C0B9C330F361EDE00473DC9EE7469478FEC02670E8659B643B92C5546C32FE7B0AD816A5080B5E3867DC209EA15AEB4B14E42AD58F34CED65ECB3B519A54BC25117EF8D392A85C2895B5A4B73CF93077E360A828570FFA02ABA84D6534F3EE0C935D97D1D1CFABBC0D82E48937797FAB31704588605082A950CAA23D6569AB793FDC31BBA561E729E80979DAB84ACD4EE6B2CFE06D2EE8C4183D33B9F894C6865D9CD405C7665E0150B2B649159BE684839BD12CF0091614E1F821046238DC9F538F769FCE51E9B8DEC0E98442CABD3A4296F1D4331A16D33CA356B11E3DC13937F814D3D6281A746F054606DC52B737AA40422471139867624CC8E9C559BD25C7C6D7F902677A84BA63E8CB817820048C1C0ADB6288000EF2163B51ADD4D758D1C87FFD574354B41CA5AC72228A7E9E9E75BE9DB18FED47C32E3C561C972A67D50A560017BE794AB9BB6B50CFC43D2F6D57E8D73CAD6227C896BCD18E0D7087F57C365FB9EBF5864DFA4A13B6B5DD7FFFCB648C1E1FE40B6A10EC0C45C74504CF2105AD443DFAD1E306F720B9CC37B4A30198D3123FA9FB2A7A9DB3BDD98D441B03E0EE6A8180989E76CBC71B0E8607C3A9E5D20B6008B010702FC5D59847AFCE122F3FD4FB5D89D3A3331AEFB96B593F724C04885B574A43B5EAC70B543BD191BB818768C67A10AD6E2D62AA4C65FA373A19116AD86A4F9A97064E0C0BF80106DE6654B4A3945983B7DDF3AAF1E14A04F6D3035542B0F710352AFC20FEC78B61D8548B9669F10B3D6E531AD07A84C493264DD49759D95A6AFDBEA5AED1C7D7D2AE6D2FB6747151CB6A5C2F9C1AF5CEDBD9CDE8D5993ACF080A0008BABC759A9DF035C648609E610F226ED128E2656A057862246B65C70774B68F54D68073393B85110285FB463DFE394D9DA0AE85985FD6882EF5B11FAEF2BAC18F9D9D9B5CBF0F80AE7AC4418EA658D68B14BAC135452DF271DD3348BC338BC6C789ED95D5C5625762E4CAC6514866613E6D533AB9814B7C337260BF16716478401689F4079644DF4F734281C16164D19C4ABA20ACCCDC517EF42C19A5B1CAA4658C27B61902ABF88EFF0795D2C971608B0570E016CA0568CCA3F7B38FD3DF5608154A33C1F0D70C2AD0EBB134A8F475A8BBEC8408D3B9B0BFE8A6F10FD6C979B13C3EC73F191B788A79B4D07AC45172950689584C909247DC8A4CDD686186DEA16676851B8A7C311439149B1A963B0CC60E5395B56ADF27C25A51BB4A2FB19E14CE66B6D11781E89B3EC22CB854A12D46970D1A009AAD071C479D9C731770D666CDF0BCC381A3D328542F6371FC6F5FF7C4D3BB06186C048B2A3774EAAA3CCBA1342927B498F2195213326C9E393153BC8846AFE2120B8FF4A455B59AF6E65BC0CE9CA3502BE73D74B6CD12A760A9E0E0D26BD105FD993DD879539CD666CF2025DACD481A122627594CAD7C4FE30948412C1C6A160C358E16B6B67653418A22321DF5B1A9EA0DFC3C82DE3B8CB0F48EEFA7DD6188023D1B8B7632270E63AA38873A2C4472F9EF1E8DA56D5328C00548DDC4D9FD79115C5F6168AA98099BA1AAD606FB92F8D253C9A55773E5629E84350F3BC3B00D803E83CC2516C6C29476018ACFF2ACF61584A175E67EB8952885772E6C2D7F9C2B79C8B2F2A77C73C8B0230F080DE716B2A13DBA5FDC8648F17573A2898E72B8850997B6085F98523F00516DC7A90B9C2701BDDFE505A6C330D1118AFABC731A1DEAB813AA0E17708122C0069FB61A02FF6D5EFDA990A23E1D42C520CF1975FF06F123E1AC0B0A86FE666F8843C406F5F1E1A36FBB7A0B41CC641EB49416D6F0AB03CAA6AC0CE3A3DD1977B4D16EA33CF75A37A6092003D097D0ED8FAEE89F761B40F7E600FD502887AD90BE4BA311B9F4CD9D348DF230A2EACBA3FC356B506ED8C357E228970A948FC4983AC3ED9C3ACC22FBFF56783A73231F7E0B91DFED20E754ACE7DDDDDCEFCCF3ACC76554C269D634DC228B38C284AA35C00487D7873C8CFE8E8657726FA845863719FCE5A9E32406E2191B791F76DA035A4C862176040DA9AC0F37E66FB84DF89CAAAE9D8804824725FEDB95E5380DC66CC72BBCA1E131E6B785EA2B2B4A05BDAE01B22C3D47CA85092802A8EAC42E963A62307476FCF94ED7EBE5538A8C6F28A6C65914CF48299D3BA2B89B3008D29CD874B79A72AB840815827566E50627C2C332B1BC60060BF2FDA320FB040FD14D52CA59B24E325B5783BA1BDA3B27415C9DBDAA01562466322706CDCD0307C3305DB08D2663C57F6D3307E1C73832F8CA712402C7402EFEE0F1BD77CDA08F5F6582540D34F1B2809F84EB2F540558EF9ED46D5C636C45856AE57FD9E4650359635BE72028D1CD37CD876E0DC598E360CAA1DCD1F9F2BB4CA27CDE012980080E91B1C7376622907BA6674F1EB9E80148E6A959EC74950A2B934D42B84D739F1DA528F5C6E1C90A238E5167041D4E9AE5352B74C89DAE368778A90170461ECC0D6B6C6C53CE36745A72F79AAA1C82D494BD89D719800A89127BC3FD55247C1A29FB8387F1E3576E0C45F4D327C0B24A75FE25EC6147C890F25E50AB3C43B94F451E5B5D67F8D3BAAAEA1FE211FCE8622600400F73C1398459EA7FC59D02582C2806D01023D84BB50E99AE9ACC217B7223EDAD956FE155152E7F35B2AEE1535885EC048C6E0C50D395B0F1C9D767048E9D2DA7F15BDE192C923F1C74ACE06600628602D1B0189FCADE0873880EE8544AF3E29314E2B5DF87BEB5A50ED72FDC093800B12CB2F870304289A73A65D7E2384EF3A388EA9F0013B2B5C92149E2538542D95FF020A23E976A7DB3E2C9913D87D6EFF12BB51EE298F1D2CFF18FDBAEF56B70CBA35EB9273F1E58A6CD38F1E682A759FDF8D8BFF60E7CBEA948E25DF0114BEBD4AF13E4E0D4E7C9EAAC2C5F579A1AB14E7FECF9E13F20DF873F8D0E090905D32C8F8C0033F5D8E9F1B9FF17EE04FE3656EB66F5E4777B60B047DAB9BDD883EAC31A6455D1719CB475D1715CA0D12762F94AE78CF3C8EE90E55E71D0AA4EBA6216A0E81566F7813E7759BED30860BF22178407783B9A8AAC30CB4D53AF140E33A47ABD60F33EE700C323277E751E5B32B221E4B9815FDCD400DC544DF845619FD733F164937144FC3D89D8186F8B898418459811B3E66796DE51D1373B248A9B3B9609FEA374784A33989FE9F5BB26D2148F7282E09C35E13295D90BBC7795DD72CDD4955E9D148BC779AEE9C7992BB85D8EAFD102FD690F2C679CB7003FC4E182678320738361C361747F49AC6149CF4CDA4B80581844F5EE4818BF61750047C35A4B10697892A80F07E946F357574527FD2D0187873BCE78EC99062C70CB4ABB72A104A770CD7ADBD20894E7BCE2874E45302DC0BCB9645EF28136F36E7B179BD003D5DFA68A572BEEBD40EB9AC1F9228C74A788671BBF4781AA31C7F8699813F32EA8B60414C3ECB894DC7B01E50924482E5C068F0BCA79BAD9F469770FBFCB3942D1A3E54250E87B3693329479217514A8D7B734D256C5D28EF854FC3F234BC671F5225B1DCC20E590D8E5D09C07B22EF0A89A5B863C2E652CC0B1623579541C63CE9C2C4F66BC43323D7000BBF2923F5B8A76933FAF950D2172C1D90F522301D9A0C22F470EB8673CDA0A1B494FD7EE9AC1B4597B2DBC26FEE33A08CDF91E3C59BA4F93E02D010FE3F1C1FCD694F05B7A8FD32D8E7CBC2934A25C481D9C58FED7E0AF3AAB527D6DEF43D53756F0C95B2B58A426F7F61D09F4FBE55D9AF053B92818ED9FEF1CB41FB5CA23AC85B0241900F73971558116C5809F565F71333713EF5BE87B0AC95364C9FAA80DBB9EA84B5A5790D20343141093F86942817D195ED8DF4A2DFC7F7090CA3DB46A92AABEEAE2D7DD8B9110F23A89E4FA7B5A1DA27D643BB879888A2238E221E2F67D9DF58E73C46023FB7E999059D3B81FB753B2AD333207873831AE42FAD8092AA04C0E4103B1CE0DCBD6B06CC2F0AB37CD1D10EC4C83428CDEF84041D12BF9ABEA5C80050A853CC73FFF3076BEE68078737F6EF483F486215118C640790D0CFB4C6E5243691FB73B1294E0D3A494A4A538B94FDD2746193D9FEA24C1C04F5B20D2D40B638CB932C35D953A9D31260B76DA878FD52EDED058D1DEFD9CE214D14C3112FAB00B7F2DC88F7EBCF79EEB1C9C8607D6919B8D32CC8416E2B981C141198DD9884DC3927EB0192B6361AB556EB3977E5E242E5E26BA60BD42892F46F3F2DF684D0D9FB41BE42C04F0C248938AC79F110075B42181DAE62801DF76AAB50AEDABF4361C0EC597F31245B0390CE2629DB933E450E09DD39E6A1B644B0FF672B52ACE2AF52780D3F6505551F52045028C4DEE6D1C6A34BCD5E95E9DE1BCE849643BD07E0E6FAF8B27504F859D73BDFC07FD2034595AAD85A9DD9AA5B3A72346D6F3C4B21C4CFFAD8247C8CAF0DD9A708E11450502BF3C28EEEDCB0E1D32D3EF1A3F6237E34C0E4D0222F496839B7374EBB7D786973E85392AA8FF2A9901D076DD4C65635286276698DD4388F867D1ED18650FEDA9B03C80A3B5BD0AB3A62A45ABECFD55898BDAFBA58137D4BE29EEE8B3B3D1C4467B63DBA1EFEF2C81CDE7CFB101B1E65084A0E92955690C8CDE6F93E23FD79B76DB475CD24DD92A7504510F8DC3B22EBCD0288B4E479F8DD835297B196531D2DC759364306EB6780FEF31C9E34142B55988F81312B310093F77CB89C6E819A7CD3450D0790CB7B5E33A3E5E51DF05A3BFEF63320CFF072D450D71E7239AB24E4D83A8E8E501A5BDBB041219E15517B15EEE237836672A761D36D11EC973BAF65320B368906392E2689A9936752563172B3A5ADD90066E01EB394C77E40D57553B883F446C42EBB9CCB47FA56816B06AAEB62C21C8F57F926420AB7C1D5E97E73F024C259011CD585C23D30F99D22197B569D67BF5965887AECF553A9B48DCA0C418778AAD65D4843221B8217D2D61BA5A46C4F9FF5B00B78CFA8B6496007A1444503DFB8D7CDE7A63D5D7F54EE5823A33EB3A155C20F0011304068CE0385A09170606FF6895A6955C211AEF5D13BB93866C9CF00A911A4A50A59133113A9C7DC53409097808A6D0DC44A7776B41A7A43818C77CB51F3E20107F080F6682D90399853104B8F3AC4DE8521048B22BCA58B5F7B5EB3E3503F638C1FD24568F23EC8C59A3359A5C9CED0305B1B81677E20EA35F9E896E665D3CBBCB6155E1B0539A0B26BF95396DB8548124519B71BEC19A17DFD4AA2A2E134BEFDCA352B01E1255A12377D811FAED7809C9B881B24C185F1D1273F405F5BE82FED08F26E6C11D39A604E88A1EDFAC8AD3DA9FE8B1111C7E038A14CE58B9598AAE96B7BE84C153A9B26993CECB1CE931E0CBAD5F7F6C18B68E14E83A6BCFA33AD2B3A707118D56803A1E55CAC8AA93EBC47F9EFB"""), + TestUtils.hexDecode(""" +626A3DE2BEF13592E52829D91DD5CCE8E679AB2384C317DD721C3D90C9FAC0DA9E07F5F329FADB83A1C3C1A06A6351AF25496EC7FFC232D060982FE36AB460A905E7E5BA6FD1D12F17E4C4C8D34F531EF6AEFEDF5F29E4F6D24A8C9BCE0F803B47777C78840CCF9AA4BB798D7429EC8D9BC547F24A203D565A012BF17903D75F021E2FD41B8128320C274B95BE21F795F0D13F1096E59D92B85AB447ABF603DA95488C8CD4EA2DB181D9B66626168B765A6D7E922AA9F2F79631CE32A6DEFD4151C4F0EAFD26B50FE8007518280A647B8C4BBFC48B75AAE50C20E988BA863EBD36465487C72385C16DCDC5EF409911FDC9FD9F1F69236E18813D7688B64F8735805AD8FF8494DA36F42133FDE81539CFD1C430DE02ED8B88D5B0DC2F411E7192759971E4AA68E5546F14CA4E3F43ADB3070A8EAC4AD82383FCA3F8FFD6A80E1984653968EAC57BF55BC14765D91101302AEA86B3FC599C100549F80B75ACEBEA040AEB4FA0C2B4EB4803BA549E0D873D99DBFF0C8992CACD6A2300B46F5F4F61FBE05EC6B203F6386F57F49223550406F6F4CD9E31C889A9ACE17D9A846F7590F8EF0A3FBD6E4E4E3D940EF78A9B0B2975A5B442F141DB9569F993C6398AB98A4C5C5B3BFAE5D00C53AEDB5C6376A7C72387481D72AD84F96F7DC59DDEBC41D062455CE042B573F62C98C0B580AF3DCA8155841FD66736706FAD04D9A518E96C0A1C92BFCB82A78A696ADC70A518B25DDB30EC97E8DF355F87C322008ACA4151E57274C2E219EFC811A538B8BA26DD44DDE9C429C8566C30AD085C1569EB163DE705612951F8C022656A2462F92344329FC40D59EA66C07D44145F54A8CAC1939A01F359F54932A9E8B691E0FC3D01894198ABA75E851DAF35CA562DD5340DE311F091E2C65CC294558FC1326856924533A46F754F90F51569472C9FBCE63991D95B43ED76453707DAB30717A874D17535C94D880164FE89B014016F1BFCB971F651178351885034DE97FE94021EAE46FD5624E2C501C133D56D359904F9E0F8A1ED887D975CFB4461923FBA3AE566A27198BCF6938A4C80596396A2BE7755AEA803F4CB7075DF5A7D70788713DCE543AE2280989166EBAE4E7DBAF3DD6C92FC4792F0F11DFBB9B4A465FF9AB96701D5795131D71285A74FB93EF20C8DDDC705EA1992C1CDA769D2F43C5EDE7214823CD8F2C7219C482A6B07E88C6DC3186E04FDE3254DA0E9767FA69836FC509F5A9D9CBA41B12F948F163B2FE487CC83BAA5986CF84D07D171EF9F6944B5DC9FA7866FA72E7CACD7B4345164E4731971C8A75D96E9EB0C61B4F1F3F32CEFB9453615929408411F118A6DE1A9FCBE4FCC71AB730CAB4BC28B61DB6029A788437BCFE5AEAA41CD90418F49766E20D91E0E29714019CCF304371CA4C498EE48C5584FBBF146B888E2C3926FB5BB12CBD0D1736BE74EB533A7C34C06349A26C3ED86DE52A37E4B8EA2C1108BBF3E6773267C5B5C3E50EA16D56B24DDB32FC7F9BBEE75DF88181AE97FCFDAE2CDCD5CCC2E141A9379820CDE613E9FEC61212D23763825D94FA1102BD7F7EB1929A2538731A7E753A7F6E6BE57172C9B8349D8EDD698D1DC25C55D7F06775C4B9534BDDCDFF33DE2F1E9BABE78DC320A202ECF94037801F42ED1344091A132A24B875535322FCA82282D9AE2C0E1E926A2E9E1A4D2BEB6A58B85D65A7847A57E6336C367F8C0812C055B18E8A0AA987599531DB98B8ACC58F5DF9D8E7357888594A188ECF9A805FD767A1CC04847BE22833994784B545C4895B18D06F157F3B75BCD922A8894E2D8E3D174A3C3657B4D4A7B7318A4864D7EA59478E49B0C8319375DED55F93DDC5A51C6048D028195D4DF04206678644A2A6A488F605228E4120FA97E271758657FFE34F0AC5044F8718C3E184EEEDEB62D0C29670250D491E1FC3E59246EE06D3CA31C167BA3FB52A77E1624E34652EBB1FA92DEB762FEFA87AF0CA5872AC6E2B6429ABFFFFA10A5F346F032F753B7075B7CB32E9E899D371C7AD8FC070D25D6C919FA478FFEB91EFB62BC331D0A975157653D07E3202452A05303C9616CE9A647FD4C97E1E0DBD9D8470ACF5D5DB77780A5D515FC7BA795A071B67F7F63D8A4C6E05BA2A7B31AE16EA31D8252562F44DBB447935A3EE504DD135AD6DAC43BB01EB0C5CBA939AE446FC260BDC488E3991D1BFA5102E262C4E31A034B8BA12C1E0AC599474DD98CC014F387B719AC06327BC5F157AB80D424BBD10769BBBF97964DEA127FC52F418DEF5DADCC93724A725CA47300A31F5B1D2D93AADF5FCD59D5F30BECCCBDF34AE458C50A5B54FEB305EF1C3F42556C2E97DA0327629DB5AC8532D6E4AFB22DA1687F536C17D7153D8791805061FBB31ADC0AC2F15FFD764E46DE3AC541B07C55BD67C7A5A972E0370620FE67449C58769D269E160C772C1DE53C46E880D5DA7D58EC100C6810B1C6A051F73B42F8682F166069E6D0D06D2A5894E4B6F74C42B31DCE09281EAE9B1DB21B521D6F910CB8BEBE8F7C09B137C7C1B7B185CFDD91E2A0D9503C35C99EBEEF4B3011A1E5996393FC21E972AA0E6F576A426141699AAA0487C686C1E14E74CC697F4E21591A75F5DEFB98B5D649EE2AAA85391D25FD8E2A20ADBA6523C26713165ED207CA3EDC7F0CBFD5468F4346A209D7A8EB2F63DFB6255F54C062BBF2C90631B539BED1A557A16225FC3DFAF9B6EF2BE10C0CB279644AFA74A03E66FF4FD965184B9571D4A8EB2357A4EEDBAB71275E3D5DD8635C53D29516E98F74B51051752AB7D1954156A906144EA4E54A11826254529835A80B6A3599953E012D4953F4B610A85AB55860C305787D00BD61179F369579EE1277406A3F55DE431E3E7EA8DE07FD4484DB4FF458CFDA28A2307334A41DB55E31CEFB5EFCCD922E475D06979E690144F77780BE1DF0667F746FD0B2F72F87399AC11B9417568D3691AFE1671E08FB2FF508A68AF6A3E0CAC6A9ABA02A4E8AFEC4B7F41CA03EAFC31CEAE5C523703FE41C1CCB6D021678EA00B6AD24AC63ED1F6880C4585E4E85BD975EC84417E8C4D4C2A4B6C10E11853C9DAD6F07BDD25387B66AC3DEFE166D6F85576DBEC76943B87E7C91293D51CB2542B63828571408F893CB541C8A69AD3054FA9EC6759A173E82B55D78CE64920548856A664E21844E97CB264F42E11754FE5B17AB60FA85897D65881207164AF2307376728D738EADD4F486BE0E5CD0F1FF2B080C8D966C28579DF5592AF1E2FF39EE0E318596B26CA5F48F789CA0712A7573BB6ADF3706D53E644B70056FEA3C7EA90D0D1621314047545C738E93A0BBBCC8CED0DBDEE2EAEB0709142630353D434C50657D888A909AA4B4B5CBD9F000061D2C2E39464854575964747D859BA2A5BBC1C3E0ED18415379808394AAB4CEE3F500162C434F""") + ), + + new SigGenTestCase( + TestUtils.hexDecode(""" +2EEE200F329D7A51E31290AA8C6581EE83A0B6F215ECAB93D0F0E4D0350B4548999ADCD8E8E40E7BAD4ABDA6B7194C206595C2747C4CE24E6EB6BDF0101CEB17716EE0336E6730404E8B6F8F1022F66C791D166DFF04E6A18CBC05966306B34745F4E213CD668E079A0DB2762FEA5A1CA548A026120289781B847A96A070F43F10280A08252564A48818052C6042280A4989199005CA826940382891820149121204024EA4240512974CC092859A122048B82812B881C9360D4B001090B60C0A398600A5100099710BB5201A196ED10612D800251A418E1B3321DC404D20C3404492055B1248102500080468C1B611D4C2100C94046442204B361189885022A08561208A23B64C43286413027121488900300212A33109B32102A561C4A80154185203010A00108D2230801B1760CA406283484E00B949022622001765CB020213B90D9C368A83A2915220465C82898BA09182203118B30112B240DB026880200610112919948884222AD0808503324A583231511646A14445A0A64598B80CA49230C9828D138685644864813669080460E2422C60204900B50113496604C06C631285E1C8295348614BB828E0182A634881D28881C1984444867089369208434A19A920182088182940A132514432688BB87113226D132051A33031C118220A450C9840518234010903929A1226D28691E3828DD2B26810094E039728D8402598243208938492468543962192982563322102A291A494318C306CD4004009874521B284D1885124274C0C410D61402D8B146283A689618808D9808464862921994C0A990454207014B3608A168D09150C9C38305AA68C14118A4C120A9AB03109122018328AD240492294650B23121847060A321061980583B8300BA08D633426D14260D1886513C6685B082E09B9601CA48D519861481248501431E1B811C41082D344249B424D1B310D99105084468DD832851B14864B102C221211DC908183167008A770C2440253388112C68423184952828DDC408C8B4884A11060CA8000DB2089C2805199900C1B044D22874802378602C040591484C0B221220790C4804C48068EA22006109489CCB60CA04226CAA46552003050B608A146914A007221C711D9088483103143C009E3086961204E239200C390611A3529D808421A422DA4208120A351CB080208495161144164B044D0A6400C4081124025C9B631501870942850034868E0B22DE3B86062486C0C336D0899305AB845003991109040B90DB8DA1A76D8382906AC6480001D09B8B836B9724779F5333E5CB7EAFBC9BE79ECAEEF30716D5B8198957F201320D88030EF5C82C56EDAC3E6E7CDD8D272EB421CAE9BD5F07FD96EBD3F21C0171EFA28612807DBDE1BC11587A52AF2DD2A9AB7F24267DA67ECC77585BDB335DD29E7941DF37995A7680E71C4E688B840A19455E569B5A777BA3137384E0FB6F2CD937FF55A389758E95A4F145416EFB0EFB094BAADFEC3F91EA5B9AEBA8F461F4B2A451ECAE68B50EBB69D358C12227E8995FFE00D9A3C6AB4E00B58AD99C9240B4D2AE6722AA144E27B6F91732C06A86072B69001AF41F30CECE4869C334EA78126A47FE2587BC76B587E25E61B1EF8CE536C0AD109033B14DB41B9F2F3E18D4F812428E9E9AB88E6DD01E8C2474F6F5B1BB1FCC3BD905F1B16034D9EC562E65F06C14F5BF497930D02565EC9A458BEAEAA5CEE6C93207AFA1C934961D1A0F6D726A4395D4730575BFB09F41B21FC5A816FF6503A0ED308D693EF4FBEB88C09CEF42B1B1982218C3BEF1E81B63DD0D9B1BFFEC50A5782D00B9EAF42DE3561E47F2EF9B3882665328D17567282D1B1B91FBDDE4B64A5876BDC61777FBEADE3144444577D591CA0CB5A665251DF22E055E25AD7543A21566285FD3D3C85E7A4849DA65A28658FF631DE44ACAD7B066E2D88944BEDAC4B220006B19F5F15805DF64F320AE38D05F0DAB0E95E02D1707C23279F3CEE21FBC0D921B334E2A41E7D07EAD955FE5D530F3EEE696248568282A4CB03C3E017FD959560DB0B2F2149F2B01FA4ABE1FD17C0321F38E77460C29E93D88CE4301B58A493C1B29C1B81C0C6B720ECF408EC4AC8BB744A79418531BDA100236268C257049D84598BE897D804FA13076BF9E426D700101D10460E1A97FF32974E1B981893C0022C1BEA990AD92C2C52409C05330FBA5EFFE835A2D57025BC8F22796EB42E6C3CCA9240E3B5E098873F45D5F2B290C93DCC1485481D3689C835EC613A5EF5C6EEBB21AF65403023EFF15867EA26E400FA648AC02C7BF4FA9EEA4FDA649DA80AFEE18A660C6C8F09FC45CC6D0C1941829488249052FE94E9E782C49174B680D7362E41AEAB16B797A05FB55E66A2A0DF069106B3E28F1CB7E90B5C0AD18936208AFE951DE9BDBC1EC66259C9D80C9623C68E95102EB6C597C955B37C510BF421FF5B38590564960AE172DA8605E01396992FB918EE2C107D5A13AA1F8601B775BD5B9226AE66F28FC62FF06FC2ACEE4ACEFE64C3234E4FD53B76CF0232D5C9D7802A040D4E529616F0F43F118CB678FFEC23BD92CA08B18617B4454CDBFEEC86E9CDCD80A8E918B73C3C3311D258C6E2F7ED1890FF0D4F28E935B41FEBD17A41048A35B9AA2F15D1D32864DDE6D8A82E65C17615C71F04A2750F5D9C5D62C24694DFFDF1C900733365272ABEAD17DB695B5285DD16AB83751AE3F63742C5F87806950EAB68E35DF9DB0FB4ACC7409BB896AFEA9C49DCECFB9C933AF12DCB7723777D0059460A02309E9794B04E7CEAEC0AB433311BCF42AC636B71BF73AE439EFC3C4B793287E7F2C8FADD81B2C2A9A09FA1C956DE94423BFC76F791AC88E9BF0EE9493BE031603BAF103BAE535B9A366DCD45EFD324A5087FA6D214772FEE650488F83EF201E9EBB8F60B86B40B2415BDF5AEB0E20EEA5153534F93EC093431850241F7BCD4DB2B5ED441FD8013F14566F6B4ABF725B3F966E0C3BFEAFB5D0C2B6D819887985CFF7DCD647E0B5ADA53D895D14F0361A8E83A7945A99A833EB3AF65D6C9F2FF811F5245A629BC646F3E31DD9D7810BD4404A1301D11D30DBEC2DE0163953760A6C5C7F033BDE8763DEF5D396BB141788D239B720590A79D73BD46EC7C3280BF852A451FAB4392630E071ACBCF86236F7C07ABA6C90BCAE4C18338308A08C1760879A8C2E0D561981B39A4694DBAD9AAB1E4A752F87CBE6BCC9B1BFBB314EF3671E95C654B619394123376DBD4823F5498991DE817B82FDAD2C06AC74CD2F0FE13897527ED8056CCF315C9983031A10E226A2FCBAE1FA327EFCE9F7241218ABCFF7F3934D45B82DB6124897DDAC45DC241CBB42569F926A6740ECD74A9EC6DACEE48CE955F9B3B296E779625A6514AC5D586BC407300572B3693C1272609DCE114A1484F09BD7201C285C2E8CB5C394B88A1FC9A0B72F491A7CB445B3D7F6D9585FA0AA6FF2B71E32678C8B94625B69B1F008F248DA1FE9480C653974BAB0153B78AA642F191522535138C326864C4C9FC895C092C1D05659F01EC7AE7FD50C9E30C7C2E4785E2EE1A7042D6A1AD17A73996B8ADCACE9888DCFA120C8DC527860734EAD355C47136CCBF738B3594860B795ADC28"""), + TestUtils.hexDecode(""" +3F1B179FA452CFFC1F4776B275BC9DC61A4448989A5C74AA4F6A42748E49DF12AA62C5DA238BAB9F4309D563EAFD739B54E8957C0E91DB05F63B2A50F11205F5AB60B0E857F1AEAFC0562A76626AE579BA3387943E8B735A4B1CCBD23A6CF56D7F38CDCF772ECFDB7CD40781EC2622C10D65BCE780852D7930281726CC2B83C8D8179D842CF3DE761B071A6B04A383624398FEBE34CD841CBDF9C256A5EAE3973F0C256F89665A0B23F0B505A2EA73F37EBC11AFC2C3D4FD8626EB86FF0267D00DBC567796011E5548C08208CB0B43A880C1590CBBF0549683BC71A8BBA2CCA5F98011E592F3B5D7C8CCA0165A58BAF8CEA629CBA860511EA2E86B4CD9E721E8D7DC608504114EA98D016C0C0EF67EEF084B8FDD8BA4825A0615F7E09C42D935D9AF0DD847C2435D84B4702ABA573499C9088EB21CFB97E5B5A847476FD25EFE2C2763429048F797FDACD8238937024E5D66B3FB40055C3DF19E213E5941095CD8FA62BCA591007D03CFB879388983D6E7A189782F36F88EE409D490C5FA66B62510AD0D0EE9EFE6DFE23139944046C62EE639C0F82E6D850770A69577DF6034084DB97E4FB2BD206281A79CBBFFFF8A9E4B70252F6F03DE8FFDBFCB0A5267877FED3893CBE5119F0C6930FC0DFD82C63CB1E7DE66DF2141E184646151CA8A927DB49A3EC63B3B862AD60551B0E562F35E109594E4E43B192BFECF066B3C7612BAE0E170F0E1D7D246CCC3A2F94D3FB08BCF9DC7DC44735E258B1F9D0D8152EE79FF9EF095EEC3FCD872D9584361A44B9BDC88BE2AEF1158D1765EB4DEAF441F2407039E98DB8D148DC8B7EE9C44D5833FFE4C52A077F57D9E36CB220251C58F61759D18E4E449E72F29351F6CB08F9D996005A33EA695C21FE883E1C3BC3DC3E8239F2BE16FE445A18AF83639156521188EDF3F15ADB300A17F88C829EB72275F6F35D2D1A72B79A01A50F1A63741A8B1ACCC35E49D331DF670D30DE8855FF27C9F6D7BBD16CDE4C4C4DD48CAA971758D714E89DDEEC7CCEBF2E89F8CF03D7E631B9A18ACCF19FF35AA24AB6A1E10DF105FFE2603C30E16B7194AD615038FE96F4767DB8882D48C97514CEC057EE636C9FEA31BDAADC5CAF6239A805BB05081962A2A5054D9DDB47AD9D3C98D053A5199A687668425139998BCB466364F656B1AD9F13FCF7FDC50652841EE475D86AB89D0CFC01C6B5B876AF9D0312A43DCBBC71B2714B0C3226967A3D1E0AD7E9368EDDEA9120B2C8641EEA203F2E943F43708EE6CDBC6748A33E3DBEDA2AC492A6DEBB9751E7AE4AA33F6ED893AF7054454467E29D7EB7F2163FD24F7B5607C2E77DDFAF72E983AB532C6585AE8D78757DA904D1FDBC10768E3E70D582F17708B51D561C24EE0D5A26559EADF5463097155540F26EBCE03D89F49D7033AA00E1DA5ACBDF148DDABEAB739EDDF99A6B2BBEB48F83E3516380FC7AA9FFACA8DDB53388485061EF5B94E92443C24DDCA823E44A29116F346A22BB3DCE7022C3E2EF35ECAA91CE5F65D7C5EEC85D741ECEBAEACCB39F881391EE2A06BFD7B72173B171B7D11C8792F0A7D9A125011294296B157591A675649716F92234BF074F78EAEFDAE1AD79E4208C6338F42F2A9B105EC5C717301C638C63555AF0A81F63D0CDD04F9C22E2FF223CA5AE1A01C7FC61E9DA4412E80D493A7C0DD49CAC10C62A7D3ABC1B9C74EAA2D8AF248946EF8A37F1F7017E49D11B89EBEC111D85D7C1512EF4F99BFFEE68FB588DF3F39735169D1B5A647D71F52F76C6BC09F5703320DC92BBBE6D7CA592566483636957D235F5D18150B6A4641CED6276319244CD8EBBF74BC5DD3AF82E6C1118D19ED291ECF84E4EC2FEFF28286898E9659B01A37F4612460B34DA8444A4805FDEDCCCA5D6D8013335B4139101F28090517FACAEBBEFE59E44A969FE3B8402D690012AB908EA590249BD9354D456EF65331608478B2050F985C5903FDA5AF0D918E7F7E167C3A669B727DF0CE96B63D4D944493C5D2BCE97F2827CAF54103A18CA8CC0483BC8B98C42657349B8438C0274E4401463CB55E93023BA114FF8CF3A718740756DD8C92958BD07A304FECBACA3CCA8135AAB901AF23E1104E202395A08784873E03FCF2D07AAB003E6581741389C238942D7A2B9FB30B53CF5D0C408C0EDFB1C4FF448D745FAFB0D659B4BB76B16D5B61B0A38039488682907151802A815AF220F82680E523E838ADB47425369CC421DD36C2E60100A9EA7F29B05D985D644A7FEA573BD24B922396A481E33306AC41CEE9DD8ECCD9DD7833F8CC77477EDC2E97A72CE2DD930BBBC58FBFDE78DDE34CA1F8DC758CFCF2ABCD35CEDE0657B35583F9C016524D3AAA5E698BBF85AAAD01D7D3CFFAD4602858BD7E2F173D6A24504E448926DEBA1F70F3B0D5B454B02AFC4D0C482BA8019A0C209ED071BD2D5B341EE06FAFA7FB0D1FFE77FC6F6C49F78EEFEC44999E4330BDF33021EBD91DE8EF2042FE4C3F19E992A5E66FD9BF8E3D428AAA8FA51C7C761C2CAEC8908DB3066D50BBFDA98B82387E92611514605D6CBCC0AF9FE08B39AA1DEC89CE77987BF3BBFBCF362B4AFDF12A8A1ADEC69962A6FB26610C816F023D87E648A77DACC3997127AF770658921DCD300EE2C8C0916593067B3B31ED1B6B73D68EBE68CB22386DE39E57FFF6AD766193F99CDA751316A5B0729FE5307C107FAF6DB4CEF4B1C6CDE957DCD6361606A6606BAEFD9A1AE08A5DB21991F022C4BF758D16FD53D6CD41F637F5569D7357CA048F07F53C850CC56A07A4C2F3BD04DEAE79498EE10B366861EA82A7E04B9202750D4FF4017239BF1BF7088A3F2E2C79DED5A12F75CDD754840868754428BD7392E4F01F36E3B450A9BE5BB95FBA71C960C7D09DBF24E6662C86D8B5C3E37D76B16845B0F88C40AE7360545B3304DA5CBD2B58C29F6EDBD794E9AC779227B0FD198EBE3A172FF4B8896F0C9BFB7A4FD9FE6ADC73E097046FA25CDFEC45CA1E7FFC4FD582DDD8C79A9F3959A4DD7E3473D6F242B0A6AD4DEF109C12DEC994F2E313EA1930ED25CB401B82212E86150BB53BA88138AE3269157FC2A7A919E21CC068E0B9E934701B572AF0E20FC2CDB2B7452CC1E5545AC4CDD34EA0097CF531FD92E3FC38CC50E1FC8ED59272FF3D631FCC239E4AE0AFA46419863A166DAA2CBC63E24C26ED7EDAE476A194F8BFDD540D640DB3A8B294E0DF0AEAB7A735589E23CE524F534AC82D80CC51DFC08EAE4FD02E6F6E0BCDFA0FB23697EE1AFFA735566223A70EAD827DD31881A3C2471677F905B64E6AAE00467561FDD6C79B45016F1326D705A854877DD91D0B147071B00C5F8A600116487D39284F6334FF56F124951333F723D68465B765B32B396FC4C432D51E8C6A9782461EFADC2CB93EE38D4945833435E2E27E17CA98998F9B33057B1C73E2E43B6A184868DA05559B3050FF42C76D7440E1A5B803C8D4B0CBAFF9FF31C7E98FE2D011B3F87416889A81DF9F48643E943336430602C5B44C1D11BC7F62A0D67BCF9964815CA0AB83E7A87DB714F2C1872E5B9F0843B82846516E54A3F7FE311839F4910AEC6CF0D23F86BF2B0B05BB71B5B47E93B80F7060A350EE4D73EA09A6D489BDD064763CACEF5818B319CC973FBBC78E01A505A2F6C4F6812819E02A573AD8F7A345763943B623995B0634562479072D9E42437FCB2D02479DBAF2D088B31EE870F11047E965D04524D0CFF90B943B1BE969DE752249E8B48C609F14FC48692BFF40EA6095F1967DB766C8B4E18FA73DCFEF18F2DE1D295B51A63880E288ACED85B188B3D10A0B025BBD934BA43A5AC5E1829DA836EFDC88F4BC6BA0F4F23A4AB16DEF3B5488BF6C974EE1BBA51D17BD472C731DD35D5B74EDDD3C9177A3503D783968BCF8A1F2549F70069164C965304DE2434530B3841A2AE7DD47DC5FDD9DE046840B4D65A08A71A3D15778865CCA2418F154403183FD44B622982C64F771C87E18C09489493E378476B3B1C8D14C8009ABD3D1A51CF806189496A4D70FE857822049D3DCD4CFECC2F95D2A8A16D94DC6703B4C4EF3E8C7EB9D6859350131E1A03EC8A21E13F045F822C48EE3E3A481EECCA508F189954AC267E6CD19C80F8688410E2E97C71A6C792DD6E33EAB2FD16B82214588B923AF6C6069387F6A72CE06033913B50F0310112DC2143802AA2CA066388C96158AC154C33E9BD72C993B410FE5E9D7CF37A30EB85A127A7773ABFB416419A5B4DDECEC10E2EDB312C86C3F3C8BACADA66D057FDD40740176D137B1F1ADA098D978CDBB938F45D4B7814F2C5B894CAE249CA8E1FDF31E81997F7C55B7A43461F5C7C9893AD0494F4F0272FBC20D80F327EE55250F9560A301078BDCDE94D72A7D113ADC7C739D7AC2B8775D961F89245C5AEA8ECEB1732FA345FCD84A0C07C65F091B4B32DC4E117D24D782C404E8FDDFD6E9E65B3633985D6DB8CA841B9F9A3B3C617F1D69FB454045C5024AD09C5C1080F3EAA64202C08838B42E218F56422722536160F97ED3C08F285EF7BCD1119BDA59DB5EC6BC8E9DC1789B3CBCD469A4BCBE1CE237366A5B51B062D0A08201D4F0EAF6F8FBFFE53F35999763DA2470F2F9FE79BDA60285D052D65DABFBC43659DC76602DC662A3357BC3E4BD07BC32AE5B5E94D7DBDE4B5117BD5A9E3461021A569E200CD3CC518ED6559BF2539D8DAD74920DFEDE8DF8FD8333FA17F0798A17B5385A9569A640685D7365D3DBCE8411D44B17BF79B852B1348AB31335AE013B2877C1D8AF62F88C5186B7313F2C8736472FC5F2B4B38F761009F7623292EF14A4A4006305CC419A3ECC73082F63BB2CECE6A624C2A6DF29DBC6A4F0FD3658C58EE694FA58741DED54889994DC6A3DB4FAF5998B577EFA399E58D822B99623D76050736C17B5218671FDA3BCDF7E81B3E85D87200DB9150253ACB07AFA8FEAF74578125E1E26128116A7446C804DE54FD2D2B1A48E684F73AE91932A37372DB66A230AC4CD54869A0115895D2CC494E6D6E8B12845551B4F3DE0B3A4C114979F0471311434BB3784FAF7F9A9B88D536235543ECED732289B383E8005D98192FBBF41EA8026CA3A14B6895A6EF0548EBEE58C25530F56E0EFF157DF6ED0ED0D5565E9FD474B38EF5BA74D24B82219F317AD51F3E7D6F8E4BD8836B91525E162DB417C87E36B3C0FD874FB4BF4136926AA6D045033C94FD1EDCD69835A116357F341372148C4601CFD84BC36A8E5B2260B90CA797CD5A41362C44B4488399394AAA431A63A74B774E68025D7DCB1963911F2BDEEA60DFB24E87196FF38479D235C98E83F1FC419C87F708677F98C84F9C4848B255DEF2D92E3506A533D36E56DF81F6461AB5BBE9D171ADDD39FDE7552C5D4351DB59543C0FA939ADD6130E25D4326566FDF49CDFAA240BBA0B027257D2ECB83209329944E8F44AB785560DED2BA8EFBC55CA31E48F4C94749E4D205A50BEF3E3F039DEB3EECB213FE92C1C3E98A9F72B6CC316D6C0B87BE7F688000A2433E3A184A68722D44C7F6C90F2AD0B248AFC9E57448E3450888A875CB3006E27C232963740B985484E7FEB07775F4B4FD89AF6F627CC56CA1AF23E3BDF61443786D3F04DECD3CF71E2C6139B584F52B6B656CE0737F50BB270830B102B781E621B3356CA16019696A23EEB238ED74D160269A3EDD35F7ADD9E065F836A61A0CDF99272956555106A349166B2C299B8D0066581DC3608048DD8BC2F267BDB2808E1ADCD37A7538B9435E9E5D7ED4389BD2CCB6E926A927BC6DA19E8E0E946442A6943F65C56E5AB7507FC6EA1DEDEA7C1AD087CC005914CE80A241D42C88380A49BC4B6850536C5A99B6423B77A75FAF76CB17479EADFEF1FC90B832C8F36D92BA3E927C9D60473117267AFE4B115E39D50AC7991BF248DB38E8C99784848013B48D4CD6E034B93E643239E78936DAC6283DB748062220071473B0579FAC64510D033525D786778C53CEBC3BF95C4FE9406943E9D68E17EAB3245C57C00D0C206E3343D8201A2F6C278DD61D0CD42B71CB7064ACCDD38551DC554007F29E1929EBC81025CD1A5AA41510BC5CDFF340F42C4FF6DA37F8E97F5911F37ABF457DE3EAB6114DC858C0C14B9BA5B652DF63D0CFFF4D6F8103E0FD15D87D8EDCA53FBBC70E3B42C410F379BF77DD17F6FF57D7A0D01FFE0044F226F8D65DBCD1803928B29CB6AAB703A0EFFE4EB47329D9D373954F0F15CEF2577EB8F34665FFF2C774EB07F0CA72ED27AFE6EDF158C3AA193F3B5CAF99F52430A3662997DEB386DCF0A6781E42180ECF44E9043AFE95BDA84FD1F9EBDCE26EEC0A4A08D8423111B320EB87156BFAEB3827389108E12E7AAB3F6CC8EF67A7C877BCE3192E503608D6F1E5697941FC1418C16093A55A2ACF2378590F4B0702998A65C8127F13AC98BADEEB32B152F3054EB7D0F200322E40CE632CDAE8F0E6C22497BB6D464ACBE9B461C5D39AF9334F5342FF31C9273146D20F5D4BFC61F980B1862BE4A147474DE89A1A3278004F2CAE293CE2709748507C5DB48D98B484CE933DD3E925E1788F2470C91177ADA3869DF6FF81308DBE846F50C51AD66CBEB2AC91DF1C86EC22ADAA6C702F1CB7A141778BF957663060725A5AD6478E22FC959FE5C918EF1A11964E66B1910018DF4698543CD3015E9876AACE37988370135BFD7047FBFD3996B45EFAB6FFA70A4191F259B8A27EFA05E7E1C75285CF70910465589B41A9D29F51F7BBCE06457A3DFC540608157479B499B2F0CD9D8A8D6F2C01FC79E5079597FB6E2D1C3394B8D8AF65DD133F9D9300DF3DA3D740CD0E7E13EF62BE1D29A3DA6745A5A87558F23D89319BAB09A15F8FC01AA388E1FDDCA117A27426D142094A11E6B49E2C541A82C685D41D6E2520881534012774B4C01CE3D2FD8FDAB8C25E4F0AD1292974C4C141173CA219C07314314FDF94A05955E210DE13F0165C990227EEDDE23A52D7F4C8A181C996D0FAF6C313EB74BBEA4C2CEC0B7B01698C63C2E1D37313B637271DC49A7EED8542EE8BDF7C7D791F7BD59A029419616F9C8F478F060B855CDA73418D0AF090844FC0066DEA9DF8D4F3C9ED58CFED2A78B427B42B033C46485B767D75526DE8682D6AF0BE91169650BA4ACC4D54E0D357E993FAF358BEEE3F7F988381EDB31FBF174239A345130BAE1B0DEAF27BC5E1DFF86B29712CFFAB670D35D19DC5B25DA43D481336C0CCC2120427F30326FC74503548344B585C082A78F96F072510D50E1110EEF01617282CB681CD352A23607C3CF7AD9AC06FB52B38294DE8F87894D25C1D278678B048E3E3F4BA0D884154C5E16780BAE2322C389667A15EFB0B21718F56767EE942E4BCB190CDECA74C92DA8848F41AEA2328D29B10C95C6DFA74B0E162591B1BDC0ED6826ADD0B04C7495FC30E586FBC03D4E871915AF71866278F9CD1B4F1AC56E8E1B7B11DBF0C9A64F608E1C3958910829654057103BEC687A02AE9A568BE514187A3E27F3F9928EEE29519BDA0065179423A7242EDDD8CC337F0B7E7FB7CF90FC682C9E60253BD0997F34F9081FD785712E52262CD17C3508AE4D2FDA3BFE232269ABB185E635E659D405AB12E17A80AEE5BA7DDAF1FAA819A284A60B85B49F1A57DA72A0866B2B9C2D28178995E79D4458B58EDB187B0CDC5C37F111D20371FB8F410A7EBED95474859645FED6F451A396781EF7A02E6B52593189EADFB1226316FE8DF79B23CC67BD2EF973CD561DD612D0C3047698EA0D3895A28B4111938F0A0354E4DA7484697C85908A3BA3E80BCCCAFC73303C767BD3587C1F9D48FD4DB93517A561DAA10F53F330ED14CD65B4A54FC43E5F5CB421B8B6CF7B83D86CBD72A55791588D4B81094BDFE45E3F32A2C3FFE809F66FF310D66032AD6BAA5B33E79F1C476029A49D49CAAE427D8A81EB642B15EF0C544C9EECB7CAFD2A854BA79E4D7EE01A96CDE9EEF45E430EEFD8A16D5D22B751F981667F36DE2E139391980DAD22462BFF4896D277D89DCACBD5CAE5EE90BC2D5954C083AADF632D9051B782190ED4AABE8FFE195000A6BA05115EAA0BCE755B23B10C81DCF4BBED61E6D31E9292DC1A7FD6B453EBEFDE55D6AD8866CCD50473705A24F519548172D3D9F92E668D679D782B7F1041E5A558A625D65E679FC75B15499BFA304435FEE6F6498138848BAD0BFFF6942029BD0C5465395F5368692D6B21B2E22A638D6EBFAF3A0EF1F9BDEF8529C6D0BD328CC82BC66DCDB2F5AE20F53B8AF66400D6C2C0A3C6BCE1E8D2B222FC54F1896E58F61816E301365E12866C1BE7C4BBE0DBDA2B504F0628A4DF1EC7942BC58C0A4CED0046D73FEAF2231FB9FF61C0F7AA564EC1E10BD65B693CFF56DDF3596DDC85CDECDF7F123F9DCB27269A7F65A435ECCAFD89A211C829BC7F5916DDA61959AA296505F6D46543D863F2D3F007D8960634841CB317F5EAC3D3A3E4561801CDFB269257FBAA6A60E7A0A1980C9BFD6053BF2EEF7414704C7160A051355CF48A0C0F6FFD683C453513F8212364775B7424D9315A920DCD5B140A8440EF7E5908D4061F580022399509C0ED416F945705A19FDF8E65C8802B67701FA1D15F06013990C7BB8D0D0404679713222924DB33BC659FE58F82A99BB1AC551426A13C2CF316664AC8037B41755F110F6441C7BC9446430D7BF917AFDB8FBEF84E895388A68763E0E16F89FF630BDE9732852B70A4A3AD8A29D2A4670757AA4202DE5D53E653848FB26C6031D07CD010501F0785D1B1D69BED49DC3B07265D51A15A7C432C3EA63A0B0D228B4F8AD4060DBB8D54B94BAC7F2179829C8D9F9CE4F7BFCCB472EDCBED73B0D18E3108156FE659CAA40B45016E0EFF20F81C29EADC8B638364FACA6FC85F98A9BAA9BB7E5261AEC6786C18487B14B77ED2B62B762D6B8B39AF5A870EACD236CC53C016158DD1E71382475657C512EDEC0977320F1BEC79D0CF39403975210DCEC3ED5B58F"""), + TestUtils.hexDecode(""" +0E27A9CBDF2D81A93D2B091B79F926B66598283ECDACC0D1F1FC71EEDF8A8CFF01741193BC4A5AD7E14CAE78A658DE7655C93D50F88FFC5E4FC993B7D936F7B7E3A7A0BC50C84190D300032369A74367D1E2165307DA61D4255CB55B12448838C0783F61210E9E8003814366A50DCF6F7F504AE587598FCD32D00A026723A34F040E5ED07F849A6884C1E96D6F15590BEC3E3134C48FEEC6AA56A746C218C7B40D5CBF994FE3DC3EDBCF546DC46907B64B3A438785544F9E33C78772F568B206B43DAF1315B0A6CFDB4797C127AF6F47F605763EB9FB0547976FC486ADDA2597CC86CB461A3B1A2C02D600039C2F50AF91BF47DD8FBD791155FBDBF4709825C2B5D302F5648CA842D6B9021938B6569DB7ACADE0E7A13661BE3C50C15AB3A4E82193BA5A342AC17A24263EC52B02857BB78C3B7122362C22FF1787DD9C3686DA382CD8BC5C70B2F16C8917AE820371D813D8367176DC993F72AEDD28181E57C8E0CFEEE2C81BA538655D888875E7F6831B1B5178F3C2D3FBEA81C12AB19E507F2F4ECDCD91D1CBA519816B87F16CC48D8132DB8F042057E21C635CC5FE3BB7D695CAAAE0A2D35591614E9FE2D1C47FBBFCA82EC92E05182D392011A48BBFA4788298AFA2F5ED2A4B2E933776AB1FDEB35C6EA224A69DF604A2979E826D00134AE1C13A7F2A17A0B3AC498804F0EA2D545CE3E37092D672277C4CD051B652332CFB8D1DD8ED703080032E4A7776A19828903A857C574A954A93EFEB26B0CA40A6780F331EE5AA78EA847EF4A624AA0B37D90BC47964B114E8F570BCEA25308CFC4E13F478861851E08E70F8188E147C1F17A769C868FB37A10638CE2D95F8490D2B4145C302993459474AF385794E4097D1E6B3B8BCF29480B25CDC9E8127C07F701A03452FC6953A16E864D6DF32B2D746E173EA181F2939AEE6354A940454F946E9450751864BC74DAE264FABAFD2449D7E51598BBA2D1816B3E912767C1DB51601DA9515DEAB9D34AD7E5F4072AE029613CD5975786FA16A7443F628AFD31B5570DAC44EEC0D41E9F2740502A2B2B6742472CE59E900DF6EB15A3B8D37D05EE0EB56F1558A2318D40C6B7AFDA5CE952344C8D27ED5E22FB57A5B6629D2B901BAB796ACCCE5CDA605B5B9D276F082F495D65EC4E96A962B4D373DE2799F5F4AFD748B9C2495440FFABD7C76AC29F0EF930FAC787873D0DC93158325649821D6F5BCE89C0F46EC9EB43406EF0F2F63F5A9CB90E542D0A3BBB219D2D174377D60D845677126DD80B62464ED3DEAEE110018B29D0354662E1BDB4BF07BCEB8DCCB73F631385617C9A9944B9E6BE8FFEC492847554B1DE4EF5514E5E8E968F69C98133AEF51A75E0FEF2C60A1CB5F1F8CA4855C5F6CCB4ECBB696189948973EAB694004BD998D0FFF5E0B5270C71244D57011835CA161E18928D1F03F515E5A271E46093F2D43052B9266373D06D040C3C735665941B9BA15C9ED03D0941894D521B3518C970C0ADDE281A863F1B09076C9E7B377CAA8D5A3813D7E9316B3E8DAA28268D53DB57D2A1E4A64758B548CDEEB8DABBBDB81740386412B2D3CDAAD98B0E90F98CF39860A11C3016FDCB87D8F83155EBB4623E3F57D1CE98B25FE024DA73449441416EBAE515FA4CB1139C6975BF953605FB1B5CF9FF952E674CEC3FBE66AEAFB1E5D3EF0E3AF3FF9FBBE2E9DF971E8D6AA5A79C0C3A4D8F4D18313EBE0E00DC7D5C913A879C448AE8D31CFF3901F14FA7D1C1C1517BBAADCFD2F6144B2FFFD3440620594CC5DE9B96B3F509BF13F98098187353094EC60D93A57EED58CD91701451C86A7D96ACF611A57F212E27D2EBE0335FE030E391DEDFC2CDE76AEA4643BAF0F4545BDFA7206E14D4146FD203F9E0ECEDEFFAC0363E210C4777017927A4871AC70725A3FA8F593BB9AEA1B048E07BB6BDD718B27F2D375B6690BBA1FA85FE48E8D85CA3B35ACD83B568B286D19CE7C5E0356FD18C203C91485E2B921ED491E59EA5A85796EEAB8208A75A57E0CBA190BD93721022C0303463DEB4D149044FA1E220CE7B253AD5564191E1CF998535050EEB66823EFC455AC058325F1AEBB3EF0FECEEEA8A9DF5022411E04FFA1AD7FC67692E76AB3E9474D461C815A77E0B08CA7FA5940C18BAAE2A7C93C7501138A7E071EC321B4BCC684AEC1546195261F2D07676E8E4F36AC2355D44C8412DCA71BB769AA2B459F285819CC9F19E53DCE686E24600344A32BAE91AB109F01DBDEE0A86AFBEDB1689900659388F2D57FE151AC876620A4B270DE0F9AF057A06FC9A746377F94FBAB3BEB63A96ECC1D26B055102BA7781F7EBC57F48D1221DFF5AB33F9B954F89B1EE348E4809219572CD379B833D690249F70C22D28036A82EEF543926922365643A92FCD478171AEF25B31CBB010164326E680CD247B85B1417992ADFB613BABC7B0B19707D9331BA1328C9677E4DEDD041D2259BB4A296C338130A397E003C34AABF3142DC4DAE8F862A9A9D7A5B8D39647AD00EFFCEDFA93C8831551A4C5FE1A6A32397F8ADE69557EF57C88D3A7EB14F4E43789148A31BD2E8A39F89BDC2E02DEB4DC2B337CA72AB3E00462A1ECC7D212EB18B25E88EB05897A3F29839F840909552229718B725F9FA2F23A4BB802BD9835CB4E765F422A10336BCB804EF6E5042ED3CB9F52EDEC95B0728B117736A0722AC389BEC0A0E593CA4196B857A7B89F23B219E48AD233481BAFD9691A35D929BED17CB12CCABC4BB101B8B413ACA50F2CAF472BEF9D3FABDE8DBDCC9531F8FE67FDDA1CA3E9B790CE4B0A0643A58B48862EA3D6FAE5972CFDB0EB6BDCC9EC1245BE418B2CFCDF3CCA609A132542E68805BB2987A7962E54D95F370F7AA9C869EEDF525E6DD9465A0A1B2B93C033CEE24C849FB41F0313A98FE766546E430AA5AC928741D19D39FFA404D070D401B5C26FF44DC9C7F928D51AE42E1FAC8AEDF8EB71BC96F05C5886E47F8970F071358B534D073380AA2037C42F69982E89B3B76755F7E5E1DF981370467B7E0ADDD97C69B21E37CA263F2BEE9CB46EBEAFE7C02629D31DC040187DC375C72040F5A43B35FBF0676417DFFA21F7BEEA23D0545D9C6FA337976F0E62E25647F7A377A965EF2C5B7EBB6D074308F93BABA96A9AAE838C16EE7DB31A64A4E3F6C416EB9925A3AB70757BACD418983A9D0E23FB8AD69083A98137D640B440A68594C65788968D3D3092B319DA8560E6748190D8A07B76F70D0E3F44F4557BC2B604A37059F0A544F184198C4C22108315DA78F45AA217AA485691CDC82AE5B06EB6D787EFD0A366DB7F1B2C2F404F50757E88A9ACB7C3CCD4DDE3ECF1F310121D2E304771727E9AA0A3B8D2D6F9051537396B7475808D95A1C00B233336383B5D5E65788082839CAFB7BACAEBF900000000000000000000000014243044""") + ) + }; + + // Only three are expected to pass, so I repeat to get 10. + static SigVerTestCase[] SigVerTestCases44 = new SigVerTestCase[] { + new SigVerTestCase( + TestUtils.hexDecode(""" +09B4887D97BCF6379CC59B6162C1E8BF0560BF44D61809170E6E28F70669A3E9496438E8915735ADAEB445CFDB7D89B38C048F4C3E00581514C5FD198B2D1739E883B878D56BB41264BE41D3D51565E2E9CAE33184A899F62DD57D07400E98E58687A9B22FA317EED134CA7214BFF021DD2162B183091D15F263B7298214423C6BB696D75C20D9EACD0A03E4262C4B08BE39FA2154BD6E5025FF791E885F2226E3CF48F7B5EB04FBE9ECF75B19E1D15C305E92260AB0D6AE7DBA7BBE73B6BC181CF933840CC10A00050228FA46A2636DD9A90947E9F13A93EF4C62BE374D76D1FDBBC5D8B55E729FA58665AA07B90C8CDDD61C566B0D7ED65770492EA0713E1ED46AC7AD1503C56D9052D2C94D49E4416AC92B70396F76F6FB481045681725A68CB356377FB231AB8F3EB9A4982FFF1836473BCBDAB6872D229467EFB9366261FEB148BA9B7DB9C4FE0BB88612ABB8FD61096F1819604D55DF6020464D3F092CFCA59812082218566899A56A3C633CC81F88ADB2E1414EF3850D10BF5A77ACE724D6C1F388928744B3E542AE491CD56A64213F1D3CC90B29105F43D237C83D5FB829325C83E654577776392F8536AA9DAE872407ABAAA9ACC22A6812CEA74C0BA67EAF4A410152975E9A83EE4469295317BED10551BA32E65AFC8C8E68DD55420C502D937DADD2EFA2CBFD1F739FC0AB2B2654FAE08C0C7F8EDD43CF9FF0B01D984D491852A372E9FEFDCC1BC16CDB5239AE1001155F89563051CE47996C5AEEB2190EA18F7F734042DE68E988367D89355D9D8377BAF9647978EB2E492AD021C569AE8BA69B15F1FCF7039A7E64AF10ABF3EA45B7222F9659E33373372E1DB186D2C2A0D75451C478AEF33E5949F240040C2AFC44B1D3A02A6D2F87902A280E27A20D4E57F889662700DB8A9D249957A7DB437CD480DDC05884FB23F868268EACE34EED274A927D9D84F1EA57EAB1A813B5E6AABE9ED2610BC6F72E320CDEC4F99523F93FA448DC1FBBDD259B102F5DC9955AFA0C41604D83DD1C2D2295EF4461456BAE86905C4C30D8A9FA48C90F37A19C41A2D5988F13D51344EC30A4A46219FE841137D5AA1F51E6C444168AF39890B6FA400D67F4806F5BBD444703074A7A1139C71746D7C4CEB3C911F5257E3E53EBFA5AA8F227809D44EE7DE13C027924DD60153B30AA76DD96A7C5ACC59B627919507BF14257AE7A26243C1683B28D1B14B501AD059B4D522A57991E5539CEF18CEB5C26D660B8822454C9C42A95E6F72B84F78AB99F51EC49789F9DB4C128B0318FFFC82D95CAD277F11E14F1EF871414881122A9B11BDFAE4A7ABC8E75755AB13741DFACD664293D1A326BF5ED5ABBB153EBE6996DD622F0A8CB473969A50366BD0B01C5C73A892B8E26CE08F75FF801B6DEF041E1713BE6DF0EFB51587BE5FBEA727E00D717647DD539079DE18AE7BED12B91AF8DBB1B8B32D2860BAF40AF8A0BBFE02887EB5DBE7AB1AFC41DA79B016AA16EDA281321CAA5DA644FD8658A7B702181001431560DD63CB21E5FF75C3F7250456BE08C0D5E34C3BDE2F606A2BF3417768D24B23739EA86CBEFDDA34388BC1F918F951E15E43B1385A7BCC559F9492C7213A14227E093E929F32D1EFBE7F1EE57C49C9055623EA42EC6C79D7FCE71FA747607566DDA69F69DAF68115919C6322EBB42C8C089338C9E0C53565BCBE72FBE4726687B0787071806C5A6C149C82B668AA64A7BA0CCC1CC49A1EEE9453D04336E5DC811E03892F7F46688ECEFD04F1876F7111712B595ED62DA00678F9E3786B5C1A5095BE8710DCFA4165256509E00143A6F1172FABE8BF21E5FCE7C79C1A44B4B1525A076FFB8DD9066"""), + TestUtils.hexDecode(""" +3AFD7FF8CAD3ACBDF97731261C7A1C969D5016F17D3E7F83D2441AF9014B63477B14A6413150FAD7C84439BC88662C5E931F06B9514190E13FB049C4AB74013233B98D48D9AFB6A30A67330E1FBE331B09C56D037E9701085D80F1E7F4043EFB53587ABB823624012384515249EE6130973DC9EA6F558BAE75107EFDB1D9285B"""), + TestUtils.hexDecode(""" +4A2B16CDB552F9297F8E391AD8F5ADC8CC5D2C56C46B800F9B3EE4BBD2F2E8A89D599D7B5CC2D88C80F271859BBC83043EC4E54812F5936B446C9513C855289C94B11551A0C7653E7BA74FFB6F72D4652C91D38DD1F90DFE4439BC21CA53E0CC7A7AA5B875A5B9BA42366EB8ECBA2436DAF08A91978DD093F20F1EFB6B0BCB90DA99CCA05E8F6F82B86D3C6EE24BA5D50AEA10B2307F57F89ED78DB4A74FBBF6EB332AFB08D074ACF0DE5CD7FEC12F76F3AB619C815B9EDD287EAD67F04F14797F8DCF2CDE9A8753B5AD0AFA12874197D1744092872521E868AF9E64452373FEB6FE25D5273D63C0EBD6D3B1028C1CD06AF32CECA2621310837C72788C8ADAB5A0F03817128EB7B766FA812C696CF886F00A1044CDD06BB28CB2E5780C8D8CC7E60AB699DD78668BE4FF9F4690C6FC98AAC9C02B66B9B9826A3061FD3222DA8482667960A31652EE88EB32B0469AB71CAA2519F23D1A2442D5B1316262131DCEC5F287E32FD343FEB4429E54258D690D9D20A10ABD75A536DFF8CF1D6DDF19291E2749A7D16EB90AB5093BAD38E116A86B730E65574C068C38BA9457C9D6D913EAFF57FE23BF3DD24D8CA511EFA376A5DF08467025FF51BEAD3EDE0A84EDC5321620998061E8A1A73D67B7021B810C7867FF39187B59D403BF7C7506300C7345B1FE07C11278B0ABA61DBB4F2B8C43E74FEFA55ED52C10A8C490882BBFE3E3B3CE579E8116A9B6686C1A100AA1F6591F191F772B5A5A50DD6CC155CB5A1BE5BA122E91F044420156CD63080F0A45D662E76DD57BD0F689D0B299042BFF485E8A382D865C26CD46B4A54728BD48458362D79AC3EB756FC6C518C9E2F0E7D5A303AF1159EE6DBE7DD56BA0712857A68836C3C78C6C9F7488572813C0F6A814709D2BC142FEF02527CAE7712358371C5426522CCC64300C2CD9FBE20C6562E34835205FCDD5A8982C920BB477FB881702827B4911871394C06B5FECD0C740AF7B27637BAC1A0CBCA537E4433EA847454C693897A32E4D1844195426A0C6AED67472BD2C4EEE179F3F6084A36A7689F4CB1F8E5DB2DDE54ACC0666BA98415431A4B202F402FB1F1BCCDC23BFF13148C7B8F61FBF6243B296A78EB698189DA95BDA85DBC11D15FFDC6BF46C53F6E472A871401E9A9AB7F9FB467EB4ECB1F0DA7E63EE8619CBC486EBB0F2120A7811BFB0557D13930574297C9464FC595B27569ADF5F4A8DF669C9EEA0A250F4D22C2E8C641BA3902BA80800489965F11AF1E1A85717C624E742F161550819D1F0372C5CAE8BC62B549EFE874461080D06346E1FA6F01514FBECCB06E34EE271A0F0031790BDABE0F02BBA4AEA4B7397FE3333EB8121820757281F96A5831F9E490366549D16763FF19FF773580ED5E3E1E2AA3E38F88474DE6D9BA6994F8E629160488CB4CD5B878CDA37AAEC9B56369A7E73F73B428639A05C1378448ADB7F074DC8154D92E13C6356B5F466D66477159B2A943799AD619A029F3010D037672DBB6820E51323ADA98881C6DE859DF875ABAF11DA5DDCA5A777622BDAE8FACE2E0CED3B6A77B88A8729FB7C50933DA6C52E3F4D948F9DC153B5B1299CD8621DDFBA48AF44E4B6F6106EE7779501DD5FB3C578EA4D32C5C2F036A7352703ADD135AB84460162417E50BF91E60797D59B9E18D324DA971F4FF428AEAF23AC0BA4E2E2FC7ABAA6C8984FE9E2D85B8ADA4086B3C13ABD43CFD1C711D8326B18ADC34CC14CF8957EC3959498FC2A7BE06BD1840DE170366566E50741957763C2DD27ACF8C3F1026FAEE1D2562FA1052E69AFDD42F446F0598866D5D306BF1B775042B035927372827F4386316534FA1B7EE633BA958CED8F0D241D4688E3C7918E2A75626377C342A590692BBFB827BF90514182D4090DF8D7323519A1AB6CD0227367410DD14D3786A26DDF91724FC82D06A25D5F56683953E8E0F20E3C1771DAF42E52024C116ED8A4C0A611680F5FE00ED9B148D15F12AA95B9BD5A9FD8101642B36911F310B0DE18171D6237D9BE1725DC299A1A3AAAE98540CEED26953D10CE8547F1C3E46A862BED428D1E10601BF328C727FD95343E2DB4D9ACD5D1CB4715F6004096EDA093D1B0A33B1E56F16D73ADB8732CB4A31160A4491FAA0C86E680E3D7C02CCEA8FE92F1E001016D220221DD10ED626017966C3450AD121365918C93091F14712BA477CF2E263296C778A2BAEEF5849455FA35CB617251E02A22DAF5C33E5AAA9F00E8ACDC50ECF47C521503C52F27D6B57C8F2B3D8F1222413E7FA4EC59296338098C9AB5A1D8A57884BD860041406D9655D17382949A03D50F1108D05BDB31CA08E66F2D8DE480C6793518D49A60D4762A9EDDC0249B422E84020ED539A14E2478F68BAB1F2B00E22A5CBB62979AC744E08B57D5B578C401A8D26D9ADD1505236082863672D911CF3A0966D303F8917093BF97AF90A7E1F9D59B09206B9CAC35110FA38D5890ED2116835CE37384F5630F1C428E213605872ECF911B014B91C2C600E8A40729D07BF918790742C9279F3114F68CDF6594CDA3CA6694223A82F66C2B4BDF3E51C6FFDC55E0FF51EFD6C934362BE7D6FABC11B8B0DADDD52108FA5FB5CA758A64377D386D45CE70605B460E8157037B5B1B2E0AEDD12A633115D6C43BC6C7C836FFF33E7D033F2E5800527164C0C4781C37DF50B66BBA5C819473A1C5302083A16F01437279D2F2DF14C878269A2F3FA40C1C761ED61501AC9EF141029038C819954089B738098708174393FEAEA7B02AE5CEF67B3C8CE6A970675CA1B8C856DCF5972508C7C6B25EE4D12D8212B98940B488EC402AC7AE3C70DF938D1288CDA7A319E085BC73A469B2D2A3303B11A683100AF6DB86937BA1182903616E3F0347BD68591B47BA65156B93F260DE59B3AEB289E2A73A3BFF38C2F3ADEDA29C7E90283AC7B86D036B47D5BA1A03EC783D250BACAE5847E41F829CB33DE08DF8F7D69C9AA4EDE8D7AB968407EED31A056BA0EF8816E127AA90065A679E1CA9550DEEF25AC5B7A34F70DCF2B116CF351F3BADA99F836C730DCC1AE03F496CF3F0387A0C2C702E2C13BDD9CF45A1CD53AB58731188B18EA8BE48D510C5812E90BCECBC6E198E708B1C08C8F864B124BB4CC0BDBBDF2C2F4E388FC19660D69CC2C0EBF91008C8243DB42DDAF57C024251C4231DF53790CE575613EE8E1C7A33C1561F3504DEAAED1E8408500623ECA5AE5A2845411749930D8E42078C032349957FC39A1DA0EAF9E87C31FFBF6AC0C1811EB28A41B1D86BD7D49AD1C468A49594956525A20A31700F122F4C4BB2252A2F3D5C5D6873838C909597BBCAD8E1333D5D617C87C8EE0F1B22383B424B4C5C627298A3BECC1B32475C9DB6B9BDC6D6DCF50000000000000000000000000000000000000000000000000000000011192834""") + ), + new SigVerTestCase( + TestUtils.hexDecode(""" +09B4887D97BCF6379CC59B6162C1E8BF0560BF44D61809170E6E28F70669A3E9496438E8915735ADAEB445CFDB7D89B38C048F4C3E00581514C5FD198B2D1739E883B878D56BB41264BE41D3D51565E2E9CAE33184A899F62DD57D07400E98E58687A9B22FA317EED134CA7214BFF021DD2162B183091D15F263B7298214423C6BB696D75C20D9EACD0A03E4262C4B08BE39FA2154BD6E5025FF791E885F2226E3CF48F7B5EB04FBE9ECF75B19E1D15C305E92260AB0D6AE7DBA7BBE73B6BC181CF933840CC10A00050228FA46A2636DD9A90947E9F13A93EF4C62BE374D76D1FDBBC5D8B55E729FA58665AA07B90C8CDDD61C566B0D7ED65770492EA0713E1ED46AC7AD1503C56D9052D2C94D49E4416AC92B70396F76F6FB481045681725A68CB356377FB231AB8F3EB9A4982FFF1836473BCBDAB6872D229467EFB9366261FEB148BA9B7DB9C4FE0BB88612ABB8FD61096F1819604D55DF6020464D3F092CFCA59812082218566899A56A3C633CC81F88ADB2E1414EF3850D10BF5A77ACE724D6C1F388928744B3E542AE491CD56A64213F1D3CC90B29105F43D237C83D5FB829325C83E654577776392F8536AA9DAE872407ABAAA9ACC22A6812CEA74C0BA67EAF4A410152975E9A83EE4469295317BED10551BA32E65AFC8C8E68DD55420C502D937DADD2EFA2CBFD1F739FC0AB2B2654FAE08C0C7F8EDD43CF9FF0B01D984D491852A372E9FEFDCC1BC16CDB5239AE1001155F89563051CE47996C5AEEB2190EA18F7F734042DE68E988367D89355D9D8377BAF9647978EB2E492AD021C569AE8BA69B15F1FCF7039A7E64AF10ABF3EA45B7222F9659E33373372E1DB186D2C2A0D75451C478AEF33E5949F240040C2AFC44B1D3A02A6D2F87902A280E27A20D4E57F889662700DB8A9D249957A7DB437CD480DDC05884FB23F868268EACE34EED274A927D9D84F1EA57EAB1A813B5E6AABE9ED2610BC6F72E320CDEC4F99523F93FA448DC1FBBDD259B102F5DC9955AFA0C41604D83DD1C2D2295EF4461456BAE86905C4C30D8A9FA48C90F37A19C41A2D5988F13D51344EC30A4A46219FE841137D5AA1F51E6C444168AF39890B6FA400D67F4806F5BBD444703074A7A1139C71746D7C4CEB3C911F5257E3E53EBFA5AA8F227809D44EE7DE13C027924DD60153B30AA76DD96A7C5ACC59B627919507BF14257AE7A26243C1683B28D1B14B501AD059B4D522A57991E5539CEF18CEB5C26D660B8822454C9C42A95E6F72B84F78AB99F51EC49789F9DB4C128B0318FFFC82D95CAD277F11E14F1EF871414881122A9B11BDFAE4A7ABC8E75755AB13741DFACD664293D1A326BF5ED5ABBB153EBE6996DD622F0A8CB473969A50366BD0B01C5C73A892B8E26CE08F75FF801B6DEF041E1713BE6DF0EFB51587BE5FBEA727E00D717647DD539079DE18AE7BED12B91AF8DBB1B8B32D2860BAF40AF8A0BBFE02887EB5DBE7AB1AFC41DA79B016AA16EDA281321CAA5DA644FD8658A7B702181001431560DD63CB21E5FF75C3F7250456BE08C0D5E34C3BDE2F606A2BF3417768D24B23739EA86CBEFDDA34388BC1F918F951E15E43B1385A7BCC559F9492C7213A14227E093E929F32D1EFBE7F1EE57C49C9055623EA42EC6C79D7FCE71FA747607566DDA69F69DAF68115919C6322EBB42C8C089338C9E0C53565BCBE72FBE4726687B0787071806C5A6C149C82B668AA64A7BA0CCC1CC49A1EEE9453D04336E5DC811E03892F7F46688ECEFD04F1876F7111712B595ED62DA00678F9E3786B5C1A5095BE8710DCFA4165256509E00143A6F1172FABE8BF21E5FCE7C79C1A44B4B1525A076FFB8DD9066"""), + TestUtils.hexDecode(""" +0B36AE74905A488C25C9BF47B4144E12E75A8F54555E1943E3CF738BBF0B9C4ACC270A71804B0D8FEEEB0451AB504027C853125BEC7E7216A82EC09EEA3778291A6B97F53B1766FAB67CD3C875C171A36D5DC23835B7B5641C4689E646C40CC2B379131DF4AE848B8C4713A1E38F5C31140662F6F92BA22E888CA3C0A2F242C9"""), + TestUtils.hexDecode(""" +279860C94C551A0A0788099AB39F1F25BEE8CC4622D20DA037005B8D6B5B7371B11BADFC236C9B0028868DFE74A9AE59642CDFB8D38BA5A79CD52278E554C25B07A07C77C1420F8F0CC08A035C99BC4F0C303F20CA1BFC0E46E9FC6F37FF1BA5E5653656B7FB488C3B600E0BEF9F4A553A3D2FE5F0D2B76EBC90C5A2A99B789B55316ABBBCEED0EC70325CE2E89890FB2A19E30E79C4E8E619101FC2428D9579737DCB3FD76947FA7BF257FAF2FCC360051F55912F051DB24C51619439369F13F34D669DCD5638D3565101A7A4D379105EA6D83163D046DE3A6F9D9036CCC347DDF8B363E873D959C33D1B56775914ABD50EB6FD2D096E669F11C288781681D693A3A52188E80D0D33784D2F5FA1954D72C35D8929A2223577F8119CF241317D0E95C615641F40EEA3368BDA7619EEE82BC4B78717CE9E9D7036E0DD7DFFFD56CCC29D4F0EF46DFD4D07E4838BB513B2EEFA72BBFA0E9FEEBD1D2B96D9B8DBCAB4241FF7AB080ADBE1099AD3CEDC4597B23171E3ACA2027CD1B6E519EF29FDC21CD54EEAC264F4B2CDFBBB8104FE81C3C65691B0C309C31B877BF0B0DB37C6F44B9A11DDAFFCC40CEB1E78D2F86C2A0F902699EC1680E46F94DECDE4EC119F7742D3D47A383391B8DFD614E375B8C32271CDC49F054D2C26DEE4BC60C3A474888642DCD4BA1AE30CC8CAAE80AA9FCCA55528AA33FD4F732677E7D1B9E320247B299D6AD384D23D4E478AC2450F676B9BA27E5D4CB01F0EA50A62A2136DC4C2E1219C0E749444B2943890F36AF1EC2C273C42F22E0AEAEBD31FA8E6C9D1B8305A0AA8C2BA6601CCF28F46904231E648AFF4D4A72849A8E1EEDCC774FFB1479897C1804BB035671E8F90D462E3D2665B2A75DBAAD3BDB00C13E642A23E84ED48CE3E9B1632ABD0B7D579E7D18F508F33DABD97083EABD3CDCD1C70523A969B9C25E4011742EFBA6B3A09CC6CE627CF95BD51856DDC8C295DBBE180C86E0097FCE5741B3F0F6662B486D1B17987C3C47ECB101DC165372CA696FC477860F3DB7A68E3102B5A91BAC2A256467873C233ED212C7537470BFE88B41C3C239B5E38230E20CE2C41EF2C355884CF7F46CCF0CD688DEBEE8554D118F9088B4F807F19FE17732AD3C145E634CFCDCFF32A54F1C1D7A7879E6C022281130FD5A8188C560658F1AB6AD3EB3FB622D52A1939FE8668F2116A05F6EF6E1AAD846A4279FC3C699373A2FE17A3E9823FAA11F088846B36F5DB4BB9930101D5025350462D2F4866BB3010D9474B5630BDB57E71AE4277247DFF67F37E3CD9BD1307035249EB1EC316D25F913AC4B0BBB21D60CE2F4ED5F08D48D0C707795C177E7044E55D438AC12C2DB918C7087388650AB4AB19095C0A480232B1BA0C794991E89A650E070A5B562D9965C467D6CE834167EB6189A41B58E91685A034C70CD7723840A5561F0F751AA8F382A3772B07864547C1862E2433811633C97F58F85B9B14D3875ADCE2494D8BFA2E0773BF4637EDBD96AF9BAE43497CE2D63D59640C7723761C8AFB534189509A44794BB98A6D8E4AA3C5C3C136AA1C31CF20EFF2F5968FE4E71415DF760A52EC88BA438EF6110CD7F3B7FBE53B13999DD3EC4FCB5CFB4F9744578CEB60F800FFF2BABF330DC20DA5C128282C924244D9E5A18C3AC59DCD0D953156E2020751B708C0B025768963EDCF0DBAD16DD68A792A5E30981F17A4C355AE3E8036F9E289EEE35D9EF136AE402B4AFC7DD04190A8F0C8F66A66B701F995F7869855F59B47634B4A1F9E715E5059371B74D65D9501CA814F255D6C4D861B5C5A903B7ED44BF55CC18DB3CEA98D7CE951CD241A661E823F0A0EA92FA33A23294338E6F96D273DAF63BE9D5D5BE92FFEAA6078A9E8C5CADCC8AE79A1D5FC384519DF06A5832CE1DED5C7A6E937E86B854ECB1043169041A4BAD0FFEB13B0017B5BE16091AAC3F5DEB017B01EA00CA323AB44CCB193063406C970257DE61FAF1EE51105A22A4703562DFF1230AE241D67803FC6D997A1B016A73CE4346DF97F8ACE220CCFC3585B8307CD4B3AF74F6E0CF49A33CD5F5E53D04A197B4AA55ECCF645447B6033FE38DFE155AA979B2D4586D5249450E01532334C8F342BF81AF35980639C7E0AD431F3D3277F21F33A0622568E08D75A97CF2560826EF3DDB8A1E421217EE28B82D3BBB6FC499AE696567EF24681D482B051CA65DF9EB7F59965F03A68976F8A2542A58837CD3DA9EF5F4F06F94313B63B6B25EA67B1ACB4A0015F026D6A683BF533C3F730CD4D8A0CEF6D63100B4D9A1ADA15305A441A71B829AB2D33D3D209B598E05F19916569FFD262EE5D4160B8DF16E3FE63AA48029FD4F080D07602DEDC1B383F286202C287844D4063584087F29E36D5C19E54CF37DD504DB01452340D937D438C0E63EC35F948A4681D74D54CD6AF91262B075F55999137B5B94A2FE4E2668FBE44F68A892A91F8B5AEDB265BC0464F62C768BF346BC91AD9F9733E3DB9B846E2DBB0FEB3D00D817DB052C69474D77AAF7DCABF21E137F4C4607CFACFBCC7AF1F27BAF377B261358C7CD69394C33C89ED66F2579F29815B1FD957553FBF4F9FA4A5C85C223BDE78BA0722375BB8E7B02FFAD17DD7410F384A88DC0A77CA6345AE26A87FBB4753FCFB7EEA6ACE2061694746C8BE7E645D8848C5742ADD8815DD48AF19021591C7D7DDBF2DED046E7DF36F092127AC47432555F2BE60060433B561E7CEE0DDD1C5650B92898C8D6E01531CD373271A24A489D95FF24F4B4BB06AA39F56375F4B5B5BEEA5F4E5DD3B918136FA98AA2580A691334F8082DBEBF34943B27024C69C897D31897C2690C3D72C22133AB467E0626A4618FAF403A63DF25E2DA82D1191787D6487D87A6985F619CD6F1B7937F06E448501498DF0A1005D408D1CBD943ECC4EE03D038C5ED1FE462540DC937F0E4301502228D3B3755E3D31EDAB96D03AD1AB3E0A631AE80F86C3AE9321F35AF90F8D4D9B2B431BD529E2D29A29FE066269FB90248265088FBBBDE99B24A0F38282847D8FF4022AE6B611743A5B5472A4BF054B95F2CB09EA5E088E8AB172B7C3B53BB32986FEC298F41E2FA9D53D6F85254ED489A3F1FF01C07D33DEB98CA4EE704F27FD68F47B2E995E6706FC8D02454D7F2A73E50CD2AB15F973C9297B3B4989393588BB6C6CAEFF67BF2E241A158EA96C1A2FAF13FFBA4358A38928C2FFD0A7E32137E83256941DE749DFED36C63F2D07C557C7AFDBA351329899CE6D96DFD3442725BB1F24EC43EA41B4DE9E4E39D17A6F26384168DB92BF9516D7DD8101B970B83F2A2F323B418385C3D20410122D414A586970737BB0B1BAC6DA0B183244494F7375799AB0BDC5D1E2ECF3F4010C0E0F3537434E5366C6CCD7F1F20000000000000000000000000000000000000000000009192B3A""") + ), + new SigVerTestCase( + TestUtils.hexDecode(""" +09B4887D97BCF6379CC59B6162C1E8BF0560BF44D61809170E6E28F70669A3E9496438E8915735ADAEB445CFDB7D89B38C048F4C3E00581514C5FD198B2D1739E883B878D56BB41264BE41D3D51565E2E9CAE33184A899F62DD57D07400E98E58687A9B22FA317EED134CA7214BFF021DD2162B183091D15F263B7298214423C6BB696D75C20D9EACD0A03E4262C4B08BE39FA2154BD6E5025FF791E885F2226E3CF48F7B5EB04FBE9ECF75B19E1D15C305E92260AB0D6AE7DBA7BBE73B6BC181CF933840CC10A00050228FA46A2636DD9A90947E9F13A93EF4C62BE374D76D1FDBBC5D8B55E729FA58665AA07B90C8CDDD61C566B0D7ED65770492EA0713E1ED46AC7AD1503C56D9052D2C94D49E4416AC92B70396F76F6FB481045681725A68CB356377FB231AB8F3EB9A4982FFF1836473BCBDAB6872D229467EFB9366261FEB148BA9B7DB9C4FE0BB88612ABB8FD61096F1819604D55DF6020464D3F092CFCA59812082218566899A56A3C633CC81F88ADB2E1414EF3850D10BF5A77ACE724D6C1F388928744B3E542AE491CD56A64213F1D3CC90B29105F43D237C83D5FB829325C83E654577776392F8536AA9DAE872407ABAAA9ACC22A6812CEA74C0BA67EAF4A410152975E9A83EE4469295317BED10551BA32E65AFC8C8E68DD55420C502D937DADD2EFA2CBFD1F739FC0AB2B2654FAE08C0C7F8EDD43CF9FF0B01D984D491852A372E9FEFDCC1BC16CDB5239AE1001155F89563051CE47996C5AEEB2190EA18F7F734042DE68E988367D89355D9D8377BAF9647978EB2E492AD021C569AE8BA69B15F1FCF7039A7E64AF10ABF3EA45B7222F9659E33373372E1DB186D2C2A0D75451C478AEF33E5949F240040C2AFC44B1D3A02A6D2F87902A280E27A20D4E57F889662700DB8A9D249957A7DB437CD480DDC05884FB23F868268EACE34EED274A927D9D84F1EA57EAB1A813B5E6AABE9ED2610BC6F72E320CDEC4F99523F93FA448DC1FBBDD259B102F5DC9955AFA0C41604D83DD1C2D2295EF4461456BAE86905C4C30D8A9FA48C90F37A19C41A2D5988F13D51344EC30A4A46219FE841137D5AA1F51E6C444168AF39890B6FA400D67F4806F5BBD444703074A7A1139C71746D7C4CEB3C911F5257E3E53EBFA5AA8F227809D44EE7DE13C027924DD60153B30AA76DD96A7C5ACC59B627919507BF14257AE7A26243C1683B28D1B14B501AD059B4D522A57991E5539CEF18CEB5C26D660B8822454C9C42A95E6F72B84F78AB99F51EC49789F9DB4C128B0318FFFC82D95CAD277F11E14F1EF871414881122A9B11BDFAE4A7ABC8E75755AB13741DFACD664293D1A326BF5ED5ABBB153EBE6996DD622F0A8CB473969A50366BD0B01C5C73A892B8E26CE08F75FF801B6DEF041E1713BE6DF0EFB51587BE5FBEA727E00D717647DD539079DE18AE7BED12B91AF8DBB1B8B32D2860BAF40AF8A0BBFE02887EB5DBE7AB1AFC41DA79B016AA16EDA281321CAA5DA644FD8658A7B702181001431560DD63CB21E5FF75C3F7250456BE08C0D5E34C3BDE2F606A2BF3417768D24B23739EA86CBEFDDA34388BC1F918F951E15E43B1385A7BCC559F9492C7213A14227E093E929F32D1EFBE7F1EE57C49C9055623EA42EC6C79D7FCE71FA747607566DDA69F69DAF68115919C6322EBB42C8C089338C9E0C53565BCBE72FBE4726687B0787071806C5A6C149C82B668AA64A7BA0CCC1CC49A1EEE9453D04336E5DC811E03892F7F46688ECEFD04F1876F7111712B595ED62DA00678F9E3786B5C1A5095BE8710DCFA4165256509E00143A6F1172FABE8BF21E5FCE7C79C1A44B4B1525A076FFB8DD9066"""), + TestUtils.hexDecode(""" +3DE9C8CDA014784F23C8CB6D41294D39D27C9A5DF8F8D939B6F2D821824E584BC0BA516037E100C68C02480DAD436E12DD095DFFE293DF8E4AFFAFA0DA05516BD579B1B03B2A43307C7DF0D88624386593B226D4BA2EC5716A8C8B7A117C437DDACE31E6A902C403DD172DA7054A1BD679C01C1D822C3A075F5AB2002D2147A9"""), + TestUtils.hexDecode(""" +4A3C0683EE52A2E3703716E44D321208374CB0ECA74F9E6A624A1947B6788AD7F6AE68F320A580D35697E48B276779D4F5D2C8AF78177F12C9CD117875E0CB039293F140C24D80C895ECD7AE9C7C8AB72395A2736D7DAD6FE3EA57F21F9681806D821C91EB790BBD7F4AECA96100CA225A45CABE9372F48732B1A0745BBADAEA0594CD87875C05B703FDACEB441736811E2B6AAED172B6EDB8FDD087EF22D30CEEAA7F9E9A0DACD13D60749C0A04C376B804872A6C5056C37B9B64B4060CDBAC15B1C00CF9AC77DB99C506FDAE0AE16C198DE0BEFC4CABD6B38BC7E268112844B8ED5525A5624A36701A2F6AC6ACD2E4E40F01697E518B5F3107563865AE8537D04FAA57E1B71ECB1E2C2E36AEB3D8AA4674A04306E5179FB7A45CC6D57692BD787137DA3E6C5395D3F6A2EAAD0AF8F586912CC6E6DCD5DF34A6E4B0A574A350D760C646FB77C76377B6F88FACCD1B7187CC10E363FABDAB9D494E749E0EABE63D45901A54E06FCEA5A46487123C3C1107BBFFA87B7D7D92BC6793A7FA3CD18CA2E27DEE2213983D08863126FD79FADE804B48830AF687B02B4931357AC4247617AC13064804D3F780EE18A452613E9C1B188C0655FBA86F6ABD38E5F7D17267C747976C36EB37267759A9EDBD6624992F704684484FC562C8918788732DAEF29EC1386E73A2E2FD02BF7811E1D7A20822C8985AAF86B8E253AA7F0806BD6FA376557910497205393841BAFA34598B7E29EA9E67351CDA2966D0873BA914255649CDC89B2B64A751EB627F0C2D0963D391036C7297518A44C6783750C3CD6DF832AACA28FD5643F94A38571BCE04C3E29E2973CD6C6600C8102C1EA725DED21C50C90DCAEFF9D73756FF6BE91E8E766598EEBFC394F83C6D36FAD25B2DFC31D720E7E42763F10AD75D8C93775609CD7B0285F0247B52B797D11489CB4EC333C27E195ED8F7071E6C3E5E9220CAB46983B4013705F5934C0F1D61E70EFF9CD5FD293668BD3D0546A884D7AAED9EF7D2CA8E84A6BBDAF7FD8181FCC9D65FD74A4AA26DFBC42EC10484D7DC073E123F95CA705BF6CC3A803C186985721406994714949BD47161AC12AF72C0A358702CBA5A6AFF793D0DFDC7009861414CC3689E907D65BFE48751AE296D798912D49F4F849E43141E1BB050F9D17E5A0C4B7530E83463469F1D9443533AE36C57C6D80B915A3B3C8D9A3E43F5E6AD0187E8F828FFF7240EE9D4304255DA0528D0EF59FF1993731735245467B1BC5E6DFDE8895714F34562229E79AF8AB5E6269BD1C9DAC265D34C6CFECB2A4D02ACD092822E1EC0335EC1BA0ED22DD5D832B6349BCAE8194BC550537B814492DFB96EE870B26B3B535F2C79E24705E662C11CAF10E0E081573BD8B12A393F9AEE5A9426C22F2F14C7EEDFADD47ACFC4AA01E0282C7AC03B667302A98CBD84902DC6BF66FBEDA65B84115D652EB8C479808B3542567F2ECCDCE06692FF06C653714E65E202AE7363C4C32A71A636EDA410AA0B8F4614E3927BF5821AD2E30B5ACF30201F35028994A8568D68E8CA28C1E2C3D482C6609AC36AD5583485034931DAAC6183776935E42C4F02ADF19730260AE56BB8C2839B1DCAE85E6F81747AF80A55A8D20132D77BACCFA3963896E9C431714D3BFB78DC74CDBC743151615C325AC3BF0DCBDBDB8CBEDE8E71A002C20B89A0E7D732AD8934262C5F29D4B600F4BC690136CBEC1E93FC8F07F6C5CB789D06D89523DD1BD6D98A3015C4950B9AAA45427A3A923B15D2DF53F030DD8E07F9E2461C5676A09D6A7928B2334C2B621B28B82A45BE731FC8ECBB030C3F85B03B7877EEFCB1B7E5736698E8723B55385337C6DF877FC8842343100030E9876CB98FB12E1749D1D6A77DDC94BCFB67B0C61C589C805A79F2B69AF01B2456B5491D776ADBD9C60466F7D099DDC395E6E297677DB98C9DE5D2BC6C5D7772A2AE30916C21825EA848AECA3447766327552527687C702A8344D008C39CA26A9933320A93764F4D0EECA250208321A4E465251135D7FEE9C69FBBD6B8162A4321D3133A6F23FD8A459B05E9C9003B4AE86B538EF5E1B769E14ED84AB3C963B3F8C64A9FF5979277ACF32EC2A65E65327001836AD53D66D420E2F39B42CF1CFC0BBB95EEAAC57D64262FFEBF7D57D7EB86430C3EB5E25EB183DA1196D8BA5E16B106D874EBBEF5E90256CFEE4DADC26A65EF8FF340CAA19B99CC298456C558E54F8B3155E3BF457FE61B1871C8605347BA2B399030ED93A26AAB17711795873DE7C62C1ECECD61AA2F54DFFF5FF6CE074937F51AED1811CADD4BFCD9D9C9B9937E4D43F1054932BB81427FEE0AC894E0F9CA81F299A9DAFADE2F3735C756E89A4D3136AA5533F83AD4465FE212EC6A6C04C1A4006521145B762B2744D01331F92408A5620EDF3F33F004790F2AE2CBE6780D1F295BFCC0749BEA94900782F33F9807F7058439D17D09FCA9F78A50FA8231D6B90B6D3E2911643F08B68A7FEFA9CFA0F200EE15F36C5A38163DD7DBADBC496673E0DA0470E644341DC03969E9B88EA9BCE9D041F34CBD852798B388773FE2EA344B017B82EDB603B6364EAB0CCABF1A496C195F7073105EEE7E444A31E5B57DA2BA0C8627B15328D713ECFE8596FCD269B9549EE31D89890D05049152EE7B5466296963E52BC368A2B874B2991123B14302234B6493C3E927B2B96C2A39A78A7D0331D19CE9291037F91877E76739ADE0D0D4FC8F20A5749907D4012DC7F54C904180B5C98C1B3ECB0363E22582E9604BB6F1D837D797E65BB0C798A810A41D4DC26923B56B79B8B26746D691865210C15F4B222D8F158A65B3FBAED2E81F3EFBA36CEE2BD7082ED8FD0CAC3948CC52CC9567D33DB07BA6A715CD4E66AA376C477F105A471E6F9A2620013C5FDAB9F064232942108D42C0117F40505AA77CBD6597AA47EDC1025CF532C07C432311B40A32927A3FD2794B8D708DF6E93844040F0A26D8B12A32020D3C49EF16F68CFBD5009D82DE4147D6341CDD3868B478C93276752FD3A175E23E4DF15329C671E0462E502B894C53778BE77BD94EFF9C1F3FA2B40A94A1E219056C2CA86A217C35223BF0265C5425953761943D9A68292D69372248A219E410D1FEA3621612907E102438C6D7B92D0868C03B8E5FE9D6AED83C4B8221DA6078451343ACC86EC5B3776F986031A0963BA78DC2045D04F599780DFB1E8277C96AB84EE3A27D145F8EE7A86C04BDC4A6AFA0A8CA9F58C55C60E32101B517EE1B154F60290F635FD13E4FAC422EA874AC104202899E020832C15FCD829ABA48CB43AE8D151B2E3654ADB1B6DDDEF1FC27393B647274A6A8DC10181C24404C56606E8A8D8FA7ADB3E1F104080F1618263342646C85BEC5C6E3E700000000000000000000000000000000000000000000000000000C152636""") + ), + new SigVerTestCase( + TestUtils.hexDecode(""" +09B4887D97BCF6379CC59B6162C1E8BF0560BF44D61809170E6E28F70669A3E9496438E8915735ADAEB445CFDB7D89B38C048F4C3E00581514C5FD198B2D1739E883B878D56BB41264BE41D3D51565E2E9CAE33184A899F62DD57D07400E98E58687A9B22FA317EED134CA7214BFF021DD2162B183091D15F263B7298214423C6BB696D75C20D9EACD0A03E4262C4B08BE39FA2154BD6E5025FF791E885F2226E3CF48F7B5EB04FBE9ECF75B19E1D15C305E92260AB0D6AE7DBA7BBE73B6BC181CF933840CC10A00050228FA46A2636DD9A90947E9F13A93EF4C62BE374D76D1FDBBC5D8B55E729FA58665AA07B90C8CDDD61C566B0D7ED65770492EA0713E1ED46AC7AD1503C56D9052D2C94D49E4416AC92B70396F76F6FB481045681725A68CB356377FB231AB8F3EB9A4982FFF1836473BCBDAB6872D229467EFB9366261FEB148BA9B7DB9C4FE0BB88612ABB8FD61096F1819604D55DF6020464D3F092CFCA59812082218566899A56A3C633CC81F88ADB2E1414EF3850D10BF5A77ACE724D6C1F388928744B3E542AE491CD56A64213F1D3CC90B29105F43D237C83D5FB829325C83E654577776392F8536AA9DAE872407ABAAA9ACC22A6812CEA74C0BA67EAF4A410152975E9A83EE4469295317BED10551BA32E65AFC8C8E68DD55420C502D937DADD2EFA2CBFD1F739FC0AB2B2654FAE08C0C7F8EDD43CF9FF0B01D984D491852A372E9FEFDCC1BC16CDB5239AE1001155F89563051CE47996C5AEEB2190EA18F7F734042DE68E988367D89355D9D8377BAF9647978EB2E492AD021C569AE8BA69B15F1FCF7039A7E64AF10ABF3EA45B7222F9659E33373372E1DB186D2C2A0D75451C478AEF33E5949F240040C2AFC44B1D3A02A6D2F87902A280E27A20D4E57F889662700DB8A9D249957A7DB437CD480DDC05884FB23F868268EACE34EED274A927D9D84F1EA57EAB1A813B5E6AABE9ED2610BC6F72E320CDEC4F99523F93FA448DC1FBBDD259B102F5DC9955AFA0C41604D83DD1C2D2295EF4461456BAE86905C4C30D8A9FA48C90F37A19C41A2D5988F13D51344EC30A4A46219FE841137D5AA1F51E6C444168AF39890B6FA400D67F4806F5BBD444703074A7A1139C71746D7C4CEB3C911F5257E3E53EBFA5AA8F227809D44EE7DE13C027924DD60153B30AA76DD96A7C5ACC59B627919507BF14257AE7A26243C1683B28D1B14B501AD059B4D522A57991E5539CEF18CEB5C26D660B8822454C9C42A95E6F72B84F78AB99F51EC49789F9DB4C128B0318FFFC82D95CAD277F11E14F1EF871414881122A9B11BDFAE4A7ABC8E75755AB13741DFACD664293D1A326BF5ED5ABBB153EBE6996DD622F0A8CB473969A50366BD0B01C5C73A892B8E26CE08F75FF801B6DEF041E1713BE6DF0EFB51587BE5FBEA727E00D717647DD539079DE18AE7BED12B91AF8DBB1B8B32D2860BAF40AF8A0BBFE02887EB5DBE7AB1AFC41DA79B016AA16EDA281321CAA5DA644FD8658A7B702181001431560DD63CB21E5FF75C3F7250456BE08C0D5E34C3BDE2F606A2BF3417768D24B23739EA86CBEFDDA34388BC1F918F951E15E43B1385A7BCC559F9492C7213A14227E093E929F32D1EFBE7F1EE57C49C9055623EA42EC6C79D7FCE71FA747607566DDA69F69DAF68115919C6322EBB42C8C089338C9E0C53565BCBE72FBE4726687B0787071806C5A6C149C82B668AA64A7BA0CCC1CC49A1EEE9453D04336E5DC811E03892F7F46688ECEFD04F1876F7111712B595ED62DA00678F9E3786B5C1A5095BE8710DCFA4165256509E00143A6F1172FABE8BF21E5FCE7C79C1A44B4B1525A076FFB8DD9066"""), + TestUtils.hexDecode(""" +3AFD7FF8CAD3ACBDF97731261C7A1C969D5016F17D3E7F83D2441AF9014B63477B14A6413150FAD7C84439BC88662C5E931F06B9514190E13FB049C4AB74013233B98D48D9AFB6A30A67330E1FBE331B09C56D037E9701085D80F1E7F4043EFB53587ABB823624012384515249EE6130973DC9EA6F558BAE75107EFDB1D9285B"""), + TestUtils.hexDecode(""" +4A2B16CDB552F9297F8E391AD8F5ADC8CC5D2C56C46B800F9B3EE4BBD2F2E8A89D599D7B5CC2D88C80F271859BBC83043EC4E54812F5936B446C9513C855289C94B11551A0C7653E7BA74FFB6F72D4652C91D38DD1F90DFE4439BC21CA53E0CC7A7AA5B875A5B9BA42366EB8ECBA2436DAF08A91978DD093F20F1EFB6B0BCB90DA99CCA05E8F6F82B86D3C6EE24BA5D50AEA10B2307F57F89ED78DB4A74FBBF6EB332AFB08D074ACF0DE5CD7FEC12F76F3AB619C815B9EDD287EAD67F04F14797F8DCF2CDE9A8753B5AD0AFA12874197D1744092872521E868AF9E64452373FEB6FE25D5273D63C0EBD6D3B1028C1CD06AF32CECA2621310837C72788C8ADAB5A0F03817128EB7B766FA812C696CF886F00A1044CDD06BB28CB2E5780C8D8CC7E60AB699DD78668BE4FF9F4690C6FC98AAC9C02B66B9B9826A3061FD3222DA8482667960A31652EE88EB32B0469AB71CAA2519F23D1A2442D5B1316262131DCEC5F287E32FD343FEB4429E54258D690D9D20A10ABD75A536DFF8CF1D6DDF19291E2749A7D16EB90AB5093BAD38E116A86B730E65574C068C38BA9457C9D6D913EAFF57FE23BF3DD24D8CA511EFA376A5DF08467025FF51BEAD3EDE0A84EDC5321620998061E8A1A73D67B7021B810C7867FF39187B59D403BF7C7506300C7345B1FE07C11278B0ABA61DBB4F2B8C43E74FEFA55ED52C10A8C490882BBFE3E3B3CE579E8116A9B6686C1A100AA1F6591F191F772B5A5A50DD6CC155CB5A1BE5BA122E91F044420156CD63080F0A45D662E76DD57BD0F689D0B299042BFF485E8A382D865C26CD46B4A54728BD48458362D79AC3EB756FC6C518C9E2F0E7D5A303AF1159EE6DBE7DD56BA0712857A68836C3C78C6C9F7488572813C0F6A814709D2BC142FEF02527CAE7712358371C5426522CCC64300C2CD9FBE20C6562E34835205FCDD5A8982C920BB477FB881702827B4911871394C06B5FECD0C740AF7B27637BAC1A0CBCA537E4433EA847454C693897A32E4D1844195426A0C6AED67472BD2C4EEE179F3F6084A36A7689F4CB1F8E5DB2DDE54ACC0666BA98415431A4B202F402FB1F1BCCDC23BFF13148C7B8F61FBF6243B296A78EB698189DA95BDA85DBC11D15FFDC6BF46C53F6E472A871401E9A9AB7F9FB467EB4ECB1F0DA7E63EE8619CBC486EBB0F2120A7811BFB0557D13930574297C9464FC595B27569ADF5F4A8DF669C9EEA0A250F4D22C2E8C641BA3902BA80800489965F11AF1E1A85717C624E742F161550819D1F0372C5CAE8BC62B549EFE874461080D06346E1FA6F01514FBECCB06E34EE271A0F0031790BDABE0F02BBA4AEA4B7397FE3333EB8121820757281F96A5831F9E490366549D16763FF19FF773580ED5E3E1E2AA3E38F88474DE6D9BA6994F8E629160488CB4CD5B878CDA37AAEC9B56369A7E73F73B428639A05C1378448ADB7F074DC8154D92E13C6356B5F466D66477159B2A943799AD619A029F3010D037672DBB6820E51323ADA98881C6DE859DF875ABAF11DA5DDCA5A777622BDAE8FACE2E0CED3B6A77B88A8729FB7C50933DA6C52E3F4D948F9DC153B5B1299CD8621DDFBA48AF44E4B6F6106EE7779501DD5FB3C578EA4D32C5C2F036A7352703ADD135AB84460162417E50BF91E60797D59B9E18D324DA971F4FF428AEAF23AC0BA4E2E2FC7ABAA6C8984FE9E2D85B8ADA4086B3C13ABD43CFD1C711D8326B18ADC34CC14CF8957EC3959498FC2A7BE06BD1840DE170366566E50741957763C2DD27ACF8C3F1026FAEE1D2562FA1052E69AFDD42F446F0598866D5D306BF1B775042B035927372827F4386316534FA1B7EE633BA958CED8F0D241D4688E3C7918E2A75626377C342A590692BBFB827BF90514182D4090DF8D7323519A1AB6CD0227367410DD14D3786A26DDF91724FC82D06A25D5F56683953E8E0F20E3C1771DAF42E52024C116ED8A4C0A611680F5FE00ED9B148D15F12AA95B9BD5A9FD8101642B36911F310B0DE18171D6237D9BE1725DC299A1A3AAAE98540CEED26953D10CE8547F1C3E46A862BED428D1E10601BF328C727FD95343E2DB4D9ACD5D1CB4715F6004096EDA093D1B0A33B1E56F16D73ADB8732CB4A31160A4491FAA0C86E680E3D7C02CCEA8FE92F1E001016D220221DD10ED626017966C3450AD121365918C93091F14712BA477CF2E263296C778A2BAEEF5849455FA35CB617251E02A22DAF5C33E5AAA9F00E8ACDC50ECF47C521503C52F27D6B57C8F2B3D8F1222413E7FA4EC59296338098C9AB5A1D8A57884BD860041406D9655D17382949A03D50F1108D05BDB31CA08E66F2D8DE480C6793518D49A60D4762A9EDDC0249B422E84020ED539A14E2478F68BAB1F2B00E22A5CBB62979AC744E08B57D5B578C401A8D26D9ADD1505236082863672D911CF3A0966D303F8917093BF97AF90A7E1F9D59B09206B9CAC35110FA38D5890ED2116835CE37384F5630F1C428E213605872ECF911B014B91C2C600E8A40729D07BF918790742C9279F3114F68CDF6594CDA3CA6694223A82F66C2B4BDF3E51C6FFDC55E0FF51EFD6C934362BE7D6FABC11B8B0DADDD52108FA5FB5CA758A64377D386D45CE70605B460E8157037B5B1B2E0AEDD12A633115D6C43BC6C7C836FFF33E7D033F2E5800527164C0C4781C37DF50B66BBA5C819473A1C5302083A16F01437279D2F2DF14C878269A2F3FA40C1C761ED61501AC9EF141029038C819954089B738098708174393FEAEA7B02AE5CEF67B3C8CE6A970675CA1B8C856DCF5972508C7C6B25EE4D12D8212B98940B488EC402AC7AE3C70DF938D1288CDA7A319E085BC73A469B2D2A3303B11A683100AF6DB86937BA1182903616E3F0347BD68591B47BA65156B93F260DE59B3AEB289E2A73A3BFF38C2F3ADEDA29C7E90283AC7B86D036B47D5BA1A03EC783D250BACAE5847E41F829CB33DE08DF8F7D69C9AA4EDE8D7AB968407EED31A056BA0EF8816E127AA90065A679E1CA9550DEEF25AC5B7A34F70DCF2B116CF351F3BADA99F836C730DCC1AE03F496CF3F0387A0C2C702E2C13BDD9CF45A1CD53AB58731188B18EA8BE48D510C5812E90BCECBC6E198E708B1C08C8F864B124BB4CC0BDBBDF2C2F4E388FC19660D69CC2C0EBF91008C8243DB42DDAF57C024251C4231DF53790CE575613EE8E1C7A33C1561F3504DEAAED1E8408500623ECA5AE5A2845411749930D8E42078C032349957FC39A1DA0EAF9E87C31FFBF6AC0C1811EB28A41B1D86BD7D49AD1C468A49594956525A20A31700F122F4C4BB2252A2F3D5C5D6873838C909597BBCAD8E1333D5D617C87C8EE0F1B22383B424B4C5C627298A3BECC1B32475C9DB6B9BDC6D6DCF50000000000000000000000000000000000000000000000000000000011192834""") + ), + new SigVerTestCase( + TestUtils.hexDecode(""" +09B4887D97BCF6379CC59B6162C1E8BF0560BF44D61809170E6E28F70669A3E9496438E8915735ADAEB445CFDB7D89B38C048F4C3E00581514C5FD198B2D1739E883B878D56BB41264BE41D3D51565E2E9CAE33184A899F62DD57D07400E98E58687A9B22FA317EED134CA7214BFF021DD2162B183091D15F263B7298214423C6BB696D75C20D9EACD0A03E4262C4B08BE39FA2154BD6E5025FF791E885F2226E3CF48F7B5EB04FBE9ECF75B19E1D15C305E92260AB0D6AE7DBA7BBE73B6BC181CF933840CC10A00050228FA46A2636DD9A90947E9F13A93EF4C62BE374D76D1FDBBC5D8B55E729FA58665AA07B90C8CDDD61C566B0D7ED65770492EA0713E1ED46AC7AD1503C56D9052D2C94D49E4416AC92B70396F76F6FB481045681725A68CB356377FB231AB8F3EB9A4982FFF1836473BCBDAB6872D229467EFB9366261FEB148BA9B7DB9C4FE0BB88612ABB8FD61096F1819604D55DF6020464D3F092CFCA59812082218566899A56A3C633CC81F88ADB2E1414EF3850D10BF5A77ACE724D6C1F388928744B3E542AE491CD56A64213F1D3CC90B29105F43D237C83D5FB829325C83E654577776392F8536AA9DAE872407ABAAA9ACC22A6812CEA74C0BA67EAF4A410152975E9A83EE4469295317BED10551BA32E65AFC8C8E68DD55420C502D937DADD2EFA2CBFD1F739FC0AB2B2654FAE08C0C7F8EDD43CF9FF0B01D984D491852A372E9FEFDCC1BC16CDB5239AE1001155F89563051CE47996C5AEEB2190EA18F7F734042DE68E988367D89355D9D8377BAF9647978EB2E492AD021C569AE8BA69B15F1FCF7039A7E64AF10ABF3EA45B7222F9659E33373372E1DB186D2C2A0D75451C478AEF33E5949F240040C2AFC44B1D3A02A6D2F87902A280E27A20D4E57F889662700DB8A9D249957A7DB437CD480DDC05884FB23F868268EACE34EED274A927D9D84F1EA57EAB1A813B5E6AABE9ED2610BC6F72E320CDEC4F99523F93FA448DC1FBBDD259B102F5DC9955AFA0C41604D83DD1C2D2295EF4461456BAE86905C4C30D8A9FA48C90F37A19C41A2D5988F13D51344EC30A4A46219FE841137D5AA1F51E6C444168AF39890B6FA400D67F4806F5BBD444703074A7A1139C71746D7C4CEB3C911F5257E3E53EBFA5AA8F227809D44EE7DE13C027924DD60153B30AA76DD96A7C5ACC59B627919507BF14257AE7A26243C1683B28D1B14B501AD059B4D522A57991E5539CEF18CEB5C26D660B8822454C9C42A95E6F72B84F78AB99F51EC49789F9DB4C128B0318FFFC82D95CAD277F11E14F1EF871414881122A9B11BDFAE4A7ABC8E75755AB13741DFACD664293D1A326BF5ED5ABBB153EBE6996DD622F0A8CB473969A50366BD0B01C5C73A892B8E26CE08F75FF801B6DEF041E1713BE6DF0EFB51587BE5FBEA727E00D717647DD539079DE18AE7BED12B91AF8DBB1B8B32D2860BAF40AF8A0BBFE02887EB5DBE7AB1AFC41DA79B016AA16EDA281321CAA5DA644FD8658A7B702181001431560DD63CB21E5FF75C3F7250456BE08C0D5E34C3BDE2F606A2BF3417768D24B23739EA86CBEFDDA34388BC1F918F951E15E43B1385A7BCC559F9492C7213A14227E093E929F32D1EFBE7F1EE57C49C9055623EA42EC6C79D7FCE71FA747607566DDA69F69DAF68115919C6322EBB42C8C089338C9E0C53565BCBE72FBE4726687B0787071806C5A6C149C82B668AA64A7BA0CCC1CC49A1EEE9453D04336E5DC811E03892F7F46688ECEFD04F1876F7111712B595ED62DA00678F9E3786B5C1A5095BE8710DCFA4165256509E00143A6F1172FABE8BF21E5FCE7C79C1A44B4B1525A076FFB8DD9066"""), + TestUtils.hexDecode(""" +0B36AE74905A488C25C9BF47B4144E12E75A8F54555E1943E3CF738BBF0B9C4ACC270A71804B0D8FEEEB0451AB504027C853125BEC7E7216A82EC09EEA3778291A6B97F53B1766FAB67CD3C875C171A36D5DC23835B7B5641C4689E646C40CC2B379131DF4AE848B8C4713A1E38F5C31140662F6F92BA22E888CA3C0A2F242C9"""), + TestUtils.hexDecode(""" +279860C94C551A0A0788099AB39F1F25BEE8CC4622D20DA037005B8D6B5B7371B11BADFC236C9B0028868DFE74A9AE59642CDFB8D38BA5A79CD52278E554C25B07A07C77C1420F8F0CC08A035C99BC4F0C303F20CA1BFC0E46E9FC6F37FF1BA5E5653656B7FB488C3B600E0BEF9F4A553A3D2FE5F0D2B76EBC90C5A2A99B789B55316ABBBCEED0EC70325CE2E89890FB2A19E30E79C4E8E619101FC2428D9579737DCB3FD76947FA7BF257FAF2FCC360051F55912F051DB24C51619439369F13F34D669DCD5638D3565101A7A4D379105EA6D83163D046DE3A6F9D9036CCC347DDF8B363E873D959C33D1B56775914ABD50EB6FD2D096E669F11C288781681D693A3A52188E80D0D33784D2F5FA1954D72C35D8929A2223577F8119CF241317D0E95C615641F40EEA3368BDA7619EEE82BC4B78717CE9E9D7036E0DD7DFFFD56CCC29D4F0EF46DFD4D07E4838BB513B2EEFA72BBFA0E9FEEBD1D2B96D9B8DBCAB4241FF7AB080ADBE1099AD3CEDC4597B23171E3ACA2027CD1B6E519EF29FDC21CD54EEAC264F4B2CDFBBB8104FE81C3C65691B0C309C31B877BF0B0DB37C6F44B9A11DDAFFCC40CEB1E78D2F86C2A0F902699EC1680E46F94DECDE4EC119F7742D3D47A383391B8DFD614E375B8C32271CDC49F054D2C26DEE4BC60C3A474888642DCD4BA1AE30CC8CAAE80AA9FCCA55528AA33FD4F732677E7D1B9E320247B299D6AD384D23D4E478AC2450F676B9BA27E5D4CB01F0EA50A62A2136DC4C2E1219C0E749444B2943890F36AF1EC2C273C42F22E0AEAEBD31FA8E6C9D1B8305A0AA8C2BA6601CCF28F46904231E648AFF4D4A72849A8E1EEDCC774FFB1479897C1804BB035671E8F90D462E3D2665B2A75DBAAD3BDB00C13E642A23E84ED48CE3E9B1632ABD0B7D579E7D18F508F33DABD97083EABD3CDCD1C70523A969B9C25E4011742EFBA6B3A09CC6CE627CF95BD51856DDC8C295DBBE180C86E0097FCE5741B3F0F6662B486D1B17987C3C47ECB101DC165372CA696FC477860F3DB7A68E3102B5A91BAC2A256467873C233ED212C7537470BFE88B41C3C239B5E38230E20CE2C41EF2C355884CF7F46CCF0CD688DEBEE8554D118F9088B4F807F19FE17732AD3C145E634CFCDCFF32A54F1C1D7A7879E6C022281130FD5A8188C560658F1AB6AD3EB3FB622D52A1939FE8668F2116A05F6EF6E1AAD846A4279FC3C699373A2FE17A3E9823FAA11F088846B36F5DB4BB9930101D5025350462D2F4866BB3010D9474B5630BDB57E71AE4277247DFF67F37E3CD9BD1307035249EB1EC316D25F913AC4B0BBB21D60CE2F4ED5F08D48D0C707795C177E7044E55D438AC12C2DB918C7087388650AB4AB19095C0A480232B1BA0C794991E89A650E070A5B562D9965C467D6CE834167EB6189A41B58E91685A034C70CD7723840A5561F0F751AA8F382A3772B07864547C1862E2433811633C97F58F85B9B14D3875ADCE2494D8BFA2E0773BF4637EDBD96AF9BAE43497CE2D63D59640C7723761C8AFB534189509A44794BB98A6D8E4AA3C5C3C136AA1C31CF20EFF2F5968FE4E71415DF760A52EC88BA438EF6110CD7F3B7FBE53B13999DD3EC4FCB5CFB4F9744578CEB60F800FFF2BABF330DC20DA5C128282C924244D9E5A18C3AC59DCD0D953156E2020751B708C0B025768963EDCF0DBAD16DD68A792A5E30981F17A4C355AE3E8036F9E289EEE35D9EF136AE402B4AFC7DD04190A8F0C8F66A66B701F995F7869855F59B47634B4A1F9E715E5059371B74D65D9501CA814F255D6C4D861B5C5A903B7ED44BF55CC18DB3CEA98D7CE951CD241A661E823F0A0EA92FA33A23294338E6F96D273DAF63BE9D5D5BE92FFEAA6078A9E8C5CADCC8AE79A1D5FC384519DF06A5832CE1DED5C7A6E937E86B854ECB1043169041A4BAD0FFEB13B0017B5BE16091AAC3F5DEB017B01EA00CA323AB44CCB193063406C970257DE61FAF1EE51105A22A4703562DFF1230AE241D67803FC6D997A1B016A73CE4346DF97F8ACE220CCFC3585B8307CD4B3AF74F6E0CF49A33CD5F5E53D04A197B4AA55ECCF645447B6033FE38DFE155AA979B2D4586D5249450E01532334C8F342BF81AF35980639C7E0AD431F3D3277F21F33A0622568E08D75A97CF2560826EF3DDB8A1E421217EE28B82D3BBB6FC499AE696567EF24681D482B051CA65DF9EB7F59965F03A68976F8A2542A58837CD3DA9EF5F4F06F94313B63B6B25EA67B1ACB4A0015F026D6A683BF533C3F730CD4D8A0CEF6D63100B4D9A1ADA15305A441A71B829AB2D33D3D209B598E05F19916569FFD262EE5D4160B8DF16E3FE63AA48029FD4F080D07602DEDC1B383F286202C287844D4063584087F29E36D5C19E54CF37DD504DB01452340D937D438C0E63EC35F948A4681D74D54CD6AF91262B075F55999137B5B94A2FE4E2668FBE44F68A892A91F8B5AEDB265BC0464F62C768BF346BC91AD9F9733E3DB9B846E2DBB0FEB3D00D817DB052C69474D77AAF7DCABF21E137F4C4607CFACFBCC7AF1F27BAF377B261358C7CD69394C33C89ED66F2579F29815B1FD957553FBF4F9FA4A5C85C223BDE78BA0722375BB8E7B02FFAD17DD7410F384A88DC0A77CA6345AE26A87FBB4753FCFB7EEA6ACE2061694746C8BE7E645D8848C5742ADD8815DD48AF19021591C7D7DDBF2DED046E7DF36F092127AC47432555F2BE60060433B561E7CEE0DDD1C5650B92898C8D6E01531CD373271A24A489D95FF24F4B4BB06AA39F56375F4B5B5BEEA5F4E5DD3B918136FA98AA2580A691334F8082DBEBF34943B27024C69C897D31897C2690C3D72C22133AB467E0626A4618FAF403A63DF25E2DA82D1191787D6487D87A6985F619CD6F1B7937F06E448501498DF0A1005D408D1CBD943ECC4EE03D038C5ED1FE462540DC937F0E4301502228D3B3755E3D31EDAB96D03AD1AB3E0A631AE80F86C3AE9321F35AF90F8D4D9B2B431BD529E2D29A29FE066269FB90248265088FBBBDE99B24A0F38282847D8FF4022AE6B611743A5B5472A4BF054B95F2CB09EA5E088E8AB172B7C3B53BB32986FEC298F41E2FA9D53D6F85254ED489A3F1FF01C07D33DEB98CA4EE704F27FD68F47B2E995E6706FC8D02454D7F2A73E50CD2AB15F973C9297B3B4989393588BB6C6CAEFF67BF2E241A158EA96C1A2FAF13FFBA4358A38928C2FFD0A7E32137E83256941DE749DFED36C63F2D07C557C7AFDBA351329899CE6D96DFD3442725BB1F24EC43EA41B4DE9E4E39D17A6F26384168DB92BF9516D7DD8101B970B83F2A2F323B418385C3D20410122D414A586970737BB0B1BAC6DA0B183244494F7375799AB0BDC5D1E2ECF3F4010C0E0F3537434E5366C6CCD7F1F20000000000000000000000000000000000000000000009192B3A""") + ), + new SigVerTestCase( + TestUtils.hexDecode(""" +09B4887D97BCF6379CC59B6162C1E8BF0560BF44D61809170E6E28F70669A3E9496438E8915735ADAEB445CFDB7D89B38C048F4C3E00581514C5FD198B2D1739E883B878D56BB41264BE41D3D51565E2E9CAE33184A899F62DD57D07400E98E58687A9B22FA317EED134CA7214BFF021DD2162B183091D15F263B7298214423C6BB696D75C20D9EACD0A03E4262C4B08BE39FA2154BD6E5025FF791E885F2226E3CF48F7B5EB04FBE9ECF75B19E1D15C305E92260AB0D6AE7DBA7BBE73B6BC181CF933840CC10A00050228FA46A2636DD9A90947E9F13A93EF4C62BE374D76D1FDBBC5D8B55E729FA58665AA07B90C8CDDD61C566B0D7ED65770492EA0713E1ED46AC7AD1503C56D9052D2C94D49E4416AC92B70396F76F6FB481045681725A68CB356377FB231AB8F3EB9A4982FFF1836473BCBDAB6872D229467EFB9366261FEB148BA9B7DB9C4FE0BB88612ABB8FD61096F1819604D55DF6020464D3F092CFCA59812082218566899A56A3C633CC81F88ADB2E1414EF3850D10BF5A77ACE724D6C1F388928744B3E542AE491CD56A64213F1D3CC90B29105F43D237C83D5FB829325C83E654577776392F8536AA9DAE872407ABAAA9ACC22A6812CEA74C0BA67EAF4A410152975E9A83EE4469295317BED10551BA32E65AFC8C8E68DD55420C502D937DADD2EFA2CBFD1F739FC0AB2B2654FAE08C0C7F8EDD43CF9FF0B01D984D491852A372E9FEFDCC1BC16CDB5239AE1001155F89563051CE47996C5AEEB2190EA18F7F734042DE68E988367D89355D9D8377BAF9647978EB2E492AD021C569AE8BA69B15F1FCF7039A7E64AF10ABF3EA45B7222F9659E33373372E1DB186D2C2A0D75451C478AEF33E5949F240040C2AFC44B1D3A02A6D2F87902A280E27A20D4E57F889662700DB8A9D249957A7DB437CD480DDC05884FB23F868268EACE34EED274A927D9D84F1EA57EAB1A813B5E6AABE9ED2610BC6F72E320CDEC4F99523F93FA448DC1FBBDD259B102F5DC9955AFA0C41604D83DD1C2D2295EF4461456BAE86905C4C30D8A9FA48C90F37A19C41A2D5988F13D51344EC30A4A46219FE841137D5AA1F51E6C444168AF39890B6FA400D67F4806F5BBD444703074A7A1139C71746D7C4CEB3C911F5257E3E53EBFA5AA8F227809D44EE7DE13C027924DD60153B30AA76DD96A7C5ACC59B627919507BF14257AE7A26243C1683B28D1B14B501AD059B4D522A57991E5539CEF18CEB5C26D660B8822454C9C42A95E6F72B84F78AB99F51EC49789F9DB4C128B0318FFFC82D95CAD277F11E14F1EF871414881122A9B11BDFAE4A7ABC8E75755AB13741DFACD664293D1A326BF5ED5ABBB153EBE6996DD622F0A8CB473969A50366BD0B01C5C73A892B8E26CE08F75FF801B6DEF041E1713BE6DF0EFB51587BE5FBEA727E00D717647DD539079DE18AE7BED12B91AF8DBB1B8B32D2860BAF40AF8A0BBFE02887EB5DBE7AB1AFC41DA79B016AA16EDA281321CAA5DA644FD8658A7B702181001431560DD63CB21E5FF75C3F7250456BE08C0D5E34C3BDE2F606A2BF3417768D24B23739EA86CBEFDDA34388BC1F918F951E15E43B1385A7BCC559F9492C7213A14227E093E929F32D1EFBE7F1EE57C49C9055623EA42EC6C79D7FCE71FA747607566DDA69F69DAF68115919C6322EBB42C8C089338C9E0C53565BCBE72FBE4726687B0787071806C5A6C149C82B668AA64A7BA0CCC1CC49A1EEE9453D04336E5DC811E03892F7F46688ECEFD04F1876F7111712B595ED62DA00678F9E3786B5C1A5095BE8710DCFA4165256509E00143A6F1172FABE8BF21E5FCE7C79C1A44B4B1525A076FFB8DD9066"""), + TestUtils.hexDecode(""" +3DE9C8CDA014784F23C8CB6D41294D39D27C9A5DF8F8D939B6F2D821824E584BC0BA516037E100C68C02480DAD436E12DD095DFFE293DF8E4AFFAFA0DA05516BD579B1B03B2A43307C7DF0D88624386593B226D4BA2EC5716A8C8B7A117C437DDACE31E6A902C403DD172DA7054A1BD679C01C1D822C3A075F5AB2002D2147A9"""), + TestUtils.hexDecode(""" +4A3C0683EE52A2E3703716E44D321208374CB0ECA74F9E6A624A1947B6788AD7F6AE68F320A580D35697E48B276779D4F5D2C8AF78177F12C9CD117875E0CB039293F140C24D80C895ECD7AE9C7C8AB72395A2736D7DAD6FE3EA57F21F9681806D821C91EB790BBD7F4AECA96100CA225A45CABE9372F48732B1A0745BBADAEA0594CD87875C05B703FDACEB441736811E2B6AAED172B6EDB8FDD087EF22D30CEEAA7F9E9A0DACD13D60749C0A04C376B804872A6C5056C37B9B64B4060CDBAC15B1C00CF9AC77DB99C506FDAE0AE16C198DE0BEFC4CABD6B38BC7E268112844B8ED5525A5624A36701A2F6AC6ACD2E4E40F01697E518B5F3107563865AE8537D04FAA57E1B71ECB1E2C2E36AEB3D8AA4674A04306E5179FB7A45CC6D57692BD787137DA3E6C5395D3F6A2EAAD0AF8F586912CC6E6DCD5DF34A6E4B0A574A350D760C646FB77C76377B6F88FACCD1B7187CC10E363FABDAB9D494E749E0EABE63D45901A54E06FCEA5A46487123C3C1107BBFFA87B7D7D92BC6793A7FA3CD18CA2E27DEE2213983D08863126FD79FADE804B48830AF687B02B4931357AC4247617AC13064804D3F780EE18A452613E9C1B188C0655FBA86F6ABD38E5F7D17267C747976C36EB37267759A9EDBD6624992F704684484FC562C8918788732DAEF29EC1386E73A2E2FD02BF7811E1D7A20822C8985AAF86B8E253AA7F0806BD6FA376557910497205393841BAFA34598B7E29EA9E67351CDA2966D0873BA914255649CDC89B2B64A751EB627F0C2D0963D391036C7297518A44C6783750C3CD6DF832AACA28FD5643F94A38571BCE04C3E29E2973CD6C6600C8102C1EA725DED21C50C90DCAEFF9D73756FF6BE91E8E766598EEBFC394F83C6D36FAD25B2DFC31D720E7E42763F10AD75D8C93775609CD7B0285F0247B52B797D11489CB4EC333C27E195ED8F7071E6C3E5E9220CAB46983B4013705F5934C0F1D61E70EFF9CD5FD293668BD3D0546A884D7AAED9EF7D2CA8E84A6BBDAF7FD8181FCC9D65FD74A4AA26DFBC42EC10484D7DC073E123F95CA705BF6CC3A803C186985721406994714949BD47161AC12AF72C0A358702CBA5A6AFF793D0DFDC7009861414CC3689E907D65BFE48751AE296D798912D49F4F849E43141E1BB050F9D17E5A0C4B7530E83463469F1D9443533AE36C57C6D80B915A3B3C8D9A3E43F5E6AD0187E8F828FFF7240EE9D4304255DA0528D0EF59FF1993731735245467B1BC5E6DFDE8895714F34562229E79AF8AB5E6269BD1C9DAC265D34C6CFECB2A4D02ACD092822E1EC0335EC1BA0ED22DD5D832B6349BCAE8194BC550537B814492DFB96EE870B26B3B535F2C79E24705E662C11CAF10E0E081573BD8B12A393F9AEE5A9426C22F2F14C7EEDFADD47ACFC4AA01E0282C7AC03B667302A98CBD84902DC6BF66FBEDA65B84115D652EB8C479808B3542567F2ECCDCE06692FF06C653714E65E202AE7363C4C32A71A636EDA410AA0B8F4614E3927BF5821AD2E30B5ACF30201F35028994A8568D68E8CA28C1E2C3D482C6609AC36AD5583485034931DAAC6183776935E42C4F02ADF19730260AE56BB8C2839B1DCAE85E6F81747AF80A55A8D20132D77BACCFA3963896E9C431714D3BFB78DC74CDBC743151615C325AC3BF0DCBDBDB8CBEDE8E71A002C20B89A0E7D732AD8934262C5F29D4B600F4BC690136CBEC1E93FC8F07F6C5CB789D06D89523DD1BD6D98A3015C4950B9AAA45427A3A923B15D2DF53F030DD8E07F9E2461C5676A09D6A7928B2334C2B621B28B82A45BE731FC8ECBB030C3F85B03B7877EEFCB1B7E5736698E8723B55385337C6DF877FC8842343100030E9876CB98FB12E1749D1D6A77DDC94BCFB67B0C61C589C805A79F2B69AF01B2456B5491D776ADBD9C60466F7D099DDC395E6E297677DB98C9DE5D2BC6C5D7772A2AE30916C21825EA848AECA3447766327552527687C702A8344D008C39CA26A9933320A93764F4D0EECA250208321A4E465251135D7FEE9C69FBBD6B8162A4321D3133A6F23FD8A459B05E9C9003B4AE86B538EF5E1B769E14ED84AB3C963B3F8C64A9FF5979277ACF32EC2A65E65327001836AD53D66D420E2F39B42CF1CFC0BBB95EEAAC57D64262FFEBF7D57D7EB86430C3EB5E25EB183DA1196D8BA5E16B106D874EBBEF5E90256CFEE4DADC26A65EF8FF340CAA19B99CC298456C558E54F8B3155E3BF457FE61B1871C8605347BA2B399030ED93A26AAB17711795873DE7C62C1ECECD61AA2F54DFFF5FF6CE074937F51AED1811CADD4BFCD9D9C9B9937E4D43F1054932BB81427FEE0AC894E0F9CA81F299A9DAFADE2F3735C756E89A4D3136AA5533F83AD4465FE212EC6A6C04C1A4006521145B762B2744D01331F92408A5620EDF3F33F004790F2AE2CBE6780D1F295BFCC0749BEA94900782F33F9807F7058439D17D09FCA9F78A50FA8231D6B90B6D3E2911643F08B68A7FEFA9CFA0F200EE15F36C5A38163DD7DBADBC496673E0DA0470E644341DC03969E9B88EA9BCE9D041F34CBD852798B388773FE2EA344B017B82EDB603B6364EAB0CCABF1A496C195F7073105EEE7E444A31E5B57DA2BA0C8627B15328D713ECFE8596FCD269B9549EE31D89890D05049152EE7B5466296963E52BC368A2B874B2991123B14302234B6493C3E927B2B96C2A39A78A7D0331D19CE9291037F91877E76739ADE0D0D4FC8F20A5749907D4012DC7F54C904180B5C98C1B3ECB0363E22582E9604BB6F1D837D797E65BB0C798A810A41D4DC26923B56B79B8B26746D691865210C15F4B222D8F158A65B3FBAED2E81F3EFBA36CEE2BD7082ED8FD0CAC3948CC52CC9567D33DB07BA6A715CD4E66AA376C477F105A471E6F9A2620013C5FDAB9F064232942108D42C0117F40505AA77CBD6597AA47EDC1025CF532C07C432311B40A32927A3FD2794B8D708DF6E93844040F0A26D8B12A32020D3C49EF16F68CFBD5009D82DE4147D6341CDD3868B478C93276752FD3A175E23E4DF15329C671E0462E502B894C53778BE77BD94EFF9C1F3FA2B40A94A1E219056C2CA86A217C35223BF0265C5425953761943D9A68292D69372248A219E410D1FEA3621612907E102438C6D7B92D0868C03B8E5FE9D6AED83C4B8221DA6078451343ACC86EC5B3776F986031A0963BA78DC2045D04F599780DFB1E8277C96AB84EE3A27D145F8EE7A86C04BDC4A6AFA0A8CA9F58C55C60E32101B517EE1B154F60290F635FD13E4FAC422EA874AC104202899E020832C15FCD829ABA48CB43AE8D151B2E3654ADB1B6DDDEF1FC27393B647274A6A8DC10181C24404C56606E8A8D8FA7ADB3E1F104080F1618263342646C85BEC5C6E3E700000000000000000000000000000000000000000000000000000C152636""") + ), + new SigVerTestCase( + TestUtils.hexDecode(""" +09B4887D97BCF6379CC59B6162C1E8BF0560BF44D61809170E6E28F70669A3E9496438E8915735ADAEB445CFDB7D89B38C048F4C3E00581514C5FD198B2D1739E883B878D56BB41264BE41D3D51565E2E9CAE33184A899F62DD57D07400E98E58687A9B22FA317EED134CA7214BFF021DD2162B183091D15F263B7298214423C6BB696D75C20D9EACD0A03E4262C4B08BE39FA2154BD6E5025FF791E885F2226E3CF48F7B5EB04FBE9ECF75B19E1D15C305E92260AB0D6AE7DBA7BBE73B6BC181CF933840CC10A00050228FA46A2636DD9A90947E9F13A93EF4C62BE374D76D1FDBBC5D8B55E729FA58665AA07B90C8CDDD61C566B0D7ED65770492EA0713E1ED46AC7AD1503C56D9052D2C94D49E4416AC92B70396F76F6FB481045681725A68CB356377FB231AB8F3EB9A4982FFF1836473BCBDAB6872D229467EFB9366261FEB148BA9B7DB9C4FE0BB88612ABB8FD61096F1819604D55DF6020464D3F092CFCA59812082218566899A56A3C633CC81F88ADB2E1414EF3850D10BF5A77ACE724D6C1F388928744B3E542AE491CD56A64213F1D3CC90B29105F43D237C83D5FB829325C83E654577776392F8536AA9DAE872407ABAAA9ACC22A6812CEA74C0BA67EAF4A410152975E9A83EE4469295317BED10551BA32E65AFC8C8E68DD55420C502D937DADD2EFA2CBFD1F739FC0AB2B2654FAE08C0C7F8EDD43CF9FF0B01D984D491852A372E9FEFDCC1BC16CDB5239AE1001155F89563051CE47996C5AEEB2190EA18F7F734042DE68E988367D89355D9D8377BAF9647978EB2E492AD021C569AE8BA69B15F1FCF7039A7E64AF10ABF3EA45B7222F9659E33373372E1DB186D2C2A0D75451C478AEF33E5949F240040C2AFC44B1D3A02A6D2F87902A280E27A20D4E57F889662700DB8A9D249957A7DB437CD480DDC05884FB23F868268EACE34EED274A927D9D84F1EA57EAB1A813B5E6AABE9ED2610BC6F72E320CDEC4F99523F93FA448DC1FBBDD259B102F5DC9955AFA0C41604D83DD1C2D2295EF4461456BAE86905C4C30D8A9FA48C90F37A19C41A2D5988F13D51344EC30A4A46219FE841137D5AA1F51E6C444168AF39890B6FA400D67F4806F5BBD444703074A7A1139C71746D7C4CEB3C911F5257E3E53EBFA5AA8F227809D44EE7DE13C027924DD60153B30AA76DD96A7C5ACC59B627919507BF14257AE7A26243C1683B28D1B14B501AD059B4D522A57991E5539CEF18CEB5C26D660B8822454C9C42A95E6F72B84F78AB99F51EC49789F9DB4C128B0318FFFC82D95CAD277F11E14F1EF871414881122A9B11BDFAE4A7ABC8E75755AB13741DFACD664293D1A326BF5ED5ABBB153EBE6996DD622F0A8CB473969A50366BD0B01C5C73A892B8E26CE08F75FF801B6DEF041E1713BE6DF0EFB51587BE5FBEA727E00D717647DD539079DE18AE7BED12B91AF8DBB1B8B32D2860BAF40AF8A0BBFE02887EB5DBE7AB1AFC41DA79B016AA16EDA281321CAA5DA644FD8658A7B702181001431560DD63CB21E5FF75C3F7250456BE08C0D5E34C3BDE2F606A2BF3417768D24B23739EA86CBEFDDA34388BC1F918F951E15E43B1385A7BCC559F9492C7213A14227E093E929F32D1EFBE7F1EE57C49C9055623EA42EC6C79D7FCE71FA747607566DDA69F69DAF68115919C6322EBB42C8C089338C9E0C53565BCBE72FBE4726687B0787071806C5A6C149C82B668AA64A7BA0CCC1CC49A1EEE9453D04336E5DC811E03892F7F46688ECEFD04F1876F7111712B595ED62DA00678F9E3786B5C1A5095BE8710DCFA4165256509E00143A6F1172FABE8BF21E5FCE7C79C1A44B4B1525A076FFB8DD9066"""), + TestUtils.hexDecode(""" +3AFD7FF8CAD3ACBDF97731261C7A1C969D5016F17D3E7F83D2441AF9014B63477B14A6413150FAD7C84439BC88662C5E931F06B9514190E13FB049C4AB74013233B98D48D9AFB6A30A67330E1FBE331B09C56D037E9701085D80F1E7F4043EFB53587ABB823624012384515249EE6130973DC9EA6F558BAE75107EFDB1D9285B"""), + TestUtils.hexDecode(""" +4A2B16CDB552F9297F8E391AD8F5ADC8CC5D2C56C46B800F9B3EE4BBD2F2E8A89D599D7B5CC2D88C80F271859BBC83043EC4E54812F5936B446C9513C855289C94B11551A0C7653E7BA74FFB6F72D4652C91D38DD1F90DFE4439BC21CA53E0CC7A7AA5B875A5B9BA42366EB8ECBA2436DAF08A91978DD093F20F1EFB6B0BCB90DA99CCA05E8F6F82B86D3C6EE24BA5D50AEA10B2307F57F89ED78DB4A74FBBF6EB332AFB08D074ACF0DE5CD7FEC12F76F3AB619C815B9EDD287EAD67F04F14797F8DCF2CDE9A8753B5AD0AFA12874197D1744092872521E868AF9E64452373FEB6FE25D5273D63C0EBD6D3B1028C1CD06AF32CECA2621310837C72788C8ADAB5A0F03817128EB7B766FA812C696CF886F00A1044CDD06BB28CB2E5780C8D8CC7E60AB699DD78668BE4FF9F4690C6FC98AAC9C02B66B9B9826A3061FD3222DA8482667960A31652EE88EB32B0469AB71CAA2519F23D1A2442D5B1316262131DCEC5F287E32FD343FEB4429E54258D690D9D20A10ABD75A536DFF8CF1D6DDF19291E2749A7D16EB90AB5093BAD38E116A86B730E65574C068C38BA9457C9D6D913EAFF57FE23BF3DD24D8CA511EFA376A5DF08467025FF51BEAD3EDE0A84EDC5321620998061E8A1A73D67B7021B810C7867FF39187B59D403BF7C7506300C7345B1FE07C11278B0ABA61DBB4F2B8C43E74FEFA55ED52C10A8C490882BBFE3E3B3CE579E8116A9B6686C1A100AA1F6591F191F772B5A5A50DD6CC155CB5A1BE5BA122E91F044420156CD63080F0A45D662E76DD57BD0F689D0B299042BFF485E8A382D865C26CD46B4A54728BD48458362D79AC3EB756FC6C518C9E2F0E7D5A303AF1159EE6DBE7DD56BA0712857A68836C3C78C6C9F7488572813C0F6A814709D2BC142FEF02527CAE7712358371C5426522CCC64300C2CD9FBE20C6562E34835205FCDD5A8982C920BB477FB881702827B4911871394C06B5FECD0C740AF7B27637BAC1A0CBCA537E4433EA847454C693897A32E4D1844195426A0C6AED67472BD2C4EEE179F3F6084A36A7689F4CB1F8E5DB2DDE54ACC0666BA98415431A4B202F402FB1F1BCCDC23BFF13148C7B8F61FBF6243B296A78EB698189DA95BDA85DBC11D15FFDC6BF46C53F6E472A871401E9A9AB7F9FB467EB4ECB1F0DA7E63EE8619CBC486EBB0F2120A7811BFB0557D13930574297C9464FC595B27569ADF5F4A8DF669C9EEA0A250F4D22C2E8C641BA3902BA80800489965F11AF1E1A85717C624E742F161550819D1F0372C5CAE8BC62B549EFE874461080D06346E1FA6F01514FBECCB06E34EE271A0F0031790BDABE0F02BBA4AEA4B7397FE3333EB8121820757281F96A5831F9E490366549D16763FF19FF773580ED5E3E1E2AA3E38F88474DE6D9BA6994F8E629160488CB4CD5B878CDA37AAEC9B56369A7E73F73B428639A05C1378448ADB7F074DC8154D92E13C6356B5F466D66477159B2A943799AD619A029F3010D037672DBB6820E51323ADA98881C6DE859DF875ABAF11DA5DDCA5A777622BDAE8FACE2E0CED3B6A77B88A8729FB7C50933DA6C52E3F4D948F9DC153B5B1299CD8621DDFBA48AF44E4B6F6106EE7779501DD5FB3C578EA4D32C5C2F036A7352703ADD135AB84460162417E50BF91E60797D59B9E18D324DA971F4FF428AEAF23AC0BA4E2E2FC7ABAA6C8984FE9E2D85B8ADA4086B3C13ABD43CFD1C711D8326B18ADC34CC14CF8957EC3959498FC2A7BE06BD1840DE170366566E50741957763C2DD27ACF8C3F1026FAEE1D2562FA1052E69AFDD42F446F0598866D5D306BF1B775042B035927372827F4386316534FA1B7EE633BA958CED8F0D241D4688E3C7918E2A75626377C342A590692BBFB827BF90514182D4090DF8D7323519A1AB6CD0227367410DD14D3786A26DDF91724FC82D06A25D5F56683953E8E0F20E3C1771DAF42E52024C116ED8A4C0A611680F5FE00ED9B148D15F12AA95B9BD5A9FD8101642B36911F310B0DE18171D6237D9BE1725DC299A1A3AAAE98540CEED26953D10CE8547F1C3E46A862BED428D1E10601BF328C727FD95343E2DB4D9ACD5D1CB4715F6004096EDA093D1B0A33B1E56F16D73ADB8732CB4A31160A4491FAA0C86E680E3D7C02CCEA8FE92F1E001016D220221DD10ED626017966C3450AD121365918C93091F14712BA477CF2E263296C778A2BAEEF5849455FA35CB617251E02A22DAF5C33E5AAA9F00E8ACDC50ECF47C521503C52F27D6B57C8F2B3D8F1222413E7FA4EC59296338098C9AB5A1D8A57884BD860041406D9655D17382949A03D50F1108D05BDB31CA08E66F2D8DE480C6793518D49A60D4762A9EDDC0249B422E84020ED539A14E2478F68BAB1F2B00E22A5CBB62979AC744E08B57D5B578C401A8D26D9ADD1505236082863672D911CF3A0966D303F8917093BF97AF90A7E1F9D59B09206B9CAC35110FA38D5890ED2116835CE37384F5630F1C428E213605872ECF911B014B91C2C600E8A40729D07BF918790742C9279F3114F68CDF6594CDA3CA6694223A82F66C2B4BDF3E51C6FFDC55E0FF51EFD6C934362BE7D6FABC11B8B0DADDD52108FA5FB5CA758A64377D386D45CE70605B460E8157037B5B1B2E0AEDD12A633115D6C43BC6C7C836FFF33E7D033F2E5800527164C0C4781C37DF50B66BBA5C819473A1C5302083A16F01437279D2F2DF14C878269A2F3FA40C1C761ED61501AC9EF141029038C819954089B738098708174393FEAEA7B02AE5CEF67B3C8CE6A970675CA1B8C856DCF5972508C7C6B25EE4D12D8212B98940B488EC402AC7AE3C70DF938D1288CDA7A319E085BC73A469B2D2A3303B11A683100AF6DB86937BA1182903616E3F0347BD68591B47BA65156B93F260DE59B3AEB289E2A73A3BFF38C2F3ADEDA29C7E90283AC7B86D036B47D5BA1A03EC783D250BACAE5847E41F829CB33DE08DF8F7D69C9AA4EDE8D7AB968407EED31A056BA0EF8816E127AA90065A679E1CA9550DEEF25AC5B7A34F70DCF2B116CF351F3BADA99F836C730DCC1AE03F496CF3F0387A0C2C702E2C13BDD9CF45A1CD53AB58731188B18EA8BE48D510C5812E90BCECBC6E198E708B1C08C8F864B124BB4CC0BDBBDF2C2F4E388FC19660D69CC2C0EBF91008C8243DB42DDAF57C024251C4231DF53790CE575613EE8E1C7A33C1561F3504DEAAED1E8408500623ECA5AE5A2845411749930D8E42078C032349957FC39A1DA0EAF9E87C31FFBF6AC0C1811EB28A41B1D86BD7D49AD1C468A49594956525A20A31700F122F4C4BB2252A2F3D5C5D6873838C909597BBCAD8E1333D5D617C87C8EE0F1B22383B424B4C5C627298A3BECC1B32475C9DB6B9BDC6D6DCF50000000000000000000000000000000000000000000000000000000011192834""") + ), + new SigVerTestCase( + TestUtils.hexDecode(""" +09B4887D97BCF6379CC59B6162C1E8BF0560BF44D61809170E6E28F70669A3E9496438E8915735ADAEB445CFDB7D89B38C048F4C3E00581514C5FD198B2D1739E883B878D56BB41264BE41D3D51565E2E9CAE33184A899F62DD57D07400E98E58687A9B22FA317EED134CA7214BFF021DD2162B183091D15F263B7298214423C6BB696D75C20D9EACD0A03E4262C4B08BE39FA2154BD6E5025FF791E885F2226E3CF48F7B5EB04FBE9ECF75B19E1D15C305E92260AB0D6AE7DBA7BBE73B6BC181CF933840CC10A00050228FA46A2636DD9A90947E9F13A93EF4C62BE374D76D1FDBBC5D8B55E729FA58665AA07B90C8CDDD61C566B0D7ED65770492EA0713E1ED46AC7AD1503C56D9052D2C94D49E4416AC92B70396F76F6FB481045681725A68CB356377FB231AB8F3EB9A4982FFF1836473BCBDAB6872D229467EFB9366261FEB148BA9B7DB9C4FE0BB88612ABB8FD61096F1819604D55DF6020464D3F092CFCA59812082218566899A56A3C633CC81F88ADB2E1414EF3850D10BF5A77ACE724D6C1F388928744B3E542AE491CD56A64213F1D3CC90B29105F43D237C83D5FB829325C83E654577776392F8536AA9DAE872407ABAAA9ACC22A6812CEA74C0BA67EAF4A410152975E9A83EE4469295317BED10551BA32E65AFC8C8E68DD55420C502D937DADD2EFA2CBFD1F739FC0AB2B2654FAE08C0C7F8EDD43CF9FF0B01D984D491852A372E9FEFDCC1BC16CDB5239AE1001155F89563051CE47996C5AEEB2190EA18F7F734042DE68E988367D89355D9D8377BAF9647978EB2E492AD021C569AE8BA69B15F1FCF7039A7E64AF10ABF3EA45B7222F9659E33373372E1DB186D2C2A0D75451C478AEF33E5949F240040C2AFC44B1D3A02A6D2F87902A280E27A20D4E57F889662700DB8A9D249957A7DB437CD480DDC05884FB23F868268EACE34EED274A927D9D84F1EA57EAB1A813B5E6AABE9ED2610BC6F72E320CDEC4F99523F93FA448DC1FBBDD259B102F5DC9955AFA0C41604D83DD1C2D2295EF4461456BAE86905C4C30D8A9FA48C90F37A19C41A2D5988F13D51344EC30A4A46219FE841137D5AA1F51E6C444168AF39890B6FA400D67F4806F5BBD444703074A7A1139C71746D7C4CEB3C911F5257E3E53EBFA5AA8F227809D44EE7DE13C027924DD60153B30AA76DD96A7C5ACC59B627919507BF14257AE7A26243C1683B28D1B14B501AD059B4D522A57991E5539CEF18CEB5C26D660B8822454C9C42A95E6F72B84F78AB99F51EC49789F9DB4C128B0318FFFC82D95CAD277F11E14F1EF871414881122A9B11BDFAE4A7ABC8E75755AB13741DFACD664293D1A326BF5ED5ABBB153EBE6996DD622F0A8CB473969A50366BD0B01C5C73A892B8E26CE08F75FF801B6DEF041E1713BE6DF0EFB51587BE5FBEA727E00D717647DD539079DE18AE7BED12B91AF8DBB1B8B32D2860BAF40AF8A0BBFE02887EB5DBE7AB1AFC41DA79B016AA16EDA281321CAA5DA644FD8658A7B702181001431560DD63CB21E5FF75C3F7250456BE08C0D5E34C3BDE2F606A2BF3417768D24B23739EA86CBEFDDA34388BC1F918F951E15E43B1385A7BCC559F9492C7213A14227E093E929F32D1EFBE7F1EE57C49C9055623EA42EC6C79D7FCE71FA747607566DDA69F69DAF68115919C6322EBB42C8C089338C9E0C53565BCBE72FBE4726687B0787071806C5A6C149C82B668AA64A7BA0CCC1CC49A1EEE9453D04336E5DC811E03892F7F46688ECEFD04F1876F7111712B595ED62DA00678F9E3786B5C1A5095BE8710DCFA4165256509E00143A6F1172FABE8BF21E5FCE7C79C1A44B4B1525A076FFB8DD9066"""), + TestUtils.hexDecode(""" +0B36AE74905A488C25C9BF47B4144E12E75A8F54555E1943E3CF738BBF0B9C4ACC270A71804B0D8FEEEB0451AB504027C853125BEC7E7216A82EC09EEA3778291A6B97F53B1766FAB67CD3C875C171A36D5DC23835B7B5641C4689E646C40CC2B379131DF4AE848B8C4713A1E38F5C31140662F6F92BA22E888CA3C0A2F242C9"""), + TestUtils.hexDecode(""" +279860C94C551A0A0788099AB39F1F25BEE8CC4622D20DA037005B8D6B5B7371B11BADFC236C9B0028868DFE74A9AE59642CDFB8D38BA5A79CD52278E554C25B07A07C77C1420F8F0CC08A035C99BC4F0C303F20CA1BFC0E46E9FC6F37FF1BA5E5653656B7FB488C3B600E0BEF9F4A553A3D2FE5F0D2B76EBC90C5A2A99B789B55316ABBBCEED0EC70325CE2E89890FB2A19E30E79C4E8E619101FC2428D9579737DCB3FD76947FA7BF257FAF2FCC360051F55912F051DB24C51619439369F13F34D669DCD5638D3565101A7A4D379105EA6D83163D046DE3A6F9D9036CCC347DDF8B363E873D959C33D1B56775914ABD50EB6FD2D096E669F11C288781681D693A3A52188E80D0D33784D2F5FA1954D72C35D8929A2223577F8119CF241317D0E95C615641F40EEA3368BDA7619EEE82BC4B78717CE9E9D7036E0DD7DFFFD56CCC29D4F0EF46DFD4D07E4838BB513B2EEFA72BBFA0E9FEEBD1D2B96D9B8DBCAB4241FF7AB080ADBE1099AD3CEDC4597B23171E3ACA2027CD1B6E519EF29FDC21CD54EEAC264F4B2CDFBBB8104FE81C3C65691B0C309C31B877BF0B0DB37C6F44B9A11DDAFFCC40CEB1E78D2F86C2A0F902699EC1680E46F94DECDE4EC119F7742D3D47A383391B8DFD614E375B8C32271CDC49F054D2C26DEE4BC60C3A474888642DCD4BA1AE30CC8CAAE80AA9FCCA55528AA33FD4F732677E7D1B9E320247B299D6AD384D23D4E478AC2450F676B9BA27E5D4CB01F0EA50A62A2136DC4C2E1219C0E749444B2943890F36AF1EC2C273C42F22E0AEAEBD31FA8E6C9D1B8305A0AA8C2BA6601CCF28F46904231E648AFF4D4A72849A8E1EEDCC774FFB1479897C1804BB035671E8F90D462E3D2665B2A75DBAAD3BDB00C13E642A23E84ED48CE3E9B1632ABD0B7D579E7D18F508F33DABD97083EABD3CDCD1C70523A969B9C25E4011742EFBA6B3A09CC6CE627CF95BD51856DDC8C295DBBE180C86E0097FCE5741B3F0F6662B486D1B17987C3C47ECB101DC165372CA696FC477860F3DB7A68E3102B5A91BAC2A256467873C233ED212C7537470BFE88B41C3C239B5E38230E20CE2C41EF2C355884CF7F46CCF0CD688DEBEE8554D118F9088B4F807F19FE17732AD3C145E634CFCDCFF32A54F1C1D7A7879E6C022281130FD5A8188C560658F1AB6AD3EB3FB622D52A1939FE8668F2116A05F6EF6E1AAD846A4279FC3C699373A2FE17A3E9823FAA11F088846B36F5DB4BB9930101D5025350462D2F4866BB3010D9474B5630BDB57E71AE4277247DFF67F37E3CD9BD1307035249EB1EC316D25F913AC4B0BBB21D60CE2F4ED5F08D48D0C707795C177E7044E55D438AC12C2DB918C7087388650AB4AB19095C0A480232B1BA0C794991E89A650E070A5B562D9965C467D6CE834167EB6189A41B58E91685A034C70CD7723840A5561F0F751AA8F382A3772B07864547C1862E2433811633C97F58F85B9B14D3875ADCE2494D8BFA2E0773BF4637EDBD96AF9BAE43497CE2D63D59640C7723761C8AFB534189509A44794BB98A6D8E4AA3C5C3C136AA1C31CF20EFF2F5968FE4E71415DF760A52EC88BA438EF6110CD7F3B7FBE53B13999DD3EC4FCB5CFB4F9744578CEB60F800FFF2BABF330DC20DA5C128282C924244D9E5A18C3AC59DCD0D953156E2020751B708C0B025768963EDCF0DBAD16DD68A792A5E30981F17A4C355AE3E8036F9E289EEE35D9EF136AE402B4AFC7DD04190A8F0C8F66A66B701F995F7869855F59B47634B4A1F9E715E5059371B74D65D9501CA814F255D6C4D861B5C5A903B7ED44BF55CC18DB3CEA98D7CE951CD241A661E823F0A0EA92FA33A23294338E6F96D273DAF63BE9D5D5BE92FFEAA6078A9E8C5CADCC8AE79A1D5FC384519DF06A5832CE1DED5C7A6E937E86B854ECB1043169041A4BAD0FFEB13B0017B5BE16091AAC3F5DEB017B01EA00CA323AB44CCB193063406C970257DE61FAF1EE51105A22A4703562DFF1230AE241D67803FC6D997A1B016A73CE4346DF97F8ACE220CCFC3585B8307CD4B3AF74F6E0CF49A33CD5F5E53D04A197B4AA55ECCF645447B6033FE38DFE155AA979B2D4586D5249450E01532334C8F342BF81AF35980639C7E0AD431F3D3277F21F33A0622568E08D75A97CF2560826EF3DDB8A1E421217EE28B82D3BBB6FC499AE696567EF24681D482B051CA65DF9EB7F59965F03A68976F8A2542A58837CD3DA9EF5F4F06F94313B63B6B25EA67B1ACB4A0015F026D6A683BF533C3F730CD4D8A0CEF6D63100B4D9A1ADA15305A441A71B829AB2D33D3D209B598E05F19916569FFD262EE5D4160B8DF16E3FE63AA48029FD4F080D07602DEDC1B383F286202C287844D4063584087F29E36D5C19E54CF37DD504DB01452340D937D438C0E63EC35F948A4681D74D54CD6AF91262B075F55999137B5B94A2FE4E2668FBE44F68A892A91F8B5AEDB265BC0464F62C768BF346BC91AD9F9733E3DB9B846E2DBB0FEB3D00D817DB052C69474D77AAF7DCABF21E137F4C4607CFACFBCC7AF1F27BAF377B261358C7CD69394C33C89ED66F2579F29815B1FD957553FBF4F9FA4A5C85C223BDE78BA0722375BB8E7B02FFAD17DD7410F384A88DC0A77CA6345AE26A87FBB4753FCFB7EEA6ACE2061694746C8BE7E645D8848C5742ADD8815DD48AF19021591C7D7DDBF2DED046E7DF36F092127AC47432555F2BE60060433B561E7CEE0DDD1C5650B92898C8D6E01531CD373271A24A489D95FF24F4B4BB06AA39F56375F4B5B5BEEA5F4E5DD3B918136FA98AA2580A691334F8082DBEBF34943B27024C69C897D31897C2690C3D72C22133AB467E0626A4618FAF403A63DF25E2DA82D1191787D6487D87A6985F619CD6F1B7937F06E448501498DF0A1005D408D1CBD943ECC4EE03D038C5ED1FE462540DC937F0E4301502228D3B3755E3D31EDAB96D03AD1AB3E0A631AE80F86C3AE9321F35AF90F8D4D9B2B431BD529E2D29A29FE066269FB90248265088FBBBDE99B24A0F38282847D8FF4022AE6B611743A5B5472A4BF054B95F2CB09EA5E088E8AB172B7C3B53BB32986FEC298F41E2FA9D53D6F85254ED489A3F1FF01C07D33DEB98CA4EE704F27FD68F47B2E995E6706FC8D02454D7F2A73E50CD2AB15F973C9297B3B4989393588BB6C6CAEFF67BF2E241A158EA96C1A2FAF13FFBA4358A38928C2FFD0A7E32137E83256941DE749DFED36C63F2D07C557C7AFDBA351329899CE6D96DFD3442725BB1F24EC43EA41B4DE9E4E39D17A6F26384168DB92BF9516D7DD8101B970B83F2A2F323B418385C3D20410122D414A586970737BB0B1BAC6DA0B183244494F7375799AB0BDC5D1E2ECF3F4010C0E0F3537434E5366C6CCD7F1F20000000000000000000000000000000000000000000009192B3A""") + ), + new SigVerTestCase( + TestUtils.hexDecode(""" +09B4887D97BCF6379CC59B6162C1E8BF0560BF44D61809170E6E28F70669A3E9496438E8915735ADAEB445CFDB7D89B38C048F4C3E00581514C5FD198B2D1739E883B878D56BB41264BE41D3D51565E2E9CAE33184A899F62DD57D07400E98E58687A9B22FA317EED134CA7214BFF021DD2162B183091D15F263B7298214423C6BB696D75C20D9EACD0A03E4262C4B08BE39FA2154BD6E5025FF791E885F2226E3CF48F7B5EB04FBE9ECF75B19E1D15C305E92260AB0D6AE7DBA7BBE73B6BC181CF933840CC10A00050228FA46A2636DD9A90947E9F13A93EF4C62BE374D76D1FDBBC5D8B55E729FA58665AA07B90C8CDDD61C566B0D7ED65770492EA0713E1ED46AC7AD1503C56D9052D2C94D49E4416AC92B70396F76F6FB481045681725A68CB356377FB231AB8F3EB9A4982FFF1836473BCBDAB6872D229467EFB9366261FEB148BA9B7DB9C4FE0BB88612ABB8FD61096F1819604D55DF6020464D3F092CFCA59812082218566899A56A3C633CC81F88ADB2E1414EF3850D10BF5A77ACE724D6C1F388928744B3E542AE491CD56A64213F1D3CC90B29105F43D237C83D5FB829325C83E654577776392F8536AA9DAE872407ABAAA9ACC22A6812CEA74C0BA67EAF4A410152975E9A83EE4469295317BED10551BA32E65AFC8C8E68DD55420C502D937DADD2EFA2CBFD1F739FC0AB2B2654FAE08C0C7F8EDD43CF9FF0B01D984D491852A372E9FEFDCC1BC16CDB5239AE1001155F89563051CE47996C5AEEB2190EA18F7F734042DE68E988367D89355D9D8377BAF9647978EB2E492AD021C569AE8BA69B15F1FCF7039A7E64AF10ABF3EA45B7222F9659E33373372E1DB186D2C2A0D75451C478AEF33E5949F240040C2AFC44B1D3A02A6D2F87902A280E27A20D4E57F889662700DB8A9D249957A7DB437CD480DDC05884FB23F868268EACE34EED274A927D9D84F1EA57EAB1A813B5E6AABE9ED2610BC6F72E320CDEC4F99523F93FA448DC1FBBDD259B102F5DC9955AFA0C41604D83DD1C2D2295EF4461456BAE86905C4C30D8A9FA48C90F37A19C41A2D5988F13D51344EC30A4A46219FE841137D5AA1F51E6C444168AF39890B6FA400D67F4806F5BBD444703074A7A1139C71746D7C4CEB3C911F5257E3E53EBFA5AA8F227809D44EE7DE13C027924DD60153B30AA76DD96A7C5ACC59B627919507BF14257AE7A26243C1683B28D1B14B501AD059B4D522A57991E5539CEF18CEB5C26D660B8822454C9C42A95E6F72B84F78AB99F51EC49789F9DB4C128B0318FFFC82D95CAD277F11E14F1EF871414881122A9B11BDFAE4A7ABC8E75755AB13741DFACD664293D1A326BF5ED5ABBB153EBE6996DD622F0A8CB473969A50366BD0B01C5C73A892B8E26CE08F75FF801B6DEF041E1713BE6DF0EFB51587BE5FBEA727E00D717647DD539079DE18AE7BED12B91AF8DBB1B8B32D2860BAF40AF8A0BBFE02887EB5DBE7AB1AFC41DA79B016AA16EDA281321CAA5DA644FD8658A7B702181001431560DD63CB21E5FF75C3F7250456BE08C0D5E34C3BDE2F606A2BF3417768D24B23739EA86CBEFDDA34388BC1F918F951E15E43B1385A7BCC559F9492C7213A14227E093E929F32D1EFBE7F1EE57C49C9055623EA42EC6C79D7FCE71FA747607566DDA69F69DAF68115919C6322EBB42C8C089338C9E0C53565BCBE72FBE4726687B0787071806C5A6C149C82B668AA64A7BA0CCC1CC49A1EEE9453D04336E5DC811E03892F7F46688ECEFD04F1876F7111712B595ED62DA00678F9E3786B5C1A5095BE8710DCFA4165256509E00143A6F1172FABE8BF21E5FCE7C79C1A44B4B1525A076FFB8DD9066"""), + TestUtils.hexDecode(""" +3DE9C8CDA014784F23C8CB6D41294D39D27C9A5DF8F8D939B6F2D821824E584BC0BA516037E100C68C02480DAD436E12DD095DFFE293DF8E4AFFAFA0DA05516BD579B1B03B2A43307C7DF0D88624386593B226D4BA2EC5716A8C8B7A117C437DDACE31E6A902C403DD172DA7054A1BD679C01C1D822C3A075F5AB2002D2147A9"""), + TestUtils.hexDecode(""" +4A3C0683EE52A2E3703716E44D321208374CB0ECA74F9E6A624A1947B6788AD7F6AE68F320A580D35697E48B276779D4F5D2C8AF78177F12C9CD117875E0CB039293F140C24D80C895ECD7AE9C7C8AB72395A2736D7DAD6FE3EA57F21F9681806D821C91EB790BBD7F4AECA96100CA225A45CABE9372F48732B1A0745BBADAEA0594CD87875C05B703FDACEB441736811E2B6AAED172B6EDB8FDD087EF22D30CEEAA7F9E9A0DACD13D60749C0A04C376B804872A6C5056C37B9B64B4060CDBAC15B1C00CF9AC77DB99C506FDAE0AE16C198DE0BEFC4CABD6B38BC7E268112844B8ED5525A5624A36701A2F6AC6ACD2E4E40F01697E518B5F3107563865AE8537D04FAA57E1B71ECB1E2C2E36AEB3D8AA4674A04306E5179FB7A45CC6D57692BD787137DA3E6C5395D3F6A2EAAD0AF8F586912CC6E6DCD5DF34A6E4B0A574A350D760C646FB77C76377B6F88FACCD1B7187CC10E363FABDAB9D494E749E0EABE63D45901A54E06FCEA5A46487123C3C1107BBFFA87B7D7D92BC6793A7FA3CD18CA2E27DEE2213983D08863126FD79FADE804B48830AF687B02B4931357AC4247617AC13064804D3F780EE18A452613E9C1B188C0655FBA86F6ABD38E5F7D17267C747976C36EB37267759A9EDBD6624992F704684484FC562C8918788732DAEF29EC1386E73A2E2FD02BF7811E1D7A20822C8985AAF86B8E253AA7F0806BD6FA376557910497205393841BAFA34598B7E29EA9E67351CDA2966D0873BA914255649CDC89B2B64A751EB627F0C2D0963D391036C7297518A44C6783750C3CD6DF832AACA28FD5643F94A38571BCE04C3E29E2973CD6C6600C8102C1EA725DED21C50C90DCAEFF9D73756FF6BE91E8E766598EEBFC394F83C6D36FAD25B2DFC31D720E7E42763F10AD75D8C93775609CD7B0285F0247B52B797D11489CB4EC333C27E195ED8F7071E6C3E5E9220CAB46983B4013705F5934C0F1D61E70EFF9CD5FD293668BD3D0546A884D7AAED9EF7D2CA8E84A6BBDAF7FD8181FCC9D65FD74A4AA26DFBC42EC10484D7DC073E123F95CA705BF6CC3A803C186985721406994714949BD47161AC12AF72C0A358702CBA5A6AFF793D0DFDC7009861414CC3689E907D65BFE48751AE296D798912D49F4F849E43141E1BB050F9D17E5A0C4B7530E83463469F1D9443533AE36C57C6D80B915A3B3C8D9A3E43F5E6AD0187E8F828FFF7240EE9D4304255DA0528D0EF59FF1993731735245467B1BC5E6DFDE8895714F34562229E79AF8AB5E6269BD1C9DAC265D34C6CFECB2A4D02ACD092822E1EC0335EC1BA0ED22DD5D832B6349BCAE8194BC550537B814492DFB96EE870B26B3B535F2C79E24705E662C11CAF10E0E081573BD8B12A393F9AEE5A9426C22F2F14C7EEDFADD47ACFC4AA01E0282C7AC03B667302A98CBD84902DC6BF66FBEDA65B84115D652EB8C479808B3542567F2ECCDCE06692FF06C653714E65E202AE7363C4C32A71A636EDA410AA0B8F4614E3927BF5821AD2E30B5ACF30201F35028994A8568D68E8CA28C1E2C3D482C6609AC36AD5583485034931DAAC6183776935E42C4F02ADF19730260AE56BB8C2839B1DCAE85E6F81747AF80A55A8D20132D77BACCFA3963896E9C431714D3BFB78DC74CDBC743151615C325AC3BF0DCBDBDB8CBEDE8E71A002C20B89A0E7D732AD8934262C5F29D4B600F4BC690136CBEC1E93FC8F07F6C5CB789D06D89523DD1BD6D98A3015C4950B9AAA45427A3A923B15D2DF53F030DD8E07F9E2461C5676A09D6A7928B2334C2B621B28B82A45BE731FC8ECBB030C3F85B03B7877EEFCB1B7E5736698E8723B55385337C6DF877FC8842343100030E9876CB98FB12E1749D1D6A77DDC94BCFB67B0C61C589C805A79F2B69AF01B2456B5491D776ADBD9C60466F7D099DDC395E6E297677DB98C9DE5D2BC6C5D7772A2AE30916C21825EA848AECA3447766327552527687C702A8344D008C39CA26A9933320A93764F4D0EECA250208321A4E465251135D7FEE9C69FBBD6B8162A4321D3133A6F23FD8A459B05E9C9003B4AE86B538EF5E1B769E14ED84AB3C963B3F8C64A9FF5979277ACF32EC2A65E65327001836AD53D66D420E2F39B42CF1CFC0BBB95EEAAC57D64262FFEBF7D57D7EB86430C3EB5E25EB183DA1196D8BA5E16B106D874EBBEF5E90256CFEE4DADC26A65EF8FF340CAA19B99CC298456C558E54F8B3155E3BF457FE61B1871C8605347BA2B399030ED93A26AAB17711795873DE7C62C1ECECD61AA2F54DFFF5FF6CE074937F51AED1811CADD4BFCD9D9C9B9937E4D43F1054932BB81427FEE0AC894E0F9CA81F299A9DAFADE2F3735C756E89A4D3136AA5533F83AD4465FE212EC6A6C04C1A4006521145B762B2744D01331F92408A5620EDF3F33F004790F2AE2CBE6780D1F295BFCC0749BEA94900782F33F9807F7058439D17D09FCA9F78A50FA8231D6B90B6D3E2911643F08B68A7FEFA9CFA0F200EE15F36C5A38163DD7DBADBC496673E0DA0470E644341DC03969E9B88EA9BCE9D041F34CBD852798B388773FE2EA344B017B82EDB603B6364EAB0CCABF1A496C195F7073105EEE7E444A31E5B57DA2BA0C8627B15328D713ECFE8596FCD269B9549EE31D89890D05049152EE7B5466296963E52BC368A2B874B2991123B14302234B6493C3E927B2B96C2A39A78A7D0331D19CE9291037F91877E76739ADE0D0D4FC8F20A5749907D4012DC7F54C904180B5C98C1B3ECB0363E22582E9604BB6F1D837D797E65BB0C798A810A41D4DC26923B56B79B8B26746D691865210C15F4B222D8F158A65B3FBAED2E81F3EFBA36CEE2BD7082ED8FD0CAC3948CC52CC9567D33DB07BA6A715CD4E66AA376C477F105A471E6F9A2620013C5FDAB9F064232942108D42C0117F40505AA77CBD6597AA47EDC1025CF532C07C432311B40A32927A3FD2794B8D708DF6E93844040F0A26D8B12A32020D3C49EF16F68CFBD5009D82DE4147D6341CDD3868B478C93276752FD3A175E23E4DF15329C671E0462E502B894C53778BE77BD94EFF9C1F3FA2B40A94A1E219056C2CA86A217C35223BF0265C5425953761943D9A68292D69372248A219E410D1FEA3621612907E102438C6D7B92D0868C03B8E5FE9D6AED83C4B8221DA6078451343ACC86EC5B3776F986031A0963BA78DC2045D04F599780DFB1E8277C96AB84EE3A27D145F8EE7A86C04BDC4A6AFA0A8CA9F58C55C60E32101B517EE1B154F60290F635FD13E4FAC422EA874AC104202899E020832C15FCD829ABA48CB43AE8D151B2E3654ADB1B6DDDEF1FC27393B647274A6A8DC10181C24404C56606E8A8D8FA7ADB3E1F104080F1618263342646C85BEC5C6E3E700000000000000000000000000000000000000000000000000000C152636""") + ), + new SigVerTestCase( + TestUtils.hexDecode(""" +09B4887D97BCF6379CC59B6162C1E8BF0560BF44D61809170E6E28F70669A3E9496438E8915735ADAEB445CFDB7D89B38C048F4C3E00581514C5FD198B2D1739E883B878D56BB41264BE41D3D51565E2E9CAE33184A899F62DD57D07400E98E58687A9B22FA317EED134CA7214BFF021DD2162B183091D15F263B7298214423C6BB696D75C20D9EACD0A03E4262C4B08BE39FA2154BD6E5025FF791E885F2226E3CF48F7B5EB04FBE9ECF75B19E1D15C305E92260AB0D6AE7DBA7BBE73B6BC181CF933840CC10A00050228FA46A2636DD9A90947E9F13A93EF4C62BE374D76D1FDBBC5D8B55E729FA58665AA07B90C8CDDD61C566B0D7ED65770492EA0713E1ED46AC7AD1503C56D9052D2C94D49E4416AC92B70396F76F6FB481045681725A68CB356377FB231AB8F3EB9A4982FFF1836473BCBDAB6872D229467EFB9366261FEB148BA9B7DB9C4FE0BB88612ABB8FD61096F1819604D55DF6020464D3F092CFCA59812082218566899A56A3C633CC81F88ADB2E1414EF3850D10BF5A77ACE724D6C1F388928744B3E542AE491CD56A64213F1D3CC90B29105F43D237C83D5FB829325C83E654577776392F8536AA9DAE872407ABAAA9ACC22A6812CEA74C0BA67EAF4A410152975E9A83EE4469295317BED10551BA32E65AFC8C8E68DD55420C502D937DADD2EFA2CBFD1F739FC0AB2B2654FAE08C0C7F8EDD43CF9FF0B01D984D491852A372E9FEFDCC1BC16CDB5239AE1001155F89563051CE47996C5AEEB2190EA18F7F734042DE68E988367D89355D9D8377BAF9647978EB2E492AD021C569AE8BA69B15F1FCF7039A7E64AF10ABF3EA45B7222F9659E33373372E1DB186D2C2A0D75451C478AEF33E5949F240040C2AFC44B1D3A02A6D2F87902A280E27A20D4E57F889662700DB8A9D249957A7DB437CD480DDC05884FB23F868268EACE34EED274A927D9D84F1EA57EAB1A813B5E6AABE9ED2610BC6F72E320CDEC4F99523F93FA448DC1FBBDD259B102F5DC9955AFA0C41604D83DD1C2D2295EF4461456BAE86905C4C30D8A9FA48C90F37A19C41A2D5988F13D51344EC30A4A46219FE841137D5AA1F51E6C444168AF39890B6FA400D67F4806F5BBD444703074A7A1139C71746D7C4CEB3C911F5257E3E53EBFA5AA8F227809D44EE7DE13C027924DD60153B30AA76DD96A7C5ACC59B627919507BF14257AE7A26243C1683B28D1B14B501AD059B4D522A57991E5539CEF18CEB5C26D660B8822454C9C42A95E6F72B84F78AB99F51EC49789F9DB4C128B0318FFFC82D95CAD277F11E14F1EF871414881122A9B11BDFAE4A7ABC8E75755AB13741DFACD664293D1A326BF5ED5ABBB153EBE6996DD622F0A8CB473969A50366BD0B01C5C73A892B8E26CE08F75FF801B6DEF041E1713BE6DF0EFB51587BE5FBEA727E00D717647DD539079DE18AE7BED12B91AF8DBB1B8B32D2860BAF40AF8A0BBFE02887EB5DBE7AB1AFC41DA79B016AA16EDA281321CAA5DA644FD8658A7B702181001431560DD63CB21E5FF75C3F7250456BE08C0D5E34C3BDE2F606A2BF3417768D24B23739EA86CBEFDDA34388BC1F918F951E15E43B1385A7BCC559F9492C7213A14227E093E929F32D1EFBE7F1EE57C49C9055623EA42EC6C79D7FCE71FA747607566DDA69F69DAF68115919C6322EBB42C8C089338C9E0C53565BCBE72FBE4726687B0787071806C5A6C149C82B668AA64A7BA0CCC1CC49A1EEE9453D04336E5DC811E03892F7F46688ECEFD04F1876F7111712B595ED62DA00678F9E3786B5C1A5095BE8710DCFA4165256509E00143A6F1172FABE8BF21E5FCE7C79C1A44B4B1525A076FFB8DD9066"""), + TestUtils.hexDecode(""" +3AFD7FF8CAD3ACBDF97731261C7A1C969D5016F17D3E7F83D2441AF9014B63477B14A6413150FAD7C84439BC88662C5E931F06B9514190E13FB049C4AB74013233B98D48D9AFB6A30A67330E1FBE331B09C56D037E9701085D80F1E7F4043EFB53587ABB823624012384515249EE6130973DC9EA6F558BAE75107EFDB1D9285B"""), + TestUtils.hexDecode(""" +4A2B16CDB552F9297F8E391AD8F5ADC8CC5D2C56C46B800F9B3EE4BBD2F2E8A89D599D7B5CC2D88C80F271859BBC83043EC4E54812F5936B446C9513C855289C94B11551A0C7653E7BA74FFB6F72D4652C91D38DD1F90DFE4439BC21CA53E0CC7A7AA5B875A5B9BA42366EB8ECBA2436DAF08A91978DD093F20F1EFB6B0BCB90DA99CCA05E8F6F82B86D3C6EE24BA5D50AEA10B2307F57F89ED78DB4A74FBBF6EB332AFB08D074ACF0DE5CD7FEC12F76F3AB619C815B9EDD287EAD67F04F14797F8DCF2CDE9A8753B5AD0AFA12874197D1744092872521E868AF9E64452373FEB6FE25D5273D63C0EBD6D3B1028C1CD06AF32CECA2621310837C72788C8ADAB5A0F03817128EB7B766FA812C696CF886F00A1044CDD06BB28CB2E5780C8D8CC7E60AB699DD78668BE4FF9F4690C6FC98AAC9C02B66B9B9826A3061FD3222DA8482667960A31652EE88EB32B0469AB71CAA2519F23D1A2442D5B1316262131DCEC5F287E32FD343FEB4429E54258D690D9D20A10ABD75A536DFF8CF1D6DDF19291E2749A7D16EB90AB5093BAD38E116A86B730E65574C068C38BA9457C9D6D913EAFF57FE23BF3DD24D8CA511EFA376A5DF08467025FF51BEAD3EDE0A84EDC5321620998061E8A1A73D67B7021B810C7867FF39187B59D403BF7C7506300C7345B1FE07C11278B0ABA61DBB4F2B8C43E74FEFA55ED52C10A8C490882BBFE3E3B3CE579E8116A9B6686C1A100AA1F6591F191F772B5A5A50DD6CC155CB5A1BE5BA122E91F044420156CD63080F0A45D662E76DD57BD0F689D0B299042BFF485E8A382D865C26CD46B4A54728BD48458362D79AC3EB756FC6C518C9E2F0E7D5A303AF1159EE6DBE7DD56BA0712857A68836C3C78C6C9F7488572813C0F6A814709D2BC142FEF02527CAE7712358371C5426522CCC64300C2CD9FBE20C6562E34835205FCDD5A8982C920BB477FB881702827B4911871394C06B5FECD0C740AF7B27637BAC1A0CBCA537E4433EA847454C693897A32E4D1844195426A0C6AED67472BD2C4EEE179F3F6084A36A7689F4CB1F8E5DB2DDE54ACC0666BA98415431A4B202F402FB1F1BCCDC23BFF13148C7B8F61FBF6243B296A78EB698189DA95BDA85DBC11D15FFDC6BF46C53F6E472A871401E9A9AB7F9FB467EB4ECB1F0DA7E63EE8619CBC486EBB0F2120A7811BFB0557D13930574297C9464FC595B27569ADF5F4A8DF669C9EEA0A250F4D22C2E8C641BA3902BA80800489965F11AF1E1A85717C624E742F161550819D1F0372C5CAE8BC62B549EFE874461080D06346E1FA6F01514FBECCB06E34EE271A0F0031790BDABE0F02BBA4AEA4B7397FE3333EB8121820757281F96A5831F9E490366549D16763FF19FF773580ED5E3E1E2AA3E38F88474DE6D9BA6994F8E629160488CB4CD5B878CDA37AAEC9B56369A7E73F73B428639A05C1378448ADB7F074DC8154D92E13C6356B5F466D66477159B2A943799AD619A029F3010D037672DBB6820E51323ADA98881C6DE859DF875ABAF11DA5DDCA5A777622BDAE8FACE2E0CED3B6A77B88A8729FB7C50933DA6C52E3F4D948F9DC153B5B1299CD8621DDFBA48AF44E4B6F6106EE7779501DD5FB3C578EA4D32C5C2F036A7352703ADD135AB84460162417E50BF91E60797D59B9E18D324DA971F4FF428AEAF23AC0BA4E2E2FC7ABAA6C8984FE9E2D85B8ADA4086B3C13ABD43CFD1C711D8326B18ADC34CC14CF8957EC3959498FC2A7BE06BD1840DE170366566E50741957763C2DD27ACF8C3F1026FAEE1D2562FA1052E69AFDD42F446F0598866D5D306BF1B775042B035927372827F4386316534FA1B7EE633BA958CED8F0D241D4688E3C7918E2A75626377C342A590692BBFB827BF90514182D4090DF8D7323519A1AB6CD0227367410DD14D3786A26DDF91724FC82D06A25D5F56683953E8E0F20E3C1771DAF42E52024C116ED8A4C0A611680F5FE00ED9B148D15F12AA95B9BD5A9FD8101642B36911F310B0DE18171D6237D9BE1725DC299A1A3AAAE98540CEED26953D10CE8547F1C3E46A862BED428D1E10601BF328C727FD95343E2DB4D9ACD5D1CB4715F6004096EDA093D1B0A33B1E56F16D73ADB8732CB4A31160A4491FAA0C86E680E3D7C02CCEA8FE92F1E001016D220221DD10ED626017966C3450AD121365918C93091F14712BA477CF2E263296C778A2BAEEF5849455FA35CB617251E02A22DAF5C33E5AAA9F00E8ACDC50ECF47C521503C52F27D6B57C8F2B3D8F1222413E7FA4EC59296338098C9AB5A1D8A57884BD860041406D9655D17382949A03D50F1108D05BDB31CA08E66F2D8DE480C6793518D49A60D4762A9EDDC0249B422E84020ED539A14E2478F68BAB1F2B00E22A5CBB62979AC744E08B57D5B578C401A8D26D9ADD1505236082863672D911CF3A0966D303F8917093BF97AF90A7E1F9D59B09206B9CAC35110FA38D5890ED2116835CE37384F5630F1C428E213605872ECF911B014B91C2C600E8A40729D07BF918790742C9279F3114F68CDF6594CDA3CA6694223A82F66C2B4BDF3E51C6FFDC55E0FF51EFD6C934362BE7D6FABC11B8B0DADDD52108FA5FB5CA758A64377D386D45CE70605B460E8157037B5B1B2E0AEDD12A633115D6C43BC6C7C836FFF33E7D033F2E5800527164C0C4781C37DF50B66BBA5C819473A1C5302083A16F01437279D2F2DF14C878269A2F3FA40C1C761ED61501AC9EF141029038C819954089B738098708174393FEAEA7B02AE5CEF67B3C8CE6A970675CA1B8C856DCF5972508C7C6B25EE4D12D8212B98940B488EC402AC7AE3C70DF938D1288CDA7A319E085BC73A469B2D2A3303B11A683100AF6DB86937BA1182903616E3F0347BD68591B47BA65156B93F260DE59B3AEB289E2A73A3BFF38C2F3ADEDA29C7E90283AC7B86D036B47D5BA1A03EC783D250BACAE5847E41F829CB33DE08DF8F7D69C9AA4EDE8D7AB968407EED31A056BA0EF8816E127AA90065A679E1CA9550DEEF25AC5B7A34F70DCF2B116CF351F3BADA99F836C730DCC1AE03F496CF3F0387A0C2C702E2C13BDD9CF45A1CD53AB58731188B18EA8BE48D510C5812E90BCECBC6E198E708B1C08C8F864B124BB4CC0BDBBDF2C2F4E388FC19660D69CC2C0EBF91008C8243DB42DDAF57C024251C4231DF53790CE575613EE8E1C7A33C1561F3504DEAAED1E8408500623ECA5AE5A2845411749930D8E42078C032349957FC39A1DA0EAF9E87C31FFBF6AC0C1811EB28A41B1D86BD7D49AD1C468A49594956525A20A31700F122F4C4BB2252A2F3D5C5D6873838C909597BBCAD8E1333D5D617C87C8EE0F1B22383B424B4C5C627298A3BECC1B32475C9DB6B9BDC6D6DCF50000000000000000000000000000000000000000000000000000000011192834""") + ) + }; + + static KeyGenTestCase[] KeyGenTestCases65 = new KeyGenTestCase[] { + new KeyGenTestCase( + TestUtils.hexDecode(""" +70CEFB9AED5B68E018B079DA8284B9D5CAD5499ED9C265FF73588005D85C225C""") + ), + new KeyGenTestCase( + TestUtils.hexDecode(""" +4B4B71C5A1BC1074F2167A1D68729CDB9E16ABA3651FF02A0A0F4C883CAAC827""") + ), + new KeyGenTestCase( + TestUtils.hexDecode(""" +FB27DBBB4ED8F4F7D2700283C2B092866694246932EEACEE72DB730EFD172576""") + ), + new KeyGenTestCase( + TestUtils.hexDecode(""" +334ADAD056F76D74941FD87E5263E449D97C06D748A82018D0C794154C20A870""") + ), + new KeyGenTestCase( + TestUtils.hexDecode(""" +06C016CB8566F5B81F8457F56175AE77DD05C35EB37B687EAE89147DD7ED008D""") + ), + new KeyGenTestCase( + TestUtils.hexDecode(""" +AF5A2ECF442AF8C0371F89C499ABC337021992F221C1D3A66B551DEC917F1B1A""") + ), + new KeyGenTestCase( + TestUtils.hexDecode(""" +D85D7C2928288CD0B90D7269619F8D8B4EB3541F7E084CDE0E39CEFFECE9AF80""") + ), + new KeyGenTestCase( + TestUtils.hexDecode(""" +62E511A6731C2FA10DFB5F68A538CCDC1BC578C16E7EFFF458A82627438E78F2""") + ), + new KeyGenTestCase( + TestUtils.hexDecode(""" +BC4EF6C46CB18061966CD872D2CB9826B0220173E42F11B451DFF93C0577CDF5""") + ), + new KeyGenTestCase( + TestUtils.hexDecode(""" +135DF872744277E90019BD1E904DCBED63741D863E82388B61A2B069E509B25A""") + ) + }; + + static SigGenTestCase[] SigGenTestCases65 = new SigGenTestCase[] { + new SigGenTestCase( + TestUtils.hexDecode(""" +3E935D3B7DB7EE991CE774FA5B93D9BE0D108BE397EE176568296EE7F28786007CAF1156280D770245611B2D346A65FFC735A3A2E15BB20C05143D9256691B2AB41D75A90BC5E8F3B30B6F5CD05FD18992924A5B59A65AF06C0F000E74A219DD3E7604B58331DB0A0AE901C29391794417DD110BC8AAF7F62CFEFB34E00E1D1273224608140352203374007875256171864715361476150443076135107682417565754553623586606381220842166273341313626571127738336004603326033470801750142613464376064342020345044224040084303114570820783867267616511300688505780160364878830103711055618008111745151375375768600743812137557362365733331614323120366135554251746566185186844142405008812716203287601083143716200564576635047520177022180063752520164642714415327778151052008642808573380026883457436064234122618236025563058541674201723048788640112813150654403774841424453305303221148753008688031332254082078242584840286177301607176788017121684433040173755555750683651813041566084354588662418642250064747473031812374021673282486827605038055324710254455817626100000230664826103172488176531134306846024723448311740230680042148850536837730552571345643370461544610780183773451078171180104582147807556873670047488518654385284874451381580620113757112803083074314684320237100037477766105712118241161456212245656034186154017004464176334326740402832764308766445851504060640576124400281353647323214821033857545523610774625068106122683180221678260362521201302863406712350682475271635857220571525343258836275054827741877621326432020580784710353875772868341878363051856158443044548840053168838728704486521268772477031031715632770125821827468281545148686412467356360106478786427517182848466386616460707311675654327102528646248552175050554380133130605483627138568443074022187057484232375461550120577463002814013083534021237475850308467047435262471236266305063408115274535542164420053544842843632328232763503405306865145032688402018882073027571768370605424427643718688264801531460682254320658441480417081480173221048303526715882527870543270488733275488344414828021760801815571212201813874340356543310486026422086826301213865460574551547165833464571331342333324361541770188154256776002570452822671053622286151572588871378618203862708670032872331727751130056133838855585607876011010676275632625203121158641326875854128131672382381020353185780015705112326025800226563074580444604700207600183643031776082661220866111632103107372146823046820244455412421580875043257154231387817356100882747432501152565307267161430120118507744308574866233700326827552338466067211465546257660701674221148284153310844242634735382144183225241003471575543715561843716168715856042071108301012801652345045255016735805665612203238088225555235253071116306808173433031610572882372184860154863135212681745772538311183131358541040558574735410488454426065881446470864680188026246287815664520033268207530852644720764714770741540141065754171222385408035558637684376620487744584745736533387425473434280735546766515087150306388383873763030720286231050777658256536078013373573731543008080540837532054265732725301403185681580340556182751534152216780045272761136256556858461150186753280004488820172321265430428278876741152805304254EF2D2B2351896FA881A5F6022A2BD420A3D39B3B3C4A138A6F299A621979031111515B402D9040361D5C6E2DB187204FADC47A8AF07382C437E85536EABD12B61F0E50679A42EB886FDD3ABF04BB7C16FE949AEB66B30B685A0CBECBA90EC1340CBB5FE2382A534BA58AFE4A8A293079D51D7EC7C9EC515697726C23AAB9815DAC184696FF52AE3C02FF716081FD07AB10B653C3D4B47C32BFB5392D0CD22D5B99264C5B58F65A5E52C8D799C17A0473A962A6842CFD255CEBC0F20E9ACD7EFBC8A7226EA998F014C3E71535A6D8ABBEA5E8487EF2A4516A4B8354B19C03B971230BFADAE6C80DD3D234564553E2493153FD09AAFB5F06DB57B388E000D149C8AE52CB42886141316AA57FBDCEB78F815E31630C8A557FC5F54CCE95E1CB5F25AE1B62D2A1F390444FCD77EB745785F5B36CBE1433E55521165BAC3B2B0046224EBAFB4C9E74E6343AD94AA37AE932BFC770803786687392B26CA7C47124E88B8B99713453FB22C210EB6EFABBF4F07D47C01543564F6D3C6233B913EC4553E8075C97A6DEE1CF8CFEA5C167DDA8258CA69FEEDD8D46C52F3A51055E890B2351CC3A1898CF6FDF51F85F01453E64B1E6CC83E28A6C22C8BED80FB7B4D27D475BA41B9DF56EFDF8FC4EDDCB453F65D836F3BC96E43F0AC0B5645B4F8D306D7272D54F86C90FBBE4CA897DF1F56748AE6D0B0DB3277A7385EE7561B570D270C9ACE06D2A0044BE7C8BD01F3CE08EC36561911F0155922432E9045486A602AA4F06A02C300F8A71504A134EAFFFC051F1D4D42D881E30FDD5DFAAFBF9E9BF745AE0F70FC26FD404FA797D9EAA76D9065C649785F5FBC134690C7D8BD6392D4EE99C488B9EE15DEF9227868A199EF358BF08EF8DDC5E45365217A4ADE0D36AF7B0D3D744C3EA3BB26B56B9CEB374710F758BC7AA68BB346EC2DB5B5E7FFDD5F0B4CE9F25F03E72A9E2F5DB15E3B4E922CE09A57E2580CBC287903703E165BD7F42D4274AAB820EB71E8420CD47F87624727E79AC507B093D22C9E6E761DF4A3082AECE1095D3A5F101EC019F2B84ACD4BDD1F5379CAC8D7B8808485C6ED1ACD5B1A245595108B4836004D6A6D61294C1C8EBAD65A0E742B98CCC7D1D2760536B6EBD19A88D17C3598E86E5A22C0EA07BE671DE3AEF096AAE6D3B71AADB38839ACFA559818EB43A3418576F3B42DCD0E128AA022234218E616169F0BA3847F0EF62FFF4EF7D4DE803682D40A5C3B7D8F4D5FA1444470F1B66DE187B50FE42698128AA93350C20E7D37F619537C220D78C5EBEF89CA0F11C7C7A93D83F28D83A17216ADC450E25F3EB00D9F365C9F5ED69DD08B68E0BC9780F34D150329E4906D30A04E47B6B6D508DF9A945ED83E39DBFF9B0C136486D01A91D11D37B5ADB8A23D305B70609F126588C8F77B6D0614DB5364CF36EBBE9AC59D4AFA18DF530AC5ED8B58D68D0CB7BF91D65B0F392AD4B408992549F8A8FBECAF25652F0F6C4AB6F32D5B147E8D85286EBF96A5D57B17A9899E854EB4544BFCE30362F7BBA0D2FE40102EDE08EE9F43D0709CFC89B8E33FD5F3815A771C56DB8D7C788C49EEFF53AABC5E341F184F92ADAA225122D2D95E3BF03A27DA0C104C6F44A3E6EAC0CBC2F2066D17AA74A584644EAE6E2B69C32EA116C91D8D6D59C9744FC22D38EE5CFD0910DD305788BCA661463AF04090B57215E702850E85AA1C66075B15B9C9D6E9325A634CB04A6C7271CEFD9DEFDA2D4292EF1535998E5A6E65C4E51DB49E27FE2986AF02F4BEAFBE174BD75E8998651E610958188820845AAEB239D2D152B2C2597D04D7614A4439F6048D2B361FD9C558F40CE0D2D86D7F76846EB81DFB4E833127C87095DC2AAD0D7CA4FFD189C5E24A0F9CDAD4A5598F3273514703ADB5D12E7966E51A856A688CB6E25CF8C724BD9EDDCF555B90C65E28E07022BDB2D7569CC46DF613EA1E7FC1D88B02594A464387DAEBD0462A5F9C8BB46D525F9BF8B3AF7FC0D0B84DF55B2AF9E3E82A1305726B1C6D60396FD086B01BE69F91C752C5D0A587540C919FA8EAE2F5D3D72A14AE9D5E0B4DD4C8EE8084342033C93A86052ADE3A2A68E4C7B5DD599C568C9935BE59AB38ABE3556FE81306358D5F13C1C50C8E5D32F230242CF52E30C43D88C50FA030CA5FDFA88DA869F31B29A95299ECE1E4CE8575B6A633120EA76B43F30E9517728708DE1E73A27699D451C143DBF335684A643F544756B94C546593972C3543EC65EF687CA3F07302E675FE0065C1526D1353D027778E2BD04EEA31D4009701AE7B2241E32E1F9427BF820CF55A465248993114A7145615384CFB4A237C0C37F5C2C1B3AF7A62867F0DA8E4614DE7BFF6F00034AE628E64DB9FD96528A788D98FBE61211D1F22E37B978873EE78A6E871C52653D1EE0E0174699FF71B0788E7561931AA70939FE1D585D733509303507801B87189CA17BA3060A4BE85F9ABE6CCE142F8E16451EB3C51A4333827641A9361BF679E665F0E0E11F657AB9277D5E3A9EBB8DA33BCA8D37259166DC8C68A7A692B570883276450A56D984B774A10AF0BA766971DB3755AB5EDE5BB8CD6292555208B37872EFA2E7E42746576F725CA9E9FF5A6903945CB08E715D4BF468AB847210E30CD8B289D2FB745726D76A5802A4C74DF544E835D61DFEF680846EBC5F715F071FA0CF2BC3AD0B0F016C9A67162B4F926C32EA6DC7C548E859B72AB73C7A29C4F06D609C3284C784E40CD460EC149BDC17E614603F26BEB2E8AE8A0CE21E00EA3D18CE1865BE6EB0B9E9C79C170049492418CE009BAFBACD4B8AE55537D8CD8839EB42FA6921282B32EFD2A76B1A965DE1BE3CB0001069D4D80D6715F8E173BC8BB972F23020E0BA2DDF3A2D390F11F1F5BE9F6134F4276CF63C5DD6A154E133D9E1126FE55C5113F5E3485AD051B4C613E32AD3BC0793B0D955FEE79B1392AE2EDF048753BAF82EB4B739746C075CF84729A90EF60685C3F7833BB0D00895924E5A8BCBCB7BAF41C78C3705C48C28559968C947BC6FBA0E9640F8845A45C5AAA018842FCA46A25D68DCCBDE8BADEBA341F8969A3C83337EF3A6383CFA4CF9B093F7C81CD8947059CC6DB350BE20E8080A32C356BB813A714557AE66E6DF110AFFB7B11D95A82F4714D09C945554DCEE53B3A06F0860BE89E7B19459CD061154B9F86ED770AC271D7272A8D0F40BAC2BE0F95064DF20246FF3AAF3100DAA75F68CAA6C532E1181D670D94A68639A4557D5FA10AB8A016EBB94B3B367058AF40541FEF88F497EDA040B6D927A3C1F034D6C2472F8A90EACAFB61242E96FFA47D1598D6107C1B4B6703E83067A817EFA9640A6A1277E59FDAD28DEB29A70E31EC82BFDDF96DFBF7756FB6D8368F9E340065997B55B00B22057E7014CA555FBE5563EEEDD4B039835F60F753E9810B5410ADF699515080104AEC812C3EC299928C66C498B0E26B1719C690BF5A42415A6F63A9278DFA430380A821BAD0A2F8377235A260A0BC9B33E49FB980EFD770BA97FFE16183D6B1C24D0D1C3F437A1"""), + TestUtils.hexDecode(""" +E3D54DBA675DE7530D3854C8CDBD581C6E392F69CF9793D8C0BBAFEE7334C5878BF13B3BDCF1D993A47A7E8EDD4B6C3EC915A5E8FBF2071F112AAC41F08CCD8CC731143AFC223213212A5BD6B6A4026CFC9F7A41C08CB99F2B375D0E04FBBE00503533DFB869DE43566574B49232566E38B13CAF8C1EC1FA11CCA3DB66887996DFEE090D133B1D394F075F8286CA6CCE13C3977D929DEF5943461BD5A22D4BB5E8FB7EFE016932D02ECF4D7B7705412CA14508B13E61925EEC0B77460C4C089C83D687C8F70D141C75D6DF24FCDB64BB8C2721AAC9CE8C6FC4750C1686A7A70DF34957DCC0CE53C3F0D280CBD056D4F921FDEDB35AFCE5DBB348964AD105EEF5A1B07BD0D586B87ADA7CA7AFA93FB75AC0DE1C749C48BD6F192D6279482D3F9781290B88B095D73E728AFC186BFF0816C1DE78119D701FAD382C65ACC42B04D69412AEB255793839EFB9E5BBF6F69B7FDA27A44C04D3AA2FDC6101E9CEC6F75745F20E077EE23D652B7DE547A0FB0E3A153473BC824AC8A31A2C9493DE64B6D40185B60431B1B34EE32797CC77C45C71F4E04E849BF8DDFCF640B83130208DC2495C0CFC6C031B63B80FB45F47BFE3D25EC5B36C2700300D8223074C156C5D9887DE8C5A97BA36A84D7585CC065F20FE8DCE9E8EB814A1D5B7A3B7A3AB68D93EDBBBBF67BD70A0FC536C81C8D6E8B139C6B3B5EEAA3953464549CB38B78A15CE3D5BB4B798E6B142BC48C70C5BE61F82DB6E2EC03616999073574E6FB35D441B78DCAFF56B8CA8F473EC0543C9C69E93B97F95FCA58DAAED511F4440DB252EC18C90D2F97AD901716AD34EE103EAB0B7982994E21ED1AC4BD62ACE6DFE12C8C2CD092E7A7E37BD4E61B4CD51D980171F8D4253A4E7FCCABA0A513038276325372527621B0A3DFAECCD7CDFE98CB79C0662F5D0234AEEE9302438B778238BCA409D5908768779155D659E92D12CEEF3C2C954C3F1A4C2912E9EE994209B608A604D0CD87F79665A25E774E6DC1D8819B85852D9ADEB174C75D982DCE29FFDD24B7AAF5946A74C14A301AE09F1386AB17ACC341D6DAC040FA6527FCB8E095CD4F1651E47CE02E6ED76C085B2FABE9FF5A510E63E73EE386AC17D5C2C94C2D528B3A9C8902D10C1610BA70BA616C58D037F148E6332107DB9F64C579064F19481669C7888C21F0A3374194FF1A72FB6180DC01D29443BC52C318AB03843357A5A98B3D5CDDE9BC49D3ED29EF73CAF44A7849AC6DF4B2D353B6A562386BD480512108CA0ECD63BB3D3A0695679762F8254116D8049488BE6389FAC08916E6407944B1526BF03551504E40E6A3266D4E773E892EAC4DD5128374BA341EB4097E20A9BBD4E5EA26BE6FC325D9B71C232DCE1974928516EA2519974C82AEA5247627F802C6442B67FBC10E359672EEB9DFF768E9333A2166336FF0004DE5E7BCA55998C860FC1A86B75CBEB3FB5A5A2519D5227A6B5A7E0EE058FEE0CAE2B4AA75099FF098089F0261C443B13911CF3250CAE2F2906CB6454A20D0FFFE8C5AFB1DE7C5BA8CAAE00CD7C2D7219FC83FB158FD6D15EDC2924AB41C9B881566C538F5E38978C3182FBDD0C0C532A77A61E5B8E666B3C540DE976098D2BC68C0CDACF57E9BF1BDE8A7BFB13256BC69F2E386D8F458D303BAB781E537517AD7D0F0378D2F258B013AEA01C97A7E8CD2C3DEB203AA8D59084ACC2B09AD3C97EA613A2FBF297038B4E721665D512DDFE5C13F11DF4BDC0200BF610D57EA7232914752F75A544E01D5AE0DEFBC9E18695824058BDFCDDF4D5884840D2B55D6C2D6EDF475CA75F3EB4D0EDFAE99349684BC9C533EAD591085BD1D6D4E4F9B00A54C97244322D505AB52B2D4E0438C6AC5D2C3983BFB2359FB21174AC02156AE11EF233AF40A695854C84E620754419CF7ED9EA4FDACEFC8879B2EBC7B29CDF9C4CA2921E084486477C1452BC3BAF529DD92748E2B1B684B1103CF4C6EE11999E4121CFC7E2F3F6C7BB9C055F800DC46D78D9D94C3B20BD1B697411FF0B41E38173D2C9FF1CCA77B27384026ED2EE25223B0007D2930D700A20EC9159A66A4BBE0BD84DA52F006D7FAC6D59AB2BDE08FBCEB76A57FFEF59C077F9008A4A231FCC302E4DDAE9F3DAA55707C1EDCDE8042176DC7DC6377BEC58B236990AA6C5876D5A27942FFF7FD74B7DA1D2EC470CF71103A64FD2917AF4C45D4C59C13F58472AF408F9C5F907C7C6AE0F402B404AA40CF8D962EDEF7B7654EC8E36C645855BBECC1337EC18F0EA65933F4D07CEE15294139F479A16133D2BF412B5E46D5B06FB170F0C93DFB8AC3F7478002CA76B67A272A3224C8172CDD8A616A4C52F5FDE946CF5733583C53835EBC90DE3ECE34299D7E5434BF072F08A44905818EE9708815CED10E9043E88B6EF12BE72FC1169FF2F925C38E03B827CDE77740C7C2848AA3B09F555E2712B341E248772EFCF01B99CD5403642448B5243F35A3073A6DA7685AD42FECB05D46FC99F7D6B8EC56F39A7E7B3579FCD587E07C05BB7E1F5D49B9015375E09A9A14F2CDF049AC392139EAA3C2547426B8CBC0C4BA76C55014FCD3940FEA2631A75CD2FF5C22B8A65C9AF2DB1B831C30EDC8EB79B797E76D045EF0B8EFF8D41404F626DE8551FFA445885CA1E3C9BF05B5C39CD40E3B37CE3B58514BC70E2EA94CD694CA88C1F47AACF9B4FF6622C555AAB7C71EA210FAA9C0BF9089DC9C9DFA77C2C4A92F59BD7CD24EF4F8D5088DDBE22DE854F8966C017FB414464ED6B991E289F7E3FEA783831CCFB51E227A6DD4F5EF50963E80847FA6B350A2DCDA3C875D176342ED73BB42B416E58D1612C4D066F1207B6E16A955DCD557A9EA37A9F24CCB20E74AC4D6166ACEBCD7D651450E5D4AEA86DC89528DFEBE07B39A160160FEBBEE5B11122B4177FD04B0A49803E498F1BFFBA898BE3B26320966165E136F7F517FEA35EDF01D36831F9AB478CFF8241E01AD7570C26EA62439013F61D48797B92964903802AAAF356C6AF7645F5F4338C7EAD5AB2898C600123888AF42A2FE06FF03D81320FC08E7589E19887EC86CC1B08204C29E86CCF187B1240B81F7D375F3762CBC10F3BADCAD7431E59A4DC136440AA72628E17D2BCFF916DBC8A66B8A83A3C6400EA0CC57A82DB41BB28CEA9E9CECA1ED826719B9B62B6CED5B52FA518FE47274DC6E22E5F8398D42AB23572CD6623EC307FB7EF61892AE3196C48125605F4F09B9C0F0DBBFB9D9015D325C546CF3B1DC886AB0DEFE2C35CD39E2AFD13AEA74F787B410883EB72DB8CA7D225E6FE8143695BC0FE556C6CDDA493F92ED62A38E8F90CC4C713A4798984007A5CBF68F0CDCC01274C96A15C3C4355ADFC75F7DB0603918ED6CB4E4491A8569FB1A9AF32528F6E26B2303C7987E39015573521E024B2230BF1BB803BF2B358880F2840CC58ACE31E551C8E2A0F8349570741F8E93066C8F17608DE35AEC342415A4BFDD13A9757501F5246ECA49913D0F02EFF35F4B3D40DF97A64B0FD02709C0832C423543A850776ED9C0574C26CDAB8DB371F5F4B731E6F510BC09FCE3DBB58BBAE1074CCAC284D5F8068D2435E053A037E3ABDC957B74339EF0063D367F7556E49D2C7A7DE3616F5E8B703B7585F526E9306C59329A18E76B85303C31E3616831F2AA2B173CD0A43CDE76AE52EFB8CF3C381097D7A7598EC833A75E97AE4DD539C31B3E45216EF9C844008C28D12B12D3C7EA7FB89B3B5D20EF5C7636A8E83D6A9F8F7DF29C9716B7D92313048A7E14B9EDF77FEBA874B9410DCAEC4816D2FB57050696F5D4F0DB47C6183D447C5AFBCB948D09944F4271368542E377DEECD006779F6F7649B946E79BBF2E19AB4E93F142BB24E6D962F6648CD0BF1BE876F6F431E883105C3E86B973E30735A6FE17346ECBEED5D101EF0AAFBBB4C072BADAA2F4D517C272F2BD2190F5F8C87D961041A121D6B319EBC959AB0603096017BF7CBB74DBC74FB866358EF8C1AA5B9A10B2C524E822278627C0AC577AE9383C2A529054528E58D56699540E4931BC65A125EF4B459A7A5FC10E0324ACB641BA33C83A7E100CB00FFE0ABF6281F8942AE5490DCCA37BF464D0B061028E46E025FBD5F6DD6CA1BEBEE282B749FF5B002210916B9CDC4D903A95972FCECB9292A554AEBD821AB4CC50D5EA0A33A699FBF07F2CA520FC44D4A9581182290294A8FCC66DE3FB5B7F5EC5B267D1A0E6F84C27C02253649F5903389A0901797A7EC8B78AF12BF2B1CC22D291347A0F8D6EB2698AFCA7CB4C23EDF250A5B77E51EFFA3C675F1FA951D72467EDAF987D5B63DE4177535974BB2006AA9A8DD9E624108229B1C5735BB039CCE47162EB52DE88703A8BDB8ED409BC01DABADFD31EBB95CAD9026705DBAE5A2D06376320BCFAC17A7DAC957BFEE98480C7A111B5ED300447A21FE62448F62CCFF7DA68689A73A2EC70BD13130337EABF26A00BF86E52077EA00DA46FE7323780CF98B3E998BB30C3998017F4BEA455568FCD567086EC68ABC40113DB474C6C88B1C1C7588E7A8C8D2082D4C70DCB8FC3D8FBAC53CAE95286F13254253861567E4715B03E682E422C111169D96359EE18265C3CADBAB3AE61F03F86D096ADAE9A6C4820EBE3B61015995707695B42B67802FAC2D6FBB2B67801A3E48843EB83288AB52C29C1F112F9233860612BA015D4B7CABC19C6294F8871E2ECF6AF334DF9C8330971277E32CF1488F04B4B285AEEAA83BB81D54B6B8426439804B027822373AB99868EC068735C816521BD75DC19F79D2E2166B1A551C998318FE19F5079BAADB12732528BC8B522438AAD252C57D3899400913CD124D2DBE90A891D95900C0256D9DDBF939BADCF6E37E6783DA2A2BAAD872F6C8C11878ED6D5EE2988135A39F2DAC7CF127100C36D2D4E58B3A9B1D7341120FFCA0EED2E98E020A46F1AECBC809A21EF79E6DBCE76F96B6930107F078A5D4464CFEAC414CA41A5EE4F87CCD8868E7922A14C247885F0DA9E23A7604EDE703C2BE3633AF9CCC32B9E5F51CF51978F10A06F5D77C67927D80AE480E7E5E005401ED95467972ED87029029DA05DFBCF2F0B9D50441E8F15804B0A59D23CFC2E3C0FBFCB10B69AADF0B37C06DBF972E264C6CDE4142C04FFD9FA0AF2451F8BEC3FDE9723306085ECEFB17C591E691F9B4D4F796E293C0CD322F02B96938A5F7D1C8A7FEB94C031DE24E71020FF37E00590AE7CA48CA876AFCA2BE3723EAAD40FD27B90FE6EA039C9F3F6069FDBC70F16626A41678A31E8AD88DE9BCE8A25D43B86EBF80E5E426FE21606E67545FF8E55FA7D9802D65AFBDA79EF40DE924FD0DA7B5C8F6A2CF993FA6D27B2861C629CC9BD2E1E6AF04F88065614F7E24CDD19C88CF2D7D2B93B7408D898525E5141FF71D18DABAC186DCD432F3895A1027C92CF8613C80BD46E4758CA26C8CD92B74EEBC5FA5EDF9C9FEC54FEAC40F0944E3FA165E515A03DB57C205D383C04B2CBFF703939EF321DF8A49BC3F5B1409EA491062B7B9982277825B52C6CC8313BA05ABFFCDFA525445B1CFF773D28536A989D257967B50D7BEC4FDE5F338D2AE81BC8EC592BE93BDA0A7DD089057E675674E8B997B05D049CA3DBD60B7F3FB23BA5F4E5A48ED8535234E5C66C41B157C25B5D9EF5C8C0ED016D6B217F4B60BFD0DA223A5D40C2A403DE8268AD5E6207C54B217C2F009C5DD052266722DC21D4AD8314DE498692E3C77C9F8226A14F27D49E0DA1101E32E5B86BC0F0348A20A360A919EC863695D2EC318A61F654C9A1526AF1538F928DB76F9B14EF598F2551EE85D6E0429192C5F18D339DD5A280DD5B1A8F59EC1F2947996C7E190C87502FDF5004772224BBD1C4DD62A8DA1723EDB41176A9AF04B1F30D09050E73579364360DB4F98034FEC1B43E6E9E0226409E6AF1609FEB862D845994BC20E67010237B74DF1AB59EDF14B1623FDC990B87B929FB7E837B1ED905286A886F59B023F40B07A989EF7A99E974EBAEC49B45FEE1F405D11A641B2B150EBE854F7853F06026CB1287FD8BCEFB15D2AEA623D7C3ADAA00B35A105ABF2D8F9715BE65AFCC1381D29C5EF398F2B76FE1651348BAAC147CFAFF34778242B32A1620E0332EEC7AF5E750DFEC30A899452ADC530DD933A07748DD522AC20AE2B2889FAC3237D23C4472FC8C6B236D4A4D19F67264F54BB9B25318156B30EDF273BBF3598AF5B34BAD41585982F6039F6E488308B47EAEA5D21A91E5838F7D9CCC8F726EB2DB82D022BAF103AB2DD444489B94E8DDBA71E62AB6251DD5D5F69E44F377674A5C2B032150C32664C96C072867BB7A2DC29033E6BCCAEDDEA430E5E155DD0724FCBC0415B2AB6DFE68A2E59403B206BBE7F421FAAC53F66040C5CCCEB19F17BF000AEA7E775211E48AE04AB32B2EA470FF97707D9C073FE72A7B77D49FF8DEA36610C2A83306435861BE01DC4B20DBB8AA6CB780328DCFC2A32D74CABA83929CBC85E406E74EEDB727A2FB5BD9D304AF46225832858B295A17B9E710BD7B0B5D19DBBF4FD021EAF29F4D1B6BD7E78C8A3E3235B5D0BC687BD5B428D2318CF4330EC343566D42D17BE838EEEDF70F1E409C189DB1AE0A205D222C92A1ADD33B8E3B126AF62818A2DBE3E3C001098A986865C6B57D0B2F5579B97B6F101EB56FA839F8789F6774074185A8E0F383E9D8813CA1670D8B7586A3A1C27A3F5A3874C4E743EAE21BC519DCC430E281D2F73C23BAB948938A46FC24DA94647150DB72783AB3FAC01D834A8544F144779A51480643CB1ACCA0BF88D203F865664A5ECE18A88CE31B0D8FEEC585F9531329002D4FFABED01EF42AF52DDF08400C58D07E98046D77C7A142B513DA0EE795DD57EA43F4CE36C8F6D2862044945DC293C8D47D9F207B0344220E3177D6E17A4B39B22CCAE3C53D4E0DC87F70CBE9BF743CEACB8932DF8F84A527C9FB84C6CF5206EC2E43D1FF8E846DA06EBFFFB87BEC09C63E9633713768060ECA6259AAFE7C787F3947D5B94A6B80FF0A7A4785836F9A1396833347C13034040D1C6B1F83782AA6458328160FA04971DE04A16B6C031B2571DD131912CDF2515DD56983ED6EF3BBE5B3989E951BF0B99C5605C38181E96690487E87240059DE21BD220059E5D7E3C832FD4569BB7DF06437197CAC141E8FE5B369B542CBEED2F9025A030C54F0B5D2B1E79011CF2A0A0DB14312E352D07BC03E654AABAA95AFD30F1483B57BB1A74A0CDF8C9FDEBE4B0E156FE86BB1E21D861F8EBE0C4AB2B23E776EC01A281F6DA9BEC4C560668B4EEC71856E6CC41741DF2EBBD4E95B661EC24FE31B1DAABC9373CCBC82F3C13C31E478097259850221928C7AC6BB933A5631C896ACA87FB6F5E3EEF36EF5B9CE59F5676813A1A7E768FC9B8AD4A0A072672BA23CC21B21A95C9BBB1A40FDFEBD2D611B773DFA55F87E9AB1CE51CC42B0FE2FE15DA2D73F656CA56279AA16722ABAED5727519EA258794503F1808E4EBF056530B318B99A74886D05D042DF4D829C425C908B58162EE30A073D4BB7D27275B548E7A90E6D178DD27F67CD955270825FB96300C4645E4CD9C175C1185707D4D365955FCFD245A55D64EFB66308A47FC85592BFB755EB4AA8B78B541274E2C225DAD649C248E7F2792A56BFBEF704551588460B192DAFB9BF6798B7D4CECFA424AEAD675DCA081E60BBED670F9AB2316F5012E2290770D3323403DA5748BE6681565A713873A5386A6F1299F0E1EDB341FFF08325510A7F2FE5EB0302727D7355EE48ED5DF4316FD34833238690B91D47165CD4CC0454DA33B87569D38880AD92A92ABA0F24D99ED4CC977A2B4E37954FBE9B9320101C80A858122793062C7AC26E71BE2608DBD2A97CF4E884FD3255D008700FF3531C045750B2EAF7730BC9A51C675D94179DCFCE9EE63C1473D15B4319AA9EDFD19739CC05C5C3C8AA618FA9096C6648756F8AA74FD18A8CD81A2D248B856902B4D30182BFC2F392450F902973043EA0F5E6C872AD43A2D319F99F095808D83A8B02BD380D6C3F3DD227EAE2B4A4867713853D63CFF405621B1EEEEF00D5BA2FF254CDF97B4226334A9866A2B5BDF1F8E8AFDF1238DA9F48FC388A339F79D648CAA0A0A69D6F16E297663E5F4CF1AA95427E68D71E74C0A2FB6B689224BD9978F7A3A4505334774176FD87097D8AB454CABEE138F2CDFC6EF0F3DB14B09DD02E7FABE9F156654433B75B951AE3C196D670192004DC1924D1950AC597682EAD1C087ACB1461247DFAB3CD42279F9169B69B33435DB9D8994AC04B15D45007F0F98334AC5D783219B376D9ED7553F52CBADF159F69282050A4C843467AE7E4C4A142A61CCC4C48DC3AAC6B8E0A8D618E06C60DC924A943AF9000F896446CB62EF4E47AD6D1FBE2B8984A48ACD7C0519D6E87A33106E9A91C298808BF04E1267349334E6C2AC015A9F704B2DDB56D27A8B00D876AD00F62434095A6F7A5E9CD4B27FE09FF69019AE5F27330792CF9A1C07FBE98D23C4E615332A77DB5B6182D277DDFD7572DA75748DFB3B9315294EABE4B6D0FC3114B2AFF5537A6B05A7AA9ABB4930E17B7FD3D8F81AA2D674DB69AD967C8306FC3E1CA8BF78F446B26D8F2FD1AF6F7FD7E52867BCCC3B4DBD7227EA992DD995D77C4A2BC808C7A3E68FA433675F489BC503DB70115A824669E4B1861CDBD557A1F78F1A4B3582B2553AC23F12A4326EF943C56F847B8C679695614BBB1DDEA9CFB7D799CE42DF8B735FEB9DC119DBCA306DA4FA84A50F79905E5C2AC1F61241D88359EE6F62DC9D3E4A1593F41CC5F3C02241CE5EB62C28A547FCAADF1DD688F3DFBA870D9BED723B02B0B1CDB4C08D093C48977E0621930A668A5CD517A0EFFBE248B4AACF3009BAC0D47F49378F30A3D2C2800CD16B3C9464563DA4A7321082FAE95DE5645FCCBC5569E942B5F860A32F04082723E9E53F2D18099BEC5E23A916354198325FA8DAEAA3F6B7AB6AAD6EF12A03CBDC27B83C818F44"""), + TestUtils.hexDecode(""" +80A3AA584B532C5098947755BF88B40612446DC7D4CCA500DF34D9A91804FED988A4EC0F7124A5C42B7298D1784A5F6D364F7445E5F9090C0CA2C84902722A800B930AC58C45A46066A0D613DA411DF5511A5401183E2EB6B6C63486D3E2976D77D3319CAD88F01EC4429BB8C69036CF1BD891DAA369DCB525D33E9803485F666532CA7CA8321F983525E52AD2A3E363E30C7D7AC7ACC1F9A7EAEB76B7290B2DEE7C681C125AC33E9EB2B8EE080EFF7E8D3751E3C35FDB2CF58C2C9BF83DA0756A75BD92FDADF3E9F3E1637503C923802D7843787A6D947BAEB26FE64D0FCB52C2C29DDDCFAF2BFB4968E5938155F652145D00B410CAD920BCF74059908DFC0916637EE248E63C3EA0CDFBFE1B28388357206C6DBB8C0D9A23942938EB523A51774245567BE82401E8877048243D343E0D1F3F4503F8A4BE59BAAD3E76B7E2D1C2CB4234B62BAAA10642B903F5A644DF2B37E740DE63C82617C405B563BEE0008F70A33A59BCF17A38B0170F736D3D617469D39CC99E3FE9A49B94DD5E1ACD03877081658F4D0300CBD5E50B0AB094E4502BEEBBE4840CD5DE6FCB891203117980FFB033474E88AA07ED44A306115FB08440212D943C6E8896370D8FF97DD4E29ED631F05CD72B343698B8078DBA5523E471F20F4EE58ECDC30E3D4E0F0E130378B42E5521AE16088C18874703CB8A38D382FC89957F592C051749FAE68C14EA0B6E11677D65D7AFEA3516AB9B75D5F464B8E119E97ADC22CFC48729DFD3881AC6422A11E0FD883F44FDA7A7370F85FB80EED1A4D35AFD4597C173186BE56C94F275E4F2AAEA096AE8FFB8E5499DFF2A00AFAD19B40A0EE428EDBB3B64F34C4ED401BA5772D647DD20E4BCB393D053DFC6CBABE37D7544727DCD40A42E83AECC1BD8718D7B2F0A8B5E3E98A568F055A6EFD74E8D81851D745634AD5F7FFF96A5C832859F92A92E70249F38052CBAC2BE7DDD217786D5FEB80152DB1210421D53569B07346AFF582129AF9E35DE9C3A4CF2FBA7B6EFC9552503EA94A722F6F9A84E190C422883C71D60F4059F912CC773AEA6C52B2C5CDB496B056697F38F4EA2BEE6D5150E92650631DC3C35B7DDC063643F65726964575D34E0FBDBC3B144A829674BC26A21C3D7D873F70BFD2BE1F71D5BA2593C221DBD6A245045256738EE39251B1F433F4C8E0C1AEAC740952A677F72D11A0437A64188A5A8CE69A4BD56D98021B3DB19481D606BAA7263EC0ED9529B242A366B76C5EAC589BE4A3EE50B0A49852641F9102E2F63D75FE2C295D2CFF1554C77C742979F1DB719FD14D1FDD0303F5FBD3C96763CE56563D05EFF726FC1BDCC4C71257A8920A8D5777DEF74D2E175A7A2541AFCDB51249EE6010F19C9D428C774ECC455D23F7EB770B8F2AA09EB278A55AF0BE2EEF172FA12365E0D539C60FD5A5EDA381620C1775EB2F47146F1E2C5B854023C8711DDA05FF78E393D1273641CE6DA638006650439C5F32A45BE179B4CA0C4DA02D908BFAC72E47CE4A2E277991EFBDCF86BF28456A6FE93E671884EE309DDF746194369B49F76476830B242DCABB07203AC83CFF067ED83B74D201DFC633F63BB2039C82785C3A80AA6E79D303F02D134B141156C5ADC941F477E955C83B2EC1938DD6E491C1D5EB0E262F62589DB9F9BBB14856AB4AD10D450923ABE90E53D64667D87046B81CA2674A266A4F43C35A5DD0C8CA7BF90D9B8E7700970FED98BFC65D22F1D1AE7DA37709E291EDEBCE413A636FFD8FBC55D921E2C043401D68E837049C4469CB7542A3A4E3CAD8272301CF07EA827C7FC18766D43D5DE67C32CD0710963188A744B70D3EAB6950687EE42A9FBAD7FB7F1ABF8A623E0846CB9D3BF8FFE2C5B1D650E3086C809B08A01E0AB08AAD8808320B2E43F4EC80D71C1B1A9935C6755349AA3E723324FF334BB9BD2D6DEED275A1F779227BE29CF8D6302DE79776B2B59BC42837EBF82CFE344AEB2CCDBBCE412258ED39C321BF78E4D7F1350AD7070892C47A656A9579015FBC1EE340502E6592D0078293C79BF17F189F8D46AABE90C54FCBF3651A43B99A004D1FA260D7758413015EC3406B8D7E5C8A3C0D110F79A883CC13C2FE40047095A1E5D0DBF136A2D33FC04D1D5F7ABAC0D43FC083F87CEF760B4A278D90E1D5FE74E999A1A58BCE582B22807502A3135700688F8628FD12AE152A506038462F6A8B45E5CCB4440577374CB6032B75E9B92B8A4FBD2D080E2DBE7EF640370AAEDC4C75829201E17797A25EA8ECF81057F3F3BF50227ACA6B4039378BA480A07085598F249C890831A4A44A5D24AA33009A0DBBBFA5CE269F345876C7FF4B55D5ACA860DA86FFDE4EE9966C44A18A5C3A1FDAEEBE3BD0B3B9C2D92041BEE72990348993491C73BB4A813295422B4129595B359B3194010DF21F4D3FAD2CFEF725BD089AD68A2001B29D6DE815B9519850C99C5F0C8FF573B2553A4330DAF4CA5D4E98804EFD6B0D4642FE94D5835CEE0987209218E37921DEE6828F29C730AD5338B2C8550FED699D266E99651ABACA63DEACA113EF34378654EEE36D53846E5BC40C189073E85DF689612AC27215C7FF655F23273FA860CFDB866B7A40AC33A28A261BFF4434C3490292DBFE7DD54F54950ED3BAE86FB6C7B05AC2DB2D26946D0285BC571F4BADBC7944B9DC667133CD308B034B24BB5177306B73DBD7D506225ADBC8B12427E691F63D4DE76EA4C54434A57FE92FDAF6249D355D5E6F303BE70BC850520314755BC500E9C1AF6186FAC1522CF527158C491371D7596C3743A94E8ACA236600D6682EC7ACB87BEF47078722D8B7AC7EA48EEE37007E766214C0C27E97DA933913D33A02C522B26800C113336312D86E0FF38A67B09B344205062FBBF576532D22F027B79FE5CFCC50C3CE52CB6632190AF1406AC18C21183D61569E14981312744C15207124F410E8B769AE628CAFACF5CFA53421AC5E0F426D62A9BBCB8E275573941F876522085775C8B03CDCD3D67CBB50F4EFEDEC473DF28D2D881AE8CE3C1BF09F2CE9188035948C4A3693A05AFD3374EE58EAEDEFD90CD8C4FF0AE325AD8E78C38EA6EBF95D61CF46203DB6455176647D1A12CB7D7423E3871F42A8B13B1BB9C2C2D10FEC92C3F9E0B792C837C07C10AB815A359679DD22584E4EF1BE4C1DCB918A9B130C9A5E6023E6763FB8938D511DE761B7A4236015422D30C64BE39079EB5C66FD3E0BA97FE1FBB0F9F61CE878052C90435307112A2F83790DDD3C2A420ACB56C8E0D76753E3FEE5D73DFE901935A2313DCAC424200606E704F305E124A28FBC0E30E38AAF3F2ED11E27532C15664376741F70F59830D1ADBB56042F8C87DC2C989FBA6CD94AB7543D0EA696F74D1421F489F070C9A2C793CF48DB7BA4FC951CB47272E450017E3849BFF1308D3CF74D9515C04E889E424CF87D0B368DE99D9C31AA1A217DE12292040ABDF61AD972729B6B1892F72AA71A1803905B75CC61C87775BC4C721D94AD74E9916BE5758BAD7CB947CC9E250B42C9525829F070B0B0DF812B89A88ECB874E0C81F7B1FA95FDACF77C916CF8E72ECF00C319BF4093EB114465B321FD086B79832AB16F83E7253B031531288F70D94BD5C9531DB6AFD125A736B66EA40EDF68D020B49D2763B016B328D8959B08370C37CBCAAC5B12297C1F3320DD9885718B4B00DD6B10E2652A69360FC719B55723DBFA38749CFAFB440265DB48F5DA31A056A59428D3284F600E9CD497B1378451569BA3F8F1D32091642E65BB229A0E676E3A80B1E18C3A36C4D17F9901909DB8E5E2203E7DF5E02F152B1D302C31C91D8ECC3E13FBF864FADBA37AA645338597001F55C638E668A6E36794E83247DA88C84441EE126E43DEE6F3F1F201738E25E859118050647BEF46D042E14DBE46E2B189CA03245A7848FE104B08468220278E230FA454EF065BCB26CFB93B19B3B35A2C1D69E301300F50DFA168C54BCBF8673B63A7DC6AD7F56D33CACA83C1C77678777BC6239632917ADB4000D229E0ACBE4A8A243E6C57ADD4C728527A7051DFA5FC4B995A3FE3F3A6E5BB9A9D6FBEEE21CB1DFAD333F6C958C675126667F0C1CED9739F2499E79AEAEDA15DBA5C8C31986564E962FCF789608949F7FF91AD70B3431CB86D7F1A3E129BCEEA58BF56C5815C9E44B60DBF7D104B8C5D85CF05BFFD603A2F20843987A1A5B34B1182A014C5AA7F5EEF615F677AE07FD093E77CA4DE721B67760306C7565D5C764D2673E02B266921647BB5D16AC34644183BA29F3DEB5D494D063A41E7615F8DE9D8F300FFBC156B69D375D8C3881F873A98EA7F8759D5B287927D5F3EEE9A242831B7342CD495FAC2E76F25426D24BEE831557B622A3F7DA57759CB2DC91D107053CF2C3D81BF1F85D75FA9B8E6ABEBF976F9ADD4BB7F788F8592300F36AFBF1800DEC01FD44BE822CD2071E328C1F0E23F460EDF2ED9A6E6B68CBBC011A86439D8D110F56C57EF270D25C5B588BAF25684BF68CC02827A927F9902283D3F76DBF53E864C7B9E44A193D119B563385A603C3E89A3ADCC9B7B9257EA51F697E14F708419E3CAF455385585E461FBDC32C921D47BB7DC8991D01062E833A41535A6978A3E016585FA9C6E248676A7BB5BAD5070D149BC3C9DD1A5C5DB200000000000000000000000000000000000000040C12192024""") + ), + new SigGenTestCase( + TestUtils.hexDecode(""" +F392F98C9CDF8480C41F34A3BA6EECDAB55B7A7413B28B05B6D8DA29B455DA20C13C7ADADE697C19BD95F4181D9BB87ABC896C07446CC52B62F7C2883B3CCC61927D373DA98BB6B1463FCBDBC7C3A676D25788AB26706412FD08C05B130F826130DC142EBFDD884EB8FADE304455EE978A72A3A123A69246EA506F92140A8AAC301826517220457575500718444602606702737036246348057773753653026737530327720617356636110021487182406485883783500307652062837008037623504275143575413277805241337630721014485311207126464251365722038703047777860484650222507051720537247120624820142650776607686280727735633154433151782223422704163680716278603431812174820280568464342510822713206812416037802546378526410045560675630237304285416623454261283085572045668858060866837604282874804876254654326261578215675122020866578445072761231803362336526243078878567202715767743383861568417748622625301333140772280730350454860126812584207355072774075606603733422242068425724752175886643765751536756230433665412301147080035348337144751803325188375752442131056834846104747661738815140077787317821773203565820682216027654224806146185675613323671341833128465031767087642306567758113743515665083376682071584772645080206870431383757154651308356136765831320760126350481621267663254431456810768528220808107371083873767157585238851353083212225832367378252330145547815686824158782844746478735016774465466740401333310057727005121237645614476264226362084266800020031025007113888434744843115873163067161007831303825424463365517676765688324200684513347206713426521057202461184363017881817403710703264672680236531845142531570466384473731728758138705644753855655816742241364617142126084780008354140654801776325821685208137803465245450505341523100083408734674154335414845701708522128274506836754076625206872353746311412316312855531504102358752662137808638173521823133750654348485071110586741851463345337506614254157164306768776078885708514685148238201860867238133581485532340048788405422353860218008258548436878687253828241261050821015817420278763365687765514675058675166754736381757223055720684127776321362551252532374142887160764038838183424628018841887374712515033240300045651318782786054437184283851251186686603270668845482075874631015013706514675820635143655714764714156053721845140813850420508700657763114833577580426428065023467825688868337142277613856181714827028778062057570322170260362422631028183028112073851046204428683517685558417500601725657238741370857627730181360274563088823835144601056210101460602232722700431633184040618846384113624585660727717184113675546163610607728213513133205278237138625783833077538572741625110451321533127067244638480483667304517823113154663264021760688615102244052321747321612302751435786674345144462326132726376720328244761422741627313648020611868614763040681674853246228406044610051800751763205151834303188718047635724013221728118711424128888062074420703056187033803211250204407771300451054423223354033358307300448270140765437102400745208838204164114740002455888478168313785353187171180330311056851418840303151441514865342313468076524833442066721446046807704220124510652483242431018436830414063580815564337474054060760627544438122721145213236126348660A82C6DE4E1250965D63B99CEFF0EE2BF66C76EA5BD2275E36469F4F48A5C59613823B26EE15F377DD9AAED3625E4C402D971B2B83296DE5A8D861CB951ECE6BB06F787AA4275345917288245199B56E7F3093180FEB6D09F62FEF524E49F685082481B42648D09F71E623477F4D9E98E79386C060311CE9C063717B3F69C36391B555ECF819637BF03B370EB3B47B8F56EFDDAC66893EEA7DBA70BD28F35D1223829F0FE82FCBE7B0D47EDE3C72D9454CD323271ACD902A883811175068522C068B9C4CF6A819E6A141737177FA90149BCDE0E38221CE7508D32BDF4CD9605EDD630C5AB530DD0F36AF49EA3FC26BC6C0743EEB48581460BBC7836BF163E819671E821CEE4DA76177343369B9E48C73AEB48AD198E958303449D6FA0707BA74BCB777F8E9EEF95B782BF00AFF9114DC954AA6A943EBBABB85A486902222AA990E5CB09323BE672F4E96A1F0F97302300EF6B953425DFB55E8B12740E91C0684D38530B65B9D9D4A48795DD27F166860115831266455A4D29A2A928A11D17F42F56D5344C9F50BCD5066EC1B469984FE4F8B538825A016A029BC3FD608488C78805C3EC39954CB1B9EE1182D416E7658E038ED6D76099E8D9BC68E0149520AF9CBC6BE7B03F85A39726298195C58DD5DD70987ED894DA457339C0C9AEE5B1062C0F24A99DCC9D4FA5E426335449DEB5FF6FA03652EE49AB4091B79E83AD0B0F62D0392AECB0AC4C5FB3DB71E057588D4F777F4D21E3E5AA059543780A80294751338CBBC7566298EA8F067A919869BB321A09736E9DBF1EF1B825CFAE09CE2A0B0660D04B2BD78A69B48073CDDA437BD3F21B00CEE21D1B87BF3D731083CAEDA4D0835C5828B036E6471E5739DC2A7F874F8E5E2D0F66D5B01183A1AAD731B11414B304AADE217028C2D68644551BB1762D5400800709F13DB2B28A5203F0634ECFF934DF3FF920896D26FDF4D4EF9808F835DACD59BB5C44ECE1BD80034437786334910F23F208309943A3189EC42115A05CC2EC8C779F6FD9621AFD581423C2A6AD702A5A9AB15D632D9071D2E104A551218F65A44AA075B02DF27077A91C91FC1A19DDBBF4F793513AE1CFA323E72B6A01FD84FE50A27D2C3F02AED8AEBFF2D1FDCB1A16108D5655BB77C8B1D982CDCF19F82ACEC7EFD6921ECD285CBB2E45C0DE0D585A8C932943BC21160F34D7BFB6CA14CB0DBBBC9F2775ACD252E5B1279CAB1A4119B816F79BF0E46BC648D2E0FA569AB23B10C2D58DDE59C0494A9166EB882D66F6CBDB186A611F4C668F6C964453D5AA9567C48DEDEBAA84D295E46B1CB7C60462C1A9606521664F49E4DAEFAEE15BCCA53CF8FB9A16A38449F000D597072607466C4D7A2144DC520451DAAFB2CEFE1BEBE13B873409B1ED34E995E34BE5C345D408A421CBE8789D267504C923F8AD9EFABD6729FD28C0AAF9D34219C9E9E03D604335CC3224655CCB4E4DA0B60044C10E25584D6F1C434BBCDDDC2F98B2FD6D18640140972FB1D00C1F29929DFEF2822E000D6334E80CE73F453E05A13A80AECA16754A85AF59869635CC9C8805543557DD7D5081ED8C5DC0D71FB935CF8D2896915B406055B349811677F5370F1DD9B179E88DA3D6D43CC3D83220F3C79DE3817A070879A0BBBD5B0500E87EC15A2974C38997A4EAAC9967EE2DE66FDEF9CA9D340AFC5D12AA0A3287D8C9DEE1DFE957346EA23E40DB7625E8584F2F2FB610DBCCF1244646E31ED89EC62CE8FD792EA52DF83879925205F13D79CFD590C291659047811D3F97F9D1164F6087CF5A53EE97C1D7237885ACAFF30A657127F6480CF0980DA55B5FBD5E70F7F4C621F02025B1CDDAF1DCAE5BB6A60E046AEDBFD07F9B45C833039DF8F8E5FBAF5F8F1C1D7C9A3312298B557D49423C814F58D8759B53BDCCF4C34B72BD105302D23A1DC342FEC033871BB3C049826790373BA6DD72CF0EE7FACD730E801B47863D7744DC7E5EB38833134CE433611F333CB89C8392689A2CFA95792237FCE981F4C03AE35D6D8739091A0653521F3CC03B4CFAC824B6D2FF13C91C754758827ABBC642053F293F79FB04542A76DD0A65365B0AEC5B4D74D0E73E57A6CC8B4E29200A3115886185BCD42AB969D392CE9375BBBEA8FBA59AC8C4332682ED331F23BC1EAA9835318B9DD58CAD9C34A73B921EF8CEE4C33639490BDA62E12717D553745463124D5D8D71EFCE17F73E5C8F01374DBC88D5E54FEFB9D9D26070DFB675E01BE95C83D82313AFEB303F82E9AC49408D5D92B6B435570A809E0C286BFB7C18215C719D3E24406C067F90F3C20CEECFF1571781D6355A48A46235C31720631F9C8E30EB9DA0C82F7F9E9F4C58DECF6C5B3A0B1D940747F27AC0478A9B6C1360A5CAD9DBAFF568BF06C5084521EC5182CF156C57F85DF79D98AFA0F3385F01A5BD1863CF836D132DEAB0F1D0DE0BC55B66040CDF41866436C9C4459FC1921ED90D3D07965CF48AF319BAEB13F0900337D77624BF0EEF80BC93DA74599CB74AA4F921AA1AD522187AFBC3135B69866C26B7F197E791D2873C7C520CC3D8B9DD248BCCA4082FC1AA98F2E851A814D4C39FDADAF5F7FADEBC2E6CEBD684C86D82AEA07B6237E320B75E873B763E1D5D36DBEBDA522B361A2705B2CDF78BA8C5019D2DF67C41EF22A872D71CFD91F437FBA0D89FDDA36E0EBF588EBABDED491FCA8C5D0AC5F6E14FCD7D6B132CB831D1EFAE21B51BA867589AFADAE45D77054C0EED8025A4D53B04282FEC01E5D23B148C12EEDB3A5972381987BFBDCC44B0A00B35A33A546F9B05E6D77891C6FB299185017653D5673A9738666D596C83224BEE68DB80BD3519764FB0B3BA7117F17EAC1CF2F7DD9A145DA4EFC006A5779E7D66E69F9958B3D16E10671C1A9D2EF491F2544FCA21688308DFF9F5DF029CBC75ED44F0F8D2ECFAC218C498D4C0638B97F8D514B9FCC2F3ED943595F489F564C34C2AAE9072419983A15389612328648ECE830010293A281CDDF9AAD3688B75DF17B10D8836EEC5BABED4918C4E325322C91BDE46655630F45F33D88D224BC3B6C3040C86076E82C1915EDD39A00C8D38EB064D3A50E410E5A35A8415DDB0C7C942DE119059CC1ACF2A375AD3549F3C6453F1CDFB8F491512865EE8FB5A04AF38DB4F772136954FE156C98C81450396653980096676364F53617CF6740631C6D80724187EBDAFB593B48F9643A748DCAABB7E8E247CA1AB65540FEFAA6FADCB31AFEED56E7AC7B4CCA250174CA4C37F7A457171FF7BFDC2C0F4A76F159157D46DAF95C7792F5CDC668175F857121A405B595338FB04F8ECE42FE7BC5B0AFA27380AD56FA7E168B9179F560F08BE04E6F1B1F09C90FC8A94A1C6D70E7A37294D16D11D73F4BE278A99057D349D6E9F0438F037A06AE3956E3EC8B33C8CBB04CAD6DE4D8FAFBDC37F192A3EE01A10A4C499F7BC6ABDFC383EACDFA09C5451BD99A21A79E2041330C8936D17FBB8BE322DD81358AB56D858EFF712E3626319C25235CBC357050022CAC0A6968CF5FB29E9"""), + TestUtils.hexDecode(""" +DBB70175E063054DDA24BCFCAF671F820D674F1D09CA173D4A1440AAF50F1FC8FADC1810F390286AC101D60507DD285275C6F97C0D2B2CF3C7F50609CEC64EB029C3DAD8B9954807E35D4836BEDF32501D0E7143BF488CD5B4D1A53C980BC70A3794E4392E4560E609B9C49900E1C56D319E1495D085440DFD081D1A7C52C0A8F64917834C64EF32A441C9045689DDD2EC218F58B3BD534F18309E1D780528D3BD1B23DDB3B18FC1F7C85324D45C3E9B25961FA5257EC31927CA35DB25E6FAF7669D60952502680BC7B5D777D77B194D0CC40372FC8F711EB048E01BBD5676CE3F2A9FEEAA4B5F29081C34969C746208E6F2329CB53A22058C0AE0852B7127FC4C74EB3A8300403F60B8AD1F95FD2991CE0C8CE452C2432B6422EFEA8AC0E1B53BC994C606301473D7855EF86687287BF56B450D2762C5E03AF26A987317C4BFB013A6BD791EFD141AB34718A37D1DCFBB63014F7F92C9E2870DE503452E271E9D02768357E3DEF6BAC5A0F0444DEE1FF5AFC79B3562C12696FEA15815B7D9BAA38C66919D137F82FE36B140B960E02966FABA1EE9CBAA04941396D665DD2C6B0559502577541AB0CEB066E066553A2DD407354123DF14F4B1DDE6B8C34E3264161796F48DB5319B3CDDFDFDBF5CE17BCB5924984143839B4EDDDAA8F0568ECCAD253C48D00687F9A07785A67B62D28B86D70E511AE08A525F66FB15AFD112C184785F91E76852DAAA3E78CB96E20249F38979031712440DB723B022E1323818431B897DACC51400DB25635EEE41761089DC47E8EA56DD0DF60B56FC682D000E9D660D0CF38C263B716359F41F3B190D201950E140D67F50287C09D2008664341A829A074F9629DABD88BE69A6058900DE5782CC621A91376E5CA31C66E3C430CD00FAA83BF765A2E6B2FCD20EEEACCB996FB5C4B63235142BD5FFB4390F8CB95BCD5853D0226F931C38FE972FBD0D6E10DC2CF29D1FFD2653CACBAB8B81DBE44A2B8F1C5DBDA7C56252E4B35888DFF7808B3514F4D7E5EAE9B51078E8D2E600EC57200FB48EF946F021CA8209E7DC6443B37D7281C73C6A3B43AA570398E62CD5ED9A34ED23AAFEFDB7DB3141202D940C1411CEFFBCED878C0D325E8CF7FDCC520CA3377BE97855827D2E6F4EC8786EA1374E006539387924161D65782C7B2C262AF9BA8FCFCB5B1477083836129DA973AB8B082324F74BC6320646448DCC8AB56582EC72EB192D3F72255D85FFAC2B5C62F245B73191A9176BA5A9FC0ACD3AD48D37E23EFA0C65F0423AB5CD0EB76BDC035112C7A118ED47C0E67E510A6F7A28F26C3D6A882EAE74BAE6CF1FD969FEEAF6B36C85F62D40CAA26B6CA98120D612598F360CA2628F6FD608F4E1E290B32C90FF71E181D4B72978DFCD189D857DAFC7B2AF8C958EEA6894ED59AD56B9AA6F83092EFECF9EC4091BCC9B8CCA245C30B54B9B8DFF3636BEFD417F46DDD2F6136B983CFAB532FB623FAFC3CC4CE8A91434377F4DCD1607BF04E431"""), + TestUtils.hexDecode(""" +B6662CABCD010DBE21D9C8E04A2857E7C78EF2AE1D5D583D2E292257F5CF7ADFDA5AE6574FC79E58F254DE8E41D988D2EB72FFD336856AE6A0FA1BB06CB2A8A1BB588F1201B31E9E62996097FC84D41DB9A57112F3F02B2EBB572602F054551D313172B84E90E907EA6E293F1FF7446C5814CDFE2425D61F3DAD02BCC6262F816C73B87F68D2D4BC0EF41D3C659D9FCA7AE921547E442B3D0BB2620208D12932CA6F3232E98BFC2896B8FBBAA7524FAB1236298C6F743146C758AE32109CA3A1F77F96D18D7A87B608DEA8D1C83F705989D50EFC5BC2228D61C6533663B1FCE85669D0A02334831DE3F2A770D2077D4C79A5928B21596B464D7EF0ADFD463491458B1F151B2EB5A6BF87D5CD39C5CA162CB8B111336417910448CD63E074282E51E3DFF91342FEF98BFF2E40C055B57FB2BAEF5ABD42085AFD65E14B3C60A00985F3B4758C0DA6B43A8D54DFFEDC07A298F4CE70BFFB27967EC5D59B91A3F8DC79B9846AA5255B3199FA422694B9C5E6F1A1C8B494D1B2D6F093E6CEE2768B1195615DD350E9072E736911B67FC83BD6ADFA60F2DC9BAB479CC0BEB914A0E9F064ADCE261909A25DF629CD56BD3CBF8AB8107AF1E3DE33D772A4BD8100F83C91934FAAB8776CAD460CE912EE635672D3CD3B14210250BC3E742D34448F8EC576F502276549BFE3D46763875F701BCB01975FEE50157F16A652524BFA5BF6F69EF32AADC43430C7711029C88EACD391423693513127C0411E08D7B4952AD5075A09D1F14287E94B885A43A88EB3D602FD122CC1507EA88ACCBEAA3E939305C0092834F30D486FFF47D373A68B55A01934B2254FC911D122343BDAB0F2AB2278EC4CDD7D19565CFC62CC3D5937C12D313D77A5BA20A6708A43BD11480FB1C7598A55EE706E9AC6BAD2641A640B3B0DB06171E3E9CF2E4FFF16AC1719DD97CE3C21564C2410E9B03CC9792661C39677FA20757F53B859655052B6DC8923A172E1801FD2A5B309CE97B3DF50031130AB05C9A0A7E6985471BA8A92698AAB7F4CD35976AB007B4A43B8D51042514621CE3B8AE764E997C18C9E62E68C4340B03DC4C63C0C7472BAD4EE36FF470E1DB5F2CB6F136B51692A1836AE0B5A00CCBB7B81450BC51605EF4AB1717438DDB7C5F1543A59BBDB7A1C13980C227DC0A412B486481A24BBEEDCB379B1979EA058ADE841258A372AD0A25E5C0D11B87585119282E9EB471D1E944A07859B43A65396A3252F9DBDA5C5C5E52C38529EC4B9ABDBB936CD7146AA90A6E1B35864516CE15123C030853FFFCAC8E65FB30696A0D64C170A6D60918DB28B8DC763A7F31BF7F55D31C6C42BA2187E07BF8B25595435BCFF169EA715F31EB11DA382D6D1D1C20B747EE14F69C8F9D27C353EC651BE930C05AD02502AA296F01B11DFA4EAB1AB6B9E99A59561E8FDAC25DDB432890F9E383F54CD7FC530AAB05BC61500C5738B058F2DF8D789F51922A66B015BDA4420051C1E537390FC4F6C3F790329C963D907B67229CD75641F8B00D2AADE441D47763682686928AB0AF9D94736DA210B4D74259442D623058D3E8DC3B61731A9A3662182A47848B8CC7A8127826AAC45D2C03BE0B1D2697D7B2F85A774F891EB45AD17C58F532074AE1B70C3689401575C33D57CC2EC0C00B643109834D5A57D1B546DE93EBDCEBAD143D5C6AD7498335B45AAFF1AE6EEB4EEA739642A8F68E703E827DDA7EAF6FB674CE8638F50DBE7E4F1B2AA8B3300BAD6F802E3F0358F0BA8C1881104EAA8B4C9887B065EA7B0CDA8EF2354E2EC5B111750827CEA337DBC55FC88C6470FF87A8B7B50BAC4BC7CC5BBAAEDDC6BD1E9F22663602811AF94F49021C86F383E1C9E64C465D78F1C42427894012FDFBCF90916A3D38AE0095EAE52FD539FF857515EA396280099CB36167520B1EEA47AB0B1EBE680506ACD029B4DE61C7389500A5906BC56C30919BD753BABF4E6F822885F13476F1DEF4BD444C39CDF1AFA28558BA48A6F99CD0F065A18DA8281D94656D94736809EC626BCFFDDD1A777A1FA67C642D08FC30461AD69C1332FAB84B400161C3802F19E89C1E962D698C1AB1C8D61AC99987E3E7AC28A8FD42696928712A9E367CE28F48CC9D17D69463A81670E2AE088E0BE21E0A89EA9ABF1D1986DEDA702919A2C9C1CD6851B3356908FA62EC2DAC2817D5C6C874B8F6D5F92FE7617C9CC2C3C221AA2434E156FBFFE8B7C27646B93C866E2FCC1A32D2BFD859B432CC0EB4745B1145F482D03A2B22BD026BC6B37BC802D8621906DDE752AD414615296A403F9F1931EA80BD8B3928F25396166562E62C06B946853C17E30C93F67577B35E81E456952A4086907BB6049906D9E2F9D1927D0055AB0CBE11C0D82D899269D145255EC8F2DDA1FE481E3B15DE0A719391088C1647F330DA8AC990FF06CE0C957F8482C88127B2B82F68D115FFE880BBBE9D4C6DD2D9C872DD4B91A4B52C217848E38805B92507C9899484973EAC5A47C78A53A58E4219B86818DD90F5483CBBDA8B56E3A12739B7B287F29DB9ED987CE4E93079B577AB4FC421885E7951098B1B036AB3A93CD7F2FD65B75EFCB7007E8378D2BD18C13AF5CD6F8B0E5443A87649C2463BEDE2951FB7A963497668993A9ADB3690B9969596DA62549F0E5B597D3BCADA83E66F565E44A0C0B88DB3EFD076DD011141D8FE0348889F0455E3E1AD8FA47F5C8F28005C63FA4562C88AE0405A95069BCF1085909198826EEE7C86D379AAF244A7BACCE44F93D1611142421DB3C82860736016C36C89A3B6FC87509696C708C0DD2A1161F6748EA33D1989ED65D1DDB8878EF158BF1C1973060C00BC132E2407D1A4696C6CE911DD9BB4B231C961B7FB427E8577CB28960FB519C9F977B627B8A59400E72FBC12B1A207CFEF4C2D34592E0D2267D30BCA0AEA3E22C8B7A308B02652E726B2CA97179AD96C8165FE64F230E87923086431D55D1FE4208A987C61E9EA8F38CB56B7DC086A192FEEFA7AA0FE2B3975296B1EBF6604DA709B8A7169A3C610061A4E85EB42AE122A162275256DE631A54E7EC4E55DCFC3FC58FD0273333CD29731AA0E18FE0CEED334427EA9220F5E6401C68ED8B0A0BA69033CF6B9F1960DEF6BF9E5978AA7C1FD480AB685E44227A4B64651DA47AE3B27EB6029D59B2DFD1118A64A218FF7DA3779A1C0227A9E26F92DF3A7EE73382A807B71ECE108E5E46075981A2FF5152BBAE895C9B0CC66D86850DA85FA737E2F1AB80F8C2741190000793DBDF6C54482514704D09055F65F1730B05925CD1773D57849EEA88DE4A3DB8BBAF341BCAC5CCD3B56FE163249334861DF702729EF012659B8AAEE1E8D4E785767C3CB64D1319E23533164D6E789DF1501EB9A6FD7F0F14DCAB73875D4F2848EBA3329D6FD40F60C626406BAABB2B81C95DDB127D20F0FCA2422F74DC6BC3AA5256F3F9F5C80B81D1CE07D62712CA54662205B58E56B3E1684D69323B4E73D6C4F29D9F70F68D5FCC3D89965E5A1702523CCCBC08B3F6427A616C6DDE12C374643F3C7E97CF9483036835D4F928D00A673C6C22F16BE20AEA0E4DFDF88DD4172D4DA21D4200E3DAF7B3D7FDAA5659180BBB6CDA4AD79A9FCA6D5D2881826B40030314EEA07CD45539BD0BA04525DC79326B5AD649B343C23F2887226706D66899881B7CCB4CD46BAEB41E9D047E87AB8EDBE95E02672AFBEA25976319BF35C13C2C1BD042D3DFA527E69DE13C84DBE8410DDA13F38B3FAEB479ECA09F876095E5761ACF0144DD946D2DEB7BB70534E85BD2E23E1863DF685C7E873E9CE29930F3C2A8F78D77F16D4D34A91F1060B6F275DC9C57BFB49A6E5C547B9CA023E418BCAF73D8BAF604E91F5AE69F8CE08B36EC91CC920296577A83C32B07B56776E5311523C346D9590D57F036187AC1CAAB62A4ACABF360D6C4E49517E30726F26126AB405381E02F4C7CF794F8979D54E87B6FB082A8B8A0B1D0A26090A16F09E94D0CDD02886C6545F917D905A7EBDDD1EFA8E5C7763A32DECAA87ED7229C774DC4287B065D04218695B3142DB41AE748912797DDF08A4F8495334E15094B51B21734CAED59D5D2E6635DE144897575B5DD00D51F98715C220CEF67CB08FFA84AE2EB8491303D41F5EE405560930F93EF7A5D3420D203629AE0FEA310855EE7908C1346672C669025E49BA520C471FF6DF9D34FE3960A5A3957E5A007A636A457688AFECB68572B0F55EB90435578E1C75A30A18A17018A7B753E479C677995AD162E7D04AF4D4743A186031B37D9FE4FE23D274DE278FA30BC2C9EF5A5F1DBB431DDD23D8D908722350C3136D26382087BC7399C1CAA1ED4A5508AA0CD3FCD89A45119EAADB689B1D94B5F58DA23A650D52E5C77B739125E660D9836647D7371BC635690D77CF63500085A2FAE7C15ADA7654208FC88629307A2DF3916262523A61C177A7E1F8FBA729B6BCD401F8033302F83DCEF604B4C3F9A5F389C354AA4B938DD145B54A00994FCE1ECEAD40F8D819F232EFCC05FB812A764486D21295E56C4627BCD1F3EEE644DA4E32A8EA4EC4FD405B74BF49A238411AC85E15E4B6755E2EA566F2C38E858641B3486927C6428CB030D1E394A4D4F5B6B79BBF42343A74383A5C3F8FD2373C3FB2D31626ED8DE1C2B31637386CA00000000000000000000000000000000000C0F15191F26""") + ), + new SigGenTestCase( + TestUtils.hexDecode(""" +9BA12496D2759ABB2CE2C3FDB3FB71FCDD7C315B4C7C5AE5C6B4B4F6A97D2335B07CFC9C4B33D9147B6231C6B33CD876DD71889FEAE5C8875128BF0D75F72E380A1C51E6D56CCF1BB2FF2453BB7F09EC9E1FAD76A07CC6A4CD012726CF9309E9EBEC279BA77B159B515A954FEC69758F40EC0C3B3836B661E1FED121F712889B77512258675704133806066748826547111521115868474531585416005713338105507070205662844057632638535166351741357313537883572686500540128261085411603366201318374814306288785181752828400800470585613434710704510035385872517651333585207787188184062530114384673018530063727426246401400773237530844578751387817248277471125878621454431146683341406818333868760704701502761143473707860535758187372162868573323826480416420733630025672348726538053525024423653243546423514553071340770645158747722387267847757250586600731582661356526504140404107264574637750025462020601372686055328846034067308301012344312705314305867783080470360821015418216663460502701754763838654027628220553546644844707313784544085501508364158844217135802560352218345288786203528513537552882486255033112148517000583211241325641064030340235323380524631220275268447538464445758352140612704781828086872330585810217000036008674504425701420181180377803350424765338285178682720218181012520214517830318082227120513518322554881166140214761423438151247072168382748504452500004758363227304767704161305584642720280148873012060716368664714384685145586365736257431288024173772381536807648611435052307322366547752204377446868057638617731102741825234125865523273560843152782032533880776282206451272477621267326281383315581785515642825006261045510323376338070785444022023713881268480640885038174347552814543067652828245641383354501751610445443231755333835224563515134301511513821681374734335016003216522571455880410230421326311811338146248236660357671633348772574361832403770183010531215541634647651601211557845444264232368206771167634647778401370320484608854756652513571656277447284614256054125825545667871576431852286416638036374180758183634577548265761215082800487735370570835434878138206660513012214466631044531375060518448334384743777234256478821032557054374186280115238364375612238562440815877116541472770062087278326687024403300345343640711805831336621255213741538544438567453332843754315440442730654367534363248630360146213140072646271447800025357255281341257570554320245275102060221620818717848621585406508157876043725614243441752316510561605237486301154208628170146326444636374671281028428888054302763653254651680624433732312785052851001186422542016363135628821440082566635447837137437567738250604600438461732334063187876327123582736038000542537210170133043240437625172228545888471831032816233708717083020220534823336673537346268102842456807765246230548276186624233334504072552008188226324457005707040616360473678536233682028686415232708258156535400766767114686043413232745516072208330587043436465427087756584440822673872786114734048782500067420780002787748322508678107138016507217573854055248812267683351608427542745123578836475638204547465316772773558376364227627315732325112263147154784743851852416083411402663045461736077851483201053723540300740062572041704370051846EC468CE48A91039F26B5E7756BFD4A483E0805A91A1A5F54C7AB9507CC918DA35CE125C51BBB93614253ED63D269380A50B1804345C810218E0DF6EEF453AB0CD7BEBDC8AAA364E3C458E6AB8DD9E21BB72B0A499AF42763E3DAF541E0558E5E3A154C4F800CBFBB451CA73A620B3748B04C7D535088254D6267A28291CAA541EBAC426BAEB242E19EED2786BC26A40841229F2934DEF2A73A5C6F3670E681F111A3A1732CDC2813DF8772596A7D6FFD5F717F2EFAFB6BAA793C345FD4ECDA18B9202309C27D00BCCA6E51FDACDD9832A630340DA5CB703F2D68CB1C17EF8242B3F3D60579616E6102B08ED094C1D0E725E2985A0525CCBA21704364E9031E086EF875BEBD0D31A922B91E9B95F6E57985EF2948D9A7638A1C0C76145CDD9577C5585B434A790D6A87809FF6339388938E2283FE1552535DC30C3F073B7C8BC80EF42553D30FBE79BFDE391D9B7F87BD1F809FB671F49F159E4C653654239EB1E94B757E9D81E2809EFD283BD9BDE81A2D316F66BAFEDA9D4A524BB270EE43451434F5F61D33C6DCA6CE3194A3017B5DBA255E905302091D5F341293D20B89F1E5F81D5731014AB1A5EB022609FD6018662EB2EBCF6F3F823DDCB86A5C82B9BBA5741E1909CD60C1AF239FE3B930D0E8786F6ED24A6A8A26E03A05B0BA51AC54F87F845D680A1FA09291405E758712C00B9C0C8D4D698CA82641040521FCB063D5FBE2271965AFC1F4995EF47E4E307D8CF97D9D22A6BFDABCB726132FA7BBF5258226B384B7C06160AF1D0CD8CDAA4F16F68D618F417FD3E78DC8B5611052D2F9E770878D7351D52FA00847A426C9CF845711318FDE114934323D02F2C5F37B9FD93E22BC9433142095BE1D6DE07C7009162F4BBF057466E04DBF98C4DF770A2DB27A5735A4733604247E2C3AA1AF38B4D9D267EFAF31D2A3162391AF0284813D1184217F93221342D28CDF90F85F94D2F66024D1FDDFE6B95774128548611196000DEF8681CDA4555B626CF2D77A2A638AF6FFD0DF73787B955DDF5B9F0A6487C60D09A466D2F97C985CD58E4A8154CDA4CBA831ED2E386854B8EE5523DDE4D0018BD17BF03F02BE38328DE99F9424C01E6F2BCF9DA3C75CCE87558B977F5CE91C9CD3FE49A1DE4A45B162D7C4EBB4204FFDFA5A6AF4CC2DC14B7423DD9C819876E42A75709E72B18689427324ED0621AEFCE11CC766858D46ED7F1783949A8C5618AA1ECDDF332F2B6C92E5EEA5D5E7DC87908547656B65E26D9FB5B2068EA5C39CFC01021CC11C0845A3797541301E6B6C998BFFD7EB03F8B3CD7189635FB13A4E42AC5249F4398CF221C7DBE68863A8E05D3FEE54B905A64A4CB6AD5B9856081AA953D2F51C049E183C47EEAAE60F980B29680675867405F605B5FE8E13C0D3C5955F801F941CEF618F62AC6739A92A818A0F6F2B1D8E259040D190F371577AFB2289D13389579452FD1027E4CDD2BAD5F78A4E6ED722A5984665FEE58FC209AA232B38F45392970F89ECFBC0690785D87A7E54E5DF49EBD9175F530FE091624B281AB66535197122765DF0378ED4814A3A4FD60490C82517C98631C51BF9C4F0AF9F597BCFCC1C25866D2E9038D02CE583AF9D564EC7A7AC4AB7ABEA8F86269B6DA84050070CFCA06862E03039AFABEDE496FFF556031F083255CD1C46F3F94119FDB8414A6E80CFF99EAF2C5BDE4794C119D5F4A8DEB2936C2C4E249E3DBA13C0D938322A91E860D4C4D8C17AB6DE6271ABC5E4F99CE6ED0D728585A985068A0A388A51759CEA3B29CAA0FEEC27A2DB3A252AB4A18E8E477004F5522D308329197229382969DE75AA3BB3C775AB0F74FCE5E1051DCD2C2624A8EBF1F447F7417BA2B5E85EA0CE6678AE6FE0B113CAF257C7BB73D1A5D91AC0529CF7DE38792CA229D1CC519368CA4DB063FA95031F4EB0A5A647E092F59CF39C9A255957DE2EE92AE1FCC4D041DAE51BB04C6B8E5BC52CD73F31AC745DD79F27908E054A2E3906A84113FD7FD4E764AB0F21C97617A82197D1A4EF7E73408B667FF71138BA727CC26A400E5E5BBCA922B104D588640484EE4867EDBCCBC45AFEA42AFCF277A63CE6661B57B00ACC1C2F76D8C203FF2123F9079EAED0B0602BB1788595A9198568006166C61806B5D6ED03761C874E9788FBF180880F9853EEBFE2A933AFA6BE7CBE917C5919F9F17777F55A29E7CCA1455E38EBBBEDC83BB062E914F4A4A2CF1E7E32362FE97831FF33926F1CD9E99C80AAA205AC365173D5DD94B8D8F3922FB192F277A09BB7A92A5166C2CDF7F18E7DE7189ED838F7850B306576D10FF014774588865CB5EE3B161E54529B8E45B2FA435E36846E80D46CEE9BA5413BA950A448662FCC5A8BC8E42AD3A75326747A9C02A6A6C676266B580CA91AA4E9F892EC00EA64065D38063881024F5A898451623FEB3746B2108A24096F2290F98C9DAF9A4DF9746EFD5B5D9FADBC67C9C06F920E5042050CDD3A1B500764E7936124B4C742677300DAB0B2C56BA69B7CECA73A6F97C961AF46648381064764F48A5D16CFC82D9766A35171CCAE17F18C82B81BF91847766FA1C361312B0E532092F9CBEEC51A55E460B67E47E91C90013501CBE9C00E1D84985D6161691E0AB8FB540207991B3DC4A8B444F319235F3B22D03640A98C5DA08DCC417E0FC232316511447752044FDDEA962915109466284D94F7965C37F5E9518826C1BA1A94371B28DE026962AF755AA44035126E6CBDDA35A746728D6BE15618180C3EB460404696D59ED13BBB60BC71298659ECDE17F0264971C5158264D9E9006C627CCB58AC9B5AA5AEAC12105EA17AE78C1D9AA9C479917149E5CEB8C22910305F5CCFC2AA90012D2B6DFEADA3FDDE35EF41CDE929B88F7395CC6CEB401392DFAFDEE51B30A53B67969DF6AFFEACFCF455825675CC2A6F6CCE9BE60D23CC0D6ACD35E9C833A3C82CE16ABCF9E0C56A2C18D1C1F9C159867C933B6179856B9050D5AAB4A547594FCA0CFAE4969CD0B50875AD6476D9EB70674434F36935378BB00B4E50711BC0BC375449CA9FE75C0871063E5BC55567D4E082BD0B07043F9477EFC5F8DEFA13CDA03D3EEA1DEBC996B88E9F60B4909A7B3BD2DAFF53CE6B6046AC2F1463ABF3BCEF4C112AC1E625DEFDFB28BC0E0D67061492B0F64B7C66B89CD1039EFFF0546EDFFC69D14F7CE61FEA845CE360D8ECD01D1643AD4C9ECD76125CFB693DA425D877B7CA327261A0CE4AE49057C622DCFF48C6062E0AF24FF8280AAC3F21010C05B789D8FA371F48F18A2144FD1F8423112DED4DB1035B2F5E39329E680BDEEF5A37B3155BAD91DAF7B0CD8346917859D7CEEFDCA7E7C6983E09D789AD7EC35F9848B639EB1F3A1B44D78521CDAF980D6F52FF981C30605E8F5C0991A479EBFD92DBBD6CEF2FE4B0C70015943D2F1A072FFC126CFE6740DEC7DBD9DF059FA1C03A51ED2EBC7B892FF0F0D34C2DBC4C1561788CFD18F0B4A3E2C0B3EB57215C26CF7E28C544EE7372D7841D349F261660A3AD42968D98D0648975D488C2"""), + TestUtils.hexDecode(""" +5F8F32FE68B556ED1D2EB8D2BC20AA36DEC7900F8E5D4BD3715419B28771E5B0A080DEB2F3EA6CF415D40EDA46FCF8A439954471B7308D3E4226E9D5A96BC22B08FECEB4C5E3CC2239473F1C9B8DFA5A29C31D499CEEAF6E34A396BF0DA53B54F1AA674056216756DFE15F669FC2E1D8E6F67BE5BFB3D5703F25D62D3AAB0398AEDEDF7C65E051A4A8DDFC725EEE940BD0D06B103EEA32D027CC20A8C61034DC54BD5533CDB1A85107B9CFF283FC3C5FCD9C3D6F8857560311AC2E0E31585E77D0806F9A4E61A70D3FF36895ED447C55DB52002488045CC358A39475BFE8456F4FBC36005218B2CEC1C573E41BAFA7A622EDF776C8AD340680C1B3002F69D3B3D8844494EA9F42D2C9C9D2BC0BDD850BA3C4DE929C1DF49351219F95EA7B9794827FC1A1BB4A6A00809393BC41852820569D7BC6FD55339925FFDF55A0C2655C85144234FDDCA91E8BDCE8CFB7199330763F5750D71CA8C4B3BF7E6469F5DD68624BD6D5B69E5FAEEE53E3A61AE659A364484B7D2BC8A85BE9F8D35C8B97716E8202B610BDF878C1BD83187F7892BD861C09FCDA64606A185B93CD2F601C3107D35B38D76D75AD6023AFDD95E103EEB7283379BD9E44CABAD923856A599B719A18FA836749E5BA95C79B1F2F1B443CE1FD26CBD2B74A0156C381BC270B74FC42DFF8D91DE4ECDDF3053007A09B8E3C964B90DE55DE5193F218685327D8C0C6CE3BBABD57DA8772DB7CA9234A3D19BE16A895E7D14337FD9D50B4A556C75A9D287B44BA5AA4E52C3262218DDCEEE3A7BDBE1B8175E84113F515623C07BAD4FC0985112DE4D77D31290BD013562D12FF8CBC5F2BC463223AA82991D7D60E38037578BBEEED70631CEADFE49823EA3D87EC384B3FBD4974C474FF9D47F467110EA4F3FD94B5FF38D8FC1C75392896394671853FE71DDCF7730C70ED26485F395F180D2F5C31AE0C2C20691CB4BC81356225E6A72DC72A1CD3502E42C22B594118D131BA5EF95F2C18B3061139B047A24E32197F89780B91D36B28BB5EC6C03232A3CDFC5ECF687BA5701F3958FD87FC0C8D09825E8BE4E5CE9089C674049C38EC5E0FC1AD542F57B4770B6E5DDA215D319DBFFBFEAD9141647A508E271CF3B0DE7C137A5AB999CC88082FF0CD495F1F1FB1E367B57BB400D8697B4620B75FE467D9B8BDF9400E14047576B3AD6AABE0C0714686015B8A963A0DBB68CE9E41FFBBDD5A792920916538E4C33F12EF0E93D249E562B71BC1C252E1DD8AA646F8C7B489A2BCFE7D29A6D3FDA2C21DDD78179861AFC766F6885E9959F753C66462DAA6E01C8B06A6F581104B583F7A5B1B4935A4EF08219FA8D114A963F3FF3AF22C3D1C1E3927AEBC886AD0670FC89C08FD4DF68EB990A0F7C51A4439C32F5F51785B20DC82586940C35D80A91865C3154D6C925250B24D4C1A9E76A267711A0813E8CCD2DDE9748FA0464006DDBA963BBDABAADD377239442DFEC6F7E8098604645D63AEA080C1F749CAC589F77B4AE0955FABED757E6576966D539FE1BE5965D03882279B2C9B6899205C9DE8D0B1819DA8B5426E573CE785FEDA3BE95A18A667AD5AA8FCE7894BA11A44B266EB7571A93CF9FA64C1132AE07F0F24773C83DED2C2885D415ABD96A21A0381811D66952252786C39EB68EF0B9B03BA7E2B66A49BC6CFCD8097C321A932E5CDB11EC6E43A8E50DDE01EA5A28F08F5047C67C988E8B4A04701A0237330598ADE8EF8F801A07F2148B44E593B0ED16DA30BF37A341073C6A92066645BD7042C3A59B374FDAC00F7F69BDAFCAE5EC0AE65FCFB785C93E49102F5A5029876BC23B0FDB7FBBC376A9E834F0D19A276BC4E22FEDA18FAB529F15570AB674B844703B47D726AADE3AD4015F52D86843A01AD5DF086E07A71A0236765DE6A777F94B1D69253A424193FA9DF54899AD9915634DA23E6DF351E9608219684EC8C8C949E900718DB6FDCD144D0BBFE1079C1BAEC516BF60C1E24B8EE6DC380F55E0F65DD64025C937EA89FD12F0404ED0C03CBA18CE2FCF169F9A1EC9B96830FAD0149D4A90B13446347CE4E5C6005BF115385F1D22EF6A7E40EE87847BFDA4CF7FC3135C4164091F49DD08389E1005271E9AC76E27B0CDF360EEBEA9C08E233CA58305CB276A8BEC9686CDE0E2DB5CFF9858029F3A5A42759E4AC6DD40AF9617CDEB03FB1F9D7F112A01B87A265C4E27BBFF596695F127A97E1558A68BB5EE4EF0F44D20F318FEE1CE988051F3C09AF6E142932EFE970C1B0C07040E7F3DB9BA53BC4AB1433F7A4F1E480D920C23A07223D7E43570320B3BA590507D580D29CC3A8C85A442BECED5880350F9D2B1AB5C746C1B9909E446D9508D701204F2427F41E043A78024EE3F60EE19B71B5BC925A2557FAA8C7BAC7E3405C920FE3FB3A1BA7C559BD75DB1E4169804B6627AEF19AE6E41B8A40CFB977C1AF53208F4D775A48C220A756783F41E13B7780328992947D215C5B5682DEC76CB035B41C007CE1017EEFBA426EBC423F710C1E962528F7636F200C2E79D8377D621513BA7EB3EE5A0DA55B81F6039D2E8BD42EBA5B2A82C3F033CFEED6EFA7D970B1460CEACD13A0C67AC0A7EBE7963F0FE21D20B2A82EA922FD889253B5D4CE4D47698D43AC11A8F4E1638AD3A4C179C522A3ABBDF420DA3E89B9FB7608822904944CAD615C62B28EDB15D3826D33DCF9FF9BD5DFD8639AF4CAEAA55F9F8409B4E5F70681BB7861F88283218E15A4282E199BFA12360FFB9BCD68D9BE5A3411FCA4E8279562F595FAAE0CEED4FE675DA4A8FF94B180AE9D0C8C687650730F05715820F67248D02EAD4C7BC0D41C880444B94CCD60A66A1C9B5B6F6690A2E1766EE10B5D03AC16F175603A1B9D49F97CF3F91932E97DE67CB523A38839468EE7681909CE997BFE5EEB364B472220403EE4A9AC1F8A4A8F78AFA4D9010A0127C0A75D3CDD87DD269F19A47C78F696218F25AE8A61073644A4F791ABBF1B180267AE41DD44AF65EC6E0AB356CFEE86095B64F4190D69D60284A1EB42744C31536F736AFFFFF186833EBBF43709BBE6903A06F7F06E8776D2AE41CFCA33A3A86342BD11B67EC10F525563A1843C8443546C1EE61DAF7310802AE9C00F44DBE7E04030BC4D0F53AE2023A7647F08A0BC6F5013A61A84E994FE0A20092DE133FABAE3AA24F8F3946812396B0643721AA13417A2423F96CA8A6529B0E17766E88B2AEBD79AA9D4D31193533CE50E4EBDAEEC976F156D5DE5917D54F9CC0527BB4F1F795401210739A42D10A0242748DE5FF6B50932B507057EECF8A1E37800223378642DEDADB464F5CA251D73DCD28A1E3772CC285A33B34C6701B585FC03C94A847CF7B16616D1C3DD646669546D80A27E9DE6424AA7AF6F1694037E774259308E71E15D7408BC1EB517CF0AA2C9E16B802CC8553458BB66D96CBA233487DAAD6E093235D901CF46F31B9A060D88DBD0B7380652EFC73AC1A6BB5E434EB0394F1EDC937E9A99A3867EB71D6E19622137B009D36ED7F9890187CCCE7D884DFE118AB3682EC08CDA8BA6DD4B79C9C18E7438E6914DC1C403870A540B74244964CA31E730A7D7591E42569532DA8094559241F2C7EC182FF8BB5A3F88DFCE3020D8B8CC0D1F54CF67FFD3A97CBA7F5EC79333D9A545221C963E0685763E59F1EBD34FB2394727896CE638E909AE6DFF41D17EE1D0BA036F8AF11335A8C1B5A0E9DC58EAB9C12F46740493A8B5AD0EAA73AF462BDF43CE44BD0973688D9C8DFF8FED961758E1AF88FD5D249FFEC179FE5AA1D135C0448D80F4B0CB68492CA399A3916A2EAB684B44E407706CC3C2F48972BC9531353091F91B427FA32693906DCAE862F34AEBBAEFD30666523EA9C27354F2FCD99A6E810685B51965571E4B4B5AAE158636497B6F952FA0B73617AE35A8D7C272DFEA1CE06E983CC65A501F73BE9D69EDDE6A4A1764DCC4B74EF09EC27C74B677920AE8C49CF4F18160E04B5AE7EFA8D5D92BAA5E4E547CC8AFB9D55F1A9DA7A6AA06626673431889C9996BE0A473702450B960231A617DF4705B07B47DBA1BCCC0EFCD5713F88F394EC4BFCC49EC24B76D531A356A6796785D755F027C664D8966B5CDC82ADE776BEECA8AB0D9DB6ACF5E841BCB4381828DB8F7358A637D04D97598A8B3BC823B891F5EB6ECF54E6F9200C380813FC3210E68894A656796C9A5B780FF486E6A93DE055B8F658FEA17035D9C212D23BB5974E1161E4F6041E5AEC446D70D52CD2F21F1A33C9938032487D9ABA74C448EEB8F8D51169E8B848242F5C769B471F0AF04E965BB0F4AE7C6F7B4AAD4E283DA762DFA49FD01D21887ADB28781FEFBD931AD8E2A26BBBBE5D88B52E8B7133134CA76C6648EA39E3D2F102177F4237219E06CBD05174D503C9288EC9C3E0128A824A7ABF418DC45EEB3A67777F74D6EC52891EAE0BB56DC756ADF40D39151E3A68719C563E99BABCA4C785BF4C2BB1BD25C7EEE22A8B0C1E90B948FC3A691670E9A3A331320CA4416B492907C3FE70AF9A2E765F9607EE1BB2CE52D2DB15F5DDCF59BDCCCB5BEBAC2784FA0896BEECF38C24022046E5DAA7607E8D2DB8CBC65541CFC6A0F20CC3AC5EBD4560BF5E9A3FFC0BAE917B479D960ABFC99EF84A696CE5A95720FED90F3AC58D77D48BD5573A0D85681238AC0EA8F0B58A01378929C691C146068897C5642DE74D79E08E5B94B101182200FB3E2BBFEFC8B44D2D1203075862D77A184B25A7790D76D7CE88C979D73E599C212F04A8B01EC3CD6CED3B5E25487957C56BEF6AB4433FFFE6DBDEA396212A6870284FD1BAACD5F7A5D9FAB90D5DA39D3C5F9AF196D9C46100BF45861679A7679638BBC8E5B5A7606D863478B430BF2C61F52D3D88B0913BF12597620D337DEA52BEE9CC8A1592698D23B23815C596981152C99453FA16800545EE781F24841FBE5A3E5AD8D08F2B898127AF40A681DF9DB68681533C349109C29D19311BEAB4C2F2DE97A5345EA7E41CC0988B2042925F1F9409D947128CE1D38F278863385A19B2CF8338D0FF31B06FD865B9167488EA157C7965F4679286077894660F17BC7289BEFFA93CB7DB990A0E40D998945A77E536902FBAD3C8A278CFE0AC883BBEA0B20E5D70EC6E10B59C2449CD1A0B55F8252C91CDC87E70E72FEC175D6D67BD43CB5AE4EE9C7F9476F4589E2BBAF89E801D5E14458F8A0B96ECF9F080E5150E2A5004C5A89B735639621157C4056DD1106CFC727B921D5890F37051E2B906885C1CA3999C18FB8C9FC9B652D82AFF074EECA9976D612ADDE990DEA418031FEFC4E972B31CBCBDCA0469E3966FF6F97F9788650298DB71CEDFC04659D30FE673602659C19A869FB3EF4262EF3FFA9E3FFAB1A3FE7670061EBB0D49BC60AD0C774913910E26E4213B76DB72AEFA3CCC197CB6F6DF773F86F12480B5BBC2068F61E16D1C0C141AE6F1811B2E0D713AAF60B90BB2F00EEDD4651FB5191DE5A246A4D8F3E9999D85253FA705CD4B94A6A64D9E9B6E18BB6855CAF6B991494A8DF75E56C2A427883E0C27246E5854B8DB2EB0FE639BDD00AD678D1B61D799AC59ADFF6A8616B357A4B12A786EB612E5613CDE533D92E87D51D47D860BCC39687485EA814DC5F5A971EE915C193ED52AED98D7AB301E32342F3D207BC03546460D33B733E1008E48D80E716FD717BA82403DBB520246AC3BC9CB91CC0ECDB7E35E6863C3C11558A8EAE9E1DC49FBFFC0F92F397828A4AE7107785939B96932B9EACB6BC6D8B3A189B5D3F6B0C7A3A413054B25318792AEBA3F4C77629F1E8CE1AAA98FFE1EF50C2E60C11AD76EDDCD8EEAF858364ADD637AB97ACBE4D2124AC0AB559E85229F1B5D81701EEB1D6834FB215984E9DF3847392EB29D2A428DAE7FAC283F93C8FED86FD2377E8216922D46A51E628091F6F8EAF967740B0EFD84F002358D3ABEDA0993DA16D0D8233090A2CD9C27D78DA0A53962FE7DD282B276A30F91C2B734EAD2CCE5E03137205BD97739F6CD75A08491D4ECB22591A6FF840B5DF123FCA7DAA98B11C85C1F8591EB988024C206CDC4A4239E7A91DE75F49541FFB6D91BE4699C0C0D8B4A44A8204F7E90AB863C3183C2270D185643D6A7165C1D043FC5108C340650F38A8FFBB13BE4BE68858C50A2463F7BE998286FFD0F981B45F5E414FDE71637D6EE77B33E10A530C630D63F21A212E844C2F7A26BED4F7B4DCE0C566CBAEF4EB4BDF2B53E743EE13A845D3C7AD5E9525C50CFED35DAF5D993B6377CF1DFC5236D51151B046F4904A02D7D51B6E331754B0E3621DE4CAFC9D8F7247788DF0EA7E6141FAC4B24608282AE29D594CEC0C82DB05C0087AB377D0D504F64F1CBB2D9F3121087AB6F35A70ECDDD15C9AD2A185C16333BB901CA069BBB0B80CB6F505FB3F382CED72CDE60FC050241B1D32818D11AC4421B66CD85D0F7B479C021AC111F8EE8F1C60B2320585EA276879AFE4034DBA277806FEEACE548CA0A5D36CFAE7B99ECB0236CF4838254A20A13A2DEAAF201B09FD027BAFC3F0C5ECA9EB5850A58C6196645F051E57B82AF4B6C2DA9441358BFD2412864950022A07542601631A00E27BCE6E203B1D3F1B844CCBB2EEF71A12AA4E725188073004849A225D733C77C068B0D2AE53E0DA6F759A8E7A5486C529B29A3EDADA69924E7DC200158DB4B612C62039B321CDACE8294DBB1A56ADC685B0B0122A4F3DE0A264F47B00C903BD30B5E4281B0C75DAC5C48E18BB0BF642F8C2CA194AE56CF7EF3B4529FB9271774108C61198A6894FC9FAF896472D1CE78DF00E714045C5F7C77DCEA45B3ED5BE5AD545D8F3833206340A5E10DD3375BDE0A068D050CB4C87E0BA95CBACBE59280BD5CABCEAFC88F5C05E3D8DCDA6B15C487B62B467E093259230D47B79F36572972BB78F90BD384255CFB1E4F1DFB7B5360EBE1230F154C3645A7A233FDDC472432F6C845CE86B078D93A5BBA3F8800C5313593D66A8A103B01377FBC5C6D5FB8A55DC71EB0BC9904B24BAD2F505D6DB5640E914D84FC71FA058902578B72C47659AC07AD4D64C3D28328D2DC8425C4039EFB2F20E3B954BD0B0483848F2C2D9528214514510CB0932F7506E9B98D0E891D8183A907FCA7AEC068B9FDF7F3479A128C6982BED19512A4271D8B682525B5028B77D6B6301181B403E5F62F64BA3CF06F0EDF321114855839E9198E5BA2A65ED952B2204809215B9BA3C366FD5C9D409BD71ACB748E653DA82EBF617D2D57C74CE37BF20AD8D789DA53C086423D86F94A96ABA379F3425554BCF92F82FBBF5C2A15947455D7D7478A84BEC6E3B9FAA14E425D2C8971DCD157C1D9E210620E891AA4304CDEC54BA7B3352556C49A172EAF19919184CA005A526349918F9A7CBFEB83510AD899BAEFD3D1F689DC3F449153597C8D21FA1C7BAF18E689B51F89B9BEF196193B7A781B96B38B9145AF7338FCFEA109542BB1719C9C8540B551A35F733C394F7831900452C0B8D36BB90824699BDB587EFCF5E8410E4ACB8ECAEC5F96E74A5DD3DCD4C85720064A14028FE768041BA1A13A46CD8A0D2C4D09E724591ADCD5EB907038853D8C92C5BA7FF57D5B54B2B324073C7CD2EACE0C521254E9E5C0CA197FDB3C1AC73FA8EDA729A858098E6F5EC11A19D4F655C6DC9AFFC4E67A49EF62D80EFBCAA383DD3DDC22C2A9B7590C16F8CF23D52392186B95EF9E947D851079C35FA11595682DF4EF4D770EB16CBC3994326B8AB3B2C279149122D178BC7B53318406738290596449D797F61B3D0CC8B11750F8D841FDD9D333A5FECC67CC7733824BBE257D40E53B43CCA19C95ACCA8FFF393533AED57D423BE0C38584A81689248BC7F78CB7FA4C94A7BDBF3015B4072B83748E55ABBF4A334AED679D89E2F18BE1B249B3F61363C79AEF6E1FB09D1948610F77A9927AD6D57BEDA02BB1E77415DD7FDD3EFC683AFB1E20C08284B620EB091974FDF8CEFBCEE1461C210E81E86B61F2D5D1882261D60D60689E39C81B981EAEBD9A42E608A34155516E4E385B86BF0A4AA05E3F99B6B3B7E401724D1442A45A696A189765BCA3240111E9259DE161DADB4E0ACFF27818C631A8A2ABD752773A83DC29CD619A58556040A7B27CF56086BD499F8B8D283683377A21BE120374B8D4561AFE781F246AD987E828FB40306366B4BF4C0B4B909ECA91DC85F521ED5869A2F2AD58C74B6C959AC71DB6F11503F026DFFF6BDE6BD70363B5B38BCA0590A5AF2A1054209A36B41B2A671293F2805568400AB282F783C356DDE30E0F87C001D9B1B9716A7C4021928253622F2DD156B3C3038A077A5768AB8AC070BBD9467E9C9630754934186BDA122CEA503F5E274EAED746065CA81A2702B582E82A33CF6CB3917D451FF59B0909E6BF847E6B610DA89AFF98B3323E1385954EDF1175C0C1B158CB905BCFD9AE7FF9389ABB9FBC5194A45DEB0570C58F31D914F9941B0242717B243ABCF5A20676051978C16FFCAA8ED2EA23B8323CD58388860DD64FA39971F9FAB83A4B248EC8161D32565917B7E6EB4937B4743C6C236E75E1747A1C83377FD1D927D385D81A9EA7F4AE5034097A0A77E2D2EB1943D3128BC0134F2D600ABB929A5281C26EDE1C12CDC80F8EAF2E893091EA274EDA1A246AEA3263E43D6C60043CFF6282AAAC620A21B523783E0CBE33F78C89D00EF8920CD53C6EC0E83DD7E1303D9B6D5280BD2BBA26376C17099758F34C22054DA031C86CC50367C81C3059114A71C565B1702981D77040B0FEC1E89436ED1896E93BA202F11ED2BA4EF33A76F86AE8E23B8FD064C8FE894244C97BA7BDA6BB56B7517C236400F591E4F28050C2958A7A79964AF233CFF8655F1603F6A0C7ACCF440D0C82D5528876721434C163D86858B02C6F6A660F53B3E45185FC7777A629C3E4392AEE4A96D900B0F19783DCB6E5028B6E56E160A37D37FACD7C3B992773ABC8AE1ACD6AD41E7340CB198C9BBEA1CDC185AEEB51E2620F0695C2691A29CBCA8E23328E84B6882A59A8C3C2A273CDBD26965564F1F1DF0B2CAF83F30E782C049DBC00596BD85426EA90ED30ED8EAE8A88C0D1363E69868E8CAE56E8DD62CB36D9A15150FE567DF7DC93CE78706BA983885155C9AF05B5FF1D0EBFD9D020BAA9196D9C871236DBEE8A703BE458938D3C882719881BD49476386387DA3508780878271C0DA821BAA1E9719E437BEE6294D8E4E2483932D0257B44B8CCD8C55028B3B7D2BB3866216A7F52CAEBFA0FBAE120609F95213BC05AE24473C98C29F4A46D985336DF8305787A0374098DB279EF0E34E6DD79BDB106EEA24E4DEEAB6DF35C58AE73FEC926174E0942D242AF0D30825274FA1D510D1C0C41FFF59A4381CCE5C6B89AF30C41733EF42E76C9CD58DEA7E881706843BA04E3A170304C551B6C801CAF9B8DA52913D2DD4DC755E0BD7C723C4AA5B001D9855236401C1014507CCB84577749DB1AF29E318241D91C4B23BD80549CD1D6E0D793E966A8A7B755552F16D3A1146B0CC6D92C8C90E97D7EC8EEE7C365697F93AF257BE24691E41F2AD26BCF47D52A1B80F5BE1C658616537630088CB6E227B0EE6EB8DB2FEC0284E58202A73CF3AEC16BAEB59D2A6E0257F0ABDE5926D9A13D89A8B2F69695BA3682E87A77DE06FF54892F56581FB16991654F60EA22856D6FF9E0BE2C4837F0C1F6C54E840F67A75185F0DE9439AB1E37D4FB3E9757B0FBD17C89DF8568755567C390032DE93E9C93E6C89B2E66E9E9D96616919D9FB461F9F33"""), + TestUtils.hexDecode(""" +E2B72659B75C1F48D3ECCE4E6543C8C79DBA860CFFCBBEFB69AF338A4816ADBA6E6673112627712B5370954A29F9C896AF05012B290C6171DA9E894EA53A94F6C87D096F6DFDC0D77ED5BBD368E4F0CA642DCF6C89462C1E694F8B9C67F641CC2859EC7289A85FA82CC1984B5FE045DA7814CA6F693D144DA720D33F1619E74E9435DAEC3B4D64888CE2525FDB063FF6C4578A3C783B364C80CF09B10D2868DA846858E742E7F5E5845C49B4694E812C39D021CFBDEC8172A6F489C8D0A5D57241A8F676CBD02446725B6B2C0A51AEC4EE63339477F0D7B7DA74B7D343AC283B6BC38D79DE45FC28E20D4BAE6D7E9DB775E4801ACD3FA93E05818031BFD882905962BBAF1A6CB0543C68A6A1232E6BFC1B820C53DDB53CBD62A849FA24BF289589C860F32F35C42F0C04C24750A47307B07BC610E1B6D7BA61FA2DF526DD836A656FCE196A8FB708DAD7F85CCDFE288E2DF71F3BBF9C0CC6F48ECAAD507AEA35FFAEE1E7DBB53FA9617583EE72DEB3DBADA8208E19C584F034D75B50F0927DA9CF2793A1218298434C32726351A48428F94A19A7A286CD99141F97301024B6CB6823A199B3EC759ACC3A7CC20D43072A5E8112ABCDDA6A17C1D9DA1FEB4552B07575FCA4B697EB8165BD0DE2403AE19DE5CBD60FB21059010C3C4D2B0DCD918321DBD7F94D59E0B08825872083FF50847A3457ABB30C5C32E4DF9735553FECC558412A22D46A165AF38A07CE0E2E1F888A5DAA2F9D39870F008E38291208F7D2FE2D75BB4E5B6DBB16662A1DEFBE0C4145CF91BD2E66A670DA776993F60A4757CA5BA0C55BADBDB1C0BE86D290D3F00EE241243CBB9CDF5B3A93DAF95840C55320B931C6E3EC9389B117E7BBF23EB6192965AF97DFC89EA6D2580A9CA0C699A66E22FB7354F203FEFFDC4934251A8488A15C3491C3C6E5DAE8C828EE56D97723C83164AD15437B62F4B06133402A3F1A261D08F6091CC5C46C517DA95717FE632FCE49C659D93BE9417AD1507315915F1C48F20A66F5F08352C83E75775D27F76B1DD73961D50F289391FE376977817D12D7C9591FA2832AC84EB00A8286841812F8C120EBEF5FA71F79AC3CE6C77862D2121B4B21A33459566998CDFF4A0E614CD6CB72F5AA2643A3A61D8104CCFB041E94D433AC6D10352049B4C104005191284CC9B23942D90F3C53D05DF898394EEE9E041B735BBC85F20D454ADBC84D3769412F5E6B06303C503BF1C29E43F93AC993BCFC20250A38BD862E7348AEE4E693B1F99FAAD7B7E8D3F5AC1CF8A192D894AA3BDC356106F4C212954B25D86EDF4FE97ABA3030EB20A9DD48CAAB2955F830523745B0208EA35AE42AE06383F8CDAD8E66D5A988D95D1DCD310C9A6AC53DC448AA80B21B78C2CCF3E46B447EE9E9E0E090BB6DBC1AA4D5A6444283CCD5E01438CD92226A4FEFA67EBE63480AA072FAB17BFC0FB0E0901B5DADB7C29631B3E3022574889681478E02D5C81B7C676122A1E7AE441D16E090D5EE64A17033D0D0C6953324C5E476C652922FF1F1E47F833C3FB1705E5CAEC5B57AB93D192CDAF9CA712AC0BA70F36D71A37D366BD80A7BB3E382EA87EC5A1F6B281C01F8667C4100906D713B83DB6A50C8C527846EB728B173CEB9B6791845C7749AFFB6C72F362CF602D70452512C76DDE9D1E76988F3C6EB14B43EF02D1081E6FD446576CE727DE20F6B25214DAB404B4D77ED2DA703DFC0E4219D44CDE16F596025C9E90BC0B52649AE81E95990EAA115368A9C6B16F64099C8B928EA42168CFC544445847EC42FCFDE6095FFAECFEA31515FA4970B27649C81B49B4AEC86D1329EB1F5B5AD04851651BAE0236C267728F1B0B8939B0849D9CDA009535E066990C664F160F5B8387D93CCA6DC94C8AC8E5A161F0D4E71417F43775F7AAB83550BA7DF60AB7D58DA72205F6F52F98A5B73C6608EE34ED7758D15AE7360832F929B73E8041B35D4D428FFCA023781B26EB65C8D3A5394B8EDB1A23EF228850F32C19E8C8638F6E3E8D64BA7346AA7BE8356CD61C0648F19FF1E959951A2B92B635588FA51CFEDCE28FE0EFF9B00EE81675223A8EADE3476EDF74D688C57C68E78FE3557D97198D74648CB71FB218A056165590A03E4AE830E8DAE1FBDE2B65964A2A9DFDD75E7FEF4C11842DDD8DE5B7ED553940AD6C74EB10802F5607668192FA7138E385CA14C99DE873F48837FF593F5EAAC30FC7AEE7FD0CBAAE64447EFFBA244AA0DB2CF145030EA2CB6738D95DF990E8B6B981675ACF4C4CA0DA779BEF86116AEB5CA18010CCC8F971151C5B61E2C106C5DD38CB9F7122AC17222163EBEEF8FC9DB9FBFE8F9631996537DFB7B7080A466CE52EF5459315ADA3C8E8D748CE5BBC02D326D676247D8F6207AFCFF6B9877B4ED1082C283A27B8612EE26C9EC76415C14393ABF8FF2F8E54C62CD56AFAE745FA698EFAB0AE19C4F1BABBAB440B71DE8510B7B664A9B9F8F80C4DD125549C0546D4D42CC39022D1BB599BCE77D24B4AB8EB1392C7B0160C9BD376B3FCF822B3DB1DD6E61A3EA2C5369C7C1DDBE7238015196154B94201F935CDB203D8D82C29DB4846ECD7F99E8A8FAFA204C5C800D7A6D0E15791E197E86AF298116E2E4BBAA7365A51CE82AB819B2343B05DE001EAD2E0939F8D21CE2482F65686E5B1DB274DBD223E97F0D094CD4E69A198751CA2AEFA95C937EAF7A52245D560F9126EB4B9F5EE30A119584AABF46AF32D0507E1F7D78175A919CE7678B8A120E169D502B02D9802C02FAFBBD5437EBC4EC674E21DEFA246A471ED242326B523917DFE2E41C1D77AD867D64C09E711CECDCEA9028BA620FD799209A93BFCB7E36EEA2971F977E99326F2F54387752BD19EA29C90CA3C09D9A02740551EDA36D7687CEF24A6D35878B44235E8147D1B752C2BC56BDC86B41588522881E7A9E290B0B2D2B2EA2F56A3C770C7BC2C144F0CAC497C181B0823BC6BE8387FA22A448A9EA92BC4DF5F6CFC946705F20D4C1091CD96C67206DC804969225C0CB11A4A1B476EB557AFEE3AF5A18E763080E723A60359325053C16BADEE646244148DBED40C598A8DE738F5546CDE8ECF09FB14ECD37E7F9A5B622701D92147C32D324FF9525BFB30E85305D0A4EE82DE52BAD8AD6A5D66BECE7002C115B954DEF31F9DDC7E87AF4C37552CE4027606044AE792882750C8ADD98B6ACFBCA0C087ED65276884642FED7AA393B7ABB5C35EB7F3A4922D97EE16AFC0043A21495D1D1D269327F9DFA44195E205F6603234B067C20D09229772354041771CD1AFB30F11981B6027DA1B3A6F465300AC5C0E41FBDEF7D0DDB432DE67C814B76A7733C5A84637E56D7D620AB3B37EEB81DF16093B5612D784873F84E6AB6E28827625F1981AE31E3F78BC4F68F215F4145FFD9530DDA56FB1F67BFC6ACE5C647F0D3CCB2A8255449638A65E3F070FC200B7CEC52C370A86C02188B3F8BD809227F08021C1CFF8583DC561EC62CAF8C2CF878A25C8C62004E4803C15837F2A8FB76A2FF611CDB597B793363F9F1A02D2026E2A87FF4BAAD424D44B24BAAF7472E36ECCEB0AB87359AB317F880E5E112EAB060D8B1A6EAB5C135D5458E628F43F054C8CF2D19966319A9894135FFBDC0E5035A1D2B4418E466C8556DC71348A34082B07C6725B8963F97D2003BCC9E4208F4B28EBA007973C582E9FB315BA0AE288332B94495E2436CB94CB705C8763FFC696894CD2825ADF31FAEA196F6C23176FA6D2499944131F09F07A6F86B1518092B51DCCFF01969F669F5FF0F8E16FFFD044C2D2DCC0E76E7762C0A0109F7C9EEF834F1584220FAD95FB4CA00D649683D15454CE7E797B6F28F195878F5F42900EAE1C1B339489141D39EC56411AC205AF6B4E0D00A58AEA1B43BE74B5B5930ACC43BA774032E7E3868F4208C9420FD59D3CCE11AF933F964AF0A703F7D73A568C89AD1AA9297D82A606E94350C13819607711659F1972611AA5EDB0B061BE6E1C0FE17BED2D0A3AC80963DBA3A28F0ACFB9DF8852573B35EE8975364A9DBF85A32952488CE99CAFDAE4584ED43E00668E531C5CE7D69DB910CEC52DBAF374A73CA22CB194984F1BED01224372675B892A8FA7426BD2EABC723ABF439C15C1421357BB3296C5B4027A4E2873D5CDEB60176B299AA06A37A9E86B96C91EA0F4CE7A32D1A13F453526C38163291B7D1EB78A7C7509FD4AD09EE2B73EED7B48BD6B8864DFF71861165F7141DD3032EF27312753EEF75AA1CD075FA76756D54F1049B3FC7E2B6CCC5A40D8A77E38D1576CD95F9CC7CCF8083CBD348CA2C50DEEFF4D6BE391E49C8704AFFF70B0FD6C978B1688E000A254EDA045A682B27166645B17803AFE2E794545A7877909C584D3D8E58BB6B0BAE76B4700B9747AAF426266A65891516A276485EE9E0A570DA8AA36C5879B0E23C9D3B3165F46648ABFEBD65F1F82C6D8891D1FE47D51E777AAD299BFF8F5A636C30CFBBACDBE423FEA9D93250C6207121B0D7D2122C6D5E8F6877A6C05DDB2401E997FD18DFEA68993ECC9522E1D9FA0B2F4CA779B6B11EDD658A6AEC05CEADBE69CEC2792669F180558B235C295082EA9E20E65AF03638A50C000C657B8E919FD7E3F1F8265E99A2ACB9CDF93F4D72A615454F6D8EBBCC1D5D5E6CCD447579B2EF000000000000000000000000000000000A12161D2227""") + ), + new SigGenTestCase( + TestUtils.hexDecode(""" +C76D6626F120F0DC3DC1A840BFA94FFA317233CE5DA1323B24005FB7EE273AAB58D8935C11BA583F58DC10BF321EE6A9C86C1290EC27382858306C4DDC149661245F19CAC304C002479EBA3FBE8203B10F8EB866F84C4BA964C33BE17DEB9A3F70D0BEBB6D69931B7A5C8D7F4F453D4B7583D6648A2D9CCCF3BA555790EB3BD1367456382700517316272745263777343070578043772431812488504440335421634222648265848838121837353786020831856580712415333215302208147066378168632077260742828733501307547176277560372528436054511866171224212737853618516810286575524353052360560431827317050484274631523727443076623201205630176106647063024526654105775786876227221382811315183175187688715152251718801634644008352335346173270831466732388742751781744268285136885233676618075730644567376260056046801283118368127378730400864858860423178431432174024128156430042136886878305255512578456815567452271245453668030586055385062026711530033343383475108202713263083330656287828016636402607650813442327778368023726478448081481213123878572853738681808620411477010631062247480543800734826263723435866084563460834818022430110577037880375342662814256421633255877085434152814408536434148614146707002044162035858310133662324605536663662033473105060631775853077483602002225412581468165821865661211467268147103283132171232547477287443230241240757844153615762424741301722062267472747003826503885544682608118155735313865325848302455485634756018273820137345741727418745261488050677330138546833853508746107616788711375147727451830073522165114147383877083481400123163777662262788355285502510077451133068444362310516824714022346257785811584806148226560441060227752554564772478727583156451406704238688634583166663607688238257518812813555154445780176360300350404665741672685880004215010272888675646851148358423071453520360300388050250721351241676211305457044364015801141683044422561272606177463587455738363783408862388284722643833723114756406862376370330214001874826214622708084084002025636767831375160242480502832474732411157747428683178362313332364104274857216211278653233102730780172388640555127240368788380054832243460744682438112304407528808054840554628757808453602377264441116235321564084234171882453426885776378241812475187760357460162405285166613408735655768736813085162678146372876548208588416884845602213600238752455130070756438507443718730864058241676520223100778537466617861873171267335652236024385153037355153660707083178885813007345133271161552764051576616612614573437834476747524844652344312488386640172186252053064230424402062806207278026457241843213823223578630525753080343552186870662772512780561337726815780880748104546146704251635867710255085600275752004733518051655028507656643504277361001831655542464863821714055377458781574581878347750535822404730758788652635060486802627610003565431211741182688234752636126335334361107773262121051470658880873527267780287051622324420455244182713745723520882604160088777146578781102532430655862124224627601834385720032400151863686860466774444313130150443305816566373132477054681352205101436236160183731116027810540738716405756418031728372050026377227020873522458211520648153707830512024387354646073575114450322344315407165806830058732AE7BFDD687A48F0383438F5D34FA545227619047718BB592AAA4511C13CB8B554321352A460C2EFF5C24A42C8A397E0BFF652AF19AE7C99F1EACDA43AB86B4F77A6ADE00B473C7F268E999E76BF3B5355B2309CD95776C48D7E25EFE74BB83173C3B81BEBCB724E1315EEBE3D5DD2BCC834E74E411ABA98F9F0323AB583B41E42ACE6205B48BAD7CF266F639DD2C82208AF0EA64FF0C1EE76E13309140A42B755C21B8AEFB23C4FC79AED0B81DBB4031886982D1D9D218E6AA8C547D117B8B2C477318268AF238687527D4E30D7414E10922F58D7C71ABA68ADDC54F34DF14F7A405CAD7E407DC42113EC1B4161FFAC3CE571C1828B287D55A0FCAFC14C2CF1A0645DC8116B55E34BD9CA049CDB60C27D914D676D0869D33E0DDBDBEB7F31DDF7BEEB59AC7D6A62F7F42DCDAC5C0B20D1E7BB4DB4589E21089E541766C4BDCCCA807C3825AF0EE7AACC7390F7A8B689A825F9AAEC2F644E24920E95FBFB117866D67387C0A46A730423A80CEFAC3D164A3AF5EE17D84FF2E7B783D1AC74362D483EDB69EDDA4365CEC01271172A08BA2C88FE98D47F52684CD7351ABE2958AF5D3EF796AEA4A5B5EDFBC9BF3081E4DADB42BCEE2A6477B7C599BB40051532EC96D0FFA2930BCF1D6B077F619C4247FF89842BE8B3D72E62C0A1B6702ABCA1C1656F2BA66EF804207EE0DE06E1E4299198ECDA8E5A96A245EE9B717D5A79F5478AE5B5BCCF8B8D3629EBCA8258A2F00D88A12A34FD0B0AA5EAD5A74783617E9109C8596F605DF1038702966175AD2367B5B9B1AD40B4D49ADD943FFFC22717BB13AFEBB8CBEB3A7B769A5BBEE0891E03916507A0FF8297C4A91F73A9D03774BD41ECA62701B0A1D15A20CD5B4E9C156A004047A0D1E57F593E6C5C3DE54FFB17A60912AF5A5659339CF9D6969D3AD72EFFCC3160D8B4039DD6143D8C77F0EDB668E44991E2819FB01935BA4DFB5D48E1D8601C8D4D8A17F7A6007C92D95565369A88E1E1CCF781766CE012605607A7F75030E3829CA5F0774BA2F5F57C62FFB9A7522FC152F64C4862CC0C9E49A10B0013F19205E3DE1BFFB88CD76228B101180429B2CD679872E53C573BAACE27610F291FA2C021B0E5D1814A23ED34BD3190E3F6A2B6CCFFEF42EE2F0B5C669B6D23E7BC699D8E785A8436A852D6E8503C8165C27362F246BC26546D5CDEBD5E5C9C268ADA0A3ABAE1D7CD250BFC59CBA4B500D9118356AB49316D7C24AF1E1673E4970834132C5134F2F1B59C45ADD894935211F8026C714B0DD6B2C2DB08D3FFA5A347A3206BFA8D9F8F49A332912FA4DDA18B1301D004BBD6DFAB19DA9FB4F851E6622F99F62FD6008DAD1C03353B619646CC869A8396914D7B7D0065CC4A3539CCB833CCD62507DEAAE15A3A49D1ED997E53A86EBCF08C64FA9F724CDFA0F4D24DC8890F77793DC962BCC4EC48E1C2DB60C88CBB23E5E9D046AEF98341EBD2D30260CE8B318894C1E276EB7849FD777271B6471E716642DF70BDEAB121B03CBF901A171127E448F7E34C161D015BC661063156B702A5B08FE53A1899DC650C37ABB75F8BC4F0E2F03E84D6A7A2E882DE68BB78022F771EC6433D540912358E185AF67DBFC36713707B4DC0FDD6FD2EC615BEC33BE08C8C9E9E436BEB31FFF5EACA3F2661E64A0AB24D0D8B80271C5C658F5D224F98DA322FC68A21D3E547F0F4EC78566C172BE2683993EE8AE09920A412B04905D54AEDB5D92CB257E113AB3D4C4C1CD47DADDC09A00417D2E4A9923E5BD8EDAF73E4B89831ECDA7BF8299AA149383082CF1B0AE388063E115836AD8B1DFB9E6A1C9D254F02DB05D5099D6994EA253605DACC9A5AB52324324AB3B645CEC06C6F57514D2D03A4DB3474EF58EB37C86D27D2598DC58CFD2371A18D0D5EF241F1E5F5B100FEDC33B5677CED61B3DD091C5AA1252B1E681CBFC124CBBDBF5CAA841235296009AA08CD067EEFB12E403027DB735AC59231D6E1C068D180ACA2F3C8BC0D2ED552BC4F0AC5B5A401F52C7D66BA6D7E50EA96E66CFBFAE392840870720D14A4698E05E741605BFBE7EECD1B03657A10B180E253D23AA6750F1EAA6328F40A6864A30D2082C8CBB4AD86113C205CFCFBB93BB80108D63BF2CF7432EB1632D37441A92FB5953813CD740715C2D14EBB2B6D569CECD0AA2F3D4D681AF6EB9CCDFCA85E72A3B8DCAD00960154D350FAD1046F4A1C3893B0AD1B261BF669650C62A0EC134DA899B0136CABBCEFB31D9DF32D51B929148836200F9D51AE7EFCCB7C113B2DC8891F0593A464CC9906DCD18436366DEE53E87BE3153A241742FDF35EAEF168961400E150246DA42F8BF9804DEBFD51DEB5B4FE1681E44FFF181CE44D71A6204BFAD321B3ECFDDABC3DEE87D2C33C7AA2AD6B9C78E034A1E19F255400FC032AB7AFA02A002B9603EF7CA090117108183C49D5436FFBC7B471754915F5D9CC154FBAE4A9A9F0928A50C06020181DA8ADFCF371EF51903ACD6FD56EDFE624FEE35A63BDE5CBCA7DC3308176E599E3B95D7F137E9DE519B417661AF3DF7568FD76A1D34A8EB21038A23B9C62E5E46DA52DEC95EBF680CF8BE166CB674D65682BEE3FE368F082DC4F368738F83E2D333EA1DEE7B2A6F815403897F5AD6C1E710BD46EEFD5D743B79EDF135B0451A18FD60070278D852C302D0D026C2F2BEDE0EBB9D016F9B817D90914F1E3F875259B80D1DF60C28AC231155377D3A2341C4AC4A871857263B0C2DA6FAD157DB9F85CE3ABCD6F769F46249BAB9753339B2076C23549A68F5F29F8A74BA874DA2806D7E4EC1F61BCA6E11C2E15EA64E8728D9B9ED08246A31DF3087F8394A9D925551F4601AC957DA056FAD48919B10951E5CE56217B11C6DC89C25F2DD06095A820BF63E4B53CF80EA8C836062822A59BD726A19BE405854E232BC0D6DF7F9315793B89E9E10D00E9C48698328B170B9A7F95B2ED96CF0CE99E0D1F18D1C73E6545C8E9F717F722A07286025AC8DBD6C2567E21DB5968BB4D7F33A49079B2D4C3956508E58D812F687A7E4FF07065BA76846E70FB42733C56D948559E50CBAA00E1503D1EF447117994EB8FF0BCACA06F91FF312351632CD6755D0703A7E3B0DA03C37B98159078DC9B8F4CF17659B0773F0501E2BF177F882FD017FE74CF9C34A6F013D44C7D2986E9CD29D444B98E26584942747EAA79949EF3C6724A218DA9D820E68C62B64293EB1468E5CEF3A9BA007D5345EE1E5251E7075B84EE3B060B1E9AF2843AE46B4681753322D7906A6E849368EBE27A3C98F9BA0FC74D3CB472D511A78B50BACA9850C4E59620B35318B8978F697D79439E2E2A30BC41C67F41BFAFC6B9F8D8C2D8FFE8EBDC3910EAD15F01CD2B1A9571C02AE0FA9189A50CAF1D6864AF684FF0C9F05E0E8830A49BFA0872C92EA8F6D9445258EDB6FDCB437601B4EFA9CBE3AC1390995FE8BDC1D54073B16DF60018E904F2D23E029CEC4A4DE94A356CB99A44F2F314B9030683CA19AB7402701E8C4225BD284BA1166C3B181701F9A47B6C999D69AA5AB0"""), + TestUtils.hexDecode(""" +320D1B2976A4A4673900C7B75B23EDBC25B9AE867FBB79B55B29B3780EAE8C159A3AFAA47CF1D9E452CAA8EDDA3304BBAC47EFDCF96CE92DB1981A5088F731E1EDA1EA5FDE9A031595A8F268E92B4D75793C6F408F79B78599D93E80066F8C4432911828A87EF71C877F55B1F18207F01820C0153B647205CA93DDD6B78B94EB59E3EAF01B66953951ABA4027F811877B0F60C9A5AE6281D82348E3EB749C82C81D53309F9B7E624BB1BFC6382F43A58D1951F7FB716C08DEDE4A8028B50544D0F26F7B9DAEA0CD075C3B11B7315022A37198F0C96D752798E0EF406875CE86C367079841F717261A2B6570A8F4F9BE1EA305E73BC8BBD88AB162B4D4BAE86CCCD406A0FF6ED5A968D4C985460FD8FBA5B3FB40E29B6ACA07F70717A0700AD3A0BB7081E09F7219F3F8829692C3DF91C90334DF9E89284D65F7406188C9A1EB7B5C491591A20EDA9399DA1AE8C0C158588FE1426B763FE9D11223FF7A05A3DE036B67541C2811AA459045CE73096F89E6BA672CA7A546D2B0554DB35C547AD9585D14485AA812BFBC88F7B248E03F2EC57043F4DEFC2B27A3B20C2EE7CE334D428EAEB228350A3ABF4628C2DCFA84BC7435818F91CD67F70F3C7D54E2C205E55BC4ACCDACB354470FD5C246F32A542106EEE0EDB38F01FF5C4B657C7C1A00718D2BFD311B8BAB6523351E93CCB44274B8F96EE343830148F5C8594818777C1E798EFB45AF1D2A75D22470B4D7F7C7A5938DF3F8288A0088719C4E36018D9993F9E69B8469E5F2ACF1977D441B82E5340E5AD5B21B66051513553BA1BA1C1D5F788C47CD3BC60079300F6E3D9F13EDAD4DF8521EDD022031A3D74A6A5F32AC6FC51C67F920233C5079A2B44BA7B8EC6DCF9AD4667BD26BD07567E078267A1BF44B15E68B71AD38226EDDF138D2A599944F70D47B26F775BB97D9966845AB3E6AEB96E1414D3BDE94160B6DF19E03BA1BD0361354E5078B3C5733B740314E2DCCCF8F4C9CB179DA62D5C982B223CCEF5F29D7B673680DFA2823A2BB279EA45D98CD91BE7D52E3E386B98B62DF3FAEDF025B55F49EE6FB5E8DFC9F70A4F093EE3898B25102CF3AA52E669D6EC69BF6C79457BBBB7CECF65B1E948DA808025A242841FEC6073326BE16C2D1953209F31BA4A772FF24BC30376EB994398D4177FFFBCF78C9A79B7F1746D077AD146514A2DE0AF9800255F3A11BA661765A7D8E8E7FE5FA46BCD1269E278555186D4BDDD03FEEB70BDFF7E5F616259ACE39969CABE8D4F8F23544918516C977F84C09D6A6749B1CE719676378E82F9B4E563D67AF7D911233F2527B5CC5D0733360CE15A173F10B91360A3CFB08EB44A09157559A0CE8B661AB4A97803C52F156627C642CD02CA5BBC7648833F2CD7E99D2A7AFB736E5AFC4FAE5DE19ACD2F5CE3E3FC887852758411E8C7FBCADB1578964445332113F963AF3E944286DC448471125E55A46D2DE35E9C0F6DD10A3BE4F1E4BDDE51A16F4239A1F6A535D3202055990606C0065C542297D490553204A6E3CA16A7FC9A1D77191E5C01C1507A332C659FD6B11FAE088BBA796F18886195A2B8F5B0064D85F56FB7256F0FE70E9C06ED18B7C8A75ED97A1DF482908D2E3E8D6BE8D0EC8020451C687D10F829257F3D09FC47C7EF008B89E2312792A25EEDC71E9835674CA50235E0A6C832E7BBAB458725EE7BF65D26A0501C91835625C330B0F8B4D46A0762F7773D2415A0DCA573B47EB8658F9EBFD26D9F6EAE9D7A7304BC690F8D2F60C33F8A7D19B52F9340BFCB2FFDC92A7F9ABF85E3352E46ED7591F354A9E19B70A3B247E3E4295E45B6A2CEB59B120B6758654BAAFED2120B226FA778FAE5350E756741093083E4E56A84B64739695C1C09EE39DEEF11D7E5BB7866C90FC9C96CEA071FF82F145592443BBCD6B7CE848839B641C4522016945F711E86152820275A6E16BDF296D34AB38CFF06A63756DAFF7BF230F024DA00C4128F025F091F4341620E0EA883042BE731E82D21DBA6EE737D90346B6189697CBF41F7C2BA7C9CBA20E14D26CA578FB05E92798D57C0060951BDDCA5D96322AF35D80013B48A79AB7684E1E1B040315A350DCF84389E54C054AC4C3428123E01C2FD66FBB2C5BE2D16B22BAB805AB59DF205B71764E4AC9BD4B2D872B8905DA230623C65DD235FEC253468E53928722D1F04C486B46E63FE63441F11B1E3617E9765D4F388D4A2B68B6C86C8E20FE0F3C48A561A0FF5070455C43A7FDAEB58ACFD4BF51A1C37B7751ED37BBC73B9C29DC4FAFD0A8F5FC98C7FF02B404AC08A0728FA82A5ADA4EDC195E679D88187F58004844065F281A67FF0A2BE0AF94D5C97ACFD43683AC721045FEF8C36DEBA2E3EFA248DA65837046B62BD6CCEA84CB1211C5893B0C5F0A5922A989CF7ED093D5D706657AA6E79EF3FAD0959DF594B9CFBE779"""), + TestUtils.hexDecode(""" +84D8CFC8120CB598A6A1CED91FEAD8FFC224C59781A421E85F7A3309F74877B526A3A2576A41A17D71229A5864953B5591878A53BA64C10E88A4F77811D5641E03E445B7BC3AAD9526EC4ED3604A371D1170618F672520C76B18148D3895386C1B9ED1746E0977C32DA44425B4737668BAB427F516B4552F5F11EC62A824FFF1EE50F0F03E01E7412CDE699F8A135D9845C7F1C4D33B806527574920AF2381C4AFA8F7E0673D1D76F6D03BBB5C3BC027ADC84B7D34DFB4DAF2D9BAAA9AAD4D443B195F350DD83A96CA96DCFD2673AF4B3425FEF1928085FAFC728DAB0374CCB14FA411A5FA2F77308BD43D44DF732E0984F7076CCDF6C2C42D0876166CC47050983FEF8800160933B87733C0B766F013947382A3593DE93F604A9A5DDA9BA4EF09954EFC9A8E6C0D90454B7F5C79140206204091D82923054A5D7BC76BA2D8BB3B17A7BCD027209965E125CC8DA21C4EBDBB4E84C342735F4C15705261CD9055FB4FA98309B45C91B92DBE2872D6F95B83243F6F92533C8E52EDB05147AD030A7ED059A3D6E6645EACFFBE84387C88AF178EBBA7ACE86F8BED1F18C04B1DB3F81721CB005D92DAD11E3D03418D3319CFDC4FC31E41917D3B34B3ACC7DB8E4B1D77884F97AAE2D71B202623F95308609A890942936E0740F53A48D036CF3991047F98CAC74E8B753779AA1EC926CF23886E0F7088EC0F1FB6B0D3F8FE587BF56B00116E84FC8D50D663B542B096186CCDEE2C04CFEC253EB84CAA2CFCE5104B667EAA7ACC31FB1D91C16DABF1A5D60704F46AC26B2E6EE4F93817824714D472FDB8407B32622562757F2F845731F5525FDD975472829D1D98C47B8B2A74BA72756B807A0DF17F4095508D4944F4F5CA1447B056E952B0A49AC3FBEDEDB06967A27E452966A6EC426EBE72BCE9D73FEF60C2B7BE7427DA1890A56F2D88F744DCE406BBDFE360D7C08F71016D2A84607F655A862C0C9020550E1FB87C45B85FC1501EF062DBEC20A7256904F9D5309191536A8814E4DBCCA28C40F34897A49A98AFB645F3EF246E2CDF4DF43070E8E61377B6D70B146F955A4EFCC98BAEBC3F1C621810D796D7B1BA0E9A441E56DCCA92AF85CA2834AE49207ED3B36E10178A7DA4921AD35DCFE3C4FA522D138E015D2447A3DCD35A25772C3B1439C871745844E05D5A266AC1C7253935FC43B6EE1DA7988C0D1BCB775ACCD20DACF4CBAA0671171337BB71E7D95A625F1BB66E3298BD5B8130BACE336B34C3756F62A0932FACA9AC3BAECE59D77D79F85AC4582E527D3AD47D230B1AF26833EDF2968DE208553B3167D7185CF60B4B4C08A0587496B56D9133BBF3513C20EB29A334290C46FB8C4461E81DCAA82D2413F8522DD889A4189306AE720736C875EB797E794839DE3619DCB6AD8A548CE43EF71AA16559350CDDE6218D044A059A8BB4D9826503539306469BE45FDAF3917B0A3A6450DD11BE8EF9F59DB8BFF8A337155A63CD20910EF598B208C14A2774D2FC55301F9CD3C8FB73DC5C1D30CB072D7E098B92D6ACE1BA78B3A10168CA4E8C1D44D95052AB5C1A7439A99D98C50A924ECEEECABD1437E4DEA5E7BB83AA5A3FDE2C98E019749EE0AFCA2681EC2C799C69F581859B28D2D346EF2FB97102A69F030B6F53F21FD655EC0F5CB34B3D363586148C443167C6CA47DE98835DBA80A092B9410B26BD023DA9E053981898215FFA735599AD0DEE853D374D6BCF0A0171FA56459C4536A7D2FF8DE6EA0C362C157D594101F9A860B800E5307DA8411E0E1468BF025092CBD1C607D9780CA3DCF070F5D949BFDE60E0BCF8267AFB9E04D5C2CC339CDCB1876C818CFE60F89F78681A8E82D36F26FE6260AE1A9E74355C0049C84C39A0333C01E77D1AE8E87F6BC96B0EF90B825188F784859F5390989C212E5CC5B829FA184E5BCA76B0B402195F4EC532931C788416811A029F492CF5B2D633F06ACD8104155D947E88AC08CAE86DF2F64F79E3AF8C82B9FF3834875DF69F1D381971003E0771F64FB343FFAE807C9C0D4A0273EFC11AF203EADE2D9F2682C918E2662EF2D6AE1B6E8A397B3FB62130BD629E315C59D1F0EADCA1BAC8CB6F067F10F6B13D70F70C3881E8382F20026746C6175F14A2331FAD83ABF256734FF7A970495B1F6B5B1CB2505B621D406B944BB5CDCE22BD9E88FBFD41F8B49C794B0022A456493D411B1B8F59D6A52E7B9CA786814F215C39F0A4D53285FA10097C151293054632C326E210110CE3CD03B7432CE2B1133FDEAC806CAEFB45A37CFC12F98AD0BF76ACE2C347ABA12A77D5DFDF6658C2228304FCD265653894C6696AB17E8103A8E23C397DB684BF632FAFEBE420B3EC111C08BE7DF73A7F763A82F01B120D326A98E92EE34144CB6C7ED15472F2C860D25A6739D925734C2CB6EE02198E96DA851860489A5F9C056C5AA2B5A90D31E7E115F32EB8285339D96124D3830F60E2E91715BA1C12856C1E25B8C59AFBE7B446F43F1B4154F8F786935E5402DC55E7BCAAE8ABADE43435DBD01F78BB882418BE11FF1893D54B5A83D6220F4E86D7CAF49E1B2EDFD6CEB82DCAD8A982BACD2DB15A66E7D0FB4652A920C339DA25B19D37715ECCF886D900D785E5E77E9AF53589DC5E785B2D5279AAE870F86E4701125FC316EFEC0D5CBC411D5ADAC374124521469ECD10832AA4257E2D8906358BF2788654DEB5D9E70798571B965376250C33706E78441465CC2563A9D2F70DA579FF7C4C715296F72562DFD9951120AEBD94D4F08212647F08B4871B6C4E31CB869A8CE1301DF60F88A517356E56189D61ED484C32718A9D37B6BD1FAB1FA39AA1147735BABEFD166712AAA617516D8CE2A984D90C73565ABF5DB9A46346FBE7AC465C81934F5D92735D30594C71AE239B2FF5C2DB72920E7A59B487DB9E363C594E34D9F250D7FA3E8DF4F8A07FEABF07D7BE68D6E03333B6947B1EC087F16C1DE3B0C5596043D4DD62770605DD89F11360A10F2320170084EFE8DA7E10E128D0E90D25623324F8B32839A96690CB33F6FF05E584C860251AA02CE00825B9F775F24E75AA788F98FA5BB7400E31362534EF1E8D310FDC0272F4E84C820E799007AA5351717BE6B06711BF9DED0CC7F96A0AFF9DC4BAF7F1F2D19BED2F24A7DD8DD1A171649F19B134C0F27CC458AEB79274DC155A9E3A267E200EBD328C16AC4892EEDC748BF522C0964E003793C0A6283528CD09456476677FB152B6DD0EBD86A410231191D86A0C4C19027F79F4615C665A75E7350CBA43D5A43A609F9C4155B7D2991250A6AA4912532B2081AE7ED0E72CA8982A5E16FAF25D622E060FF7C7639A1401B39BBADDEF2D1BC3E600ADE38A5540015C6D99769175DA7948C1636FF28B8D739E65B0E3DD43D5F25853309CF5DA4722DB29184EDC0294BB966D023093BBB10FE6A9A17F8A37608FD3FEB1878C02068BFE295FB809DBA10046D57C50D1A5515A3F4099F98F8262DA6DA7E64C0A2B662DE9F58C7F0CBF6B95AFBF75708F3B70A73A7D30EEC7B2C897ED420275B1D3DA2B0D94D689E21166E3B42B942DA7566966C9C78BFA7C64A7D0CC3CE47213B2C1D3D0E75EE00AB186CEBF88BE2C1C042253F48E2642DF054EBECCD82A02DACF3CA849335AE09789A705D23C1B49ABA88BB60ECC05F70BF02B067470802447159456D4DBC7451E41D034306F3A40AA9280C63DC86D5ABE401B64B48293B49C3A4119A966F652CD00B32342CF603A3D02E8F829E97ABA53B035C3C72D2EAF8F9DBFBB83D61B5E13F721C719B3D6E963E68CD0A6FB792DEABFD08ED01ED50A407B4C3EA558BAD59A9EB0CF8D5501A75A11053DE46D2899323B2AEF99A6308D64ACDD681A256DEF931C7E5F488D8878950F0637D478BD665B9C8AD85816E3B8F9C586034E1DD2381BB2F8130CCAABEC2F43D455F5150F83F160F9E43DDD4247424ED273F31F07EA12099B0E5FC35998A6811C8CD1825F8A1687AF77836165DE0BA2438275DE291B65C90DA0CD5880F95C8C8CC0F256FD0B1A9F9209C659A031AACC5D0FE8B0DF5A4E9D9EFEF76ED7624E9ABD6361F0772ABE1CBD5F78FE6F872CE769A817F4F3195E65CCBC3FB2F9BA021023585EB4F43F471EF4307AF047142D79BDADC744EEAB4CFCF8FDC682462985F828A5CB69483076EF94D6C6634000BAC9B75529594261E3893F832DA297FA448EEB8D098166732671773CE215F777ED8B16C6511D47216BA200CB3082540D6323F9726BC4CBDC1A89D9698A49EFFC5B3928461746597F24991A5212547888DF1AA6F6BE3D1AB887190F3EECC6DC4E9B0B4E4672CED38B5DDBD3C00DF9461FD62637B3D7FCD361C41EEC7641024382C378F15BA8A14C1BE3E47C4301624C354EF8D10CD26E354385B7C477F355FFB8998E9AB2E2C0C2FB2E3E466A1971ADD49B31C6A6F1E9C0ED9348A337D995A08C65C1E58C950558A4139D3274872FEDACBBBF77B4EE9D2C54F9A6142AC8A2058C2EAD0606BB37A6B141CFD97C9780DDA16D54A5ECD9EAFC53576A00CCF909F3484B64E37AD1F63334F39B94EF033B647B68E1FBF3A0BFED69FD8877FC22C048D4C15A8282FC2B602D3B1021CA6B9A7E844B065C62B0CBD7FE328F9FB5DC23BCF50A11558290A8B5C1F642586C7A859194A0A7C2FDFE0F4352555C60637A86A6B1D800000000000000070C0F182430""") + ), + new SigGenTestCase( + TestUtils.hexDecode(""" +05F78DFB8DD95ECCB19A4E223909896CC6A32086977EF3ED299269E51878BE84D29086725EBC30BAACD7C10F04AC9B3037B7407C63D36864E577A8FFBE89D9174A2ACC4183D106E7F478109F5ECC2160C0583253D7287E39F2BE1E1FF6DBC0127A322CA8E2BD20BA4419405CD8950831BAE2E4F854DCE2828025369A1FB3F07E77878741641453852638027541273502161744187110423466885282676035866631880680212377455761475822537381311428256306028053075841275812862151082114225553333632208035118820600216464008332253350051356421018671288648082042327826524064231463461787457445340458144872151441075521254341210228484201564136088803605035560122810660262424606074018703052055371555875382226471026530180032600112827753232300073074181386480534164225448647716638448527736082708564276203618062484286666008357240756656266712700838805173838263510506272540177577752234807311255185168734122463815356405123855254518275503443802574060346470206813526234734131654288881363708638820352751020216175724418860014818114623484543247618186431467841145500584206376100245427354377078068051005766127458621211151260165633001348137530712602370312371232020175626206103837672301778747622163741706566121434014071278363537881306583436007681866270754208381518840617617808075330388482526180736260681245127862565373032388826478887465858427858051220613172202211345601088467637001415045874412557332067277484377551504066843600063121066341371643283786784761068601064575354243720165161606071462467454388636873636233778021648671534367133507427605374074416722337133601751734478484212371667138687221813155227282016661347012087060844717657163652206587018728132833730304737025362757761315052144646422630627111723456313173844406042412780701303413724368817117576255854668574228750452553070204351788025621430144242371001323737372064343217801782040275037004610781844438384742255584167536370662184616027251211143638677564508151383860530708048252122840866600333828445206788217648545821445206684478670700853248527254603327501006210154518503008755220176074648684464420077608424316613061505360032376774670110586687775170411382701487278646233746321110574082140788743715263036142246810378474651821327267878687767558532332766770770556676145510857677602768584841218228625328357130763700187376638323351202458842267224561707545685515711742787471041306204421583620103716561184185104727138066730485156405743817162476012062163020146660802807525251031404783027088628746507335166655450455814243664167181412115564530746315868643783184442146216216845873256853767015455878677678280687482518218081546136488640838635431565180552472320787367186616811775854673275284425445068256835580334212418571666556783641407770327517431140237301214478304666154718470055040784840142143820856651337364886780162504570540561687240205801871073843068104004486611083157177770070276412274284501525030180108545680011733761885871352405735268564864488888408546532680830132441854774703851551130551311212088487888340480334438028463403314317118862855268314010187431362037387131230675578024177157366237440614241826465088416751852758868580542326571477612173575680005143247771436458011248538443205703184858134812623530080474087351382103253482864316815ED9377443018FCEB94C82DAFD2C91A64AA5FA118DFEF2C915FB5C1C06E09A9915755FDE25B00C2D6A8382A8F9BD031F4F9CB0CD25CC035F5D38EDFF23E27941C7F38A6E958A5D7569D234DBD2A94B296446F553CA82466AE1F49CE4863D68462FE22DD7CA41E3B5223878FA372DAB34237763BCC0B9BEAED3FD27AF301D4BF779178571DDC3EFCA493D98DC24DFE77536701B08DBB76E3759B237EA3A0F9496E8C7587288EF7192DEC95A60FC480B9E1F533592962DA075833478222BE8B378E63506364B78ACE0D27A5017D15D58C018EC843375A5B07887FD25E1C30C0075F944A9762E59C94359728B04C38E9997448263150BA6E69FE461EC1AEB5FA47AEAD3AE1848CA696060462D29F331C02F80D22D8E3BA79E63924D2D4D3BD901BD79076852FC0B02FBF48BE9F772FC3332BA583228E55EBE8EDA94884CCDF80D17654E27FECDD237C0EE61E8DD35B1CCE3C388DE759B1FB7C3D143A153DBC41D2FD2E9D0F754273C21C19F5F13A63A7DFC479FD64D5F5FD008DEF079292629032111D2B16AD8D61566A73DCF219397939669A3B219F648DF45D541E47FA70833A785045B71A606DD4DE82902DB7C1899D44FE0D2413F886374FD1C19EAC8132F37A3AD31F8BC6F9582D58A494DEE3372DBE3C32E10B18B787D8E4D3B6E9679EC94CA86BFC2B23B9B4F92C1BADB21D5E5A58A9ED0FAAC419B51C1993983B5A7F6694FBFD5F1AF15A10057C6AC46E7034072A1A5D26D63B67ADBD3771B7E78DE3BFB9F6D5CE594B285991BA243BA22B3B54453E6F5413A2CA1D9AE75FC1FEF7E31A7A3B7CB087CBCF3F08FC9C34B1670E7F6D5C32F165D3796D1C369E7C50E9A122C116A8279997B0578625912829142D95C43DEA2165E0D3F9313592C8982FC1E107052DE326109433DCFC45A1BF14846D1F8F146D154CD5AAF417449788DD7E6D470E7C70C7DF7D8A1B62A503B1D4188AAA5C32BEA44C9D849D3F8B5C91D1BF97F47D83DC0D063639F79B9F08DB24A13A06C1ECDBCF73CDAF7510CABA36B890BBF7DC241AFAF317C24026A6F6CDC8426D99C0F90A2F1944B797DD68B792AF00B15D0C78F8528F0E055FF01E73E455BD5162389E0FF178312AF5DABCBFCB28AA2C0091862A010484C0930E7D9B6D703399D40B4D83C996E4CC415525CC895EB460EADBEAA104D6251FADABAD74DCE9FBBEC08F9D0899BECB3D6FCD573FA9FB94D9D18C59C724F39F0157AD6C8C01449DD56F37110F68BCDE8C3F66CAAE7968A2FEF4B0B20A7CF41AD9D40266EAEAA0C21951ADB946B78A3ADF6E81AF6DA0ED92749B119936AC4C7B798DFAE058A5F509D90ECC08EDDC2ED7234D3BF28ACBC7235AA971E4A3744AC9D47221EF2730A18A5411C85B6AC8DFB2396AE770A5D1D960D7EDD4CA6D0F9FFF6AB257B22FD5DBB3835D05D060369F01C65E58E2C143AA4FAAA554928531B9BE2D0E2B6D9F0D32AD9C9A12DF38F72A21D2906AB17AA5934F08EF87B42E40E46DC1C35DCE85B0501F256DC439C2B3A332E37F3A4E400304A6ADDB09153A7FF7EB8760AF870C252EB258EB658512BD8EF92A89FCBB50CF6F76BEBC46C97AC9DDBAA7450CAB49B4190A8B39767F36597F89027EB3C09DDCFAFDAB286863890EF528EDD073AEABD6A7C9C3D04EBD1A3CA3197249E7DADC74CE737CA5CB5A3C010FDE6267AE82BF9B8AC6210EBDB68BC5597E10D98F6B5DEA2777512710C58694785F544E4D886CD8CBC8E6875BB61DA19BC7FCCD76547C4ED44A935FEDCA88155AC0E428EE506B1BDAB6F00063EC1EB0D3D91B6D9EDFB85E8F90C42D9B058EE1FE208A54A5A14E4983E9C06A7F549647EB8EEE92B3C9A0B54912DA9185C7AC272C2DD4615C07140772CCA6CC3044FC59F7271259491BC9469BC1DD07868D6463740387DFA7D2ADD1346D6BDA59435B84F6AFEB3BEF20B007F8CBAB2DF46BD171362B7F7AD541A645EE4E62A520324617DD097622EADD7DA6939812673AB6D8E5A25FCF00EDB519ED4877B13EB0E57E9AEFC8B63F22C0816E70CBCE0383D689706FDB45EFB6474A7F194D6603B745F4D85577F79387733EB0975D783D7DD3864BC89111E1273D6CF9122B43EDF7F6757E2CBCB6C8AA3C9923E3E6870F9FA92AC02DB2B52491A1EDABC9600CDD515C665DC88889762A2012332035055C896145EA883A5D4EC485BB24B1F659804B8F10FAFB1B4C619742EF4BC5EB665C48BE5F5C5093ABF4E9E6E43D8E4D7E15F7D38DA74B567E4017FDF540BCB9492CD35C2A3ACE4CE579282837A8B55ADA428C1D190BC77764A4E44369BF90F24CA2CF566F7394978F28E24689323FB8C5B2D688578A9E5A34305D0EFB970490CB172D6FE786F5565CE921D92A2573C302DC9CD0431F8ACC8E0F1A44B586257080347F933387385429199F4A53851076447C6D2114CAFDFDD13C92D8C300F26CFEBAE984D7A021E9B462D30D19618AA72C58FAFA0FF74CA67699992B502BA0EDA7C6CD2FECCE6B51D6C704308ADB4B86F2ADF28FC43F03807C5B7391B3163FDB66C6EB76A78799682BE26C536059BC179E8F89D87469A57899C1E18E03F16DD6B5AEF7420990DF22CF4D3E905E1B5B1027DAF56DBAC8E9E3A54BAFB28A8FA5A51CCCC0872AB53884563C0B7876F68A48F1F51B1AA350C93A23FAE59B6BE2F8088F58FB9FDD432C10FEB6C79F9422F0AC6DA4F8288A23D16546715EB6104CB0499E5FEB2225C97287C19BEF3279B3871D6AD522B30DD96BDFE4BACD75CB108BD622605FBC0BC6F2212D76D8B50E22F98E34B6C53F53AD9E48F11FCB77769537756D20BFFD1D775B42625E6E7C4EF65D7FB3EC718B5FC0094273B29487759E8010FC317CB0F9AF34836426A4BD2B79A3F48E0F38447D96DF0FCC545FB51DDD3C6B849FF33BE3F9A9EBDEE04B422B6E032E134B7772C6D3D4430C67BB2B1B0FED7C801F5A58F23E08E1735DB1AB32D66A66A7F60E2F98B811950CEAEF309D6A2476105E165A673A4F9F49A94FF751DDCAF839D58CA66A78FB5BBBDD80C5B87A6817D329E5747EB580A7B1670B3B7F52CB5FCD6AB51D48E7F0D91434F6ECD742DB8286C2134713E6FD638891DAFAE78DFB0550E76A8A54DBB1AD4434786084BF17BABE7711BC40943A6BE4D6F9886802A078B00937170AE765CB3F5F71BB792FE3F0DE18085C3F402079F491B14CF2DF6AAA588DDA39B69A5DD267C95465350B261064AAB109D1D8781B399F0E0885BF2C646452D54504BBF5D5322C6F4A3C25F4AD945EBF079CB58A84B9309C32EB6FC35E92F526179DAAAB3526382B8F02EE2AB9D102AEC8F250348228437DBDECBAC81776D4F4A0CB88E1F19CF6A10F48F72BACE1D21BB213014280B788D4760D8FA471F9C35A2509D3BD86C1F0E3E92A74417BBF01D1455B64DC6ACB49001442C55D1105874773ACEB0AC4839BFDB021E1B653BE09EED14DCB9216BE75F0E2B8E9BB3D2804864BB92A618926D568DE28952354A7CED0384A9D21203A68111929E0B0F34191162D722A01F8B55DEC3F9DDC9D0DFB3E"""), + TestUtils.hexDecode(""" +C9ED9B897C34D7119115A0758332FE70D4A9E11FFB2D6A800AAE33F85FAC59E715AAD93BD79DC8D958079F3B5C2422F8FD1A1AF9406E8DA3297226440E30183051FC9AA52AFB8BEEA2228E88D193F231F2422977DDABE4AF4F0437628C6AFBE68F70CF4F56153A2691F7A4241EDCA760D4B3AE0A17A8A0214BF1BA65221DE64647AC6578F4C7E4A14C401F7DCC30A10A695A7F72B04393F4E9C4163AB68667B1757154BFE711BB54255F4DAA9D8AE6622C71EC8ACE5BB79C6B4C8AAF1B0A0099EBBD07B292CD7B55E44ECD68DFFF4173743145B71F536E7D23E78C63679FA2F3C72CAADEFD5A9471280CDD3DD8DB83F8AFF14FBEFDC8C5969B050D263EA462C28CA64362F7F165C3EF427FE5E90A83310DCB07C9612E9A0B8EA1D0631D84B4A7F1C7485B0C91C3B7BBB0EC98D353376B692BAAF24C5389D50250F3BBA82173DCDB52382176EC5CB8BD531DEA049C5B815D788491608FFA2AE8BF486849810AD89BF0352ED595E4EDBC0B81467D72944AB83C3CB2F90FCD10810EB65BDA18C43F9A9A5D98E714BE992B7DA02E9F7C389F1A22810DC0A473F8891C43932E0F6B5D3A21C3B611AF6C394AFC576C07572DC4A1E56B4576FE615E516F48544D099683EAA886CD41DA848567F70C2103C467D271919CC5935605C0EF05909635D431571E5A316E299E553EAAFE9C7CBF5063E2057D297F60B5DE1C17AF6B97192E840474CB7266A76D509A10FC7A71721D705A9DAAC5BAD8A52290C1D8DC7938663B24700F992FAB008CCB3801258245A0F5F329A4FE5553F4130DFB1D673338889B357FBF11681099FE9BFF18AEEBB31DAD290C1401D49CBBE38277AAC8A99C8BE4E6EDD8A0F3C901082A789A1037768AB7C3C704BF1C6E890D20B3DB6918C477350F4F25756BE1742DCB31705EA9DC975DE0C38C21D29B340C63438268F6CC399BD644EDCED36A7B50E8D65A507BEC51A31BD136525F4E7AFC1EF9E0E6325D032682EB4AFB7FB22F1716EC6F4C9852054429B5C5FAF3BC86213F6D800281913D5722F3A380307B59E1CC290EE66FB9699FFC627770B52619256C7B76D993FB4024D2DF0602F102A6A1257A200DE1F39DB54614FEC2B60F3728F59482D71C7E5BEC36F0D90D6FB0B4FA252E7FEC4F0FB9EF539257EFE87715ABEC75B2A5FCCBCFA5666F1C9BE2F0489E04E63ACBBB239EA8397FA2EC24C25C538BBBFEB74EB8E15FF93B0FEDB7F36FF67F7CB244CAA067EB2C005EDD2AC9E0765DD38E51E7C71AB72B056B230ECAA8985DCDB50439BA261A0DE57E68700C64655E1EB8608BCCC33480ECFFF1BB75D0AB69CEEA8F2E3E9515331A1EAAFB9BA32AF62798DF761267475DE343CFCF5A352C907A0314365B8CF6FD2E72F2142018C4BBCE4CF0A160266DE320EBBA359344A60D32CB135F5FF943173A3F9C7F4A68489E78621401425E5B8E6273309FA3313DCBF13D7C69B63C1EE34D3200BBB4CF57518A5E66D010984AAF34CA9B7DDC914A3AFB514FA1B9D3FCDF3324998D0D9058FEF10C30ED6B381C41DE363CB31C5107E7C00D4C0CCE485DBB4CD2092CD929E5717DB8CEE4790A48475E1DE9178E49B13C5173B6F301D5B7BFF1A9F8B3807A5FC84DCAFCCD8D585B77014EE285074E64448589A738F1323C7A865C3DD482499640A3F166F38E37C6F9ABA8263E4F3D1C2E7D7AFD16BB02B9B4BE8A055452071F278C32C3247DE2BF83A0633BABE7FA048BB18FDBA27022736615"""), + TestUtils.hexDecode(""" +2BF99640D1E8D1E76A3CFDE44072BB410AF19920F9FCA9F4EDCC534073063A5D196360CA825E70EF3574000607834DF6770604757CF5FB2E9F677530030988AE35E32C2AABA32FAB3E38B990CC1EDDE319E77E78A554161EF485FEFA16506826AFF3BBE5AF4A248A1ED0BE5049317E8148AD899E970A55191B2F31BEB20D0DFFFD774A5404026E95A04874429B59FE1FE29453AD21790F1F520657D657D175B8E4B8C497D2D271D904DAB7B93EE744B745BB50D310645FEBE6BA084686263F92A6550295822E84C3771010B4034602DAFE05447A858FB68A8B3F17B4539FE2A7839C7F2218888BB8FB8DFC54AAB71CC165B335C2F266984B1F402AC09F963016DCDF2FAB74E77D24B31CF35A36E2003228C0EDCD4E0639049C168E9A06D5646657D0580297C60F2F05318D039698482AE9F34501719251F82FE375D237D964221CD95CFADD4A3724A0C23DD3E860ACFC0637BA76159727F58E0220F31008E789E699C93593F2DBBEC88634AB2474B644699F90F56785F04044ED6FEBDFA8910A286919FE4A7B5AB253D578099152031E4EFC75094DCBDABCA8072443756B536E87B87114B354E4BA4452F540A9B197FAFA7C054085340F6358DFFE0FE4FA4C9ADDACF68C619A672E841117D1728EDEF147E797A9B3DEBD9D4469C71CBB684D134B18EF7ACBF66D52D2AB45CA47C7A1F7861E3EB59FE4CDA18A29C7C635E20CF68CF8C869A372866494C34F703E85B9F367E44D4AE42277BD8BF805DE61D988C848D6049DFF914B2CDCE4BA147127A9DEF6DD79BFEDAAC5AD4653C14D086A7CA154CED8860D12ECF86F351E558CB7C6542017E233005C1A7AF959D7E83CA03F3A07F1B9B7DCFE30D66D81B8D5C36C6BEB651D5A36E9330D2D585E36547F88A32241CF28014CC96A3E234ACDBA99ABB541FD370BFA65591EACE4D268D3EC17D86F4A37A359FB95CEC77A8BD4DEF36D23A46AA72906759A8F46D78CAC6D160F277E4C9E82F7BC3B48558E1607747D7BFBC8DE7E50BE365E62D003246F429E67340D1949C950957D7EEA52096B584192D935AB88E00F8AD54B0E1D7EABFACBE81E2C1282E9F5685F37A54EA44596516D9F5CC24AF26C88C91047E70A53CAB06A33D71B6E058ACF6FD7BB045FBA386F0E07BAC67A3EB256528680E4A0A31F91957FCE294C7EA84E7492CF8D265962164325A6536DC8AB542DED323FD2049930AFF783C466AFE9FE811716F6FE75ED28CAE3D768E7F73EE9C09547C40C3287ED5584AAB2BF801A3DA15CDB3D02A7267B131D22E6F1CCD23FBAD9D2446AB8B303E3B89D7331E8127E3BD909A6FFEDA8512057B86120D02F0AB0D8663AFF465451A4C8E29D8AAD0BEAF00B51C96C09A0568AFC3EB9C4FDB78E372669FDD78A296C6919602E4C9F60513E09F1F5D2BDC6D73AD9E48FB2A5DB13D6E935AE49DCFD455F017A41A0E70095A55DC012F15E94E438C266B081D25EA275FE2EDF7ED894779004063921AB3E84E44CD2638CF2EECA02BAB9978ECBD62D153FC4390A6F2117115508F355349603BF1DB25096D00C4E4B4296632F78C655BA6ABFFAA7B72292A1F71010D6743242E553D6326BB361364B44794164019ED114876FE166F331400EDBC665EA23AF4A178765731206A9F63950B3EB5B89922A565DFA8A23E47ACF14DA53D2AFAC6F5AA9FAA3DBE216E9AD2C07A32CC2A690B2CF1DE943000E87EB95D906C9E52FC103574C5C50548BD9EB8DEA4A0CD0BC3153A2193E30CB6385756FB0224F6392AB526CA21326B065C0C9C74F5203AC313B25F584491ED20C32F40A896F99088D07916D4F84396B67EEE7182B3600E418D353487083F58AEDEBAD6B9C73042748D2F3DF695A579611A41F4865329EE8E807F184ED2528AD1503A61B13D4EBF24D7A5371ABA6A053A4DDC63B0FE95462FAD2A62B9A23D50676D6F1B172F0E59DC0B77EA7C45E31CD89CB8B8BFB6AD07017B5E76D6798E08764B5BD293B27B48A392B382554EC877783099148E4C81401665AE7DAE8CB36716C56D0047BFCC5F57F5C6162ABF8700BB394CAC55D33E50FF43D20D2A1C27A1499ED068E40ABBF855213BCBABC2BBC71A3C7F8D11AED8CAB07C0BB8E5F10C5E46E726A353559265A0E511389C05760B4A6815EC4FD407486AEA685B37015BDB6E8DBEBA29636FD23DEF0BEAD64F38668244C56CD37517D586E08159F518512BA72CD86684768A42EDE0241C0EC6D286CF3DC133A64DFDB52E1E6C59743DA59FFBC28BF3C989A0B49248110871832DC53280A250D8C7704CF6D0A965BF74EB1E7610EF67C514C963DF6ADD4932CD7B6809F725FC65F32E5A8B7341C4587DB20A79F4BE0F42035B76FC1A7F8132A5C5D0CBBEA2E98006CC2847D11DEC848CEFEF19C29B45117859371166EFDFD9B1202BAF4183CCA16C2BCEDC391A01973B63AFE3389EB1E2520FA9C88063D038E9EC6F2A9429EAD33A559C79496A3DBC52E2CCF27DA58AD1A840207E7762A1F10F5ABF5F158B05FACA08CF40630E36E4044B69299835CB1EAB4DB06F33EEA1E1EE9692D427A04947FD1BA3D9A24C0C1ECC9CF203B25C11BC196AA12CAE8F8E1E2D37BD51002024F51BBB136EA9324B80B02A1D43B188A8334FAC96FE409CE4D056885D0AD5922F065772B895ABF623DFB4B0D956F68E65ADC37F34A10A1CCDA07A2603991F29598FD24D2C409FC1A3086892CD3EC9B22D7F01086BBBB12497A1B3EFE60E88F6E26FB4E2DE03B9FCC1856CB46B8D6617C8F6BB67993402A6AA24E9CC42A0E102BB46BF5D33F84A13355087B9B8B080FB8E82153ED8587F56A08226628178BEF5C7F139024B95D2854D8F37DE6068B4A717F4A8DB54E2CA731603E3AD6FFDE96E21A60A66B5F9F5F9B024116A999960D2893CF7CB3DF2781296E6B9D30FEB57842EDE5AFE2441AA32C8DFA2D3FA7BB1A3B0557AFA82B0D0ED8E088D587E4CC1CB6AB6C2FCD2826387FC289EF4E4B3D884A9D5DD354EC742D52962797AC5928A7419947699B10A46B69BE370AD481B2DCAD7ED5AECE4A7CF04032AC1445F6C867794ADA0FEF34E18FE0503A89619DA244E7FD4AEC38448147B49B8A312D3A6858BFC3AB91CE61ADD9456F4E231A55D0C134ACE6D43E142A40E0DD75D31C6EBEA609D2CEE42BF221B6B83176CB79AE6BF46181893DDF1527DBA791723752A78949E8767A194F6FA64C386D0B00F7EC3E22F2E059A37569B4B95ABE43A911D1AEBA678D9A15AB025B0171D48F17BDDC8501A04F907B9E6FD8DA942C728BF87A3EBCF82564ED11796E25FB861080A010DD2F0EE1CF8A7146520FF66F034479E2B8120E4A28FFCCCD0E4FA1E6A5E9E87A6B8B87DC8A3EF2D68D73F2317F294FC7A15A3A4E90564BABAB922B210878B64C20AC1F8BCB23756611BF042C201DA4D0697DB25E64C688572A3DC62C236555522127124608422BC9141BE17386F6423579697AF73CB0ED14513220AE13AA49A535AC241097190AE9B4AB6FB24E8200F75A7D3848A16DD3676E3E11BE281E04A9B642A1DB504948A56EA9A1C8D0A50F97F292560B12395A1B1138DEC127DE6679CBA8B849E33F888B1F595795321BDD543EAC2A28C4D89CFBC732E7CA6A7A04F66BFEBB4745D489A44FC4A5E255281AE35735D85DEE377AF98751BA4CB8835732DB983635B656F24FEB594F0C0EF5846B854BCED5EC137D8FC1471A41CE845D486E905BD247EE250E766A7F8624181263F2B184D07DF33614EF3BE0E0BBE3ECB0E3EEDE05AE25E2861269E0B0ABF9884A9DB377A360D9D3BF7E66EBCB490F02D0EB9B9F95CC59E7049C8F96F80D05B93AF90753930643422A047252B93FB9C0ACB4B88B0090AE098D1F103239C03D569DCDDD4D3E20EB00BED8F1C67F1F2D3A3A4F5F1E554B2E462564C6C1F4780007272ED5CBCCAAA46165B7978B206E3E099571DB7EAF27237B837884EBEC15DD26B40CB665CE45B29841B2DED76D9B0F1C9E3A0AEECE530A8A16F7FA1F45F9B9B7610A393D4580C5DB025B78B02261F5E4FB307AB6689934F3BFAC66ABF1C9FD202E07F20A1D82747E4ADA8EF9D5CBA6956434E94C9BEB21F32C74DA98F796C575B3B58F43B493D2D3568964580285CFEFB2E62B06588379EB296324ED06A7F1FD4F8790DF96D4A773E892AA0D9E17095D7329D9B31DB6FBE956D5061EF8611EBD39AF2E5903F2F36A75EF2BC9FBD833D8E8D2044D33B44B6B744FB66D0BBFD90CF7702567E92B9FF18A41582BEE4A15DE30290CB07A5E3528A9A27FE160617C351B8BB362A22C37F340F4C3B6FEA6289D7E4D637F6A1EB28A7D3C0EC52686D5A9AB790FBC2809F7F06F4871C4E3A24758975FB37C3D1733367024163EAA8F98CD93466FE9D53629E519176F349685F0E61D093801EC9A026648E72A13B8E4C05F906387553681D00719E572B06D304BD71DD1F5B36A45073127CAA88E68036BC26F9B6BF7265E86803373277BBC5BCA7762F7AFDA314949FEC84177FFBDC696A5497FB40C79E70E566E391F1BFC2B324D2B310A450D9807A5A72E0647DA940FA6BC3BFAAA4BAAB81245DBDD55942457B21DF8BD499A2E819A16BE59A6F7E6676CF3BCEDB9C646BE387279985182989FAAE983879BA0F0FD0ECDF712326A7385A7FC1B2C3F4F00000000000000000000000000000000000000000000000000040A10131A1E""") + ), + new SigGenTestCase( + TestUtils.hexDecode(""" +A4ED7F80956F1A44672C9030C85547B54619A313032627687F1F158976A2D28907900F84E3B9D5336FB661CDDEB5DA32408DDCCD61859AC66D5E623EAF745E858C1D51E75C98A689342747AFA7C22CA287DDFF2B30EE9E945EFC4FF74BD00914687AC4136597D0DBA2AEBB464A55C00007A397971F11CF922E5108F20B895B7941207013811437764076602057327650014846512521051134044721728840471240468158620851514470636303001350088771812801531688000733466441861513742525412601875458731315486847771662050347316344525702707057377764035718082720307174511475224256283107861781131553717714042076114552115453832756862775232773050805741536122157711646367700242428287222761460706108640730202305048004271137750473622514020882603385871776073866148241884265850313425124232184264815577340717562333801724206311260451483381762216524703666716683462381156603313541080053820757730826678818322826883061861335148373782208061718105775375826777672423588433254824486101823767282154027254361868335678543353805617821481162730652045145287554024323481137013167450247203075702807580765272817733061138110138050742533065402722575387148728268663883012058511436440708755322742756705443143872727618411601186033417307153814781410058448267271130100732602686516231834311238647026760152547113031066482361633044416843658581330423061736710024767084324838453061881648523633073145626613485686817505362474214104803222606853556234224865753748040484665857228745563151400065331467076364034001854708148516718643014448254581642662324580472540817760016334875431813615733342068658625221436633877448827353301133165100217143140503533081867240242288376423706818517408834337781383674383187725187780523321864245136772216405236663621124437888768426042072813436208810360206554680333862732263101403067212832824174614502520062327687743605156465476282370734160232624636614258885304101344844586018105357847251401285316763376185064183603001641775527412116344815872823276550347785718752750352857227783051142305354808613116667716627278876620522410851068428786657414384410663404801846405041631402661336873256432535608683333558305507630406032814477633143263257074135750334036686836723317701210415018766018220628550711780864682005421263438423340416413353070086841488211041250620327222208657643663862137722367033353738671553527108308134351574435151103425678758048472876854021260323038826835101538487847208802126638654312684104325807876770077436312012363386725511475331337542627020144121211014663122140658514307281185501024006018177482712312474614161700446687886722647162278322132585863401702314217876006468328164146581047085401421760440321582542441117553056048835224066102526308431765121152602773303251363080350616883864358271348413640038283567734581504521116644336856306352571210550150067264084884453428240000533610751625013670107040138826466331222242287483473037278656425874000521127357382325247351023460401842120860208858010418511736611802200174883450035706425872070364332078257248857812267664537025601262182676445510008434415815140885773555147384536274812741577500878000523602141344148306644333741235746141117460853768768473488606543427458420223345786350554613242521843216282474064647007816386531203354608282C7D03FD47511B27620F8A1E8CADF4475E865E001C554F08A3C8357B8D71825BF62A6312D4984FC343B28C5C2BFB5A945C0EBB5394EB69054F3FFCDA20339C801412E8F06680CF79416D0EFFE1A4A7568279FBE35302106FB0A2C7A991FC66627A0915DCD8C344D056A59846FBB72DC0F407B60E25ED5B855A70694548E4F89D9CE64F56D41F1F905F485D5ECEDB38A3921EBFEC726FC9DB03608BD182DB7D8E07A674929C406CF7151AA2C04A3BE99AF5257AB2A178E07820A15C69302A78314E804EA86D2C2E16761CA9D4D781CB18E5DAE5B671E48E9BDB2DF6C75F07FA0F285256007A891A6F50C49535C19D838966BE3A6195D3AB635E038312F222D164522B744A1BDD080CBB76B0D3F3F864CBA93AE9A8FE4FF6856BAC2E5E7B7BE9ACF80BA79ABF25DDF14F84355FB4C43EB83A532863B46E6E6E64BB64CFAAE4170C2498A4E61E8B270F27559D38EB709F2ABB04AF4DA3A4093400D5D79D4EA004C7DB83461F3C10ADEA1D25CA002DF5F238E0C1450801A700D0DFAD0661CC10AB6BCFBAE0DB95DE9F80F59B7B28D9C02D11788AD52DEF7F4A10A0A3F6C7DE7655371C5C4148B6F8444D4BDAD3AF25708517E4530CC22C4790A9BBC34999A2B186B4C8AD6D522610A3FA43766C42BECC3F9D32ADB22FB75DBD152E7E1D8D39F35F3DCFE8CB2F51C5537E16D0D231F6BC75BB925F14C2295437EEB2DC6FB906206B4AEFAD0CEB91F33BBD3C0E773B61984B781C39ED2EA1AA55D039BDF859B93B5F5618F565F6011EFECA254E516F5EBA19DDAAD7120A11591E81941EC42801B37AC0C362FE593907CF0C99AC6479646EF6C7E4093C38DC132C288F1C0184036652A7DC583B2F9FA2330155014E3E8841F659F910E93ADC4CF082C87CE9D5DDBC89593A99B2E4AE6C43565FBBAF606AE69ABA8EE6EC61FBB22FBC715969F08DF203CB83CA8EE911410A56AE22145211637D5BD82260C7FE5CC6CFD9CE9AFC86F1F1A67A129556E3E989694454C57D5BB6B24F33F5D81386187B0BC6F33734E5EEB3A2E148DFEEB5D3A0D3B771F77A010948BA781BDD7F75DF23123D0165BB263D25271FF6FE747F4DC953AD2EDEE4807A698BD1F1229ECD00714E18EF445279FBB1BFBE0FD7F0F80255690718293D67D27919C482FFC5CAD430FA4011416D883C3C3AC9E4B3DDA28C3BC0DFBB2D2C03BBD196CCF7BB896B5F0A026CCC3D9A36A41BB9DBC8F7C4887CDC64E8C6ED97719B03686C1F1A2888778584CF7702E74AA4730E1B56EE347118EE07CECFBE43555C77CB20F2519576C6D67665F3DCA0A3C436FA52DDC964AA0CB9EBE79E8BD5A2A0EE66510F40E53DEEC226A987C5219FB639A07C52E58FE5236BB4613CE4CC53A721C55BA0D5125ED860E340D882B6F2B0F68AA1EE6D2C1ADB9925780C153F58B8047B7533FDAFCA8CD67EC95B6FBBA84E94806220ED4AF1A2861F4B3FD3122591706B8B3F5519FB51A7A63ABDB03B411746A6E2351C499DEB6E023913BA4E2682424752C17610EFF3296E7C71D09AFBFC4E9921FB13CE3169331B774B322B1925FA1DFBBEFD745825CF01B9EB0A03F760C4343AF3AB8EB8664D7D04298CAABAD39845132763ADBFBB42D7779724BCFBD8A387466C16A1A4CCD9B40569765EAEA58C2C74B0BF2D045C57C267CF9D57D4B1ED237793B45BB947BB83D9EDC3DA763EEA702DEB209591ECA2B3B53CEF1A2C2C09DF4F3CA377857EE30F81C17E098C37AA6A852E759FDE07390973B41322E6F45E552D98309B6EA13E1BB53A0D0F4F6577C0E94AE96DC0E9B5FF47F7C0E57970C49E103F4880A3E9F3DC694FF4DEC024C662F42D44EEC975C7440100F09AC08F5AF04287D77C409A261E735A109AEEC92127991CA582ABB9C38AAF556C0BD7891F1D3E9F76756ED0F8641418204F5BCA432A3E15C446198666F9CCCF6320964A19D1A992570908B826AC75C67E1D877A1EF3522AE5952874377CA0C0BF6083EB8D3550E00F019DC7A909802217A97C7C4564309543326567FD57722DEEB12A3A6F37063CC5882825893B636B6959DD2E6CE24B2F762D59E473429F40D05579A66FEF7BCD812867312ECEE3DFE08691D7DE66DB3C9F6F7B80013FF92F1986CBA42A31EDEC08E3D71DD8F104A1CA29FA8CB4A7D46434E572CC6DAC54D73CA6C86AD04B948C904A14196D00DFAB1CFBFD366A594E5C8A398C849CE8B1E88BF37C09C48C89B4264265A7447E86FBB8DAC8EB39894F80C18D8E405FF15069EA8DCA779662993DA4C0C60537448A39DA002BA14E56CF148783D6F9A97E166A2CCE8A01B67DBD891F7E75A70798FECD48CBAFB97558CF2643E4CDDDE7380E6BA2178677C9A8F1352E75718922C97B1399A84A602DFFC5086DB40091F825467833F1BCF99B7A8EB719654BA1C7D3C57AC0C1E2A21B6C16C548B6BB148A3C4624C648F27B168E534ED0198FBA6D8A335FDF8CECD1E762412BCFCAAF484738982CDCBE17A2A4515E9152AE926BABF7023806A7208560E6C14FA56B06A736C3AAD6AE686101B0A09AF7221F66919709F37837F1DD496E4567EA2A7983179E9E86E252B67DB29D1899AA33953F71FB4A0FF655637E4C125FEABE278F55DBBCA569EAF05C2CFC9926353CDBE609A3325BE0B9934344B6EF5BDC26A70CC1796F594F74CC858F38C2435D692226131BB627DF3DDC507E50C6CA9E8270FA43833844A6B973D078653C1B2CE63E5DD83E888292CDE058CD57E9FEBB432FC177F0E5D7AA96557D0B6763F8801E04CEDB88BD9DD73B72372E309E89F8230FF1DFC1AF767F564AB6218910C9D8101601EC2E108C04F72467CAD035B8288F370720CCD840E5294962B6B8C34C8393AA2E84BDEA310B0D8C32C41A57B40B64F1761901171F958FD17A469EF879F566FD1C786E8D40F47A1444095E831ED353A754604B570F7D87430507A0DF27FCFB4896B503CCE146F4000FE5F20E7E48560B053A64B2ACEAB204EC523C13FC73FC857799F92AAAD7F66A8CC5C89C5685A31C603700720550818CBE3ECE24C0CB47A9B90E0EEBB36053B75A56E68252E95DDA53B876187EE2B1F8E273B27D0A955BFFB67D76D291D4160A7BD3A516BAD136E15F0428E01705941C37619BC4347CA00C5E5B7606D5B52721DCB5C4D167EBAEB2D2F33443B073E7C9AED9700D5B382D5F61281BE2F245F6F7323F6F449C4488BB8F3253E1DF2FDB709DB2484C03BA27E53071BA7C7B510D607F0548454026F960DF5C97A727350E0DBF51E7691A2A2175B57D377CF206E1A38EFBE2A3E81E688684C69B9F7847736C58F0526BBDE9AF4EC377DC8DCA89B97BE3A29A30B820DCC0C6FC54420A5F7553C62A83F2540E5AD504CDB15955034B8A850283DEB9FC413FD746797CB846025BFCF721D03DE7EB576C083D0597304102084DEBE13C73BA3EC43F1110510C7E135735364C181990A18E501F9B60D249DF5A97E9BBC94BCAA322A778D112C4A26CDF73DB7A4B5C195D4DBD8BAE251827F38E652642D12729B1C8E69E8B1C2282DAF805746B1CD"""), + TestUtils.hexDecode(""" +258FBC2A94EE48B415DDADDF470F14FF8DFC069CD949BB88812CD27B2BC3D9522E00F302C0B72533C9A612A251BCD292A291F3652695D318927CE1B922125B287FFF9B1AA2B79180622C32AC624E0463E5F48E86EB5952CA1A95BA51388760FC5374F0561FB8873018DEBF785FEDAE4CCD1A41820EAE9D7056BBD329E7A95F21A4919A109BD27D26779C3588C9A886EDBEA1FB97A8048DED858B299DDFFECD4D678820E5DB6CEEC8B1EA879C9C22FB7F59B227B4F7C6AAC577767D899B2F11FE39D1ABC527DFA0E656F25E53CA05630215C5CCF0FC071F124E48C57C5344BB103D51A1FF24114426A324BB16D8F80D3CF2D0CE573F4E50DBD1CFD66C05430A1109374CD84156D2E31C0C3F4DE2F1E225B5CAC05D56C4478929E356F7F46032E2719E07BB1EC207B32D241C87D87ABF28C7CBCD38267CB011F26A9B49090008389417C7A219A9F18203E6D907D63AF4C42C60F7FD99C7F9394021640F450A9A072BF2C1CC3EEC88BEC866FF1FB5F032567AE053A408342A56E3068EA168B9E902068EF808916EA58004FF31C31DDC3FCFC2CCC92E0DA09623FB523AE46C8CBEF92A1CFCF4C0F523430E60449E5825A81DEAFB2E26B3131F0383B8FEB4B1B4E1499E89E9C5FA2ACAF1F37C422CA41ADBF907EB984DD65D8314E2F71E8AE616C0518DE9B8331FB00983490483362802FBA242E4CB71056E3256BD097504AD13F577B36A2F9FBC1EDDD25D9DBC09B3401D58FBCC9DDC8E74BBBC897552FC826620060D3777455BF76EDFC059E5C02BBCCC0F05F86ACE1903AF2BB08A962BFE9E2C435EE8C580502351669AB7DF3D9F6B4720A0509BAEA97FEED3B8C769AC5D0997A097852C72DD6D5FA0A7144E08D667F21936F434953EC3C88B5BA2EDAFC4F87BE8BFB5A592847D15D5E5D972710A4A75A5772DA4D9F156563C17B1F0F242457A198658524B0D6A46DBCD26EB9400DF3C4C942FF53E1102411101B2FCCB58E3FBD16E725147960AD56C6CB6DB336857EF137C49D53D16E98CD7A0E856E2D6B391A95954ECEFF3B9956A6D0C279DD9E1FA5895D37EEA8C54255A6244002C7542789453B41463B084E7FB3361923C43EE1BA115CB254F47E55E6EB79C74DAB4C9CCFF486B8CF5830F23BA23C5CFEAC2DDF7D71EB5F54141C100E0AA9873D43F0AC1034C54193BC63A560A0C661047C508062A70B3E575CC185462A75230D91A3021330D95F3C807688B032AC15A9623A833DB718D04603ECE983F1D21A4513E80CC67FD34EFF8E377B775142344645872844BA46F5AE6971E68FD8ED640BFDE9F276E26B208A8F3D74ACB739C7EA6CB26165EE182F165EFF21905DCE3D02E432B1193CA108B6ED066CE95D549D9B12445E05E0583EBEF32F17EB121D80EC26C1F154C4DA2ECAC841BE1CC7224576EA43ADEEBA53C4D58785F36B6BC0F8AB23340B92CB87DEB0230869A52DC634F68A83BC1AB8A4102264CCDCA39A51C331F6DBE30C18C00A966E5692CA86399264399DBD3F02FF8706302462D62E4D16B5C2FFEEB02A7E8447C2CF1A3FBA5046C792FAE0B1079621D59C1D7AAD17CD6578964D1ADCF1256F2A4EB4D534C51313BAC17A9383B5BD02EDCCDFE59998D2FCA7F3EF52CE0B1842368EA66E0A83FEB581A7137004655957E91B25F5435BEDC0ACCF69238AA4CACE418F08ED0D961E13B2234187597FCC012769F798D969C13F6BB4042897B0D8C32E6CFFC06680B1E0A40F5F149B5974B0E7F0D45367E93B415F7F6DCF86C2131137DCD0DE30A3F1FBCD5F8214AB20BEC9738AEAAAC200900F4B2074688C8F3026140A354A22F83BC2ABA66407F87671C3E7EA4EC6F8272B6D16F3C66C76ADA231677A9B1CF496B3C241D2D1ED7DB703119CEB162EB097A0AF2729D0D6CA8DA57D83E1BEFB880EBEFE090F6E98D64296F7CA90EA1C2B26131676232BB394BCD1A06BA83004BEDDA287073154D3BE16C242DD65839C2E1125B3E66DC93A95C62F5DD31CAF9895646D5E2D183D40EA09843F5DB189B41AA4CD1B40C5792C2BCF9F44823EDD4246100457299E30EB2C66896F89F4FA250AB19CA06EF5B899CB96FC5E0369B773691E3447E68475A7552C10F96F44B3282D92AE49A246508A67EAEB9F4586074D6FE8A44D2D27C7B8FB4EF6BF701084B73641E41AA7275C1D6B517FBE3D60F64BEB9119F3FBE96A11AD45610E63CBDBD79929003BD1F2DE89DCA036973974FE5C5D5A8B5BF82DE0368DC60D75A138CD91E8A9233BBD439666ED1211EC2FE7D7BABB1247315DC480CC64CD8F7859BB9BFE8C668F112FA96EA48BD91088EA44F40D3E57314D3759F867BA52E52BE822400D9B0C2123F50601EC5F8E8B562C4B1F49F9779A99C926FABD8A74173195CE23173F4CC4098EED74C8E0FA74320772EBD1847AFA1B397F5A6F05A00179DEF2E6C3B092D9182CA3C4E382C4092396005D8BEDF6248C81D3AA0854F0AD43C1079CFA1E0A42650EC9D7B9077BEED377BF5FB2F3D2717BED04CDF2F7E7D1F45CCC6F71A780D2E5C3516E5F6211815FD691E036E4FA002079448AF0E005B67D2939CA88CBC57567F634BD0402EAB06805ADF8BE550B3E27452B372CF8C92A7055714A228986FDCF4045421321555BA06173CA0A761BEE635C541FC984C5BD3857DE696E9B21EBCFB87ECA437E9A7B54F4CBE2A601824EBEDFD5446556B64E1A88B0BD9CBA507C5419CB8CC4CACE48A0C9668FD2D045E9057B13BF0785F59B35338501B73B44CB749EC2EBEA97C9D29EECCA6AE1FB719F9A67E8E175D50B2705B6149E9D5D257B34487B547FD050FE5C998412AD0B4159C2225EECB67903FFE332CC3B86266C22FF7776334543C1E954AF5A89C4FE59C1F1AAB5097024E2AA7BC09831C9A5ADB713591106CD3304873BCF11A9138FB08B7485E123DD8F7C107E336659DAFDB866487E197589DE47D2DE8298EC3560EDE21A633F820BE6352CDE9AD51515D309C4BB4709F171CAFEB407ED1A02BC4AAB53588C2CD4C273BD527F8B4078925FCFF8954536E0B4366E474801F5B938A4B81F037764D5CBAF19F237CE37D00246C60DA652B76469BECABD51F873DC75E520A75B52BF585D664B4CB9A09F8EF3C03FCBDE6B9E595C1371C2CFC24C16EBC392C75D2BA04212947944BC0377DB718A7FAE0F6F9008AC7DD30B94C1FCC6BAF750217C0119736E4F3B7E744AD72F1F0694BC88F71E4BE51ED8669F0E814E12FD9F833286E2064708951DAB852774D4620A26100FB44A8A92B86E17507C036CE6F3ABCFAB91193CA4BC4D4198DEAD7CEFB71B01FE2506995F2ED3A02EBB0355E6B67A2294648B8D1C1445164D99B966588CC253D1EA1361163024372E2550E9D29AEB4234F5F9B20AECEC01862CC98365F1C57FA4D5E0C1F8BF189E169669F825DB43172D1F682DFC7729B2AC0C103ECE4ACD982D86C515A208519D23F62934AF981DA66B97DE2389F2F669EB92CA4A5C4C844FCB19903371AEAEFB32E210F2D1155576566C7B529A98A1CDBA36B450F3948F34F90A49F50E7412E6EA68BC3BB0B0A0AFE3BDDEDB718D5A150EAEA784859953FF1DD1B371C539243547FCDFF4ADB06C61CB49EA5783AD06BC8C1F3E32A95AD3CA6D69EC1D226BF9DE0562888839E6243CD150EF6953C158F9FEE5EDBF173997D08509EAD1ED4DC2AAA33E18DCA6F59269CE457C412B58C4483BC96AF5069D1C2E3F2F8DCC5FE2825DA21AB2280984C359DAE44C2367D6F002D64AB47F9B64B5656622517A5F7D5E1A78D4182B6BAA82E0490659CBF2724080A9ED39BDFCFB21BA362DC29C750C5034A04EA5A85799E01FF8B16ACD2EFB8328BEC686AFA20E591E7C7FC55BCA8BA1A3C388B785AB0F57208CEBBC5619AE3A0B799D1816B013BD67D440A7AECA7D0BA517846B68F70CB5D6ED46C36F663D6F242E8FD8C620C9383EE1BE9250D63467504B229378D2589B525348DFF852AF1676A18DE321DD46D7AAFD3DB1825F192FBD3F160E8CA400B201B1A61D0864257CA340F179F5F1967659AF4789846A4D086041441DCF4267681B83D4C8539086E276C21BDF677961015CE550E41C2C45D67A09AD8F56AC3ECF1058F366F2E35BAA9353A5CA40C7021DD09AC9FE0187C10EFAC7BBBF3B1A462C9C6C96699741AC16D3526BED3B30AE25B8E8A9ACD8CB2BB6C28AB89F0A3F0D0F40D10AFEFCCB067A37A2C93D3E8399A366B5FE4829870DA75B93249DBBE3C9AC9FAA70C4E414EBA720C323E6627759E7287472C3DB9CA9B1A5FF03E872374D6B893BA4887AB227E989D9D4D348B3965F7B96C5094F42D84432EB771BFE757105966C9A08D6C58DED7DC216B3D0ECAD2D0B025DF33CD3D813348B5E08AF95BBA08DB5BFE5D0A151C98A01ED27661CCF80F416A1AA260EBB56526AAA289F17FF5AE97CD0907D9143BCAC73F1F83A2A8DEEB3ED209EF0952D5E463D87145E0E4D8BFA1741E3FB737E14B5924F436D0183D98EF836DCA3F9623B50CC13EBB5F94EFBB76EF9BDF40CE6EAC9C49852D08E2A5A193D1DACFA04EAF3C545E0E25E37E94DF51FC1976BAD069CA530E19EED277141BE62239F47441B88F6555B0A998C1BAB53758A41CFD8CC4CDC54E1158DE15910408A6E79D33CC37F61917027E9D2F186466F704647B1CC1CEC06DC1AC37D1A668D44DD8B12621AC3CBD2039BF5A843A86FA492A847D6552E1570DBFE008F51652D65D03D8B613AD917B81CACDFD19DB7F4DC9A14E237CC6D7268FC5D3B228BD88ED36D8360488509C974E01433D78701CE07108C67D0489AE94076106B045DF7CC508466D35BCF156901E53AD2B5ADF8795751891A5839033A40EF3F5DFE0BBEBFB2C9D1C000691F902AE490D382EBC87FD40E76B30DAA963254674C7B6F304DA2C8BDBE8E1DCC87DE0486B4FE6B57A18D5A9E9E4BAE776D6147FF9C98372426EFD30C3B2479231E624A253A7B0BEE31E0FF739F862010AF03E227A12C3ED1F33EF1C0DC9D48A100FA24CE5C5D8B5F88F92BDB6A3A5328B0AFA983D57A1D3320A682B5CA94E75DCC69BDF2AED0C05887B791CE6F6F8885E4CC55C3FB050ABEFCD3AF2CA603172AC78B3AF2B047E506639498D0391A06DFD328B8E1BFAED8F76C6E4A93E733ED1097DAD8663F5BAEADBE1562D40C772D376786509323BF059FF17A5E6EF5A31BD668954766417E6633BBEC90B53ECA61BADD4037030A55A5EF4129D4958F6A8A5ECAA1AE7E220A87AE996AE8D9AE46B9C60FEDD98FF1E67807037970C92CFF9EA4B64F0BF8907198A6C038F9826CB968B1F301952E1F409DD6AA4EFFCAB157E792ED45830708ACD7A50BE8C08FCD12560344221104827BFA495604A57826A49F90B8B694B2BCACE4040627AA0989E3DB4FB7167F50E8A04982084FB3ECB0DDCCA5F24A7398620D19B37309A4DC0DF28909E16645F35A81EB3C5EF6BFD650571DAB03A7FC02FDCCA5FD09C9D2D3DCA888B8261433DE88D05DEE5D6165080A237D55ED718486AAAF1E2534CEC3A87048ADB40EB9F9DDACFB2C883EA6B20BE1EACBDD72432C7A6C97721FE1E0D9A5589C951F7D46F2C5F0FFA909FBE12E1CCF00161E741C4505681B0B018FFACD460528795CC3810BF7F94FF9B75884956798F21ABF36DEDDC1F95890894EFC15EAA6F19E9148C71EE9BF4CFD41EE3E5DF8A449FD95E5744793B9C223D26ACB44E691D7E5B68D49A19687F0237E7287841D3B0B4483E2A7C29CA81BDAFA5D96D9D2CB6FD9724B9903E8CDD03DA810EFBF94BC7179349E10566B5A314F81327F76C5A8346E222C408EA43FE29439132CDDE79D0D69C45C7217399205C2DA4D33DB521940C4EED74CA22645D5B6A549E8712D0B8CC50DC180067D13457ECE66D489F687DE218449D974620B3B5462FF3A7F00C439AEC73A53303AC51EB84BBEBD51AA48A5DFB8F93556BA540F5101CADB8BDB912D7BC87EC2AC67971AB99093C8616C4D1F3E7B06003E4FF22D99E6CAD7558EAF5C1410199EC97720E5C9278548E7EDE62BE9105A2B27A54D95673849CD5D60424ED97BB64798263F98A63DB58BD55965D3A4283797CD88C7CA67B1C4F90FC7237EA35AA24DB18A4420B827B3FF7FA5472C31499480EEF5A97BB967D1EC46E7B05A3D25212C75972D48A9269D67048132399E1BE0C02150A3D48717E4DEC2ED47458EB870A1EEE5381209B5D182DA2093AE46A4D99E3D4F12ADD71001BDB936FE8AA96797982F88EE67AA2E0F340E7AF498D5AE05C177F0BD2650A02ACD4CE23018F9E00DCEB9794C5C76418EFA65634E01ED5E9FF94FF86AA73641117BD554A9391874A75C7CD1E7759755B9D2A7F367621C0011F61B588D913C7AA0A0EEE3A2201426EDDCD56A020F54AB41CD899721D6E1F05F8774CD5FF6417CB68EE14C20D9234369C9CA59627B8796C37B4ECF1DE2F981ED0FBCD5737DF0B82637D599A61826909C978A2B68CEF01C5CF84B50BE77B49C1887544779BFEAE3F533286287E48F0ECC0D36C27F1209314726855E61E5EB5E9A5D7E3516E29DD369F94D72004742E246AD4699C64EE996BC7B2A079344ED32A528A9CAD6D5AC02970D0168A8B5BC713E28934F2880774418550AC2F534D06B61E627BCB8711AD9FC6F2A4D9301EBB74E1F3C73B05F28DCE5623BE1BFA871C14A947A947CFA806AAC43AE515D6CA65436BA6B66F62B0FDC8AA4A748DBB72D9AB087AA39561271A986229EC02BA3719CBB1798DD333248E4DDD0B6EEA4169D3B03C9F4DEF9616BDF97AE993F0FEDAD31834B6F78E23164B556A39AC1F209581F61AEADD8E504E81A808B1E97F79F987892A8F7FC35FED9B1A2E9D3E17BFC5AA64680DE98664FEA7B479567CBE307AF2A8516BE4CBF9EA030471428CF802FAFF85701AF96CA1D8F50F5A79AD63F20C5CBB954011BE4B1A7F627A8B5F5A0D022D27BA6FCB8D3587E8632A2FE5794C7E8FD09C9AFA3021B9F43BA82EF48A3B1F3E40F2FAE182DDF9558F7033773F5627906E159B794C4220219BF1A9878B175996A16F3CA1DDEDA56B16E63C504354E5E42FB90CE4D2C1AE7C93D8CE27480F3BCCC076CC253B574A7BFA6D3BFABEB3FA6A19F196C7E31A0D6E9477F828689FD951E0FB033DBEFED6C680F0FEDF2F43F48C0136C722601CC7C4B48B24121ECB6BF84D6B3DB240FBA1E014F7E3ABDFC1F9B98A16F4D39826BC1EAE44385FDFEBBD649BDDA129FC7EA3F50A5F481D3B7508EDEB04FDDB3006D6EE943930E3F0AB405D151F21E8AEE5BD87F225DA6E155158DE27290B2048D384BCC54F0EB905961AE4CE5E6E93543016F62445AFB5C39C3EA2F3367A0B8F0FBB83B37518C5DBE1CCA1DA9D0B54F34B15A1349A2F03563732DE14EA9BD238F481D9B262DF69D24A91534805ECF57A538D8F08B2FF11E96EE692DFEB106D3515A7C69386A781DB1D5434AC18713CCA12C92557D1E7DFBB15605AE3BA86267F3E6CBA42B6084478E460F092BA2649C8C94D66128FABA2D0EA7D9BCB20663B0DE6EED2623A061778DCB40373B8CA38B02B7A49F6940D6D11CEF549CE80212CE8D3A85CF2D774431343FA1FFDBC71C5334B1CEC4D4E0EB643E1AAD67D1A5B73FBB1BFE47EFD83CD17C798044A504FBBA5726429F41DDEA7B7265A76A48B0BAB4845704C771638977511092BF6C6DC9D574E6288C6A3B96BFD37FAB695F8DE20F28ECB27EDA70A07FB2ACDAD88DBDFB2DDF06E83ACFD3A136C5DF4811D34C242BF9206D579BA8DC6D20E8600B726C9F1B918EA573B9DB2F96444E17B6EDC15822B85D452CD99CBC847AA205EF79E574ED9625E33B6EDC793E5"""), + TestUtils.hexDecode(""" +0EECF0C5C5646C6C01CFCE8A4236C503F9C21F7A3FDF1B708851290611FCEC8D28234E40B9061C15212969D6BB647797B77E3CD2AE88051929E75E9A0D8EE4491E6E709DD1E43225C545CB3656C0F84520A56BFE0B3A26E2856A1661CC2BC5BD289FA800CE140070BE31080CA1245114624EA0C215E76C32921E54F83796F9CD9B5F0FC621AF39184C4857667414EAE4A2A7D18AFBE427B48441A99E9650344EBA609B879C42CF4DEB120FB5C44D542971182F83C87EAD8DF96ABBE1A7CDF1A75C538ADA01C1EF73E99F80B792F61A548D3A2154008B20AD71CE0C8AA42480D8CED5EE8099590057D15B339A8D22CB86E0E3FF8B9E902EF7603098B356CA6A3E8D8826B1B02376825B82420239F04AFC1088B16255EBF6030E183FF446745EDFC94B6DB334B4818F5421E58710703493859503559DE0AE797A4194E46AC916428FC84944B9F97BF2BE5DF2C3DC0E918F8AA58C73D92A052E59DA75AF1E3E30896AAECE657CC427857AC6EE80438C849B7D129726D27DE10043457BAC8B6CF88E91DF12ED3DD04B930ABCE64F4A140B551720FD7122C0C201D61F4856FD901673B59EDDAC1486563A7807CB94DA76A89E3B358A78BF8054D7657246200685FF47BECF5AC5852CF2AAB51CA8215CA1EDD6EB6B1B7CFC6D1E79E00692103FC124A48AEA58D21C1682761EC72712D2FAD386AD3153C1A07F40135F38D6E3BCA30F387DF057D4E26FE94E1B89FD1C63CAE97B0E0EB18D53C45F5A1C0332F35FEF2BCCF9192758BAC873D3C48506D23427332C89465C8A08516B1E0511C56DEFBDB891B15DE0A58771C31F398FB27BF63F3CBB9AC9713F75EDF32323DCA0D2CE330340B2B5946846AC0A0961CA3DF970B827C311F4E7D04A859BE995ED60092BB8FECC2B0C5498E9B0F88B4B70DCC50B6C01286494C91EA3390F162CEFCE4B83A5486AEA9FA866350A3A3EB411A601623F9D77585ADAA9DA360B0900EDF684095A9A581DE3949F85ABCBA9525398CD58A81E91AD655649FCD21CD40490A5892C0E8CE4709B1E8004223F8B842389306CD9640A3D32412B4DC53E3BF04FC39424156B3E797E7CA688AE6DA5A4113C8CBA7290315D6A6DEAFA09680857C18B696094FD67DEEDDF1D69A1A53F73696733CA54CF0BD144AF0873249CA50F897CC5B487247A1DD5AE8E7161BCE9C5723DCBCA44796CFCCB5D16B42A1EB3D2ECB6108DE4F2BE18AB41C287C6B4677E56802CD919EB1EE762306902C9D731EC5F0773F7CE7243BB6A9A832C4052F11E5E56D20BB6826AFCEDB7DBF9B4F72460BE0C45FFD628EF44F0BAF2CE179D9627E5CB1D10235D3AB21206EFD5E74A823DEEBAB0DA04BE8D9EAD7487BC96EDFB71737A15A27452792CDC237305E8537619930567AF51EA8E5848DFCAC9871C7B260695A340F03A48CCA700E60220A35A01B2E195BC3D73A5A8C6918567BAF8EC47B473DBB487F77CB37EC6E37D2D6F885208AAA845C5ECFBD2F128CF2D5A16C167D26B00CECB517E753A121CB4CA8EC8B3A5F735FE28BF6E0B988E03E6FC2DCE9569721E1A03D91760C0EC81B4C1DD31470DEEC860469DE3A74777B5A8148DB3E7BA6AF995BC8BC14F30C7567886CBBB1C6D40433D93D52D9D866D897727F55558CAD5871D461ED8756938048C877C9183AEFF67132CF8AE015F59BBD60DDA63B1C2DFEA4FB19ABA2019BB52A135935F73BA5FA359EEA99BCB8254B3A3D82BC2A8AABE2A653AD58B2F13609D762F2D7E89370BDD46E46E55B9B9217A5157BD696ECB992809D1DFB607F1E66B77E417CC0EF7F3CAC38705619BE39FA625EAE2615D9137C0F702A5206D95A2DFFD7ECBC308CC453CB29507B8582A1B200A33C24F6FCF9D3E37814D029DF14D9D7E8D6A98B36BB75A1FE45FEB1A61F212C03F28E9D45FFBCDA5796C2FB2B9BE9AA778BBAB82F9C2BC4DD45B64DDDB6FB1C71F57E11E49246606947A4863434C8CD23C0080F11B31DC7BC0FA92E45415C57314661C1ADC1358AA49EA4D69ABB9A230BCB0D85A8F2885D261584392656B15643323B270C68ADE3D7727B35FF8948B1501B8458FDBD59282E713072F0799C2EE69EBCBB441CC1200047A23DA61DDD7F73D59008D9A802DFF46490DA652B6EEB1BA3D3B38FA04FC2DF2235380B026AA69EE90DF21FC5045895581D27AE6A6D8F99215B116CEB03F9C667CE8DCA4B63F1B875A2B2686B30D1A59297CD7A491178E3A81C83B907A1C7850092C355E130C3C41BDE7839B115E8A51D729D252AC62CE03E8B9EA488338E6ABE1A1151FF037C94350FE5B89964069FFE68C238B901B72847385F937F148519C0653F932048D6B0E7B57092625A1B4BBD72DE1D16E7D96A509F39B3A9E50D1FFA7EFC5842DB79B8C15F2842502278F5125EBB082C5EF78BEC9E872DCAD120FBF2A3D544F15EB51E7C14155905C50503A3B12C24ACC6A37A051D54C6226E0FBCC5DBABEF1C0CD4A89463873379CD95B3708C5E56FCD03C71B3E5788AF19033DA37771AC10373544CC25696F0A342307EB92F58D95353F45B5B5791EB3EA3DAA88CF74B3331C21DD448D00A1DD026A0DA7443B0028D1E35A304B0D7DEF9B74C09C377A9A5B1439D64E7D22C687FE420E1E037D0C1AE5B2DD33093C1E130B5D8428AA2E430CB5FAB92B316439CC9E7593628D567D7055428B7E6326E7A004D0820C22C1CD015DF8F0082F2FF4D39A05A66382107C8467F00344639CD32F9A4BAF3DE73640F06344D64BBA6E4E830FFB98BB23C02D0DD9D1AF3B2E9224CFFA7B62CF7CD552DD26128DB065C1CA91083D7426195F9DB63061C20D9F8ED337437B4D69BD7AD9DD13349708FDE783E86BC1F81BD2A317F3B484DF3912A2FB97E8F5AC62D14ADEC7A7D1029FCA2DCD81EEE23CA87D66BF43E21273D57DA057B35D8FF70404C230989B15DBBF3B057367C005B5ABC61533C623D2D774546119AE87B2D5816B5E7D5039F2D1FA568E338D4EA9FE809126B46D2EC92EDAC8717FFA55D678BB94F0C061B0744F7006E8A0A703156E8884A81AC0D8BD86EA1BB7E682E43F99E2482EC27697293A00792676042A660598B8B54029E00D5F0C7D10B07E4275620C3D193D5323FAD46AFC4B8F4AC825618E872BC184AA97DDFD96BB395ECBA6C3D42580F4BB877E5AB7D96D985811B580417D6B006B1E6FCB3C14F84AFDCBC38D495674B8AA6976B036B5306EE593A0584A55DF7FF214C1C6930CAAE7AD69423CEEB46E95D0DE88317052C5C62B77C43CEA863AFFB22F0201E5C451BD9ACF2D8746346E776174BA21527EB5A32AF89F12F9E26A99F15AE8017FD9720E3CF71741C5D7A23DF373B0F229B89A1E1849D569E0461267267BFF654CCC010F135AD41EBFBC63A3BF4805405F3308095A90D4C541BD82BD62D8EFEDF4B9097AEF796C199521931156A3E7A59A7641F9A0D6542C05EF29CDAA28F5B733C7B30376C975FF08485C8CCE4393B5A8D3735A13FF6704544901B22FF2A239BE8EE2C8CC56175FC928E3676209A003DB9D7BE5DC0FA7C6B3A5CB92F2BB9EAAACFB740A8AB47A509D2BB76060196F26D54690794C5BFA48435B79C854E79A538F1A796F1D4323C016A72667E85DA2FB595E5F8B98E5BCB30FA0BD14EEA3055BC037B2D11B6C4C8522961ECF541E3F2A98185ED50E9EFA20516B0353B0DB96A6183AA9EA9C2C8CB7175158FAC07B08D5C01089B7E835D10ED00D7B3CA28C22FDBF1E0821297DF5EFEE9AB47BD245CC29ADE18C0D0529F9070A2F961D558012908E824B89D95474D0201612B474F7C2E4CF4D66AB165883089013A4A60DA26EBE8D7FF70AC279CB81A22229BB098FFC26EF456B49878913A354F66B8D8F730FCDF1FE01161E606FB890B9923ED849E6DAE68BB3364E6297B66682BA3CD3F0FA7EA4B41B8C96C70B16D606DE17BE72119251F6B64DC78A97924CADB77C228F4118F2C93CE007A4A60BCAC6950FD2526670A9ABCB6436F8239DDFEB8905B69E7CA52BD6FD1D3669B24689E4CF050C7760C0001B7875F76A195E043ACD6AEE609E76F1C800FD0ACFB96D93BCD5A0FFF5F979A96CC82A376DC443D694AB9D190A96EE34D6083702DA6FD73233AB5DC2CEFCBEF22B5B32F66565D0DC948297D83FD04E919CE4705C26506E896943C5B1CE8055434180CC62086FA39A12DE595949C40EE564E5010E22838ED76DA6CB72305F5A160B04777E10B24D7B502EDF16574484DF1872BB115FD6E91E0C0B0AE2FF35FF01F8016D8EFA6D5033E7EE3138769D88A96E20637AF1F435FAC584F94AF8F9C12E3DF67814EC28CB50C5C8C473EA39AEB6080E127FED93AF5CD75677003754C9E31120FEFDE2B23EC17520063884FA1CEE1D4C0FAF3EA7139CDA87C050CD26A349C55362401D311029BC2F21D29793FC8661DB90DC18D96079AFE00EF88B007DDA214BC8800BB7BD30C942CEBFBA0DEBF1E68E9903515C990C49D323A73A804B0EE4EF439BC5B67F298D63B9932C201634AF618DEB8C49DCA06A0FC865744501BF3804668F3331155CF61DB1DB6CDACDBA1119D3558F1A0BA05633AD518C563BCEE51937C0283F3516B812AB2CF2B80305F5DC15437811EEDCBA7D236E7E9AA8BA295A7E8412494E683F5985B920343891E4F44E585A6785E2E6000000000000000000000000000000000000000000000000060A0E12181F""") + ), + new SigGenTestCase( + TestUtils.hexDecode(""" +C8C32C98B4C3329B1E9F9B8B0A06F728FEC8DFC05CD45B51C28273061A7C84B44D03DEAA1D3D423DEF8D01DF94252EAFEE18AFD0B714F246A2AA8B22919F4A64E8254BC8DA58D79694F68A8B33FC23190C4D19E3D686EC528B46E14D752CBE218D0E18B655AA5332AAFFF4EEB5CFFD2BA6A03F60DC018CD23EC259AA4325EFCE08852158642851628354014253336656040034734085244624702650458046023414141653265662553257528848144434538583171237621870046622542527580662760688425754461883673651187381743864383543514734285686547356774154037857147010824422821820372371434640278657362264124415854343344041688413722261224658655223800244426352431335075843223847830638802787087632058358458134612063704650052330674634702657828852755171178100888071574872500003761125174467551513406085034688414064261281865718534556361580681066615474883681774570757571780007105873237730643787603255741251882778647716627735424330287653567230817703068376113812788174132853265501737207541765673284844633087711520768836556152784146844502445608448350455765277306601008336883210200716413782342871820515037658772672513172866057305014605013778856128828263337372405472843534375648655082510264478061188683265047702226038855710017543066112306303885632257413744062041317752202814804005205448814280410780017846728458263376183744528251332866682020484544067715461251381023268133503550626017320763011688141043558378413875642643444584351184365058376728644264005672381788337041681643525641530354046426331448556436657662128333156784163856374755524078102415500647382668666204378324674242332458875560880870446801506724870770075377623558535018066536113077736557373140121445368728505234510843712443083486066118634707435307287834841377048724203643811402168118565240877002038527641833114558786071676284684057368570785252016484650654480760442014125342136012513131513754542527403415643546752574520100488478715505263884185412513443846738708103777317714028531710677723682545550823825506760431583105357435861166168085225017870015035876442236026623862112188700714876376877706235072035840614340577178021553082422411251301420001307586123370726600337582487275247806637312456726385287223783713615774466050881878126110710021758600135101147142066365521572708410557043546161410781630038172422202645550360675605422888073255353264416833160257185872065350608713265217047530036306438828400667786630573535515217683235415121861604404228766416241310412807607544783206736820630303115444301271607246665073637418272420826411083048741645574851556481310322648258642846872020371271453707105300457683437487543257460657574378450022804404154248422852870054400115704171748041775074284552866412884625787625020238334401546627850511538557453800533335000553567035164313872271652448031663187004542613853645488711616002127354808730021575550780772055654173636682015662428213111586672337018624237806607430261432561653583383546454223153687813363744535756030611834227116883466042873648850082482071801637617701364885353218608856781116835784815225000572468806855765577805768462876401546171442778806140835684815656874817750328776567238860658770156531530633503227851364168542031232554515285878430550188057083146685505544383510160372216041617018142A2055798CD4A9FAED4129F4762117C2F9FECB68F55285D58DF9B1D97319AC4966C0BCC41CD28E76896A2CA0C448C002E606702A1D2716B18F92F3D248C5E576EE28DA7A4928CD072E2E06960D642D78C34A55DB793D4C6C27D68E2E7C2E05F3E997DB884F02DD4E294C0A37EF6655A74F98B3D118D63C8975645DD28E326540E289BCC194695E2962EB6F573FA010D9AE6DBC9DF30344189F87FA5A12E7F096B409CF4905A15010DD6CEF55A88E3A39ED196CF05DC1FC8A5B706452F4E49A2D07DAECE812F69207EB3E4D86289E956731033D6F0B90E9442840DD8ED3D4D7298836D086D4F171C0AF60644B7EB187EA185FBA5D04D6C42BAEC690B6F1D68764FFFEF1C719F690A2BDC241EA2A145A7B9193CDD67C671D14A676173F352AA90886919A765B2D89F46E9C13F35243982F81CEF10680967CA1D5AF9331BF64951F1C48CE1E0A24918FB07573F3899E19D3BB2C386C943D2732F5D287996C78C67DD2031BD6C635D53C51DDFC4B71A27DFEC7A308E568F2805F667B1A85F6436413A186571F99CC842C9CF43146B588DD7B0283C5FD1D09CDE662B510BD85FEDD31E3DDC957583FD08A1F8EFCF2CEBE014652E64E558EAA832822D089A3D82911D671543FE6F31812A435C1741BC2AC8C5B33CE4E3F546B970733BA7384152FDDE245FDD7989E1CCC430D134E36049DB88A3817AAA482BAE3B53D9A448FC536AE8F2D01919588A00A2A2CD1F1F48710F5FCA8709286B4B7E3F14FEFAECFBC830D3DF005FCB6612B782AF5DBFE7C2436DB6385A0F2C929849785ECE26D52EC9CC70837FF75C7E6D280CC9B3A61C8618C2E047BE4DB9A6A89E22EA3AEB8E2953B5336A388E3837DF09BABC71D308298D735D37FF4EF3D0D65247B72DC04E1B7A61BFE131E4264DA5A46B664FF4C44279852214BBF4867FE3B8AA274ABAE01EFCD237DB8D41F71DB2B386F596799C670C042149E289FBC3FBE0045994A5263E710EC3591C770717F5D6E4362ACBF5A2C133E9896AE4B59553353CBB626F854149A25728C4113686F16D0A6EA7BC54C8DFFBC8D7AD3892AD37048912B09648814B415D74408AB3868D6B1114FBF9739517D8AF886316E19BFC66D55AC4F76C6814E96C6A8F846961CFF17C8D6A1FE362D071D5013B2349724BAFE710D990C8CB0C6438535C5AB62AD3948140C1DDE116B7E552E3677C001DDA26E3D8B53BA7506EA0069B90A26FCC35FF94272C1C90B3D910FDBA5FE8E2AFB5B955847CFA4DF8460CBDE80DEE5DDADC25C00418C126F7D0C5B8C1B9D8710CD3C995500AA245C63D9497F6279130B23347A95A9D5694B512D4BC088290620738CA448B08ED871DADBF1725D2348FC4DD6FB64003E044B67595F64D3514B4CBEE61E9E12F1163B56C105EE952616A331B263330B29DEFF153306EF9CF27C9B178F671E998C07DA69C9D38B750308A7D78ACCD69EB30E1F04D86417B76360805576DFB5BB9022EF9D6FF249EF9D66255A03535CAC6323B084C5550BDB703159F570F47196115BD67DE8BDAD32C9BB29B7C6FF96EDF4313B101E28ED28C37AD1DF54FA6147F3CCFE8A890A423B047A2613CEDCAF70C0FA123BF1377482C1EFAC44C483539F54D3D54BCCF3CDA71AB23A7E27417C317F5B1DE41E99CC1F695CEBDA3A2ABCBACBBC7E87BD1252DEA50853F4C47053E10AD30490FD3244B0AF23B7F869E13F96591A363E05574808FDD2536E7887C0F621600B2352E3660FC80B7DBD09C4D06375CA6AD8227D60E19FD9532BD932A15CE6A79EE821447D6DCD26367CFE447C3FF99A408C2EF4E1EE16C0B63EBF1101FDC0E66C5F5F4E99D277876C7B007F26AD220741967A0023342B09CADC11C0821B4E3B42F708422E36449C37D197D4652260A29BC9DA316009DFD9DCF2FAD8E7C66E0856B16E2DC625DF9EFEEB36D17E56A97E85BD00988581F28A742A85D6EFCBCA370FBAF39F1AC123922CA40EC5B180D40F5EF9EF892E66AAE5AFE52AA7E0DFE6181A0565CA6FC3FA284DA2DD4F6FE76C5F3C89C38F8C635AAE6B006829BCA1EFAE1C06E35446AF3D64009BDD36C17E5B12B5A03A64E6BC2E83BBF6E6C3785933564343950D229072F11092DDF65DD267C9685574D6D8AD15DA4B9C835164E95215045F7BCDC7315374289AF7EB80D538F6484F5BCEDDB3AAFAF69E1A74B177DE4FFC6A869B9BD98F7A3E7109C9DEB78898FE57BBBBEDA72678E7035EB555478BA70E405BF2D3D8563B3AC065627BE1F4419E716A62095E6A7C5A54B22327ADA84530EB5761287967E6D6135F523F01C20349E337AEE6AB7D57379C4E919CDABCC46326E09EE6A254C08440713FE744CEE9BD8773783F27C28F657F277FF4D96FD0A1E0842529D1A55D1120E0B0087DECC8244A655C43D33019A9BFD54ABB232739A6D21DB35D8DB48B8F854E82FEB295005F55D9626532A8611AF392B67B0191530FC64422E02F9B99BB0E337C663230B5D7C92CC34EC68ABD6D9A32657247D4F4E90139DE57CBB0CA2AD179F75E244AD5B4D6A4A21179D5F423A125F3A52DC6E7E99959F3E3DAEF1C56EA39ACCAEE0B4E0EF1549763CEC5E1A138CE4A2B1375A370E04259E67ACA9E833C2D969934F9A494E03F10F3B843C1A24615BBDCD322DCD2E633960393DFAAC490E69ED03E9DA0E748EE1C30683034389D6291D6DF8ABEEB363F5323A20B8E09715EF0B406963FBD178D5F46954B356BF20B90C670F7946516A7EBDF67381BF26E5AE7AB0BB69084B3663E980F2C0F8E5180AF4897C6A0DC2DD052417CA772DB1F48F1336B49345759677AB31980F037FC4B6EB7546942659C5BB685FB2C862C7CA37505BFD34DDF9AE301BD9296F98C24E110E410068916F98D5B1F320D7D29B125FA3601A77DEC33458BE0875ECF4049996544D2A5B35C628CEBAF0370A8F8502FD349A3C431D4D8ED56281184723B569EB08A904CDE35647929AE39E6A112365058D618CD44DA7685D331B7A16AF87D735C6766E47EB49F2D93E05E9F0936E923AADD01DE901B70555FA8E4E16970D4272B29CBC34C1E3B57ACD0366DA6B3D0BE72DB205F8BA635F0B32A3A38B44E257382665C354DD0182C0B3956042A87F6F98ADC5A2E1E7CE21A4E21C8750913DC0FC955F2E482D41DB96C35DFFA5417233179EA6245BC10B69050B4074847C89DC5E8AF80747E9B4A44AD7ACD06D6D051A3EB7B0CB3D8383950BE581DA314518C85B9E5E727FD3136C7A1E5B35DAB57F4B6331F565C66A9753743C93FA31E8BED38A489B16ED62FAF78FE5D69FDAF311A1CB7FA4AA4F0F1E56E3797802AC6F2885CD7A1D38B2C944C47F4F1D937EC11DED2DC2D8893A651D1144629781BF77E94DBAFAB247B4955408FD4983CF62F106D93D49738DBA52AED82FF67A984C749C04CC1383DE98C0AFC8457B9B134B18084549B12F7C50949FC2E5C136EF2CD2A05B81EE1DADCA5658873E65D09E0DE3F6CCF51DC6EC5157EAA10BE575101D83614A4B679B196D19F351B4727DC4B67C5E32843A4A2FB41AD38741847F"""), + TestUtils.hexDecode(""" +7C29C0B8E2A111F457E2384845E7698DE4BC9BAEF093F15EB03828664AD31C387B247A525623282460D60290FC479A928024CF62571A57F77B17DB0AC572CB59723490DF79E9B1B31EF2C9488B6D758C43EDD9162D8F6C0B03F43B08D646172A1F8DFD71D4DD805A3AFCF1C4265BEBB71FB251DC9DEAE670A664BDF943ECB00FB7EFA37624953F94CA760013FF1270C1EE7FF58756CE19C204220713724AD03B10F1D6961CDA361539A8AAB6ADEA92AD782F441428C0018D85C0505BAA793C752DADFE92BFE8F033931D47575C9F83547DB18DAEC0FEE90E83967E0D0DC93281000755303F0F5F05DE041211CF842404CD5E24DDFA3C7C83DE3EA21EEECE37A52E16DC80A350B3A18E88EB3C81C74D25B56CDB446F6198DC88F981F2B1ED8DC94194D81CAAD971A9A3933E9319047C5F31530C7C98793A0633875A14FA5635CD1B0441FE267E79C1E874BEA968CB63E20E7C48E7BAA9CE8393FF9A239B5A1D613DA65F7DE78BDB793AC72566FDCD06CDAAF56E18B773737A82298902F7B4890EDABB766E990ED87C94005A2E2450AC1D0192D72468F81DB414F88CBF07707A95F549B7A9EA0760821AD710D52787730EE8917272497E5891656176F991F254A5D582B5975F95AF740421A3C18A82158AF11DB15C154F17ABE1163F997C64A3BD989A573D12642B9AEE87C1612A39A8A4FAF25E35AFED3F2DBFC8FC8A2F9DFBC683CDFA3227107C50526149557CD773DDA16E36782A278A93CD7F4D8FB47DFC37DC3E389D164913316A885C3A800DAD0C57B1082BD4D804BB6A117C3B41E7D8AE9CC9622AE3CA8EAA9A0B502FE3F5A449BA8E768D2C98013F681C68A5F4AD3CBBB83F302457679BCD3F35C4D6176DD8D2B670E87EA291EDCCEEB9917F98CDDF5EE1689DBBC85BBAA30D191F1965EFF8FA9B0073D30B1E2456FAF880110BA9E75E4E29C6106874D32944F49DC7E7E7C56ECB9D287F2C2E87A779052F9B84FF97AAE007012A5EC497C4809F0193C69E5B29940510A354C866505424D4FF3853C94687636543115A73DC407C47927EDBCC4E0567EF4E451F0E464A1385D2A0D740C7327F6E92EC6091845356C2620EB163D9F774D7781BFBC6F6F652A4A2DEC73203DF5643E1B4C3C3DCDF0B4A0B160598EFB56499D2DB1F1E76612356AF3D708F9D61D968A6A0193D9146B2983972271A4C02E2136E6593DC47FDE4FAF2540A8F7744BC3230529AD1C9D2FF65B7671B5A5B16AABACDE8D45A940ABA4171E21090AC6AFF54CD8230F7BCAFFC42C028E6023E55DD02E4B7F976998AB5614A5681C615BF8E9E6959B038188F71C75F6DE44A6B0498F2A9254F3B0968AE7DBB49872D775CB0A5725206D648862734F202DF470770AAD184F822C56400F16F30F8BE40C463CA3EB5ECBB15D51CEBCCEAB43BFAD7DE7679894B90419B65912D67DCF2335212E82EFDB6267EEA331C1439BE2AF62E584C222C1052AD91C7F5DB6AA649F230248A14AA6A532401A28ADCF822089140FCD3B1CF2358DC26939850DB2721750F1537424F6BF2020A1B4684ED79402917D1028C1B59076867DA809D6C5D3F47277755384C20624388EF0AD68BBFB6A63005AD1B6E48ED654E8362B2AF7BF114F2D144A420712FC4EC71D408BE55EBCA8C2F185E7132196B1B76AA7BE44EB55DF7C82C768943D649631E4D87B408DCF8FE470164D9E8DD1F48CEE7F6BA93E239F889119A4DEA118D93F1474E516139036D640EC788AEE708637A619BD1693BAB6C9EE9EE0C495C0D0F8912C0F14199AA69B960F53E4FD8E2771DE4AAF72117A5B2388FEA0CA3BDCD594D1760905F26482459BDE80EEDE3FC89F592CA16B65B27E9A21F1789BD0327A26EE2224C61D80AE8FA6053480048D15019A80FCB5F3B3C6F64C168690E4384AC05E856BF341531045D2952F2CA8BAA0B8926CC41AF2D8BC5A1576292DD67114D521DD4AB535A77E5E9BEF8EA01DDC7C65446D11F90D6CADA94AA1AACFB1BC3551353D09252FE515A465C1879071F6FBB035DADA0BD25A022B026AAA5B5BD420237FF097099CA2402E68E4530F97A003E50CF693D1DFB551DC4695C760138E88B8D11F3075DBF8A6D9BCB9B1242648C0C9DABDD9D49CF132B0766302437C0CD81A0889585869DE92E6CB30C31265C84F58E9437CEBA891422967AA546EEF720A8FCC16EC7591AA0D47998275DF1AAA5ACAD1E1C5868CA430F4FEFA0277262C69311FEDBCC083114AAEC9F99FD98631137A117A9B48B32A6D88E76F96DC58D741395BFC102E147C456D3A78A0FA3D186485D65B4E6755B53D301BD13CC88E75277AF3CCF1EAC6E9C56FE1F10DE05A796A14381551705234F65DD6E717E9EC275E38690B73973C9CAB27DB909C5C13041723BB18EFECAD808667643E87620191008E4D10F471AD153D27F1FF00D8AC6A8C5E59197AECA5AB496D8D10BC79C49D16DC7948C6AF62703D36059587F6EE038820A84C0F287D79C713B066E1DA5B32BD89E5FEEC248B34AA5841E8666CBF09C47EFB17BC82170CCB557D41D40CC87F2E6C0246F0B272733854CE162538DF34559473BA5979AEBFC0D6A16EA7B399687E672145A1149E382954815B41E7E37CC415057D7536E65FA1A35B8EFAABC7B9B0000E08B593496B01E8F14FC950632C659C0A7F7D59787C7FE6E8FA7FA0211A945ABBA5044918CE8482C6EDB366368A9DDB2F2BB66C146BB50251CE61DDEDD8D6A4A60FEAF0F794B7B0DB91C52D7ED1A54AC85D7907BF3A5A96A60BDDD08F60148C0B3237DBD56628982375A67F025B0E3F9EE13DF254E1D6DDDBB057203CEB267200C7788D01342C064FDDE996183646FD3C1ABBA5D2155383CF391FF16C78660D0BBEB549483A4A4A971017A8659616FBB1C3A8A2E83230B610C0C74B8EB32667765F3C2F31F8C0D4BDA3D812DB64448684AEB482DFEC5C37EDE742091EF7EE6F22E31CBA2C9B9A6656888F446A1E9D52D9E6437D22594A830958CACC6F175D4CE8423178B71E7CC81BD6DC2A7F6580A8A3A1207C34D6A1646BC3D89953A63D22A30EB9FAC74103FA527843D3BDA656D1F22E729C3A004B923D08C9CB18CF406FAA89D0D63782C7264D5A8C8078EE6D259EE168A415E7BC83E4F17D9E674154DF08CCB21ADBF5B35AC28883F6943083AA97210C6DAE492C6CA4ACCBFADD99AED15110B10C9904469B4F06ED32546130B0EC4B281622A5EFC9C94B1F2280F251AFCAE857C4E17FF5CF472F038E02E5B7B3CF5CFD2F3969B9B8D5A27C8EC38DCA4284F0280C24F01DD97A618FDC5EB57C45D9E2A05B44E69FE2E47CB50F596030C70B62437F2B91A67FB84205D95CAE259AB1D5FF0454C5B4D87F439DCB7FC62B704ADC7A84502E1BD8E6F52109BF0F36824834D574E07B9375E693AD477A9D74E94BC4E883206DCF875AEF7FE84B9B7C1C9B1858E4BF6735235FAAE21FA566C866ED7C952B1BC19A911984EC25AEE310D8A342AE32F46255E0E00444CB0EE90C37152EDB6C741F5F394B5D47154825279465F0F8B19DDD85B8D9194A7AFAE5FE609A245AD68786C9AC044C008A1B3EFA3A8F4FA0FD49A65B6FF562F33DCB63754BE76244326FB6E416EE3267F93D7B2BDC4705EE7021D5D2EE66BA8D7B9DA7EE6C354E05470B31406DCFD2C32C94C22A72DE90E5A9DFBA99ECA95F73A014A3E9B15EFCBB67FDFA6D3CAFBE3ABBB28C4DEA6AA21F87693D68F0A60331786DE02BFA9E85A8D2AC8524EE184EE738BB3FEFEAD7E19030AE883707DF67ED12E8757B86E6E5FBA26715DBFAE2BE0F90453868931629FDE97712E08A280FF8888007AC27DF2C7113C30604C5DB17538F026F17C7F07D2A94AD5AB367F9CEA87BDBA712363D11FF5CF0590030BE9B342A7ADA48C08BC42F923DE939DE79616CD346B3511F41CE695B3F939C101F687DE7292CC96691EF3F3CB653F4A67D2EE09C791F993C726D574440EABFBB00E5E6328FA70D69FDD5F2EFFFD37C9902AA45EF4E9D06059B0D8E3686C74C94CF2F0032ECF740B31E3F297F15343A0093EE0B8D7F8EDA1118D329D05A1B992755181429D410771E37B56E28AE2ED8C4DDE8422FFE91ACE348E443640578687C57D79DFDF917F8E60E0A2F1C6223056C373F58C297F0FEE3060D31DCF6851856D1D05BB38B1FF426BADA10FD84B2E08AC149F91DDF4A5CB38B290DED4EA3B02EF7A3DF42BDC6B6205D281CE4A48A1C13FA8080B6B4100AA123097A4140415EC7CEC57790D6EB0B4200AD3DD9FB7FBD056A5E3E9D7B7EF47F44A63DC908B6DD8B020854618F7662391DFC35A88F4F5750D282F81DDC50D0132707174914293E3655BD2942C09F88627C0AFE4B921B766BEF41E246FD23482B5B14F117E8EE340C47C7C405BB3692C4C9E541148C2B38281EF0274835860E19C2D48953545247BD1F7A76CA43956C069A17CCFB4D0B0FD478556A209B5376BE9207AB174D2CEC96E09E1F8C0FA07D8920B2ABAC3490216DEBC67030E9285B3EF6767AB11E8CC935C4019B7E68FB9AF8864358E6927D350CC8B9A40662A0987C1C8877AA9903CC89A93E1979ACFA279FCCD2E171A467B76E1103C4EB166273ED7B4878908B67DB77C4FD4E49DB46109DA4BA78D69E03B48518F302647B8186F787F4CFCD87CC5A45B98F7558ECD0612378306C9D69FBE23B06005CD5AD84F73A563B1A3C7988CE0157D2D2703ECA8575D8BFF972CBED32A231395655DDB2188BFFB413624639D361B3388A9C9E13645C563A87C610F6FE79AD50765CFA8149E27F7083A316EBA050860A69BA56D002A78640D71794980C83573A5DE69A697C2CF2E17C90BAFAAD3D421C6E1D8A55B3FB4700B666AE3CC3EC114E9DB428F27CE427E4101ADB49B84CA7855458841DD1F4FE76D9074D940102FC47EA633744C2A664E22B5C5AA2721017F3FAAF4FB033FBB1D508EB98E1D643406ABD4D69C030A2349408C80993D9F75271F913D7417DA995443377E6F73A7DBA24E034A9C4820117D1F0BD69C93FF55CFFD2D36F8078209F5711FBD1587435517291498926E7354558945F721D00A73014C06B2C9BF04B7E695B9109D769BC2172CA7A70700A1D5AFF6F5FCBE699FAE81BC34B0495A82BED01B983444224B4B860360C07F8C3035FC4F0C4B7DD4D37ECAFD32E8C121C677ED263338359E25BC4173D191E869ACB4A5F6D20FD16FE50454CDD269DF8CBE5795482A2B40D52BCE5FDEBA62D9274C9C67127580795BC01752740E606D849AFCD6ABB8340613C61A764B6B92863779622E40EE7A8994034E7D303F07EFA11ACB70419A53897ADD558CFE157CAA3D47917CFE0287500B3D70FE42AFE36853188BC815CFCEC9F56030C83E85C60401912C14A75A082DE2E0400F6348EAABA59312C51A7E3B6A5B39D606306A304B4DD3472C5B89FC65DDA54650392A02CC6761336FD114D848BD889DA4BFE6D32931793A6515510CD802E3D9F2C6F8F2F9DD96ED039462C587395C7E6861FF48B7980D492C23E0635464C7D1969C12A43BF0FFA3089E6B367AA65D4678A571A0D47A75056B34E3F8819F8B6ECBDD6BE580D423D902D3C22D9D787E0F1B6202DFD392AE028292795FCA0177CBCB09AFF8B579A87A854432827CF797E494ADF9F96A56777AD6215F284EA91D35563F25355D12BD155C6C364B0C8423E1BBC809E736CE0BF03E0C0B728F04E6BC8F3F07A0D952AC9D9530C77547B687E193EE2D3565AC755DDFFE880AB0524624E17E019466B7D0E8FD6E94AC2BEBEFC617BCC5D529C83A90D36D57A93BAA0C2ADCF360377C9E9D58C456FE9F3D49CA37A8C3B5BC7C231842B57D320310943FFC0ED2F5F622988ACC7842F8410BEF0E0671673E7BA61AFCD2EA83CF066A169BBD97098F4B4F3C9FE73F5CD779F502C584849D1AAB52D7059D1D4432C27FC9284FBBEE43D07493A38B139152ACB71A171D454FCF936656ABDBDA03DEF3C7B27891088F940C200AD454308001FEB2DFA0FC38FA74F85A30DF4FFA64DB48E7D40C158F058B58174F18BA482AC445A6A63FB54CC6C7D4C8089794E8AB5B38C41C7FF4C6A8A5F294EDC3FFCE3C01F2C5C7FB569CA06567C8D3BD34F82046DB4EE7F7491D890DA1FDDC55B12D90A7853D8FB52E86AA1FBC669C7ED349A2CEEA9EF18F76C23E817AF58101BC5CCB0346A607D6C60BE5CCDE5DB9889E040223FE98B17D31D64E8C1456C01353887D75EE3B82D66CA0679B1C2366C44E52D73B09D48A39D1BA3FC87D73772DA601EF442208DB763F0BF888D28338709FCB008B83671442CD9F7ECAB2C1E26428391E559306904FDE5BA21E1757D94F84F18A5FD8A067C556834AB257B9D2E1290FE0ABD3BD622A2AD92BEB2C6BC61852D58384A20B7409E4F212F630BB280A46CF89DD702B2508752D6A4DA94BB769797B6E7FC318B0B3ED50D7F8C5D8579526D536E4D43F93C055479D53BF6159BCEAD8CE87504EDF7DB35E1D03EC7B4F13802AAE0207A2414802BECEA39664110A54C37415EBD7BFD5D73E871587967F24EA34B7D06CAD805EEDB95F1023B7BC3A74A59A6C9F3A4737FA1BB087012E0162CFF15A539E86AFEE30144F320FBAF088C6884489F84F16458755561C9CB0723CEB6ECB134083C3B82E93BBB57FCE8D51374D38746BECD09A059AD6623EDE82EBCACE009C0C27D5FFFCAF76C9E91BDF5EB895FA1E9C3C0AEC0BD73B1582C067A45CA5D15E2D45E7316CD4B176D9DC7241B05922A682DF919B2D2DE2F45942D3AE254FA55C5D90B8DA3C7DFE2DD8381AEDCC9558566E8DF302022FEFE51F23AF6A018AAEF3C93FD608B0903376E193CB1C13021808ACD538D3426F9B3399686B6FF4DFC0A4552DEFE49D042BA76136719D62884D8B93A349C22E0320B823740DDB3794AD53312DA5608DABACF69767D76327BEA7A644A304A132F2D2FA8E7C8F4AFAC30E389A995C0A2F912E98447CB400FEAE35B3BE089F46CD48EC8E38D4F2BB44F1734C67D5125D7266AEE3E9D1E91F800ACF8038D43B6E10750DADF6CF70DE75176A2E9C340BCD2F6D87F976AFBCDAF5E35DA9B268D3AE1F0F8172A342CAF9602593A5ACDE03DDB482E80B825A7E91E8B0EFC1C8D00309BD170D9F12BF5017780A54F440A58BE4A5257AB67190C62DAF9332F3594303B419D44A38C3A8032E38599B49872D241AA44905CC851DDD0750D04815ED88711353DC2264C0302DAAF2FFD34E9716FDF8A81F7CCB5757913B380A68F153F62E0BA8335F8525CC3A20145C2416581612B9C29C0B1B941946B2624731FA50420716162C64AACFBF94B43B10E59E0AF3836A05B9335B0C44370CDD2E45BA817631FAFA2E0ADC801772F6F71860CC2623E1A802B370823D02442108E5C142B68CCC9CDD0BC2EB9B861D763C715D516540F19E70FB474E120F06BC19A6629E8DAF67556AC60D17C252A44901839143BE5EC76B834FF11DE13762EB23843D3FCF1FF9CEB41CB02DAC74ED6219288575FA294157E532BD877D1B711AF3B98CB0B4BD7286F88C6C00B6AD9E40D66F38525156A4AF35F2FD42A5F25A201C66DA4AB5C4D1517BD6CC9FD9764AE2756379D73C8D81CD044174860FEE5DC42B4576008F13A3504674E0D224A9F1AA780C3003B7856692676A5E581418C65BA9F049CA20C3EFA566315DA220E837639A899ED54A07B5741097C47FB90A81A41700BB5C0D8C3317E27A0A6CFA77292BE9186396BCDE5C654C565754DAD120719E571A4A14207CFD205BB4A66C02CB68EB9E50DA7B1FFC324AD07D8A8A54729621776FC5DF15CA39F3DEB6B810A735CAE0E1A84C6842E80D1CF95FDF5A6FDCD613C54DA1CCAB4994EBB81C632D192CA9AFD7FA662A865C6F193B7029A9B6F21041E3D13D50E5A1DA47D3D3C4B101488D2308954C801DBAE5029E866E869167BE7DCE6476A64FB245247A84E46B5F0D9FA9F7BB10756FDEA659788C032AC654CBB83F23BEA1F285DE190BBB5EC4135E8FA1B134DB5D1FFDA08C06682C2DCC51E0D848F8CAEEAF51DED21830730F6BACC2A4BACF7BA62D14B009116EF2D157F64A7ECBC971D50349712DDB0871D007B2FBF83A832416CFABA2B9CECD37207EB9DB8A017AC266A5FC28DFE64B52D0CD7FD7498F718B32804CF98D2F17D22C2957782DD83F4FDEFC8A6AC5B6A562C939D2D0A0FA6078F7E6B4C95159BEF010C1DF8448158BA29E1FD1AA076972E64A9D534B1F27930BADA08EB87BDE6FB0A691D4379DF0001D84F2F833050E18869F2FA7C00A6481E4F87C75483310949653D6B91FEF1116F25E5EB0A10C8C8723E9C1C80F75C2875FB0C448B3E25E7B359304C08C310148683E1D8391C432A8413057A7AF45289B1363EB203779550FE1F074D3B4CDB77B90700E3710D6EB4BD1FCC209F2406CAA67B98E44AC91B876762D597D0F03A404394AE81BEF8F54A1A898B2F0F0CC3D3B6D84D759D1F1C5788BFDC7657794E384ECB2D5307CD92F3E135F35720A44743D93D111F38791B60E7A64F51ECD6801DE0ABC356409D00D7F785EEB88FF3FDC801C94CD7972EE402217DF018958A79DFEE835B2E7C591D2604B83E2C8B3CEED7BED4DC66B66EA13BDA4FBF5DC3158035A279F57ECBBCACEE3FF346386ABE41D0DBB32E15B02C49D3F216DB19474D295AE0A8DADD1DBA9AECFA9C92F0429352B558F69AFC7070DE8D47032956A9978AC2F388DBBD63AAD776BFAE969EB990E72B7D74A0D2002CD3CC664E77E52"""), + TestUtils.hexDecode(""" +81D31B99FCF0F04C0B2292A8CF472AAE17A659C205B067FCDF9FB4158C42955886D10F4BE022BC564230D2CB21D9023DE837E9ACECE2AA7EFD77E8335367E9F43A4D4526F36F336293FD0D372E81669B04DFB4ADF2091D18C1B2649B751E1877BF3AE489862C22108B02242EFA218828F53B317CB6537B2794E9559D2F93E3BA9ECE302BA948DC7C6596FE4BABDC3CEFB7F750C8B4D041204AC0F185CCB264A76F81A1783FAB19EA236D41842D9DDFBD2028DB890A652FE07836FAA7312A287A920543B8C393000E03F82FB712391915D75DC5825D9494C6E64122202D002BF7AFC234B334B12C164911D63333A2060B8D44DEB4B7E1B3E24F8EF98C09872AE4BECEE4561316B16A90507B25A20769A7CC25DAE276BEF51364499020ACFF97E871AFBBD68854CDEA120840FA1BDC1AD62283159E19938BAE5B2CAC8A607EB2ACD1B77FCFACC7981E5DAEBA3986B2E918768204D2C0B61914FC6C14A5C36090E52084AE245D9C6082FB8C3B5FDBEEA0CB779A656C180A01C0F188C2B4C11010B562711C5A4F10CCC39BCF5F09509BAF83D98C61E3A35FD7F483342115D41D8DB382E7E5D161711B8F718A2730D73ED7EED07AE04313F3D29D7FD68A92A0706936565924473CFA0125CDB2A2E22238F28ABECFBC0BF8F5E6852E45F24A55E54B2F26C5B9D97A3FFD4CCB09AD244D2D0072C575CD59D01EAD49A55FC2AC8857375ED477BD9287AB0F03E83BB29F19A6C1FB8A6D4B510A55C57ADA1B108785A16C52C71549162B7ED916B8309EE880B9B203F8E24B16E3CB4C774353D9CC9AA100BA200F5D197640DF6E0C0FEB9361B6E59481CE285C3CF2A54489A48B568D115FDC3B182D8341AEC078BEB288F0916C651BAE7ECB5EF165686819CFF2516AA90FFE3FA621D24F43917C218319456D58B5EB1F00437CFDBB66266C15B85CF5C28B29B1C2877F551E5A0B3FDB4852AA17B83D93183E82280AE94DF3136A82BB09D21DA75C6228DFA56AC2E538050B1155DE4133B40EAF22C63DF128E5324B4DC3FDE208ED528D4772C1ECBA1D11107CC3B8258F2BFB9CAEBDDE1B808D1F909D834D3ABDB08A2129B15A81DD01B82CA4303902AAFC1FE21B7AEEFCA8AF1167205142C65B41A8124C8E2FB6978BCCEAEEB8C701A97A311B87C9F46F6B23F8547EA728D46DD907DDA37FB143A191E66906B9715E6FB4D027A6F2B4DC94A38DAFB229642310FBB0CB28BB8415A9AB0B16E78F9F77737D0BC377F6E39AC869743067A7CC49A0E6974D86346BD5F91BC3D747A659F35FC133B02907E0E0442F948E2124AA25209E61F5209680B2E2D8DDBDB1A7BF0B8F1D17726D21C8730875255A401C381157EFF65CECD067F05EE56A9CA6986601A0FFBB473228EE9A64EF04196A78D4B5EC68F9A4FD438DB71E9A8FA5D0AC28D35087ADDDB4341C25AF1A0148D50C5041C87A508BC0894F073505880A550C17079B255C3BA5F58447C51603A599AA7EE288299551D339611935C5EA7F07D51BA76A0A9873635CD7AB35F8EB5A25A2B4453A2EE917E7103FF62D9476AA1B0C64777F4D05AAA5240DBA6956E1E1DE3C0EC1774DB2742D5DF8A6BA8E287631AB41B948954C594A63B7156218EDF19680D863879D79A8E58A1D5F975A35D589805B734C6ACD3E23EA920C8C1A9D8389B739CC3EC34776D2E816CAD3D6AE89B29CAD96D707E7D31BA731749BFAD67FA376E743920E119C11E29421ED033A1E73F2F522EC23D097830FA05CD62C432C70B10B9843CE2D49A544664EBD22213EACBD40922F1C3EE99A3E393CDB38DAAE81027F64FCF273846A9A789A76A50C79FA50A436D84FFF7DAA38DDBD5D40370B02ECB6F202261C5B284419F06CF4947A319753B1132017F46890A129E13DFC62DE2AD552F0931036F5296BF394311A7347702EB998A8DD6643EAEACEAD0DAD94225623F8652BEF131B9D4B0A6F5E7F4ADE344AA1D99C764DD9F9BDE6CC040FDA976BEFF40F8F4B0C5E6B20497E209F08290006DA5DD81AA46C5A0DB7EE7241E2C11CC411E4953942E2BE4CA6A61FF7C21DF482C8737012879C2B3AC90DA6EFC2F27B8507D4393D1647C4331F307C41038755386C53218818A255C2632A6DCB9F589BA53ABDBB4F7A9684D8C622F0B5DBDD8BBA59F92F5AAAEC121939263810535AA0D61A67A344B7B98568C8567ADA14B09BD6E021B1F8A0CF9B6DA08F5A1D66CD1CA8B0641FB300F11E3C4B7236135F4B01E5A50416B9BF3B7D88317315D35FF88A1663965CC183E4E34E4130C3AAE8DB39F3491D85B38C68C1F818DA553FFEA24595F5897071C84EE46FAA74FE240225EE1E325D3070665EA89F70BFD998F080C330E4759B4E79018DAB231BEE7BC73C20117E77A76BBEEDA3578CC2B26F03591E314B0FD26DB529BB0E6D747058DEA808B45064B832F3B1008F675CA2A92B5D38B464C5CDE4E570029891F83975E063EDC4A9B1A731C36B5EDA5E8F5D7ACE5F0A9F9BCBCDA5549203A9268B156DBA17E38BDC3D964CF11373DC778A24FC27613D39E4ED6311AD3E307BFFB3A1E45FA8BD2268C0B674368FC583489473AB3D4CE941177A3EBB06E6273F3C90FC5734514C4D4284954F5ECC0853523DCC3681257C1EB15B3F7AB7FE42D70899418D43B0198C971F9B1C069A2B443DA2C8E463CE510EC8B40A366B4DE82E2A206D7812A9EEC1AEDF669A66AA4F76364DF2167FF1416DB7710EEBDA11B0E8065E8D8BACE915C5282E742E0F1969E8A2B3FE29DF8A9034A2C2172B234E39957E5BF6DD55EEC3C4EA1C694827CDE661870E4C858FE91AAFABEE9E28AC3469B156DF911E00E31B44C2DBB43FAA617DE7782E14566DF4A744D8255BB741EF9C5842DC5AA275C73A7BBC254CF6E9CD1ABEF1AB5427CAE5FC4867BFD1D55478C29510493BF720C03256FD7F10B9095BE2AD621D8C2A6A667EA12DB50A09A4CDF0EC604ECF6F73A371374059F00FE8F84BEB0EE5E45ED467F44479E7761A20A06ECCF795017D46D4F554E73F3B79B4BD7DBF44217938BAB271A50F40871C6AB4E3158B9BD4B12861E9865926D87D79508AA23C085B616938970924DCE2F403F0297420B3B8DD6EC376600B1787AE8756B5CC414EE213DFDA291C4C94E4C36C9530305BA904EC6C61EE75E5C4EBCF557DCA2F01643403B5F25611CFBF3DB4D64AD5FAD075DF9BC3C317E0E4E6BC398C6EA02C58F4CBDAEEE9C66BE30A0BBD3F23F2C9528A54C080129633AADDAC8CC27CBEC1CCDA9D6C6A5D6E1C15F9F59AD01BF1003913185BF93B398BE28269D04383A3EE314D69A07AE8BC1E036DA3430CF772EC00C1AEF7D7B73CBD2D296BF0064A53C75C24ADA36D60ABC93CB271EA846C950BE8A58126DACC14295629E08403DFD9479AADE091C5C71BD234DF9F35B411CA6107724BC00E6837EED6526AB76D3E1AE0EE47FECC134AF895235F5E5C42EA2FA02381550240ECFB60AE9A37D77FE8A057F28711D25C0BEA2550B32EE8E926E539C499ACC781F9C3675E2D6A0D81E10FA653635CBCDC6686A8B842718E327A50CFC15E68DCDEF46FB3137A6F867AA63F97F489745E735B1215669DE7388AAE461A01F9DF1EC3DB31B7588D2A18650C60FB08CFB59F11283321E208823597E9AE5384755B1D106ACAE8A1C3151E9AF98E252A10F068BAF2B6116D37BCE404910DF63DA5891B00F5C8968D1EA70E54F1BF8E495707197B086D0392EEDE6AD60C5D4B9B108467435C9E0ACAC31A7E590D6A36B22EF1582FDEE7CE7E378C089AB6B8588325AAF6063D075005AE65B09929F41DD70B45B53A50C53D779BD37923213AA91A2AE0CB6D979588EE8D0DCD15E89929526574A5F8AA538CAADDDDA257F15B1294E6C85A2BC8DC3FE08F0D87963341D630238F25516990A79E27F2564439EED4C359FA83C3B7519928EE4268836D8D45DDBF62E4A9A0DBEC3470261EC5CAE7D0791C0E976C287340724D88E676B79B33A035D93C5BDBBBCFC0B6BAB952DF2A1A975C8CF7380C98AD3428C795AD3DFF70E63B5792F993AB4642BAFE4EA0771BFA24020F0D17A65E2E6F4F77A0801AD4C59FF3BF6C8F837A9430BD76CA46EF919CE743F685570B95667EEA2BE078AC45C46A54FF51D89E01A3726B23B5158C914B7B7E6B33AD8242B32514F251873DEC8FDC8BA607D156440326D4B5A5C5D676D0098A73E2A25C84F09111493727FE5D04C8B1FB9554AC71A3101E4CF44328553A23DE7BA2AD3C2FA9E9539DC47A58CE3CEB6E51F20C87AC6B2B14CF803DDC55A2E4B5D37A322A49FA38BE1B8A562BA7D314FBFE2BC2F58B04A3722EBE4E90FA3AFE1E80E4A5602BAFB9EC70739F3C6CC223B790C603FDCD188CC5CB3853DE9161A2EFA4CF3553BE3E23C386C6AD5BCBB7C7E497C30A0BF906B6E35585A69E327ED95D25107911902A3024C8B404034450B19254CBD832DE3E6FD46B3C2C602C5CF5A93D8E966DB63D111938C3BCA92D98D40B6B023DCE484E6E958EE5B2EB5AC0275824391F54E424F4C46B7E572F263E3B727E680556AEF3579E1AD6A0A43E764BF519711B60CB41FB2B85E34BC970BB3F98DACE7C8C1CF3F7254DB18B5DB18AAD3BE4B098911484D323427F8897CBFE41508DB7D501818EE418690134485A7DBDF4177C82A8CFDBF00000000000000000000000000000000000000000000000070C10121920""") + ), + new SigGenTestCase( + TestUtils.hexDecode(""" +8BE522B4E26631EBD3EE598B51CFB44CC1BCE4693E87BB76EF1B3DBFFC2762169025689CB13EC243DCDB536B5592EEBA1C9FF9D3162BA69C6C8445C55561A1BDD5DAA73A89A567873FEEA609BAF57AAC39B28C9EBF0DB477CFF938EA069ABAC4C134644525C179B81B69A61400FC131632F9389409EFB2DAD28347B6E9DBC50333478537234180110216703713666267407332042117167285231861686761441210671057343688833122224741016000006637280104670885810336860677835038360856671708501706307554348172486017384536610442118411464278512074201323472226152744306444283276447347407701534240455752818374185812151275332674783343510375328081677738151215483531374201701647010142025428074334717432007611874182847823042007734883110521200373123872310064376640658218187215811731015263781030348654333721768352476037106520857001157228053468718674413501266737641245546154041643241410501404202331467303823172738661537631326412120620535147074330475675267385001422576156865466315087754081624344371427068152314726807147108662880315204371650357351315826372165054702134004232425418802463830782403784381115563683351588142725828012118040033543738720206011440856443223582817212677271158874776566724605581535176600567745870103826357027573672874654377285231557526888232382155662024100070470030473727043681088635050714638852408071501850808072334837044106823681822708546272403308813276035006162706663335231815226264468284147368331351772564002623064338284502177258683770086532412113081781761102623530322278262028713438163458525017410602014725837473653188830358083120808408517263643700355801282287367867716818464087758327804282311206361315488554266670483253832715616163087472867038811365080210210237462345637776788467178451732482673618811867731483512036158155276111185373836686408334604023734277527830555045716275074072450108113304336412220335448801703313347077660185246467603160827384258610827786040227788358515276647106422642717356782036318301654248323637160122662488623837433257521667160846766448032050502541655122882873257375732786387202663327831411364154328330125623422884575626558307557713473653281565632108110853544346667326373177215875188880426237318478516556653371343073506220865321058770816713770387242752781203737258042510133435774100138260342867165785468418463736503584203606438045376454072080283716557465775044371518453200301088283116123715262003810840120273260615472300483880225411134203712750473122131553667405410661065824344668381608711445062248365838180162845050471728814083565587567605831314536481816873614238866537046728070145831458843035350778852054744668616084188465173248757877750305585700014307233313471722355344716426435421467416072887431031342617388642656086537070667614703030736144320532164032037145102411420812042582084583621280125835662622287314366231327281824842763423073663418856204041328103787818034738187202808802170064570017265628525011080747850142683771068084483578052255237768183672270141750243375737386806347814658588856114864068441442642086057430676653065800650578614485827138703358681848874801543363582130444225273015665625525034606073587464023021552772813060801271401248635688136384706617355687552587855202183037066184600586417823285581816200837FB03CD1DC103C479132483591620A98B17B885473B466814BC26F9F52D1AEDBB07645BFD9D05B02CF3D37CAEBCB8DCE34EF4185699343A4DC07D7EDBF603AF8D3F4C79EF169BDDF5A0647F9D71732FF65A8142780E5ED3EFDD4FF8D496EA676516529564718CB376D9A8C922E038D84995A29661A54184BD3A32D2B962B3DBC167524DE2C4B07765B6BC71CD4A5510C646EE0AB6892992E341EB0E54160A8939AAAC4C424BE9D7D1B4CC1FB50B5731950D19B96E5EBAB09398CE0E476AD189004829896E131F1C0231CFCB374895A47684F063B821FE0C8DCEE3B2BD5DCE499422AE0C668C267A65735F7A21106FB7A584CC2D89A097DBE549B3FB84AB8351B6A5F61ACA27B4C38C3755BF1ABE272030333F976296E482776FBAF8DAE13A0BCB7FB2992F74F178C4CDEACC841B74A1A7355F6E09B0F58F9DB2461E26CE24DE7F8FD744AECD3A6053C49C7F23C8F7F34B35DA5D60B16B81AC9C9FCC14A5DC5DDAACD10634929E6540A5AE3BBCF8BF7A04F1ED438CA536279B58FB02E1BD481D9CFB6189BEE8FED30D46AAEB34F7C4DF8781A38B2C40A7C7C27347DF54728AD8B91C4B09CF48ABC5B392DC723E95157F1BD0DE34A76ED0C89905F4333318267E4BA6EECB1FF87F8AB78AEFF5A494B7323B34A019440CDAD40165146370E23928BF831BF0DB4A498AD2FD15A15EFC1A56F656E8CB58E93CAF38EAC61F3E030EB00EB2F9627514349C583E1E2D93CDF6775DCB56517F92D89530D29A55DF17135AF8014C34645BBA8D9DB19F28064B55AF5520841E3DBEAB3FC4A4AEBDB1C431B2F7A83D4968F120DF098B808DCC94D29D26B8211E489B8EDBB87A4CEA0750296E802796D1647A97093F5988024F92FAA1E857AFCFD5E43021B0AA190DA6D581D654DEE6B9223A31BDF5CCFC54178AAE8F4F72B6D9B43D758F95DA0E4E6EDA271E2C03F1BEC31924B827D933BE6634AAB033AD507ABE2EF144A9629C2CADE0B491042AA23005A25B163990CAE9E3F03F2B994CD1CF70716C4B0D1472185AE2630DB3A5A6F154A60FB7340087C554011D95300323AB37681931724326309355E5E767BCEA044DBF1F2BD2645A62D68448C1E978FE1AEF1A178D743DAC130CF4912F16D113C229764562FB8EB2D8496C1891487FB9985208E2DAE8EFCA29DB5788D7A623856F14E41F3232B048C794500DD52836C45AB7CAE336BA311DE88E1F108242DAA925FCBF4801A7D5D400E9E98B15323E7AF30566FDFD118011D1A6C8F795BD263BF38CBD66EE93F0D7DA35C276EBB3C7A2A511AA852C35E31D0F7EA0620214618B92A48A50262107D875DB22A5E6B33B7189F6F6918E036FEA3E7A918F59046B9ADB01B074DAEB58A775E9CF56E5ECA2D521298B355A8FECF7F8EC1586AE72E3F8AF3578048D735D8D750A28EE0EDCA3E3FC303613177DC3F9DE2DD92C583AB35866EB46DB11A4EFEBACF3CA6B9F87CC6C7819CCA4A3E2B7D6C5E9A61FAB9185B91CB90631051CB64E61EAD02D98F4361CE57A5BB54A21FEFEDA318CE8F384464374C8F4FE706CE462A38A2A340ED573E5F703B418D1EE2F71539A1339FBF89A553D4E3D6E309FA50FA08F9A3CA504E8A0066E0AFBB5186E5B3E7418DB1F14E73FD481B984B50595BD937E5AF3F735BE67B2F8E3821EB5B28A4A60A27B382B2D4E84C20F6CAD8DF9A200F819A664B560086BFDE6E6C0F76A651E286C4B0DA27DF31CCCA6D2101501250F251EF1D034B256BDB4C75ACCDD7E4A31EB13A71CB44187314EF2576383BD8E8AF0594E9FECE0738544571D241F7C0EAE00D9EBEEE2B63BCDCE13037CFD515A63541D93B3592FA483CB4E4121893BA48608C109358DFBE317FC21724FFE6F862EB5687A76F56A5DAEB3AF226DA6E66EDD79294595A7BCB4A1FB4A54132B8CD7EE4FBE8658355DC420F08B4C9412CB0A4ACC24CA5E174316A8B5692CA8569ECDFCB37452A48ADE1956C52FDA1FB81F507CD8654A716AAD3C9D8416B99390A190BFAFDCE5D2F054952795E13639CC0D509557793E64C2FDBFE16B19F28A67FB0787229D5BBE5C7F85BFD2D257415C4E024D72E7F7598DB32E61F91FD68A8ADC38D558D2AB6C0F748E7D0EC81BC0B3ADCAE6F9D098A1F43C1450581C2B084DAA7850ED84C76812DD7EF285F6A530EF7DF815A4BC54947CBD146296D615F5147C38EB5CD2BA842F1261542B5D75A41370860E8EA881E2E88FEEB020AD954420AB03ADF14DCF24E62DDE75B19568F06D9D418AD71E881613CC755FF3D11BF3DB0C0DEF57AF0668FC38F3FC9256DFBE28BA606441837B5B0EFCFEC92E6F658908CB4326200175B7388411EAC613A3A75EF8A1F856F3BA32DC777C668228232CC04F4FE6E9089C8B3EB9B4A74A9D4740AC8F14B5FA73C43B3ECBF1D37B50F89855DF3E899A2B3D277E6C72D284E075C3FF09024C3E5FB3B7349656197A468E75047402ABAE724094CD92170F4809160190D1F3844A0200E42E80D27A1A67DE1E2B8F2E10FB0B076D7827C0116E6A2319D99CC38E53A14F4B31BD4B2BF694AFD629C0B12F41744905C24886F2A7D1C23B6E3141632E1F1088A85CD9F6AF9A005576593C9CF6CA4F94BBBFE860D4F1C2388EC112961636CCAEF5D84157F8001BD3C156BC93C5B2FAFCFBB67406201FDE2ED395A83117E2735373E07C0BBA838ED01246022DA61299F080588E58CFE32BA6B0FAE8BA9B4B7C3DAF383EC14335A4CCBB7B1F2CA795A06C02BE537FDB9DEE0B46D54408AE45FC77DD54EBD248623E403217DE8C67B1B3993B23E14C5043F310FD87410699FE704440EB35903ACAB6CCD515880244C184EE43BCA31EE2DEEA3A5454801EB3BCE0255E85F6EFA63877DF43116EB900523AC48F662E61F7971F00CC0EB44D1E6F33EAAE274B8A618B0C0A402DEA2BC835962EB45A60DBABF55744B890301AD6FB863E84513F7022D52C9ECD758261C58525BB806FEC444D7BDF7D02C25EF70F9CC429EC33C7516FC84281684F6A9D63909A6419EA190028F20E301A3230E5E7CA25E86509DE71962E7BD91025E18B194F07DA2D32424AA734E94D8AE3E6F2099802700F37DC29405D2B7BE4CBF35FD58EB6C8DC6EF969114CF45DFF7B12FEB37B16DA34D133A95A6309D1CF28CC96D8D3D581E95B2CF94E737A757A36FE40EB11AA0F3F913C1B7506C11F59E046082046C906F5F25F310DCA23442E8423BFA4C977295509D6C8B2FC30C282CB561C60D44177A1F73E01A8E5F267BCA5A5C652F09E16C35AFD2655AE0DC738D70571C4E48EF34DBE632346F804DFF6D565A542BCAD86D0F6E52FB7F9771E850A39786689E1DD8E463E75D64E41456DA22D44D1BEDD3629D0C93143A1D67718C2863CAB7B63A6823BA00A6BBAB6C6089982D780A944B7455148D7DF8976D31CD9D13FD39216182453CE38B140AD2B621A71390CBFBEFB55FD66B9CEDC8F68C9504C0F28DFE00315A591AE709DFE9511269917CB4A89F89DC1E4470A162F89C45561A362A7A02F5FB4A8D82317CF61B533243BA755418729"""), + TestUtils.hexDecode(""" +F55B1A381D9258CAC6DD7B5A57899867FB659A56873F31F815716075DBDD56D6D0D1480AE1242A17485AD259BDA2533CBECE28A906271A3E65FB5D48AAA124993738FDAAC65736230FA07EA27D96F372B90A16FF778D0ECD7C0F62174839B8C7FC50F0B0150D47D5CE9F3715F5964DC712A681626821EA27E912B80D2D04C346B67439CB5E06193B6D7F2161B4F8E0341D8F1C0C7F6E3B351C4EB62E48B555EF00EC0DD5CA6A572FB201D1A4570676A04000C382F4C332C34A0436B535CB3C3F2378682A982034E01211CFB23285395204ECF985F478686817A5F6FF4B694082B3032990597A8C3A85B7FB5C2C49694103811F754DF0434D09C1A5245BBA980D6EFCFC9BC63DD42362477537C6712ABDC952BAE377AE7EAF9FF0CE2E9EEE82FBEFC1CE56063293BE659624CCA0E23DD7EF4412DDB587CF3C5302CE5AFB39BA8613151A04491901DC30706B46EBD1B26D4ACA67587595100AC51770080FC32ED0DC109D525088A2579D8873C6929554C30BDD1E2A0A9797B1676A8CEB719F64A336FDDC3F95BD4A68F472F00C4778745203E1A7736764CEB94F33109AF197C98D94BA3F07E857A5B251858ED850E7E578057E833A2CF95D7505C4973B709CEE834A40F32CF07AD1861CD46CC4DAD37DE66F8037DF1B14CD88E62F81B9DEC286BE4968ABCDCE54F83C5E9E4FFA8144A5877D75FDF75A38ECF60DC180E9B72F256BCEEE087F5AFA5C6D779117070ADB4A671839E8032E55AC52E806C82AC16FCE76A659D6CBABBEC066782C4C068AD4FCD5EC425885A5CBC5A4BAB43D1A60D499C497A2DC06B136A971BE8ECEF3FA6606252029FE5B33661883608702542F7EF44720466D91FA1CFEEB9D8CEBBE4E252CBC096D99551BB90A0534D723B02146FEA94D1C1926221092B97F1A143E6B4D5A8438239B2E2842633A6D90A18DD67D05B2CB560BA8A964E0A49BC1987FF47895D664F92E27F8C90059C5C38B02B42D7A179A09B70023BF7D664A94F7289B29FEF89356BB51959FBB82562F6827CA2A3892E934A9F271282C204BC3C6B34C57882EEB552DEDC0644B43FB28284FDFC82A1148447F2457E94EC0437CB5E0E3B6AB7F7E48F0F53C80D7695801DBC0E96F9C00A4A96AF8D60676DC4A6A6D97CEA344D7E911BE7CC9CEBBB23C562BCEC6992AB1148384278D94913DC4BAC4F73313BF83CFA2591420B18429D1F88D68443B960F61A1AB8E2713794225DF2D4EF88CAACABF6F095DA88C52C011AB3A07D7B71CF209BC84DEDD7FF2D8FF02A0727196D50CFF6520602D9FCBE57F890D19EB7845C6529EE5CD98AA2FDFCF37FD7472D1491FC5267F1D7E6E91EE891D880D5EC20FFC761344BAB59A327F829ECFBF8E550208976BDCFB75BCD996599B68CB29B27D9EF68BC975DAE08AA121F4D95805EB89F2E8B2BFDC61058740881E9B403C54745CF6D4AA1747EBBA56473D00FCFC62B5F5DBA4209E0E7473A0A311619437D2DF22F1D5BABAE064970850CD51D4A62A51E9B3D3121B766632B18F8B7CDEF40B249812A6274D4C69C9EEC096044026022B1FF055A05B6BF1C919230723A952589F540E77D7D24A413F542E7E0D3F7F55B8B335CF3693603210E979718E8CBDF76CCED68396DEB561EE27E9008D7BDB428BB293E1A1BF2675D8A4568D3339682854BCF9E8820A084C94D78E5D0938D66676ACAAF7B411B466B6588E9E2B4A387D84F23963E252EF36A948F25625DCCE664281D76BB6EC1B8E20DB3A7140B194872DB439D89F18E74E1861E3CF9FD442F1CACF4FBFD16532BECBD97CC9A007978D17922A68CE98369240A8D1E8AAE6679CA5DB79D83EAC1A571D0871D5AA28F6EA4A8EB60770E8CC43A78E6BEBBD4FC63CAE26F297F1E21BCE999A509BDCDD20AC938E38702215C398726ABA5A7AB3F26DA34DB3CBD58A7882FED91C33803FAE62E9E69FAFBD698962F2C7226A641AA7B6CED1DA8A400992333EF5DAAC77B55F94D51F74226AC03F7ED8F3D567BEB678D98694E9E0D483815D080A70FCE76255C82FE020DDF32D4BB7B1AE0EC1679B3DAEF2C20FCD7D8F74F6FC684FB678F02DE6B53D03FB656A9B9562666F49797EC658C0E8ED14480A0532DB85478FC2AD1E21F8883F2EF3FD97DFD757D883C1507C44F812639711256EF56BF6F8FC4A73EC3AEA3099F6C2BE6B2380FF3AB7007129D4829103AFE70851917E02EC5F2117DE110FD8F4EA25FED6FBC24BA063B7ECF7585519132884FC12DE1BBEF498B92D6E2062F1A4F7C97FEE96BA87ABFAE76C50729AA68C8F374102B3CFBD69139491836E4587D0085F92FFE2A94B6A87AFE29C84D289293D9CB4A733F90389C96198E2250F5BDC83F123FCC4E42844DF74FCB65986CBAB77B692CA210AC22B5B56E30BEE2BDE84663B22507E00E0D066D5B1F5245EDFAC6D860D0493C218A541A1FCA4B48F1A916921153933383284BA268C3AB003CD58FA979A08BC48A57C755688B0859AF7F21061F9F1B7DA44088ECA4D393E8DFCCA52823FAB812AF36212CD137741C14F0860CBC7ACCE1FDA39431C32AFABB84989CEC971D4A257BDD70EC71192148824C17AF8F18816CA94C457E1023E01012A245F28FF6582C9015153DD7662E4321B465B33B1D5DCA9B1CE2FF49EA3A811B5852AF5C42FCE7FF42BCECD31C798C3B8F685AB50B68654192357CEE577F5CF1F85A50F269C28A1F2ABEA382AF5CD089C146B9473C8965A945091ECD1C02BDF64F9C3FFD035D8238AF974E7111BA4AB10288F105659C9E2847544FEC0B29B6692FB53CEA0DD312B24C1ED3CAA1BCFD94E529F6C27BDDBB7C764DC0161FCE578361E02E0F5F3FDB095B6CD311190466177A5FBA62BD18595DC49C29E8EC7E1F2F3FFCDF17D477F4AF8CA3EAC53B7018A026BC942EED87704108027753DF67BD36221E9121B49CD40E8EA7FA2D6961604BE0095099A4413DC11E93B4A876834776D144269BBBF8A9875648702B589ED4CCBAFDD726DE8E8A58AA5D1A6E142A470EC342BC3E2E1B49C7203F283E99E81E38F1D8D2CD820AC98D8244A705BFD9B67E771A0366C7C6958DCB6921A81C0C9D5152DA37CAA8CE18D6B97404B399052051D7343B3739610329A37B8BAAD173018708400AE02B8DB2A2414CD7DAF038F94714031B1D83A5A15DBA53585B606A13814F04FC925C3454E251CEECEABECD8CFBD6FC04F504508C04E25724807004612E2796987D34D04318F82F7E1FBA83A4DEE3C86FD1884B17E77231629F5D5D11CFDE976E639C60B436DD9D302C380E3654E671ED81D44FC595FA34EDF90710A6384BB62DE0D89B50C14A44215DD1121C602A79A003955D860C88470EFD320E8AFEEB114E547E50CE967572DF5A5C4DED09222FF7821F91598A0A9C41A731D64429AE7D9BCE1B4E90120BBF94EED78098C9EE30C38628297C86DF59930E72CA561A61B6EAE517DB39F5A61FBB8C1838E3ADAAB46187F0B5D09962A39955343631B74BBD17BB2E338E5FC8C43BF8B2DF3A78BED744A481A1D789721928962AF2B9E2187E6B52A19274EF68F329C83F42A28B49C447FE284A25B71FC95D9322E752E28C7B4B656A743CF6C56CEEB758E742CFBC4B8D8DE5465D63D3D5D6EE993A4C47AA72BF82126ED6C7423D3475AE098CE6A7E6DD6F3EFD654BFD5DC4414B8F23F9E29CB0D5DDFAA689BABC7B5A925AB19817226DCD242EE46B588D7CB8E88183CD87C6D06FA1A40915A3F19E2368CDD97A16ACC2DF4CBBC0B30C6289D7004A8B48EFE4186BC4D844EA01BA78E4D1F0CDD2648D0363CA73A19032A537F68E0AC01CE6701426A03E071A109D42EE5BF358445907E1D05761B8F41AC8A9CBE2657754A8C4D83A3516EA465D5AD57367BC58DC712A5C055F68D1CEAA494D9A845474F610BAAAA4CFC96EB51D41493930534D58533E20575B980F4379A80393DBF797969405D6A514AC0A9171B79D6EBC5B66ADED19821BFB090BF76FBF50CA6AE07CAAAFF584A7013A71D54A2B60678F6F02DA726E7448A2379C28BCE7DF968154CCD22F1CDDBF25D91C616234539731B8DF4F55E21F37B29BC77DB4BA802D9BE419ADC292105EAE58CC81A636D479B550D33D057B7AAAF28F743F7B8C17E26AB2A846AE08E804E5D4BAC09D11C736DB32F9DC9CEAD0442AB7B6AAA70633692959A36D6DAFACAF2D7027E5BF9562A93A1B35AEE5313C1E2015E65AB805850DCA7A65FFCAF14200E1EF0DD8F8F05A11126EB02C13FDE38F496E5EBFB09E9E2B4920E619A67517FA4749ACD8B0857C7EC5A6E94630CE3EA0841C64D2EB895A9EB7CE5E757F2FB80BB4F0FA429E779BBE314A491B2D45F9A79655396E70CCEB319C3B405C33BDC91EC2169C3A75C4F5CD7AE5AFD6CAF6C9F81A9223484E7A12512B600794351693E1111401F74E1439C99D77E8932E069193DF7562C79EEA22C41DEA4EAF9E93456378CDDD6C8AA97D8D69C222614E203B6A1FA6377A7A0CAEFE709C90CB91939BCFE926B35970B13A06FFECD44DD8A360AEB5D0432A532E8A3C275E1DC4A07D6A3E100B04AEDEF14A52C09AA90438D65C8E6141490BD1ABCAFDD5925ACB040A91A8E11D242521C1F00EDC14D62E1C6FCE721921DF42164B4B34203660DEF02677A6B8C564075865B030936F472CEFFB3446714AE18BA14A6E45247C9AE1F2836E2341B61940A63FCCFAAD809C84906FA0CB1863625E59B96CC2161A4715606DB12FE3E79C90B64CB9D3A93B451E1C746F6B820B4FB3B3521ADE56DF9D50136635F29EA908FFDB32C6582715B06487B391A36A6A7B96505FD8ECE767C38CA4D0F9599FDCC1BE27C9C60D9190139C4F02461A5C42310CBFD5CF506720C9A13067F83AA1FF66CDCDFDF59B673B6C1FB0301DB118F3F49D1BAB49069A9FBC2D653D390DAFC3CC5CB35F0E50EF4CA808DC69F0134E3EEE697597FE7E5C2A2CDC5ED4E81F344879A0536BE0076D7A351A199530C77C0AF25D5C7D5629641FC8A3567BCB1456C1AE1D216C1E408C3AD6CBC1629E14DD834819F94EE0D255AB1C61BC7C324445F67CB7BA0E5AC424EB9C3D5FABC47081752F98B0011AD389581B8C20333C2878367795E31F99FD2C082B04126A3A61273C94E894BA7ABD8C6FD743FB76CC4FFFBEA78A1CFBBD266DB4432ACEA74350AC06F2EC832BD71FB09481A045F7A17F22F9AB65CAE6782A2928147BCA3B521E001D4BACE5FF499B1462709525D64E72201D5620B5537DF7A3E8DBCCC6EB822129B7768469D18C891A60B948DE2C12F4E4DB574C6C8BC586A1B57E727853FBCDBB4EB148DB234D8759B2AC8ADA2FAD225B5420C2B93D7FEAF051B7B768E64BC6EB83688B5E7E59059E1079DC66C5D8696CE758B42AE75123CA0FB72438DB97D39F1340B2891A19A4084BAA1A5149FAA785F09300B9DADA3C45F19568226151382ADB16617D5E59FFE8029F0513A7156F67D9859A13C2BEA574BE10E319F1B69740CDB176A962810B8AA6C368805EFA56E4AF69E908A205DC41CFC3FE69E4A6BB7B1F541DFE0A0EC1B29E3C199EF07538BC8AD7B0BD31B6A4DBAF70B83443A9C6C06268F597A6D1BC50171ABF56D18BB277F83203BB671DE404FBC4DFC66EE8DD4D92FB1AB2ED20FE8E9327CB15CB90908F37171D10E759BB8D1BE2C895604F87E2307AF7720AF99F0552FB15229B0FE7B45A3005E6CB0DC88A6D15AC7C364189A84A6615A344FABF4D0DD82EAFD42892C86EFEE6E9F7C248462E4C6CCA369CED819AE94B3DC856A3412A0DB90353E6C6D9DFE31913C3249195A3EDF9F84BE94AC6EB82969AF272AB8802BA0E8967EC342834B8A38163C90431844DB073DEB60B388710FF880EFB8283648CDCD75615D35451D8AE4711C1D7DB1AA59675061004EF8164AF3B4095F0E2FFC5433BA41ED72AC2C683D3959C9D265C302E0FEE7258B7C870F62D40961AE5AC43D3BEF8241B38A574F75EC7CD608781EFC16B7B9D36C3844B6FBF477CAFBA155B91061"""), + TestUtils.hexDecode(""" +B3AAA36B5B5A4676F1DFEAAE36203D94EC2E2092F4D46070C5C03089AFE6F991B0AEA0528999A8151E95DAA67815DAE9F7C21956CC4AB73395EB4B87F82FF033BA5BBBA94E238F7B6C184B5F2B1098ADA6FCAB8CA0206DBB3BF6548F932E522D5E17B2EBAB6B4A0A2AB6D25E86A071EB858832C2B8D4D718FAF28220A9801583DDAE046314A9A8D02EB15611E74994E87D555EA1BC1D10DB200A385AF09D1DF4A8D460189EE7FBCAC70862816A41B307F6DD179D990BF03C634E103E37CD9E254AA378602DECB325919E6C528F90D1EFA69E1815F481F22A3D0E58C9AC8018350304B887AB7F5509545E35334349C910C4B7CA7841288879CDEF8F222DAE22D5E18589DA715A5E35CDBCC9E79D3B6F6151B8F5972631EE4F015ACE124311355EC29CD3D4B9AD445E4B88BB961F9DE36DB01B1725AC1F0215DF909AC68362ED611E9EEC491BC6C01B3CA43C0C517267FA44C43FD4F195FBEB882E09BC2A0E13AA71706298AB6655408E8B8BAB108F772B6054EC543EA36E9382CAACE0EB62A5653B43C6868FA8AA6129F902310C6BB228941FCE346586A40B156E8572F6AD4E300F74F6FCBB9691C351B7F5E9BBDD8C6187085193DED352EF786AD96525E3B73DEA31E5468C8101190F57B9952B4D8CE57A3CB1A89A91C766785D6987E90BDB809A32B8EE7BD284C95F32173FBC55AF1EE56110DB65C2D6DA456659BF0B54184C348E6FAB7C397FF05A182ADD25345CC5B3B40FDDDB65F107F1A5227D93D6CC4AC4ADAC5720E5D3D801342FD06916229C61581F39A7FB0903F90FAE6F7DCED0F0804E003E584B51520A7A8E4232368D7B555F5A5F4AEDC83C408696CE2122CE6C8D42EEF94C6F6FABF71B34321B3C457016BC576F01B94410742B52A60634B6F57427F9B7508BF9DFF7665B8D8DF8D4F5A4EEA53F9A7DAF5BE52353DF441CD839B846FCE51338B74AB01149667AF5A74C42C6D9B324BE5338C69FF350292EE69DFD42D8D186247EFBC72423DE170753392F9EE3A851FF2C01E3E34C399163BC611785303DCDB61894E6E32DC4287C87782EB136D1B865A7563426D23FB354D373869F0F13A058B2F626951A2C5F4BAD5A14FEECD94A76DB50C69F434064682509E46C71D5076F00BC058A89CB669E253FEBC72AB42BCBAB6851B5DF111A06381609DF87972EDBA0F9A77EC972923AD6F49CE0F52F3309BA7E614DF4C3424473EBEF40EF15588D728F7609C4C2D4C691E54A09E6AD00DFAC07E69358A5C01EE4B9383CCCDF8E8B7E14DEE51D8B3B966F2C1BF547E1C58756FEC20278A8C4547250129516EE0EC1CBCFAA8C3154AE3AD9135D15B957174C1F380509065B035B1807FBF48196801831736B168E009E023616A73E7D709579676B0BF19AFF259BDA7F1313A46F15526B5D1048D853FF83A6BCB6F446F18BDA693D38A313C445FEB6C5979AC2CDBB750C536076D0E8E7EB728C3F01F9E4498671A34909959EB82A974BDC0AE784B6B514BB435D2FFA7B85416E56A4610BA354C3FC1118BE292B6799D4EAC3719AB8EF6040BE4C6BA12AACD9BDDA672452A04432FB09447C6A125F6FC27A589D3DA986152A0C3CCB72AB00ACA16885CE3A2E7F596706C7A81060A29A3DE21170BCFB1F6029C859489D58EC47B78717705795D5EE92C3504F4B0A5EB542D24C9F4A07F5FBFA1F5159F845997138296A18F9BE82B7E756E075F60D794243606BF1ED443B207816C854291CF3E2085957D52D6991345AB1150D46E62C6FE96F802D21D2A15D1266973FBF540570F0564C97CAF5F54CDC812FCD5C21C8654193376EFDCB5E7A9CB60BA929E00C933B685B9A789787212D1DF26C8E87347C923523190C89C7B20320AB9C1004B8148080954CDC8BC5D2EA91724C4284C21A289324EBC3F41438336144D8C8BAF5476A9AE92B522F88759F2774D9ECDC52960FE0C1A20B32451F4E51A1E73029572CDFC5E6E6F6CE2C0A712D4C4A74A26D7D8A14CDE65A4D277F8617A9A8BEE3F5EACAC1226B0C1D73609CFA4C937FD4B133ABDBF5357A771D80502A46B57A430F6BE8746F67448634BA215C7452011A62AA480C6F2464B1DB9F2096DE42C5E2EA1CC50A460D88B5F10692D29D9BFD03B8B8743CD0500C61BB7F7DA4CE336D25E68BD9A37841F5558C67AE45E3FF719F70E3CCEBB0128AB619C23AF8D82CC7E43041E7F6270DD8946987A090955B30C6152B2EDEF4269732C0D89817B9BDE594AE9E44945F947BA87C769F7F632AD3BE05CA6A749999027172230A8A36571534D151E0A0E3B99968C47F8FA9FC2FF4703789A15B363D40F57F2FF7CD3202D98E47ED13BBEFA9DE66BCC5979D7A57C91EF186DF2F2C8F02B474624E8F4729653414F6DEC7F763165164944BF7E9876686233AEFFA733426D63A3C4D31A4DFE5A6A4BA49CE45F0C9B0D85ADD85DACB28D4B75779F8A14B415F478E84D48A797F0C2AEFF842FBCDEBF9B03EA1A48760461DCF60592D8876BD967A1018FD85BEE5A31112628A0C6ABE9135C43757C2F1F70CF69C6E34BD5327E43838C33A2E01CF017EFFBE6C5CD676B7C2EB4462CB8EC2DF4810B759B5660F221EB8AAFD11E816E4EAE234AB54A4BA67F26C5787952A9CAA9504A4F26194355EDD7D7CC0755E70DF38F323603E1CC8738306A4FCDB7E6E9C5AC26F70EDC1D714D80ADD9628D1CB0F50751FBD7C4B4FB9987756248F7A5460B7BD30982CF3E60EEB075DA4C2054EFB0ECF972E67CB8350A1B8A836E285680BF8B59989E0CC9B0CDACABD8D4527940ECFE45E00300871992C69F23BCB4BB5F79295FD520E4E7D89C448F2FFA69AA40590A11F7F856FFBD486B53334B6537568D43039EE2FFCC2A0A840A4BCE03BA507DFFB7CFEF8762B8FA40E48390C94F4DC6B74960BF9B67801F7C461DD9DB9377EEC32753555BDA4BB5043021DC9C4FA543AA3F58CEBD08003069A8698CABD428C091F0B06220708EFBAF640975E09A58D6CEA83A719E49E9053BC67923951C4117108EEEB2C0818D988FD73697D14C2145734D6C65E0688F4FB65C8725D58BCE41C152D292BF9EEFA242AB204C77D7BEB511E62E893E255FD4DBB7C537E79B2DF6A445CBF67DAE85F6686807B356B7DC2AEE18F92ADBCB5D7CC4C80BD2CC2FBC2FB06436B1B088938BC7C7022357F51EBFD466AAE707D75186DF4D50390B1A3BD4FDADDDAE17D17EC36961799621BCED05C06C142094DC22D8AE2C70D8A2503FD7AA71E08E9726E1FC486B97AD3F2C490AACC6361CEF13400D34502E0CC7187BF226F35C09B784F5432FC44E0E6A913FE34A3E11EF957E668381AE4024FE33C264004E36DE439194DC5961EF2B8CCBCF0A2DCFD77366649CD20D73AC577898D593C1F769858CA8467E00C783597A49A70320BD6EF3EC56BF7F5BE745204D6EEE2C702860D6A4E8AD77F5B23EC389CA800CB4DFF1DFC22E29C1F4599EF131F5B993B8F9256795033309F8F3B73DDBB3280BEB2582D81FB9466CA18C5A028BD09F90C4A1A725C10E49856E07C2EA752FD019E7F4AF0CDE66B9A2FB9E22F4C962B81BBCCD218E916FCFD83A5CA2BDC582D0B2090F2172F581200BD0122FF6EE52BDB61EDE5DAE73542AB3C38E85B8F871AB1FF6C5FDE0EFB25ECA17C1D6F6777F5F9020B1826F0E309FB7476967A317A7D7BBD9E4EFE871E80A55F267D6FA3CD631250B594ABA0EC0D28619DAD9DF904F46098B5935298CD0B37EE80A58FEF57284A4CD061E093840C9D4CAA6DC3D2C1AD09AF739905A4CCB12CDA458BC9ED96774F49C5F9A1C43781C2A08BC99C0884BFD9C25545CF6B9F0F343EA84E8270C97BC47D706BC56B8E39B0DDA66D7A9E130E572586B9F1715AC35A4DA378E7B10CC998021593DBFD027001D2288DA1A6D72D9A66AC8930317E5154CDEA34C87980F16D1FC4EA87FDA2D47267CD5330B39FE941886FF642EAB1953CCA30ED21279365844C4F5043205D482485E45FCB6E52AD8B31A7076BC96FD88583B34720106DE1158FABD0A4F4422FEAA65B1C828A3D4918A36A99D34B99B052C7EDE5A9F6EDD59E1FBD2B2A025DF5457A9A3641EE8F65C13E7969911F5AD7C520F3C9F7357BFF13626262340429AEA5DE00798D73FB517185B259DD44BE7AECA1187D14F161C0D68FD44A272C38EE1686FF56F55202283714B763833EAC7654D3485509BEA34A669333AE9DB252DF82BCBB65E85ABCFDB0B23FC44BF4527E9C123AD4CFEF148F49178984BBE8DEEBE0BCD4564A333310F8BFC436810BE3BE1349371F35DEFB9A95AF245D92EB0DE9E44230C85ED86280493715F540ED2146EB903ECFBDC1AB2BD66BA8744B983EFF9437673A1D32DEFFFEBC94FF3E46D25B3565B71D7428C1C9E28FE9E191B79B490654762994D98EA1F75808914FA6D93A1CD216D17CAD2DCC519104244E2E9EC3E607A84142528FADACCCC6AE316A8BD0818413BAF7A90535EC2CDFADE973B1044FEB5568748C1EF7A1DF8A35597D2C8D86A159A0C9B88572569C50820D9C85C8FF52C072A81B8684C4EFC7900048FEFF31B4D4F144264EF77488CF854523303E418A5C42A1A0AC90AC5B6D4E84B51C9EC73E2ADA8EE053E81D629F5A5EE992B86B7984DBF7FA031A6BADD3D6191E266872B6E0F4154B7080BFF2F500000000000000000000000000000000000000000000000002040A10181F""") + ), + new SigGenTestCase( + TestUtils.hexDecode(""" +0297C0FA60D16D4A0D17A019F55A3F08EDAE88B98ACC1C7DFEF6BD42ABC7F9B95BDFACCEE817B390524985E281177E1F58D0D332D88A53ECC69D36CD3F2CDB5DB5165C52C2CE37612A4CDD2B62BA83BD66684F96B835670FD22E8ED003408BF9D1F52D90CF1D2D3EAE66D7D85DE8FF119E46F27EB01A4A88666B02B2C5CD7ECC71475126233751606406113524782512715333860324438760638762734863482074003581724563351353138370627434260445637442177740371643224671617725441344250077330875181226586513706860871721017807300117550675284633706413607083013276585716370368050360711636355585577030632744062432341561238384284175207553145658474417404154724103855270733216724328004787058212163440458651245376828170458827746751653134524478840643478264478207475568815633525051308106624207867342115378165346422073070271412006802582227512715153203088321004847547556737460264581323568705360343334431146566351401314880877404717661204337656538731582228565331786427057033465157483413750216317745537626715720244052725853713888388134843772034588472347173687745730066205583284724450000625141552705674515631427087434751825444380103432251711865645505836042741704560123523466822474632315045847723202654748142365813273005127174240207784056454887672623315657661530444776343656142117642778181763467027344577108463016407222826446461136448285450720774714430371008081132006480153606526463888054500118888003781136213148822370121275828340188141732881861617164087530333608831350247480601478725271843745774177873867312067462502403637155718413362531502661247285480024810234235400373287583667573412665140207568763110311725216005676866080753252314482804083063666176263420837737160682227765684481183417033821367724774461317852010100623286300633771066431466481720800788057135404721823251208256681603522737022068184055137381511425223830770027241631858506536650561586474834248364664527764288258583362258253611711468120685118836063400130368635701515801213185810606620114471462062014451636631838874230368660332432366768312320537254065462521272660077350618508423570831123312654084175610472468372463383236355463060552050638703827717733247850374664833535811821007341633446035721564215452045174715401058443708781470787635660678122871062520772570612807708024277164210323003680110227842476577255318133076620664182015776421146370080642876232368544572781206873058413012137383478200823323051100107156883162232725863430855777107357615856648065557274370204175012652058202246626757621404800874450550038325336061484681482363078018181432130234117583142652832864715748075227663747166702378321453044770646634388835406301744345204662683538438062348531701370655844554268761343776785460263714566588627783555812231322607824008010540740805513544233266705274246487108817323774438713754288718083217056316548462085815377128322036330530628018007677542067157424064876784444558815064151587171085581181235145012554740075736440276116856220542332347645738730270817668064813705460748025865533377527104018483583800012175176185223246188313570514482238856512801400078072461421870713162071176227243553400204034625862157643623617203115234046563256232806750543822670848323427755448215870168576404750227120773663868780623554673551445E94254DE0F4BDB570C48E4A4B84D39B8B491B4B272EE7207E36529E757A3EA9B5276ACDFE4AEA3CC6A05CABA81A46731C132A2EBAAE20587477129304990899FA1D512C5CE65287A6F8C0B1C8C27B44C21E70BAF94607D74A425ECB282990C7C05C66413809E6FC4211DDCD4A3DBB34B55359C85CDA312B23FC57448C8886B74B9DE589433DF4647066A32C4ADAB91470151FA69CA74E696575AC9E666B94568C1932554DB63A48FA9A44E9A34B0FD6C006148ADF69409885A99E32AF63FEB3EE8B7E8E25D207BFDE31CF17C2257A6100112B0512BC42DE1D38A9A292723CFB7F4ADBFA97EC6DB138F916CB479BD30617C74872E5000DECDE34884086D2640BA4E26A21FE0FC02F13F029A317D2C28BCD5C88323BB73C41536393234015DAFC26AFCEE2C42D8641C0054C6F8BD69CCC8EE136DFC1432DBFF2FA5239E032DDEAEB6CE6741D24DD87ECAE126A7B54DB76E505F93A6352BF154259AB84E0B6B3268DB1EBA038849E3C1E1A638CBCCD8C255BBDCE05E5A12951BAE8EECB62C4D8F69F89AFD2E57A216BE5FE914E82FF2FDB8DC8180FF798979766F95E06DE29907EA2BBEB325E3794773E1A1647F196F2A0D35778B1AE8F34B02A9851D132A0B6C349B3718231BEFFAD69739BE1CA60F863A91CB312AB3D9C3EDBA8D2EB3DA894FCFD91ACD00F1211239CF8922C5F970352B754C92A1A69D3B0EB1B1207F1E02487EA2CA8D1FC41578566E6760B9F65A29B77ED07491D9AFCA386CAD30B940BE4237115B4B335B080B77956019FFE5407081981C1A62ABE21EB27E5A74318021DAC60F710B5C310EE59EF7C4065C5B97E44639A1736A644A32AD09535B94A9E26407BE3DADC4BF50D27576151BFC5A57179EDE6DE8BB2A8E83AA215FAA3EADA0993FF66F2569CB5446C73BF3C5451FD3A0498579D945F23A26980426A3B9E8AA23FD26F9651D1E06BA56DA1F85B7C4C9408A6F074062DCE52FBF9C6A8147F86B793D41C09E3FF4317D68DCF0BA7A1104B30A2930CD8E248D3DA02AA931F4A3A6E46E20BF4E9B3EF671E0D5CA23BEB7527DBF6E36D622356867A870EE5D36F1496357897772C89D1D2C11F8CAB88F26F7CA6C941190DDB06C57001B70534F1092E23D43AEEE40483E4D3C4286AB6F51E07AB71DD86008F5B0268D8F3507ACF6FAB2C2650F1B43EB4B3E32A959CA23B2C1EEF2646DEAA03A81042B20B9A03A0595C86C5D8D85DE2DC31900E983AE122DD679ADEA13AD7C1820EB1D35E2237EBFE5E00A5ABA5DCFEF82E52E8AF34993D30160FE3866856BCEF955EC731D99B1962181A31602FC7E6746F9869F747ABA49C1804D742D6B072CCFFDEFF827E9F66B533173743FAF5D88798698BC2466D0AFCE77BE660CED7B90B43E4C81ECD9FE5E3CF23B27AC363A964C1EB4D2B75A60D439B6CA95E2F9DDE270FD722D4E14199EA6A5EF69D2D59446E8F2C8BC072C1488FED4C7CCE0B547B70F629E70FF7EAC26A56DC35190019BC5A141F2850DA2FBB79C847C338350A72E556B349CD82C2562D93C273A62815F6E17CF7D731224F9B4F0CB1CA6FEBFA28707A26A37A1CD6CF8793E34FD55865969AE291A23929FBA90EA6645AF179D92D65198E30AD5D7FDDA597FC097A021DB3CB85E1196F76A17AE1C8B907056E7263924400105359DFE7099C4BF08425F68C513714114CE9BF6505D4AB1A4C31743C62E11AFDDE423C9C4394731B892373B156BF828978C17D833867AED249B609C4107A43158C2EF607789922B6F72AC827998F7738D662E9A15CA66A1200D7F6FC9D8523E4D40BC70D8DB762437800114A6BD2E58F841B53DB842D345969DC31A8003402E6C2BDBB8782CA5198170662662C3701AC0F6C7C9E35FCE3DB31D363C594C7E2C98206F280DBDA61503CEBC145F73EB541913007394767E8FA21548FEAE6F29E3CEDB09AD37200D082635B3D87CCB2DBA9E56E00A50C5592EF3574D7F49EBC1DB5CD33A1DC46E5A26D80203A3AE44D346283217C72299370B254345409122A187F099ED7734863615F91E083CECD1D74CA49F4CD8142361C2378289CFDFDFFC5B54E837E41DFC9204D4905956312214EF384EC9A0D907F07A143228E3B950FFD27B85B43A1A5DF06736D57F91EF4CE7533B5DE81B2CF21006855FE5448E0071D40CFA25FA76C9482E7E59D09FECAD3FDC45BC640D36EED01AFEC01FEFBCA2E7EC71F36689EDD0661465F97628E817A9517311C5BCE985F40299148BD7F6187590E72FC8D56960A0886D93510D660AB96805E160D202FFF3752D6A1AFB68A5F06624F9A2127EB5C008DD5C43B3C6B4095A40F035BC095941CE8F89905A3C6AC8FE51879D9B5AF24847A52E1A5AF4548F3A70EEB3369E84558C16450CD9D49D2AC5CC6E022721F1420B93ADBE9FFFE2E91926FFC4F4E443CA2523AE8E7A96F10349D5792EE079FBED9E1BF96E1CE5F02FBB5F41AD564EBA9EBBA08C74C96132304FC0895DA7E6E34B5C99D333B97C062F343B249CE8A42C916C1E473AC763D0643063AD226EB9ECB4A51BC7B8291D58F8C1E1D331375667F0F80B71543B052A7CBB8B95BC267620FAF7CEA80D8CECE430BF1E515144817CDAE07802F5BF8416E41A179AF840A27D7E0449D8E7AB71D6A361E56DD57289A8638C16A6BD4C6B946D60C75533D343567107E67D12D1C7FEC1628F9C75C7F81033766162C4E3AE0635801EB74DA2EE0FE14B3EA5385154AF110657E7080A21A5CC50FA7ABA75D6C68BC002ECA08BDF02CE3A2675066FCBC846917365B988FF162866F19299ACC1E79EA08E36742B31953ADB3F7E1D38AF6D8B2072B35EDF4789639694EF82B0323743CFA075D839BBFDD66B6B6753D5EFE3FBDB97FF00F7BCCACDE4BA8EE392C4996FFF9A27F5E7EA34AAAB868983F2BC2127A3083CF3229E15D0CA9628D6F9CFCA04567434452594B5047767AC031CDCE5C0745340543584724282BE058DA5306D986C8A20CCF9229D40221A66CEA47E3FBE5B85E5989F464128F7941E29DFD73BC85D470141DD8845344DBC8A66F45CCAEA192B0904F58AEF8D78F39C4CEB4E289B75F2401B8036853188083C60AD910FEBDDC8FD7EF70F007B4B7EADC1F24E72B97AB441DC9B20323BE021C61C4708075B571A30D7E8C9A08FED5DFBCBE215345ADEFE946F44C9BA0F19C3D4D0589495864BBA958AE84888AAE853A59E274A07FC2452B082B84153888A5C15A5896EAA0CFF52BFC525DECE99AA476C465D5B53D175108A996812E21BEB615DC5EBF7AF1F4CA7DE7BCFC49356DD08224D08363EB068DDB19AC2A4B37053C0C347925AF4B5CD05C35413AC450E344A149FD32CDF9E37B38AC4230ED4D04232A21942780665C97F6BD893E438558F8A1A4865A9CD7DC0100B5DE099B163A3640B8DAFA75468BC0A93FF75CE9F58430810345124A8D4FA546376E8E56DB2610129A845F5351A31142973810DDDE9CAF498C7660BBBF3386C3AD4EEF7C3B5DB7AAA2C406605B60DC8710B94153884CA47A99D64DA2DB26D658C9DC3AE5E6CEE"""), + TestUtils.hexDecode(""" +DA2755DCE32D07B6D2C2DAD6BBF7CF5D4C26FF0C9B6FB9E064B51829A1ED51A712E26DF8047B487FF0755CBBA8FFB60DAC3C45E238608F48205A582BADF82C2E7E83D672057B9A9209386D2AB8D93BBDE0C522CD1BCF2AE95573749E0D51B85EA01494E3BD97D3CE0A61B26249E4BB94F9667D6556CC4313669409D94AA4F3BB9AB70F736D34245E2A789A5FE2917D5F4CBE43010C5215AF880118E1F5FD47A4C195F3C74307523C688AB76B7CCB157F75FFD79149B5508E7E527ABF718CE8E2E4162BF810F35E234F8CB65DE0930202C1896DDDE02BBBEC8D03BAA12AA1C91EE798FF7ECED608E3DDB7BD04A1DD9139F4A5613AABCF7AE495F9CE18D73BDA0C91583B72CCF6A722C319AD5B1051E65C1B91DD05AE5A77220BCC7576F9CBFC8A12CD55883AADCAD1AA109522F286B00B70C8E3D4C6EDDAE7E1752097C85233583BA0E1C05C5624FF65A3F3894158982B633EC92C24382AF48EB2DF5EAD30759E99D67B8BB1144939F4080DF0E1689AC0D4CDC73DF1CC2FB72B92D5A69019087294D5F2DB196CF82B7BBAF953F0568663596F78B5A309738BB294F7AA3FC5F3ED5BFD4768CCF3304C836B476458E14B233C156C8407636FDB3EBECF49B97C96C31F51353B79C378C6F47F1913E5B14A82DEB126D688133F9139C12C45BA24CC9C7E2C16A26329D463ECF59746F5A99C6B03896E851815EF36F499654E2764BB8BC60EBC821C4D0B4C363EEB7849332A9F1053A975B092AA3AAE33F06F760BA1D76DE07A1F48ADBEADFF1E17C34F9D69E409DC5AC83C296C402E042FDBFB0B6B4E023B15B318337B6A1CE69F1CD3D93FDD0FEB7AE259A41383939253C317DB949E3BEB9C8F7A79D083BFB46C50AC00D382C846B78FAAA7399ECB902CE8B73A1E89374B1DA65B0723C67B24899342DF13C07A0BFE3565CBEA5892F8979E404BA84847AF30BFC04D8EC77B1C5B9400CB97622E6D3360836639670BDDF4E9CF9FE3D6B98A5FDA42422DAD6C829B9E33F53686E2663D232162D3A78A7202EEFBFA4917BB8E89375279C96C9054C2570DC3D90DCCF0E418B69E6443C1B2540BAEBE022ED9A9620C030377C67FF4C186A59459DE7DB1ADFE2923C01D9B8D3AC940486052DB67EB67A257BE7AEE0D3C77BBFFD0FC7C94540F11DD96C5100463C27D65D3BB6B7D867590D573D1C1BEDCC0E8D122FE4FB82F1404CCD061DD7C3D15287F39CBCD2448DEFE1FB4ABA858DCE13F74414E1A8C41B730A1DFB45B859545811C2A9DA01C342A1F3C8B916F60B5E4802BE672C2BE31531DD9E7014E681A8AB1240B5E3D5C0D26E7040D4CE05F9017A32E1C760F466A8D7A68FAAD421B2E2D886BF0007858129DA2F6B92C4CACBC1786291D7C95A3F6A12483B750FAAF1DA03059F89C761641C0AAB21A05E78E1131B8F45C60BB5E8681086717B918BD4FBCFCA1BB5DDD740BE289D8DB1C24FE083B3DCF0E496B1941ECB7D51182F9CB9986CF3F04F0CA4E01C63EC879FD4A3D5619EA1085B1431FFC019286ACDF3B4AAB03D6265A7B18F24CC2815269681BD37263B44DCCA5CF6FAC2ABB1DE317118219A73095D1BDA10B66B6B55421F049B71E759DBE6154F1DB98A7E3FC877FA90217A242B21F39490F2116A2BE8067168F26439C8D1928255B5A50CE1ACCC222087536BC37806FFABA03B7E787B04C2C67C1B0BEAA871F39D3DAC2221AF44CC7089E520BADCFD840E5EE24AC53FCFF1E7D6AC26694CBC15B80E48B10C054E8DEB00AE387CEC9972A28448A6BE3A01D5EEA837703D2FCD1EB2521D444F900846F59074D715AEAA2F46E956365B7E67C5528841145C442E6FD7B3D7171BE05BF8BAA415260F645E2FBC93C46B9F94D2997929349B88C2FB1AC6743B73DE66B30B44E5DB3E07E0FE9713D9D7575EE4E40327A58DCEFBA0EE95E22D06FDFB720993EB134073A80A4F06F8303C7758DD37CD7236E5D80AAE2E9569834846E7F6C75051302486B2564A1D8D987D1A3648192A63EEF4C2D25AD41FAA02C9F227CC9F655A72CF7207ABBC66F9C822EEBDC89833757013776C11C310A22C226ECD33E5B0772AE2DE8B8E9A876650D4A57B863BCC6197261D7D06903D414AF0922312B7DE6D9E64F99509CAAB8D808DFC5F046BA2CE55817512535EDC2477D8462A1817E45D33B9D7390A11E30C3860CBE2C4B519812ABA3AF7050227759DF3B6FCD6D3EE5C60C1042DFCDD7880888A147AC47A282EC51D0DF664451E37D7C40672A27B965CDB805CECD3EEAE38A0AF4C2349FF39947659686D30B9ECBDADD80C9B06293FC4BD5E7A0E1E9E883D7A4EB05102CC1FE45F1C9BE23043BB458E6B8B6C1C187761004EEF59E398B1124B98B0EC0F7B29394418B38D8A3003ACB85D96CFA0C3C63B2ACFDC2BF5540D029A261243E06393253B2C3FE253A220DC7AE4BDE0AB4B386DECA15FA2A05465740B072FBB0C8E81663E320AE931A2DC7A627C805AD80819B9D12EC271D9D16736156195302C93490B4F85E8B4F5199CAF233974079A7AD590374C4E5589D0FC26F70FF2CE51FFB3E6742AD5BD9840F62F745C42D6085E46182FF73FD079BD2625338105FB39110B660F8C55D0830587671CC802AFF63FA7FCFB3BDF6D65B362CA0B68B31FB802E7870C3905B04B41440F549583EC87218DF6A0BE0E209807AF053CA121D704DC0C90A499D1742658BB096C776514C89F6B2D3FC7FBC4A38C10DDBD3C08F64AB076C9BA4C7BF24EBDCE9C82B1BCB8E55C4135976C878B95B6ED108C2031F4E53DBB19205A7109C50289C743818B90ACACFDEF20EE33F5C9A7142B5640F4D875122E0E5"""), + TestUtils.hexDecode(""" +583E9A28CB7C3FD65D84170B159188C12E7E77E0F39C678C2ADF349676BC5A4336041A2AF283D3A0F61BCEED4255E2A04749CABAE6811FC2471148869D81C708E4B56FFC353196CBE05205F737C91C80DB8FCA7C243DED5BC6113AFFA87E14E0DD0D3E7A70B2EECB847762F5521D372C51317C95B6EEA2785B552D9AB045E48C03321DD041053C328A0081D86323CB37683CBBCB3A68A2F850E5C7A4826E88B1AD51D6C1677DC2B081DDECC66A01D3D3CFE26531B4EF89528735A8CE75D4B710C0F3FF05FAC74C99585695BCAA1D1FEA42D6D5EF176B90649FA92D1F089FBB63882AB9CD539C88028B380E610421D3C09314AF44F6BAD1129107AD1B84624AEDA7F3BF3A7698C478EF5DD2639D9555E53F60F327CC66143438C589285006552FE249B3DE8F4768B9774591672541385018FB6683CF04C85CECA1A9FDB4F44EF31AD9B78B70296CACBB35A600C486202BB771C75E83E1A0429A31ABFB75558ACCF835FCB68FBA01F5B766F3BF18C23B3DDE511087E8AAE570979BBF17C8C1FD69953823B4FEC56EAC6AE11FC4292A40BA01717F3A6CD108BF94520955F978354D78347ECD4A0222D89D1D7D93ADAF7679AE101106AC49791B3D17B6391B85E55AD4A12ABBFAFCF1D50667B37E49CA69D3CE3AA6692F85420B246355ACB51848AD2EB94CBEEF5E32D455FCF42FE73562B5B149CCF01236BCBFAF656E85C1D9775217E51D4F650FED78D8BBF2B47C67BE41F69AB2C2B1904E86506A371602A8B84A50BA179781215C0B061522EA66AA7CCA390055D0A461805CAC87ED7AAD205777344B7573D76690B5B46AEC4665E36A9173D7732F5E67FA166BDDCD56685EA1A41D440E469B7B65D7869744B1776DCEA504B03F6057F9A2D916BBBE6A5032356F4C3D48A495455381292C52E78F8478A56FF0EE7B94B83F1EE690F7173729DED18DD712BDCE3CBD887771B1D87EE2946F1ABE293F3D7A7ED224F6969D31D2E1F71F4D45607D7EF59AD25A40B4A43EC95FF0C8691D4C41E97832F345CB50890865AE483A163966F5B45291556826DD061C30C8CEB552EF8BC2E987BF6C8F629370A72941893F549864389CBBDC3D38D9FE7AFF8682EA318BDE62A2D11E543051A88B01547728E30CE25784251B73B771EA65259E90C4A859828A65A87FECEAE332B9F51A986CABF15B622AFBFAA04C19678DD200BC0B338C29B65CB121B70DE6EF964360F2D54C4D34BF7270212452BECC9EFB2E225A6007B35C000D276D34AD19A966D49D98E140DEBE503215D716B243CC9387CE52DC10C5B40BC765C2E4D3CBCF8E1617A1F0133DF0C98D0AF71E18DB6362A6E4EA9E454E1D6D986D1DC50AA580DC7DD131E66EB543833FC42A575A84B652E63164BC3FF383040E6EFF2B7550C2AA0905FC7BB4258176585544DA49F48A844A13052B06676568244CC66660021FE78053CD4ED1118C05E517107F614294B97CD4ED6685D2FB44B8B01E538874186E6F8D27D1F8829243016B1D505D42204FDADD54BD985BD647EB79A1BAC18086FA8A3568343F58A8D46A6A35C28DF1575CCF1700160EDBAC0C66A406A26DE724E1CAD5AD52554CDE52EC6B5063918C4A137D758C08272E4C2ABD41B7EACA4C44A3A7CE60F8628F3B13CFABF50F16D02B375A7FAD7460C53A8008BE19D982E9794B060CAAB1AE6FDA80320EAB2E02708063F4721DBBD8B9FF951BB6129139E90E7C1754D4682D029DBFF5FA9E713330AFBD9DC2FD1148BB388F4F857B4E4C63FB107386DBCA20AE196CBAA995F522D6BA4D2645F724269CA1A5AD24D4F56804FDD9A305B30C46901B484CE8D23166A5036ED775CD192BD47D9AB6612CB6D9181C1472A1F11E02E7C82470E8C685E92F21996663B18F8738469D61D98336D7C53ED2670A8DC26C21BF0BB105F5C905D2AD7432681AE8EFE5D868ED0BE906474CDDE2BE7BF5B617463EF59BE4A210C3D5682AD4DE5C059F1136D2C455BE02AA1E276F135C5001388600FF2F6BC6DA8AD0B72D1F5301DA9A8410FDC410B54AD0BB2561B01D646214C867726D82D3919B4C76600DC065C5933F8C7D3C916C374A06D7F062889CECA4D0A98FE843F8BE1E724D88F6B6E8E066D7B660B0FEE10CE8E36C4E60269CFC3745AA960C8BD9F7AF8788C4CEA7C4BAD51A202162CED055B6B60F8CAF85ACE6F60851250B1BA0ABCF9DA2C7EA2BF074EAD9BF81D73ABEA3966D63D1E60809050B7249B7969AE420E40387C36C4757AEC7CB328466D118E3794903C33F230114AF1C0AEE0112197DF6624123146FB3CD30F6020378040A8546E20767B8537812D0941836A0651AC90E084ED6673BCBBF18348D0E4E52FAF06FD1A42DBB1EACA550553595A388BF27735E85FC4965E61CE82E96430F40EA3B35B874CBAAE2612A714BCE0DDCE94FB0F4D93DBD7F6B03C7099956710E5EFC5C996F8A7CFAD679B496044F5204056D594DE05B61CC143F834BDD5D8B9F89557FCC09702848EF9A391CC4C3F07F1CFAD203B172CD1F44E4EF08C35631DE23B8E0CEA4C4848663FDEA9C9ED8B97B5C7F9E94AF6A90E5079E40A791F1262BDBA96BFABDC30643E2C3159919EE5288FC75703FD0D03DAB0C36D0CF06F0450A5E6D710764085D0BEC8B26FEEA7E5C2665C7F514AEB5430F9C307E7D03B30401646A0D93561FADA21975D8BC4EE1F20329FFB4625B3A484CA08DA09C61B45E2BA9C88C29B14E9B650869EAFFDB7EA3697F4DCE2A72752B2459601E044B52F0DE99BBA5510128944C00357845F374D60E373CB35FC2868DB5B948EBF9BDD3C66C1740F00711965AD9549347CCB3B5221301159472AC8CE0B3186269FD1CE5CD0DD456222F10264B117BA250B391C840E51D8680BB622769ED264148649D3B954839AAB5B27546B8BB58A20BB52FC8772FACC04101148C99DE07B96BFE58CF2F04DD5541CA9D24873557902F0BADE63229CB8658E8E5F815719A73F29F81208D0EA8985BF2DD770177C4FA88CBABBD0C9181C0DDEF7CBCA5A6EF12367882621E64ED026A859C60D0B8690924EBBDE0C0E3562E10B63520D8C801A6814CB1AF9F03C3907FD9A7AB8567FDDBA869D7200E9284933A414FE681F04A45BC3D909267FE62FAE7A52F2F84D3C02A10AAD86A1C7A9686A2B7A81DEAE6A1289B7A0792BEB805A620A38F7610D9C3AD1CDE838DBED11A760F42A271020761BC41522EF370726A4683DB705C7CDB858AA8A8036DF1328AFAA0A4B31839DB7518164B11E6EFC15755D1E0D477EC004F5593CF7F862AD24295569E3D5095B8B0F1AD427C1CE7039DB9D881D5E6AA570144255939C22AE7EF4BBF9CE36FDEFE30E64ED373AAE944907F5BD02B70312F7150CDF487099468B19B94703358505F7A5DC9317B9B17C44685E5D609A0F5156A1D4EE517BB681CF5657AAC2A1A678687E9995F089CAD494A6C039774FE62AAD3D2BEDEF62681AD24884D1630909293B54C68D7CEBEE284EF9E70049748558DE03DA23B478566B42B8EB327DD8BDD473130F1D967BC0F6E4501DC64836EB877BA0AEBD241432C503E41DEC7B264E08006C006FCA366EAA277CC9F5FA6155C9E48E852B718A071082FEC580B4AA599CA7708AB4C1995B6DD0679264D8372B5CD0EDE9E40B6CC0C3DB14D00B2C7D2E9433F08C23ACB77F991A454A3D1D71379D08640FA5074EB5364A531587907607FACD9AD9036C8AF221650F01308F53B8D0E432E5529F435F40A40E66A5483115FF438107F88FE5F1D541C500F8B12C9DE69CD5B14C3FCC5B462153F9DD49974C34EB1C5604606E56C746BBA8D90E3DC4556DBC3BBC656A54E08ABD3FE1C39F24E99D3D022828F59B80C4DEC6EC1CFFAC05E388D3F62510AFABA69C5E3EDC898CC8BB842F3886A88AED03739C85DA459E8329D1AE249E26EB60BDD2EE30191099C96C397D88FAE9922C72A275BEC1C7734CAC893D906E976FC7C0AC8A090986EB4F5FD7E94F8B2694AFB4170CAD4F1896092A7F6EE01C300DA97538FD5FBBC6EC28D158D3AF40D3598753883156B0DF2143131C2751F2B26DB6FAE76773E55AED9D115E7FA60267DEDDA65F41CAC5FCB0CA296EAD1EC688C742DDDEC5292EBCD47B0570ABBDC2CB6EA301E58778E1C3352E393598470D2FD2C45BC3A611343ECFE61AD64E71033B6B7C053DC52AB1CB246682750E330560F15B3B2D83E63F33BF4EAF608393C1F5811B0D12244184F20EC0682D236F583CCA8C8D332318AFBC50C03873D68AC44CAE4C2826E966E35EDEEDF4B232DC4B3BA87F3478FADD0D8EE55B408AB929DDC85FAEC0AB503C2F8192DF7B719594C7706B98C593C598543565C27BD8A0A0CA7E802B86214889D8A08337C65BA31BA08BEF281FB69DED0B30AC13274E1D98FE3F2CADF6B6FF28334B338984516877D3070F379991A078E1D0D25CED600D2C52CC335711826066976251DD11AD21B1C852E05F3D9EB0D37E95F767108AD378770DFF10854754BDE53F8CDC14F6A48C66463053F8DE46B722EEFC6F2BC2495CB107F3ADB39BDB2AF497FA6AA2CCB4F9801964FC6B88C9656D76C0FBD9A436D1AB57D763A8B814D2957E6344312AC137B3B6FA74AAEA860186C02156CAFBD455E8B999AB52B70DD05112E5C94DF3352AAB3E2071C343F656E959FDB000000000000000000000000000000000000000000050B0E141922""") + ), + new SigGenTestCase( + TestUtils.hexDecode(""" +7D9BACA9C8D5E302BF5CE4C85B7685388CECD82D72EC259976F4CB65C360D74B7AA8B23CA3C9D786FA3D949A9DFC1600C821B808F0BEB38F815D7688928159D7D9E9C1F80FBEAEB0718B4A27E5AE16AF325F2362539164D1B0F282131684089E9C61442C8C6EF03818E4FAB383498A91F1A6BA3D1138FA2E6863E7BFC37C768B80881102106834535885567854243344502211757522267523162088466534441253602763327188226627581385652565414151784380762722456634142628231458738808653824328765256787544665871806531822248171715644617852253306323676053473565268176586832213365052846420073311447520430470886788436502856868764754304758685773064126124086602270614670066264160503303628808800428371124331158623773024150040258466354242631322182837265206682145238541377758026231302173751556168744863422724538416543335044260014140700080223635662746130854042515087002685102861285410486525326637353184253282228015078475041117212844878141825033873150751831805782170351465068071671207478634401484255326350633185463351180560737581677164273148337620650506318728817625581311474587143474200631175767306836700454673165201446440552351405570370765020236227650155735776370575127458246010022264663462424423213765310260018843165528661703717074062347113507035301545373865105171508624854887346415101230182053334304844180245311205556878267210221681707671130563111227840346163445346756381740517462567744211002860288204613256541014522561605650738111510652486113003236284705828187520165420710141265210772323357340165116445210432428531411538578270768734622774714255868725625185866516828826288225225382481362346231732171642643803148671271817471106245053755183045102417242701340831385358686761031752488155811285174784301446783814603452746400881104301515340323411220606187382848113531273238682142164176684773160428640811770836021008816722262735542177425024011656734742220208177654327651838237731115676205078445837425763855715746545685101718301140056042410640767435220144420781045324711834710612775235483708256718366036056834856355047187872866251726612854101127341052403064311315244428128784365157205414785337848650728144772332137377841026231712784787072708207440534642352015738400562513805485583235012405755534737647887617687056613236528823413687622035830161327666432826703008462403420246788067276833355848330825352627051271045102466531806664112101702762667023185287441052104507353315241367611074381635451018347836601447556273501604602706013545264275427561702133764222721520838326555538771678808754764612652255384672763068833424642760475458348132214166041671261184323442617226644673580125123380608502007202213714484438825036152616448882228853238503436651346737426226137454116521806224384547167800842813436447366152212332813016632406320458758564571656076278257144143508780111883350040472187651326241722885506068843614384407717837823233334577603583138607157753607181603248844021525518610382536002436628707660830482135508327523234521413058137640267365080463880375267721714644672516818385618535542842438636753417412616738466876353522248666700120623351178721720464482820874272415685137628481655455861246778640761403677012083646508583110082074453101204426410178432288412156182720465184485112240375BF8365FEE3A6C811138E1CF73BF1D0EA525F2BDD4988CC157A976B949022FFBCA93B2664028F9D0ADE28005C84CA7CC39EBABEA9C92075734D9F83990353AF6D72693CBE38659C9305C804B8A75C8BB1C5FFB6C5A681155A2A65F85C8DD4A14C6B61C45D6D2BE9411C00A29DAFDCF3D9F1EC1E2EF75214043AC120DCA4F22AA7354AC2B6443FED11A086B22630C1B45B2A372FF2F1D0660C41087F5CF818FEC1FF96F18CD710FA09F66589010708CF8D299EEAC86E1E989C2DDD60A2F68DEDB62B0E6421D4DF285AA2A32F442E35688826E0A9EF9FC32C32F09A28419F37DE7747DF9C86B5A54A558D374FC1C083A46321E7237BF37491214F54973CE3BA8D7229370DFB27DC68F33EE68BBEE33DDB63B3AC4E4346D6D96A6A300F49ADAEF370C98AB1A44A4D5E98C1B19ED433AC13C5A099894CA3481A36820E5548A04C632B0995BA976A359DA6F029DE8443D7AB197037AAACFCF2F61D33B604DD3BB09B26523B103B0AAD0D2163F09294A48042E8D23599DF7095E009F393C4CF5F295C3F5E49F2AED1F29926653C48FCD8D93DC39422405C38EA9E28FF5ABBA4FB699D158DB7F70E30716DBC1627A27E6A93F594F6241869332D4F3CF41731B84C17DF195B7C7CA7E4563AC9EC1CDAB2D1E52E5C6D38B4C63C3901BD860C038A34284E71834247D1D3854AEF49E2BF6F67FFE4256869A41BD44B0FA2E0CFE0345EB3886BC4356AEE11A26838D4F2279AC13D6CAA53F110ACBB1F6764BBE47BF3C4E1F0B9B99B00B6B9E0C50053FB32174BE392321A3E0A69BDC874D3F3A42AEB79C4BAB2753713A5DECE419E2BDBCFCAC6CB741425A64CC7D3180E097B5285E0B7BCBF9B7D97DE81DF3227C2DDAA369C87BBF3F876AD8B81E9208C2EAE363C3A0434BAD92F49EE7B6B805BCA9CD6C0A2C3E21E5D5DD9AC4F427F62EFC96C13F6EE1EC761CAB24E61DD6F509D08E8E5AD4EDAEAEF0679340677882BCDFCB6928AE7C2052DE7116CDBBAC3551CE0DAD8AE909D795393CB8A6292C7FB2C16EE62B8B5F05CFD5553A7303919D563B7612E65EE69C97AE80D3E407A448C88D508191B98821F03F3823DA8793054FB0D051D9BD12D090E2CFCCA4DB20C6AD515E5E8658233C095781D5BB1D40BC47D3BDE5A6379CF03511B2A3C06A2C315730A0349F83512778A5123F7CA9FAFC44F73B1259090F8746F1AE868DF6D158636EED34B8FF85CE3C07F7378ED5A3E7577A6FAE7CD3EA0DE0EE3576C48008E2E4F8C417F3606BB1E9DF468E40FE74A3C69A672B758F1C3AC570E44E9A08936788B44A769B28DCABBD3266A82CDA0CB6D2014B73BEACB33801007C40BF92B647FAE6631648F7E91DA022993A9198153B7B3C31B487C863A639ED7AD4B235FF3D44E3AD573036902E3C41A53D34704237304D2E4D72A3F41DB6BEFCE9DA8945CF5A9AA2217A2B36DD2956C3F4C811B3D2A95E1FA88FF2ED95A0950CDB1A14DFC89ED6E996C854C1FF056A73D7BFD1E8F08EBA003E3E834C71598E42430B15BC0F1FFF6791D639BD40923A28FC4B72636AFF01EF4F01C4894BC78A3AC69BC595760BEE8A227DC88AD1E633401B4EA43BFB070ABA4DDE38FE0EE6BC4958F1E6481BF478A9AEA4EC2AE56993CFC33975C06B571450DA0026DE58B99B6D44F2AFEDE582920436230A6E81BF051BB54A41AE6E6C34BFAF1C7F03A44B85ACDDE1B44DEAAB8299905FB5AD961FF224C717E96DFEDEC50D5CEA646D2FFC5F7B6017EC540924D1C9FDB8013F2957F271C85027985FD4184F22E790F91CC7C44C1890AE83932483AF25FBC0A9C740BAE467E2CA24AA7E86C41A9250260B3A4F805D6421B8772691F172FB63939606D50D03F7C4AA09EBCC2E5289BF4B9EC64A1307869CB4EBAB5C0ABA222C86E21D6EF32B82B7409B10C67F7A7D54C850C277728C15230C56E3B0AA375440AC0B55DEFFAEDE52C2F84BA5FD49A5AADA5AF6C9EADC0E413006F4149081EA8B06A3590E55D55051AEE474E416C7C76F0C41C372B593A5A22CF9D520C59F98942B2870408FDBFA063FD14B6615EBDA85ACD3020382E696B84B4E6E6E28B1F6E279EA4C5AC3444E670F5B1F01ADC3331B4E13B1387A082251FE63E391E3AF0FFC8CD5A77D2B77DDC75066E04F9BA89B65E62F3F74B5EB53068449A3A59A3CB8351B5F8012FDC5B3F7ACB10AF933DD9FB5C094BF085FEF0B27D9B01AFDC95B3B96633C5082369F03BEFA13D53FFE31836D1E02ADEFFEC0CAA084050CD5CF34E1362D4BC422418536A4F5048639A0F168743459733CC11EE616D810DC92B266BCB0B78F32269BA68F264B669302E8FC2E35F998E2B0438EFA2FCA0B14F0B337701A4FD5057AE3F1105526EB726381C54D605D21E9A1887DA4F8AA09C3D4CD0E617BC072F4050E125763812D4621F1AD8001AA027546E472F8317E9F37C27BFD4380D4A5A8C77FB426C3F13E462E06B6D7C59C8DAE7EC747E4C08822569421C70EB62DB7C3F1EE9CAF7CE384ED0B58A122A2C0C669DC843CD21F63E01CEED8CF7C63918CC7CD04B80556561582A4CA24732956700D5AD7E65E1F7D770EC84C6A8B7F7737F4B597E305199C8DE6F73F3CEB730CBF6E87E53114D931024DCC1F3EFC56BAC8BCB374C92E2D687E735DA892726B2E7B30135D1CCDFFA0F81B8986A9E646B9D875487D960FE87360C625557CD5ED7FD45D18CFDA97B410CA62BAEEE3C90C9EC02525D74606EC7EC1169B250E8FF4B94DE08AA95150E52715C18DD6A03F2A399956F3308B8CE72A96D2F41E2CD901D4D507F336354AC24DA68CF8F83B69F12E54BAC40F9A7BCB1D1165E456DDE5C60F5BDA4F8C435550B492B14642A329C90732E6618CC73B5A32C71CF306BD89B074C8174912556C3FB05DBD4216B246239B096CB8928162E3544FC40EAF652CC91004686FDE0A3FDFD80BF2770DD4FB79A7029B0DA6B01C8DB069414B26A05C180CCDFFE049401A348990E0247B542C7CFCDE012F3D6840F406F7BE782DBCF4F6080BAFC7BBB201EF6087D38C211727C15ECA30F003AD52CD540D8BC4DB81375F44E0E092A06F9E9891F6AAA178FC39B3E2868284330B3D2508B486836D9F1F5AF0464AE1DD2D696AC0EFAA4D9DEF2E5CD28A5E1D42E813D3F16DB85BF565EDEAE869A88D082EF43A33F936533D151E0BD06457135FA0450AAC65438C729AAC8598399FE8AC0042E3220E936F88295E45BAF653F405B12B2FA9D386BBCE3B46137253E7C64BCE7E998DCB4916390FF7E2F074FB1754B60C3418DC6C5728E2FA364ACB2C8BF63525849F2CEC268DAB24CA73C429EC350DA2900583D9C8B2BD0AA7F5458B00DE9E44209946F70BEF1C7ECA26CF08DEF56CDBD6C1816D52A373F822321468770A6C5D8BE130E6C752D63A72688B786168480AF505D914C13EAE57905AE47E10CFBD62C2097A7482432CFE5500B804E3715411AAB787FDCEE2F644F38EE9A0784E88DEC94FB9599A68A0105577162A6FD575EDBFAB3D6DA5D2CA2F086A8D55A325F8EBDA84E79D96D794097E62413CA"""), + TestUtils.hexDecode(""" +5870BB288AA6130708F7BBAD9FBDD6D41E249D620495ACFE90C61737B57DBA890213D4741718545CCD8B3FFFC2DB33C39AD631D5B5CC902DE4D340DF03E09248F67E89D28071AA50FA532E94C391D2D1A61B1847C6B1088BE555E5C2694EB0FC1F029095ACD9DEB21EF886BE577682CA96AA2EB3DCB24B871336AC5F23C8488011860B455B687BD4CEF5FA11381BC292B4098BB2CFC1822B48ECFD28AEADA71809BFDA190836D3215CFE755FDD9374115E5A0CCAE15240EBA0147C2F89D8D24454D7A5AC2D20ECC0D46C040FAD233FC51C870080F1FCEFAE6C073AF5F7A78D610E23831D5990985FDBFDC6D101ACF3DB0A74D71739E0"""), + TestUtils.hexDecode(""" +4795C93DA899DAAC44BB2F2CCF778D14AF2687E26D40A5A962084FB54F037362BE239723AFB994A15B17B6B779A80CA4C88FA1EB57DC4BF743734929201969C7DBCB295F9D5F994BBA406E24C4A0EEC73368785D9B2C8CA45CBD7AF0A772442692E69FB79AA17FDD80198870BDA0A1F0DD2C89D22BD6660E62802F0D5183A7A9CCF5136E6BB33AE991EEF920FD80EF911BB94AAFE0BE9CAB7C0AC60A8E763242C3E8B4099C7B8B1661E63F756A0B743CFED12484E70151E39CE81320A687286A3719ADF712D006AC81966286C1ADCBF874A359EF391B892D4A72FAA7BB43DC894D0BCD7B77BCFE845677DAC9252046C2578F15C5AFA19ADC9B5D5D6DAA9910F3DC0187F1B12F7F19ABC6ED9AE0CCEC15C76E6003D7F9040F2F6C61FB568C16FA69BFC87E228AB08092D2132E3F50D07FF7020B400601C603BE610F10F19F1014DF1C56D4953B9143BCE64809426F3643D37C99BF27582E4ED66ED8987CB16853148712F82C3E49A4B2C763C010E74347F816DE015F8568024C1B6272A4F0691CC4360ED0B4BB81B576F46A8AA38CDB39972C930CF0774CB5B59871EEE17821B30F58A25BB9702C1A4868CE50FC3C7102E23A75AA751556DE1BD3266084645C8F6AA90B2ED743FF39CBB951A64C5235F1255DA9117630C150E1870066D5DDE4721D2621417AEED53FC1EC5F89D5EC9BD7A6FF0C98E4A2006B0118B2848312ACF3E25AE401807B0CAB45BF54C186A85D096C71C4D14948547792C290212269D8ECFC79BC0FAA3D37F6364E3FE33B326C8135851B20A7D95FF10BCC765251ABD53F4B98B0FE2BB89FE5E15E06D130F35871B5492FFC3A1DDA21E7C6DF0392C714907B7CBB0C977880DE4BD44E3BD1C2B72729D071CC1FC0CC93870EC8996940C943C0209D3008B90F22A8597320B201100F131214CB43E6922168E574BB7C6E4F4A85CE11BFAF32256A649E5C95BFF1B83ECD8825CBE665C6FA98611EE7F4977512476010015DA2D3302F7CAD95FD70910974AC858006DBC3AD8F8995C99C8FCE87078CF218985CE6817336E501480B53F81C1058EE0F7BBDE9E212BB1B067FF34A3F8B55DAD9CD0DC963F8C8B835DE200C294EC402D01DEA0540F5CF92B55252EE651A4190714581ECF2C9617E4AED4BB0230C23AA16FA9502409B03E6A3FBA7D213BE13180EE2CF63B73D0809225F59D2FD14A12119F0A531D250BFF575DAD676F692E21604E2C83AF932BBB7DB4F3A4B15BCBB45CE3C52C622B14561A39BC6582BD2ED428FF05A50B57DD355469A5B36BD5CA04E731F688BFBBF30C450D35FA94E74F7E9172D7F66DBBDF13FA634F3BDC891CB49CD5B33DDE0FD7EC8C7E538ADE84B446781918DB26D363598DD54345FE4CF3673F69CF2A368EB3F6C6FC98E369D9A514F8359CCAA96C8E8B9565945D7C8894B6BFFBA4CB0FE2B1317C424A080A189A5AA8FC4F09E94CC90F3CD74626C519C2A99C39734F26E3FE99DB512896F881034580E2882914411AB3581D8DB80B46B4ED9B22FBAFFC29EC1DD88BCAAFF56A56DE5055245897764C3A45D511245C3523AD1DC7898DDBFFA290683412E8B7882514372240CD523908B0C92FB26AC669327F840A9496BAA63D1915D3D1D8BDBFE63BDCA662E1AA2F4BED11F07A4096A348598BB1E9A239B2DF0CC2C1A7D62F91A6D18B1175CFEC5B74D63154FF2141F82EE5C7DA9BBB4523001BCD174EEED70225F16C73F2F443079E9BEE77205D4928A05166CFBE014A2079661D8B609EB4E66F992EACC830D0FC61621D65E34DFE8EEFA5D782C56426E9EFEB253EB8233B08A3A6CA4AA8D3916CFFB7783C9ECAF0AA859CCCA99AA460DCC193D878D6643492C10101CE59809C5186E3459444C395B036390AFA2E75416EF6F04939710CF080790BF2C6E626BF9E872C7D13CF642E9D9C57EC8DC106721C04F13A8BAB6FD151C8416F523D4F2EC038A2525096EF495273976F3D1E7DCA57D5758A213FE5872F242A67F1C2065083B1BD0214642976155FCDD227265B6A4EB47E6C44F56179CF514CB6D0BD33349381CC4EE48CAA16318DD5DF500E7BDCBF5A46DD24D0A5D5DE106B0B3F66DD75D210379C47FB5CF11523CC42A77CD80423F41364D064427CD016565FE2F1F7F2192670FC6C17AB346DBC50EE30015D353239116BE68967C1ECCFB9632969B848C2C7A768CFA771C8557970D77EE918ADF6208C9D803B41B184814A3C99178E835D89BD47403764EDB366E6050D9B342B3B3D6409C577214BC7CAC261C989906A57A0B4BD9BC9778B1D74076CADD4ADC43C7E79F2A0CE5F2E81C36AFBC66B526D080B85E0372859D64C28DF6A7B60D3A066FD3DEB847DD2775A6636F4693F61361B9D84D19A40A0EFB2C8861D9B27E43BB504EA6B082AD62CB4FC1B6FC163AE7DAF8D6A54CE4E9D33B509D4D7936267A0D32389987DC33DE09ED37043816463DFB828BBBB3B6E4E5286C091A494ACE782507BE750537EE9F2E609AE4992B8FD53E0A38CCE7EF962B75F749B74103477AECF55497CA31741D70B1F207CBD694A8911653DCB4D1F919B728EB2C03177675136C11BC2B772C5E1C5F4BA0FE431BBF4C1755E8DBF54A6A111733E855925296C09DAE549E5AEC0B6E0D9DE07E077825941D970BBC9B7DA939DD2CBB373F75530CA30446F3DE199709A5E68BDE9D92C6A323933F214BD4F3826860A131F301DA7895F34EF35642926FBA61A8E1C17492C31D2D13C20DB60F9C6E90FC0152665A21100E034065A67E2E676C33DAF403218848859342991888DC47F12A2E7522B62B1845A123723639593543CAFCDE6D9FCB2547746C2A7DE5182FAFA8BE1C794E8E1C968B70C3BBD84899AAD7A2231706C108406A7BDD6931A70BE7441B57E70AC353B9E8127DED14FEEEA41124F0AB57C6A0A857E022BF717439A11919962445A480D18B2367AC9E483C3A0CA5C3AD667E7A1EEA7D50335950997959333169F8E76E07B051A89B1755AAED4C49E0532E9D0DF5C9AF99EDFEA49B83AF8147440CF93C4056551873EA11887DD9FCDEF04F7CF1F5EEC712B1E70124C6155975ED419F206F5C16C3D7CBB13321599A4DAB457848974B74087DCBBE990542FB6F7F36D22469E3F68EC189893452D6F4EB180E9A2D1D1F010524A1F501F8DE4C484B35E47E517E166D1F9394DC6CB394C1FB1DB6685F07ACD0D25AA4CA1E3BAE21588A5C9B4D229A4C399854EAB3AF379E3D4456102F021019A8097B06CCC6B6FF912158C3DDD27DE33AC093EE6EE76CA9F8A90C2AA8E07A61221FD9DDB6EF440D6DAB8FCC2138B396BA43DB70CDFC90031F424D4C917F4F4C04D6B7ED87FD103FD195F39C755500B8C4120CB62D3818680EFD3564D5626D6486FBF8CF96C3C179AE85E573D1CF858252DCAFDB03DDCA86FCC65DF85E5A10AB4C549E1289FA57EDB1B2899469701678810BC8E709563B4F99AC7943684F4C56056E26C788B3C8E87DEB10319D56A52B3D25CC491C6771496F4A94E5A67FA60777E899945E2F58C9D7D5759CE41733E6845D6247812B11336062C88FEE525C44EE8F73EB1A0BD66CC64330356C7F2DEA6D3465E2C6EF0505AC68502165F1701FD40E0D5F7DC41583C076A81E56775034124910BCEFF7DDE4A2FA0072D6A6BE8695A8440BCBCEE4A3FE9ABE0F0440A9090ADDC40915D2D33D88F1489888729BA0FD0433828257C44E0C4D46E9EC6C9586D5BA3B9D772ED20BAE620E8D4619E9C720632FC92E153D7068E67A6BEEE16A01731EDD5AA48DE29B083820DE5B1171BAF4E75262353CECF8E2C2174E530D4E3B84F12F2729CBEDB10B62902ED39156C32E2C68C7EEACD2DE88C50E9F6BC117707A0E931311EAC9F836CF4DBD7DC289ADCD4E8A536DD3C7C5DB082FEB4BAFB6B7A48FF9C129CE97FDEEE396502319F6CCEB8B5FA38478DF2C0619CC74E43BC22992A526968AFA9D147CF6A2828ACCCE98A97BB63AF3576670C5B61EB5EF7D30BE747E1668C6CF3226B5DFC8FEA39E9D1648003AF4EF2EA6DF3171F7C2230B9717939EC70E53CD9230BA1E77A1C07D4E6A3CA26455CA7B8B6096C49DDA4A9BFBB2E03C3B6F5D6EAF4C78B87FAFAA5B82C0CF7321F5B8B1D9FE67E765A2C073C844174A21E9E8E16656C0D3D888BE6EA17CD1827AAED796B716DB2B23473472A574BFDDCE1D9F92E179FFA2231E75D63DD2834C792211B4AF030FD4010DDFBA1109F1292C3063A65F612A6B40849717C6B35176A42FC5DE4EAF90943B398357AC5ADECB7E77F460732B712CB0EE509D880E2B6419C2E365EEB36477BBB110240F3B20A66CB39722E9986997642396316E7A23532B2D75389B4E39EA49DF5EE29FBB5EE6E0B4035CABC3ACBA0D85AA7214553A9E3ACA04C0C8B800495220A8E0BCE1D0EB6E650EA0FD8334FE24C5DB224F5CE49490F0EB8246183F844705CD75CFDA3CEC386BB2EEB63F14BA4BD86465C25C97DEECA55D14803EE1ACF6968D8820474F86554CF8A1DDA9209CD5162B158031020277870B55FB8BF5B7A961238546E8BC5FBEFCF4E004413AD9FF4671CBEFDC08EDDEA1690D37D29786157C2856D3A2D3D2AFA5CAA4AEA82A0906A4EBF88E661BAE0A1048687AA1A8ADAE0D1A1D4349526DD40A3A3C667791DBFC13344A6568B2B6BBC6DFF3F81C42638E8FE8F1396B8AA800000000000000091119252C30""") + ) + }; + + // Only three are expected to pass, so I repeat to get 10. + static SigVerTestCase[] SigVerTestCases65 = new SigVerTestCase[] { + new SigVerTestCase( + TestUtils.hexDecode(""" +6C9E7A1EE36625760E5D2F33DF2929DA56203234069160E5F2BF039C11062273073C237566CE055D871F38ACD1A9859A824467F19BE68E4F00645D225C42C85A557D2C5ECB442B0F028A6528898EE2B673D863F32EB9EC8164127541F32519BB88E034A03F46F7D193CD3DFBADF63557926C5C8F5B766A7FC5EC8B3F948BF7A821B54C9441AB0BD833FD6354CEC706FAA500ABB5289B90B1BF917677A29D115F0094BDB48DC72E261DBA120BA6FF5E52A01B178981DD8296444656D9442DF9CBB6BFDAE56A230F6F29F94CDCC265576AA8752ACED07E99895CAEF0168BF83D23FDADFBB928CBCDABA25FE2CD26ADDFB0DACD74940F351426942F176FFBC5F3456DB7C912AA16B86D0745F87C9F45370A8456A1ADB51DB4052B5C9EAF60AD7B80A42EA4BF92C841273AD761DEDB0D34BF579600B149FCCD42AB1549BA0ABEDA57EF71D1FCA5702AAD083299BB98300189C25F3B270A87658D0B2EA56524147F739EB6C676D7BE73DD3B95B10C55AB46FD01549C5168BF7DA13A499785F35A1E3B56F4C567F54EA9AA2817A336383643FA2EA31FB1B73E10248DFCA05C04131266498E1C9491135A50E63D02FADF4165FC9E15E3E1B32FAB8337684C49193E1BC4EDEAE373A267A714AC1F909CC657CD8066646327E0EEA041AC9F2AEFFC80691BF60D3C94C642557E4299D395922216C65E75B7E1A5028960384BF816C9F7054829E7985B5841A733F33FCE2455EFC89BAE84B47990E8D0AFC6193E4AF9BC680AE24FE591E88BA6A2AE12DA3858D21F492D24ABC4FE4FD52D5ABF24BD254687B918792F0A003A5222DF45038685C725CE7579E02CB168BBC666ABF669856E10537C9291692C0CB0CFA906270AC2C7B7DC31D4F9283CB2DB8A462AEC0B9807BBF4AB4576FEC6226B4179322B67AEA53BDDF9C9BE5E0DBC43F78743068AB5BE49F0E62F8E2EB1B6C6736C05C9413D065CE0CCB790548041D7E832881A839B5729AF94AB79FD8A16DFFF78CAAA141D97CC0650F86262F26159BE8B361A4A041E9A0B6511BBE3355A4BF57AC09848847EE0243C3BA774776F7E9A227275D74E6E3101D382818763ED1E1353AB9EECCD920CD28922D559A4048F40F062164CB661C4F4AFA81A3D55933C4791EDDAA3939E5AC342B0AD1F438A532C6CE786681A870D94EC88A334CCEFC6ACE7D988A1A82BC0ACCE785F123BE23A7C92AF108E5ED4F0869E22DAE273556D1DE386623A6C3F115BBD119271D3FBA796F618B53959FB98012E7D5B9AC688940B87E2C9C065524A00D3A4F4DBF52F4B1A63EF5C46193BADF7AD7F988D4464345B2C3E549684F2F905F6F89DD641473EC05108A52D8DBB91768C541DE520B17666970AAEB506E75D8EE9F4B4455B71E0088AB25655213B75859D25F559D3C324D283D397ABE6F0AAA386815768D03357D775964902413153E3560CCEF1FD44B65FF1B287A92A9693F034B7EE668934702D7501CAF6DA4EE98AF4E8E64B0340E0BB8BDC533B0EFEE1915A4B68B93C5E95321EEDC234AEFE71AE2E5DACEC2F52F83723A2392A7F8E13BC0301CD104D852E62A7F828AD329B3D9596C58E13FCC0ED96C1C48D82A2C0F4D9D24DD8421FDCCEFD497A9B05FFC50904770401373FEE7DC73773418AEB4A1F599A4BB38EDE8D10A3CC83A1C72DE921969E3CE3E8EF2F7DA89D344C80D61CF9C5A423B1A4F3567D96DB2DA3DB9B5B5FA68156BE7452C8A0181BB9F0DC75CD9750883D0DDAE53FC156D67A74200869046B41DF4BC4396993C08AA4897A0BDDEFB55F69CC1C4D7B5FB150408427B416F73183F2B3CC16E3B7DA63CEE1143ADA1A056626A077B6D21C3DD974ED907C5A094019225737EFB93319AD3B40A4F434AE49D28391C17A999C744A68C55A91B862729583D3DA46EE70C5CC461694167D32D21DE75327732C63BBFBD7B30DBF2057A0D681519F6E4AF608D4BCD0B4750726770E156AEDE85417BD759D5FFE401CB2996F34434DB428D9A417037201FCD260FAA98084502EED5C27A8916E44F5929819D21A69CE16BCDC3CC8141E285EF897B1402C15C952590119051E369A1B7BE443FEAE6E32BC8F3D647FC5315A5200CD5238DC6677466EA86EF8D18E5A79F262483E896B8277C741F516FC040C1090F2495BF1650B02AF30456733A071AF47D7A15BD8E32A49806455D3BEA74AEF5D00906AD2F0C045354EFDE7C9A276E73D9EDD11D1CA5C297B9A6851E7F67E21EB061BB55D9E673C4A75FEB84D52629EECC53C24BEA95153051AC206C87DF55410CA1FE6CFC3F403A6D9D43EA84C60C945E642B2836338B5AF9F69E52708B2E225933DB320BB3F790D397F22D7B6F8A433CDACE9810AA0E27C699555530C562DBF7517A4162628BF10D1B6DBACEF5C9ED51E55D9A89D60E0FC378C47A21D5E0F2DC3BCEF5E05C6E0261530FB027E5032558CA2B47005BDDE99909930391EAD7F3F0A96B3DEDA54A11145F530E51DEF892E5AB0204D614E6E38AFE79CA92C28158D570120353B7A4DE0889846D835294939557ED0AEDA270D4D73ED84D3D49F9F032D43457BF59BB7D66359DC53F9B46963B21784B06CBCF04BEC1E33A33371532716C9EDB3FBEDB81999B4372D0945C10AE826C60FFE93170B6D294B3891B0D2A7B35B28A8971845DC2FECE237B80F20B379CC4D136DAB3FBB3792C63EC61F5C755BC9DB35086FBF46D2B7970DCA2A8523FDB4C7A0B8E42F8AF9ACAD2A0EFC113602A4EA62E4EBB7D269C3A40BA2C44EDD2956"""), + TestUtils.hexDecode(""" +C4F59FA2DE30C8420A7E7F096BAF6AD69B1C15A5C6E61C9D82AFCFDB6EB8F275BF5787186AAE781F487F9F88758C9C61F35D5083EE70424B0D0A51575010C2A907F49608115D33EBA0031509322AA7D3061FEC3162F96A565F98769E9A19235D89D1B21D60A381DF8EB37D58C6A2E483A8EB70736E4B7BB911F7AB923DC29F1E"""), + TestUtils.hexDecode(""" +E895DB64C57BC3C2A97F0EC933410E98F6216103E3423CAF06A671964C514A694EB6F65CBD1137CCCF8881FA403C5FA0E0B2F36B9F4009C378210D29E54A7A5A9B793197CD6D2F38D7E1F3ACA69D48881389381C89FA676DE426D634F9A157055F17283ECE8248CAF14DCF11E2D56355B047DF632A18482E79CB2D5A743966BAA8A76121BB69C2E68155ACCB0A31DA6EDC73CB09A9E660FEB20F66C7BD967ADE32149C5552EAEB2EA175B56233F3B370EDD8679269CE0D2B43F6B2F65FE957E7AB37B982043754EAC8A30B36C10004EF13C692E219AA7AF0A4C5286910C7100DA41E17BBEF2DA2AB03ADF3074BA1DA15BCC84805B89B9DA88E9B400AFB7E3BC8338D354DA953AC0BAD822756CA92E5DD9507F42BFEFCCB32B4B91A2BE5EF34C2CF1177EAAFB250AC9ADEC4BE71807589F1003227F9B76B74E07BA67AC60819B2AF766A47FFFC7B76D3A7C077F5EC69AEEA3E963859B82C2ADE58BEC2152EC8205110975D37C6505E0DC776FDE071097E93013D1004F4E1A2FD79B877ED5025F527F3BFF137F041BB9BD001E949F08B4CF88DFD32FC7CDBCECCFDB0FA2DE7823E110BCFF58A412CEA2795753E9C89678C3AE24268F7489F72974B6955EDD04E190D99BB0D7A252FAD5BBA606C1A1F3ACA733BFAE3309EA0A6EB7D07E36D8CA336D2644FCE1A41895D014D1A60CB106F3F8075F9378461738D63D115D00B024C677801050A1B0B50DE057F85DB6AEB2C9D6BB7402A66E3AB4DB05C58BBDA12F695958B8AC7B4E45EC6C952F679C1EEBDF860E348982779AA6988EFC2AD1DC1EAE22A27A5B2C61C97B3B2493CB6C13C5F6E20A67B88D3C3ACCFAF0A425742DF240634D1EE593828FE6297446C076F979055988AB834B2BD82E14DC086400E1C956CC0C30CE7BFD962223D23FE9494964A811B93E8D7B8F34C89AAD45DD4113F2AE7BD94B53FC86E8B2AE82E51EC6F3EA4C30D60B86072748612D1607056B5FF6A4500EEE78A5A639C7B74169777626864DD9EAEF0E3AD8493D831F71DEA95BBFCF81423A266DE56F3A8FE8E6C3C0D612FB62BD642188CA71CB89834F30BCC28BD178845F1F6F46C03D306F7ED4E68759427AEC2701198C3C05D385DFAFD528CCE8425BC551469A0ED681BEE4D12A843E333B5A8E0517FC61906F9C4E7809BAED4D3D16EB22F1FA9AB402D988ED59F9FED0455E9260FD627A24A17FE7CB63E530B48F5FB6687A2E8C49DA79FBD69A3400056665DD11D19A2BC4DB1D374AB6A6E42472A27AC6B98F676E8EDAADD514F6D44DEECDAB5A6DFA0F84F139A803A2524BF335DC52EA58FA50D98FB5CD55D5D50A663CF647EEE56FE8E664B3BCAF9E333978A7946973FD113E4FD3924E6C09E60386444214DFA7A4D671FC23890637EB859134D79E265C59CA3ECCDDFA018223C9BAE1CCA103962078BC5F0DD02246FA28324F7CB2FCFAD07C25B4BC2D888069B0CF5F23C761C0E47109881CD31456A64B940B4BB9B4C2C3B8E6BA834AAAE69FDFC47D44B3C96887ABED36015E7B64E8542928F277CBD2D3C512C24DEEFE590E81C684E063E7AADCF117B48943DB771FC2207F57A745357555D419C9CDCA35CC1A7100A6913A3B6AACF796FE3F94DD2F818982716CE0316542A1B957E12DA43E231542CC14FCC66D728A68326B2BC311248330F3E98F81EA38CA924A8E4DA97CF673842C759F935BE88163CE97FE4D9457176F5B8908AF948F74D5D1DDBC521825D931C63CA8A8E12242626305AB6A2E0624564EE041983C18C2952EC3D9D159BDE3985CF77897EE2DC888112721D4854E914A5397E08B54F4A54323FF820821BE026EA091ECA6B7D80D91E3DCA2EF7848B86FCA6BB40CE48271E1008368E3EBB5E395E1CCD0D178F1A6257D26B6BA4B7CE532CAA1E76CE28FA4CF9E029E2482B94D3ACF97A326D235D1BDC89F70002198451D9F1F12CCD5BCAECDDE9E14AC80742EB31E6464C83210A39F35098BE0378D074CE1CCD1EBC1C7770F778D605F2BE59DB7EA07D80CCDF55F16E985B142FB7BDA07AA7DCA5B201E1950CF9A728F21E9A9D8AC4D1327E3BC0FF339A250522F631DF2E75955154893E4A1AAF9866FEE1637EE1AA5106D244E99E6F31FC5601BB7B79BAD82860B1D6059D9B132E026418020DB06EB8391FA15B7A0F29E36D966ABD3D2A2FF3F2AAC34C8B45C7D2355EDBB80B224BC106EBC6750E55070F85A7CB6003394E5161AE26F5ABF83F0DCCCF69B86139AF8694FE1DC00781EAE09CDB421814878043DC9B0530E5545A165E39A9B7DE88B4AD2AEB90D3C329412ED2FE1D97B732C8439DF4F83D228835B538DC278FF0A2DC42F41B00CE3ACA06B05C4839B896931515D78EA3673A378279F4E89CE08E3453FF2FB453BE031C6318628A731D029FC7BEA2BA5EAC4916278B938A6A6ACEF5BFE2158F2AF43D8E56A0649DF28A250D2F2536ABDE1E008EB631F4BD0EB55573A40539A6004181A9D2BF7A1E53504F11E014840733844131AC668946E5B827289AB6B21366C5D0E2649219B92C4760DFB705F7F61A96564C9E840D14B0BB0DA82DA50F8B8E752BBFEA3B0A337BE124F72D8F8249195BC19C3E0B62EAE496D38CF7500B4F10665FC2D28B9EA935F7E316472F4FF401267541BDB62301554B2009928C6445BBD0EF21D09972F35081ABA9091A6C23FED29F5CF9E0779F7EFBAD88E62A454442B30079BE0AC9C64826B98C1E1001CB0FB0F0A95F7965FE9312BFDAEC33F95065C8E59D3950F80ADC7FB334F202D3E5F8DA481C9B54A75983930FD1E5ACD16284F07193FBCB50D0DC00EFF8203144C11EC61420FC32D7982CE896406BE769A75DD8D3CAC753ABE5A278655BF54BE33A1B8374EBEEFF212C39CE514668F1C456EAA2532828C84293F1A5BC9EB5DEDF558A9B4C1239F77272C67E1AB28E1EFEC5893E09C10662B53C8B8255B1C8DC8F8E5120A25C75EEFE79C43F7A8B37DF9D1E4F32486933DA1CB0664C5DB39E21BC227B0CDFE7A5507F07F218A7A47DEBCD9DAD7247B4D045A13AD4F75EAD2D45C339D0DF04577F2E0FDC780392553033C738852B1BE4E63EA3897D6C9C4B11AD6B58D3E2D342D32840F649DD83E759866B7381A84C8ADDDF413FAE18E6431B1EEA73A56CD889B76BC9786BEDEDCA2541E4C9B24E28F58AD374C1D93DF2D3F2C37EC594A0498C574579A7332F72C0F9750877FAD5B90B968D88F11682C4071E4EA38B816AEAD6BE54D2F371324F2475B862C75424ECF9858AA4E200CFBA412D7E3E6C308D8DE11DD185331AF9D41AFE8879965D6746EF21FD98D3ED3806FB5C4619C98E347D76B8B89849395561EE286DFDFC6A04E1D47E9F5B5B49257784C39364DFA88AD630DFA59CCA3237F4A2B141A813D22C6FFE73C2D99ADC824D93E06A54B6DE62C3125D94B49E950DEC361F961F56D3671C9925377F6E670665322B8489E833D3830ECCDD0F53F4A4F9D68F1445F3AED5C9D766409B59BAE7A72912E98B3BB57342D29B6ACFD14336B7B8B6B7549AF8CC8845E10C2811287281985D5D47685FC589F2678ED893F57B85ACED75632E50DE5E074E6CEDCF1AD499BCE67A7F498564DEEC677C708388DE8FD7B099CFC116096C45FE28890B5EAF06169939FDA35E1215F238E8CDEDFE670065F5DE3272A232FD53C250F5D779B31694FBA91B554803676E4DEA288463FE1063009E9CB76C317DB400ACF4D2D2B6D16EDEBA4108913F60AEB252CDE413690CEEFDCFA638963DBD04F4CF21AD74DDE65F0F1E7CE70AF101A6DE9A59DB21D38027DBBF76167827950B69418266AFA444C728DE3624A1C81E5B1641DBE879CD822FB2303CC3A9FCEEFE3DDF7DBD0B7057248A28D6062D76EB13B92C9C9D003B69E1842A54C09CF6B484520815E2BB237288C64FC696FD3BC45DB30CB86465DF1188BF47956E5B916A8009715CC9A9A6DCE44C54F928816B41D018C5FE652FFE4E33F352D383A9C1365F02ABFD647BD6B42AD163730F8BFDA1E2BE5F614D79597825BA09F457D3CBE7561E7E89EAF059E977D1EE88848B781F21F723890FF1F9873928412C8F11EEDD2C0C39C9512790986A19E17B2B70A4D7CF49D9D18CAA0C2023134CACD169200D8817FA321F04ACC910613DFF250EB325DBEF29EB5611B2AD2A23EDD538049B3F43EFEB4D60983792B4BF05567944AADB7AC4D3A5D80A1B9D8448B4C0C115C3B5AD3885353F47D5FCB9B7D6446F1A7210BBC667FC411415F23CD40A2A3D64061D71C67191571A97D01088A24B6711567FC89106732D8892FF985B8E6CF70163829CC085BE4E408315361BB1B2003D6413220B134506D3C304C0BBBA9C9C45D3651E0571B6B115177213D8595E143DB90BD72F7EB974D8D0A0317409D64D5837EAEC9B8D44DD7ECFF6CDA9F729382A43B379CBDD43FFB18AEA35C1A996CEF1488D3B7A81EE7CFC0B9623418AB3919A6EDDB99F222F0DDDB2F32A20C8F84FBF4C49B4CB3EB50D9C4CD25A6F7175467066D25E6437B67F2DBC70C2E6EB0BDE2386D03014A789FB6DC08EE33C0C67951DA9D74B9C94845D2A99037E095FEF7919920FE526EB5DD0BA1F97DFBD2DDC31609C1B7B45EC3ADB586FE3030A0C7A9DD034A3C2E6F9849093CEE10A181953547F8BE328720A4A5A8290B5EE00000000000000000000000000000000000000000000060B10181A21""") + ), + new SigVerTestCase( + TestUtils.hexDecode(""" +6C9E7A1EE36625760E5D2F33DF2929DA56203234069160E5F2BF039C11062273073C237566CE055D871F38ACD1A9859A824467F19BE68E4F00645D225C42C85A557D2C5ECB442B0F028A6528898EE2B673D863F32EB9EC8164127541F32519BB88E034A03F46F7D193CD3DFBADF63557926C5C8F5B766A7FC5EC8B3F948BF7A821B54C9441AB0BD833FD6354CEC706FAA500ABB5289B90B1BF917677A29D115F0094BDB48DC72E261DBA120BA6FF5E52A01B178981DD8296444656D9442DF9CBB6BFDAE56A230F6F29F94CDCC265576AA8752ACED07E99895CAEF0168BF83D23FDADFBB928CBCDABA25FE2CD26ADDFB0DACD74940F351426942F176FFBC5F3456DB7C912AA16B86D0745F87C9F45370A8456A1ADB51DB4052B5C9EAF60AD7B80A42EA4BF92C841273AD761DEDB0D34BF579600B149FCCD42AB1549BA0ABEDA57EF71D1FCA5702AAD083299BB98300189C25F3B270A87658D0B2EA56524147F739EB6C676D7BE73DD3B95B10C55AB46FD01549C5168BF7DA13A499785F35A1E3B56F4C567F54EA9AA2817A336383643FA2EA31FB1B73E10248DFCA05C04131266498E1C9491135A50E63D02FADF4165FC9E15E3E1B32FAB8337684C49193E1BC4EDEAE373A267A714AC1F909CC657CD8066646327E0EEA041AC9F2AEFFC80691BF60D3C94C642557E4299D395922216C65E75B7E1A5028960384BF816C9F7054829E7985B5841A733F33FCE2455EFC89BAE84B47990E8D0AFC6193E4AF9BC680AE24FE591E88BA6A2AE12DA3858D21F492D24ABC4FE4FD52D5ABF24BD254687B918792F0A003A5222DF45038685C725CE7579E02CB168BBC666ABF669856E10537C9291692C0CB0CFA906270AC2C7B7DC31D4F9283CB2DB8A462AEC0B9807BBF4AB4576FEC6226B4179322B67AEA53BDDF9C9BE5E0DBC43F78743068AB5BE49F0E62F8E2EB1B6C6736C05C9413D065CE0CCB790548041D7E832881A839B5729AF94AB79FD8A16DFFF78CAAA141D97CC0650F86262F26159BE8B361A4A041E9A0B6511BBE3355A4BF57AC09848847EE0243C3BA774776F7E9A227275D74E6E3101D382818763ED1E1353AB9EECCD920CD28922D559A4048F40F062164CB661C4F4AFA81A3D55933C4791EDDAA3939E5AC342B0AD1F438A532C6CE786681A870D94EC88A334CCEFC6ACE7D988A1A82BC0ACCE785F123BE23A7C92AF108E5ED4F0869E22DAE273556D1DE386623A6C3F115BBD119271D3FBA796F618B53959FB98012E7D5B9AC688940B87E2C9C065524A00D3A4F4DBF52F4B1A63EF5C46193BADF7AD7F988D4464345B2C3E549684F2F905F6F89DD641473EC05108A52D8DBB91768C541DE520B17666970AAEB506E75D8EE9F4B4455B71E0088AB25655213B75859D25F559D3C324D283D397ABE6F0AAA386815768D03357D775964902413153E3560CCEF1FD44B65FF1B287A92A9693F034B7EE668934702D7501CAF6DA4EE98AF4E8E64B0340E0BB8BDC533B0EFEE1915A4B68B93C5E95321EEDC234AEFE71AE2E5DACEC2F52F83723A2392A7F8E13BC0301CD104D852E62A7F828AD329B3D9596C58E13FCC0ED96C1C48D82A2C0F4D9D24DD8421FDCCEFD497A9B05FFC50904770401373FEE7DC73773418AEB4A1F599A4BB38EDE8D10A3CC83A1C72DE921969E3CE3E8EF2F7DA89D344C80D61CF9C5A423B1A4F3567D96DB2DA3DB9B5B5FA68156BE7452C8A0181BB9F0DC75CD9750883D0DDAE53FC156D67A74200869046B41DF4BC4396993C08AA4897A0BDDEFB55F69CC1C4D7B5FB150408427B416F73183F2B3CC16E3B7DA63CEE1143ADA1A056626A077B6D21C3DD974ED907C5A094019225737EFB93319AD3B40A4F434AE49D28391C17A999C744A68C55A91B862729583D3DA46EE70C5CC461694167D32D21DE75327732C63BBFBD7B30DBF2057A0D681519F6E4AF608D4BCD0B4750726770E156AEDE85417BD759D5FFE401CB2996F34434DB428D9A417037201FCD260FAA98084502EED5C27A8916E44F5929819D21A69CE16BCDC3CC8141E285EF897B1402C15C952590119051E369A1B7BE443FEAE6E32BC8F3D647FC5315A5200CD5238DC6677466EA86EF8D18E5A79F262483E896B8277C741F516FC040C1090F2495BF1650B02AF30456733A071AF47D7A15BD8E32A49806455D3BEA74AEF5D00906AD2F0C045354EFDE7C9A276E73D9EDD11D1CA5C297B9A6851E7F67E21EB061BB55D9E673C4A75FEB84D52629EECC53C24BEA95153051AC206C87DF55410CA1FE6CFC3F403A6D9D43EA84C60C945E642B2836338B5AF9F69E52708B2E225933DB320BB3F790D397F22D7B6F8A433CDACE9810AA0E27C699555530C562DBF7517A4162628BF10D1B6DBACEF5C9ED51E55D9A89D60E0FC378C47A21D5E0F2DC3BCEF5E05C6E0261530FB027E5032558CA2B47005BDDE99909930391EAD7F3F0A96B3DEDA54A11145F530E51DEF892E5AB0204D614E6E38AFE79CA92C28158D570120353B7A4DE0889846D835294939557ED0AEDA270D4D73ED84D3D49F9F032D43457BF59BB7D66359DC53F9B46963B21784B06CBCF04BEC1E33A33371532716C9EDB3FBEDB81999B4372D0945C10AE826C60FFE93170B6D294B3891B0D2A7B35B28A8971845DC2FECE237B80F20B379CC4D136DAB3FBB3792C63EC61F5C755BC9DB35086FBF46D2B7970DCA2A8523FDB4C7A0B8E42F8AF9ACAD2A0EFC113602A4EA62E4EBB7D269C3A40BA2C44EDD2956"""), + TestUtils.hexDecode(""" +C1E665BF7B8BD0198F069CA17EFC55B7EBBF9CC9D41140BDD0B83AA08062FFC717D3F6C22DF38EEFAA6EEC91760CAE0B3DFEAB78B03A7AB7A993B2097B7B887B9812AE2D0892B696374C034FC9E95083C2B61B09DE97D9C500FE55E489C53CAEBDB57BC69071C15808890F8A007BB5FE773CCFB729463113D93E9EC9EABE2047"""), + TestUtils.hexDecode(""" +051F8A9A5DC6D35B1485288359F818DEB027E1231DA8C048E79E9FE228AA0E9F1C0B7F4C573B5DB8CCAEBBAE8EE38D8FAEFD3B8E7730BDC0E9DE365B20E5A0F9635A0B39C7C0D6163B7876ECC6ABCD8A5F608E7253537C1C94C209C8448E02806B2B5EAFAE2483170B4E4450380C2A87A51F82B179EE0F46509404A3A9BD74D04BD75635B797B500F656ACAE5DD76B04741792112579E24081A6C88BF4981346E2B3D38291026D3AE47BDA50AB0B23B0881148489CBD057CDE9A4F6FF108B7ECCEA44D599CE3ADED82AE0E8F74DB7D604161C8664B7389497EC9F35C46FEC064BB867E867E9309C10FBC07BD5E7B8A74BBEBC1BD0E4A9B36EFE297E9F2D23DE32ED704EAA377F5C3BC4BABCCAD5B4B6B9A137F23C46C0423ABA3F1AFF00C6071CBA51B7D0A8E677F5138DB7C013CAEE1F68501430F0F448AB283692A18D15D8A46BA620EA906A3032570A659F594236F0512389E1DE63B8E40AC22DB79DE60CCB9BCF0B20EBEF676A91AABCD01D3AF882931AFF8C86A8C946E09B8B5CFDE62D53A03DF07163B081B293EA0287AEB97D1762F34361DDE654D400DFAE5B351D90742A0A269865D49C9221DD89E42FFA63EDDF449B10458CFE2EA7E1A16BD22FE73F208B4472DA8094F28CB9DCAED6E843C57E9E3258BEADA48D7761FDE0104AC6F0CE09F95E1F4AFF00515AC2E3703D2FC6D757B12DFDC044E854E50FF2D897900B0B59BED90BA4201694E29E6A830D8039CD835C706EF59E7A6B0ACA7B7D0B40D264661711E0372BAB7410A74460D07FA988A8617D31074950838411037307B052FD536822608F9D15BAA780AFAE1A8D87BF844D3A4FB31A176BBCBEA46A72BA990FCF821AC3A73ACA01E09A20AB93FC737ED4C4DC482BF9BA21D7178D24DD5D6A29633386933A3E8F28982731F07606AF28BD2D81004B044B4EAAE67E29840BC78EA66FF840031D8B2894B603733E1A0398FB0E4952B2ABC567668443581C860F87A76774E6742807C39FE99269E3199DAD02B246D7AC24E5BD9DD91F7D16A76E72318882FA21672A7D5B1A4F212954BE2B19897243F60C18D1DED2AFDF69DAB8C9B10342471C633B33C52E95A85D3142F2E46C681AF373C5E92BC948FBD31207F015DD32DE2591DF4639E4E563344D440653592EF2685E1320AB9E51837F6C06D07E5462599FC6F8BB120826E738E2223CD4B8C7CE446ECE681DC6D6BEF1D6385B0AE7E404F502B87989D969B81CF42085A7B58A41EF73EDC73056DA72EF65A7AC8E284E7F51E723102CFEF903688F870CEF1C7E5264330E3033691680050E926E93A1C0C4161A7DCA14A0FF338D431D68FAC204DA28CCD1CE7BA3B7F3C45B4FC74D9E754A1A2F7F23F0FBE8D2FF01CE4683D8842E8A1528589E7D9260368A654CB514A85DA9C2EAB74C66FA17FDFB256D585D28C1DBA35E18779D7B6DB876CC0A98CFF752A0E8DFDD532ECB04C4101AF32E689D13874B9F20AF652069C1458D7FB382E317AF49083B5870078B39221464F376EC0BC2DC1C3FAF10EA4EA87A2F9D547B535F60406E8E68AD190CD4F00EFDCD9D54D4810F31B9F68F0D95E32CDF2747B9C20FCD1694FE034EF6B5460F163AC78BA235A441DB2B3AE84BC28CEEED7B3FC2A4D63330D14186658788DFD7652E477B1310317C86921394219D75FB6FC319575745589F9E2096801E57E6AED2369FE115C2D937EBEA3602194B7432B01F55E6C9572CD0FF8BE8A4796815914D5F64D93E0E709C3CF88741C851C8BFC4CCE6F0AE60A6D2F4DC6FD8AFC82E065956971FB8B4160AD68EF7BFCB3A9694CC7EDEF64FF08011B183BEB7A2D3D9024753B59900D27F52DF6D4B2576BABA673A0E33CC57B501E1C74F63A988E1A157078FA8B3F2A143CC9D41A35412B4E0CE6B1D9CFAE7470BF4C778D026A9AF86DF7F974E2414FD7C5F0FF6D62293C6E2A62D4C5268CD0B604047C9658F97D9A7B86E1C953FFF95CB478028FDCAE6E8F208AA208A282446B2CE8B4C7E893E269FA8E02C082F82966A4AE3FD86BE89A8CC8BB3D6B105A91DCF76FEF700E5AA4A15BA0F753129D3369915D7E896527CF6E71C363EF65B2218A5FCB8D8FD96D6A63A8BC547EFC942DCE1276E268841BA00E35769B4AC706BD65B275BABDD530771D854EC38AC0529729786A86C7C4161B3E7074023516C84B4B4776AC47C2ED1587861126A7A707978F2B2B2972C20F237FC223B56A67538F9241D926DB7C992A3FDFDF999884EF83EAC7DA0F6523F53CD40E473AD370C77B30DB2FE408783D24CF4C3512E3C6B677C41A67849FA1792313581EBBDB7BE0BB3EE85330FED8B5A1915F6343F3B7C928CD363463385436038B64BAB5D055BC39D18F9A1A8196AF8DDA5A1F428434958F5C89F07D7A53CFF2118E80060C5ACA71975C4C92A589EBF5746AC92C50FC1F915C146C2DEE7531B24970790A4AA7DAC425940AFC4C88ABEB998D549681C95ACBE9F7E274521D44E9EB759C2946504161AE7FFEDAD3E62D045AD77FE8C2B8ED529843DD341E2E50559A29AE26D431C9634C4C19A84FA0257F71CDF27C33F14D57347BE8B19D254E3C353CDCA10489F06214161AEB2A9D3049B3CE4689503621C46D192C1421B4B033775D9218DD2E216600E64D977CAB0E1675666A7CA773E4E139DD4EBE94CE35A28284755C52BE490514B25FFCA4174F54E8A5F715F924949C1467A282D7F2DB468DF363F9A55E5D7858D8F95D8083D6A594DC1B07A8C4FD4AAAEA0785EA3D9B50798F0A96AA386F17C2BFB94FA8EA3B5EF71012AF9285CADB1FE330A267555A942682F9333AF2E81515969B76FDC020F9CD29E848B94F26F4B53CA5144CBCDA1AB6CD2FACBAB0A2FC0F5B88DA0AC0EC08B9EDA7CAEF502FDA52006815743520F841CFEC3B4D9AA732DE408D6FB14739E8FE77CDDB68A5F6AA215B588F1491988B4460F6949AD647DE9105CA50CFB413A971BC8E6179F0724FC28D1A7D30C41180735F4FF6167810D9E88A5F7FDF791BFB474BB5478544EA74C9F07598D038CBBA17B83228A18B2AB09A8BBD2D2205EECDF01044D5A1B2BD50D2C8E3D5511450A4E594C1CE7067A6E14128BBB36E95C143EE6A51CA0EEBDBE47E9C5A87E81BB904013DC892D03F483B1DC82986DCE7A6E10192E6743283202D78D11B2169602A75C2A688DBAD50C9FDF1A1A15A470D882ED4B5207E659A94776ABC3D3583E1D2E85291D3726E75B7AEF9344180D325583A05266C196ED367E906121C33E701D428B46865BF32AEA4A90262866A024209A7663EDA4C340B5AF3E899F009EEB5E8D5003635EED501CC02D5D11F504C823C17E961D0BF611519961BF422647D97119F5745478888BCCE367639772953C5731434B28913F3F709AF455053F6B09519AEB6B755CB02CE74DD814714A2E0B477C05202092525EC03C5B365A75086E3281D4BB5C3AD9D742806E58B5CE4E1E95269AB18B68B2928BFCF7EA683967C0B88ADA99FF35E1D5A661CDFAD76774B42F858AA54626B88050D992FFDE16FAD3A8CA496CC6BE339977BE24D33E8BAB86B421F4BAA9C12A93117E43415929F0C4DBC9737EA5586780886A8EF4E4295DDBC967A2B5523FAEE0C060468F9704509C4CB14028E8A1672609A8CED43F1B06981FBFDFD52296D7BD3B4AE68E7D54BB2405799278AE29B66E258D3B9D276FD34E192BDE869092F6A7F761C6DDB0DE9454823256C7B17ABB91003B1A3B66CBCD4F9ED068409161635F6DF9459AC382044EC14FE8B2A586FE02C74232BBBF27800ECF627AD1C6ECC93C13EDA2DC20C8D6714C519D6A571E708787BF342DBCDE10EB1BCA5A7FCD971CA52BB68FB33ECB7F90AAF739F0C5B61BFED72CDB46A712DB6928F84892D3EC2F6C7023A6B664CE9CFDC33D2F09D38B5E4D182C73FF1D7B474C8AD6E883ABC78FEC75C8A390CEA561A86B92E2A4A1950997594C29A35E4A71B0E484FCDA63E5EC9666E0A463325DBCF7258D36B85099AB7C81E70FA66F1A471D4C1593AE68404F31AD2667017C9B5B3843FBC48D831F6A9B5FAF7C73A8478A7DADF28FBD9DDF979418870AE61E94C6BD47FF2C39073AAE16FF18B161B9B21413E66E489EF9F8784E5DCBBE29127B0C51A5C1E2A04E9C8794964D1823ACEB9ED0DD555964687848629EE06B0712483CA30D6D4A91E047EA33D30A062D8249278CDCBBA2A1B3C133D3E671FACB034AD0F9AA40628C0E2288B56F7A76DCDFEA762A8DB323B44925285557C3501999CBE145D15EA82169007A97EABABBE69479E03D40F2FE9217F14664726DCEA227107412B3CC742E4ED168E051D9AD4468131AB035708ABAD78659CCF5988F70680C124468CB80BD9924B0E41CB25AA69E7877CF5EA348403AD0899A5FCF35D4F22F3A73F0207E96785F4EB9AB93B6F10EE0B247D31F3D62A85B99C88CD3B19BB68E69C51AD5B0A8E9E34ED611E24FE2644F1697A8A11B64B578FEE1C5CB31A605CD987D765FB68D833E4BE9358D869F4DE0362E6889FBE8E95B861E078CE6CF0FF35768AD49803A71E8DC60296032E50A9D0A4E64A3D4661E7C55DAFC6FDD1B18EB1003D290BE486C520A2F8F0EFC1CD2CEFBF7E2459CC7BA88695D1122A7494A3A41C329EED2A8CD2282A607F93A2B7DADF0F32414C6BA9BEC0CB00000000000000000000000000000000000000000003090D101922""") + ), + new SigVerTestCase( + TestUtils.hexDecode(""" +6C9E7A1EE36625760E5D2F33DF2929DA56203234069160E5F2BF039C11062273073C237566CE055D871F38ACD1A9859A824467F19BE68E4F00645D225C42C85A557D2C5ECB442B0F028A6528898EE2B673D863F32EB9EC8164127541F32519BB88E034A03F46F7D193CD3DFBADF63557926C5C8F5B766A7FC5EC8B3F948BF7A821B54C9441AB0BD833FD6354CEC706FAA500ABB5289B90B1BF917677A29D115F0094BDB48DC72E261DBA120BA6FF5E52A01B178981DD8296444656D9442DF9CBB6BFDAE56A230F6F29F94CDCC265576AA8752ACED07E99895CAEF0168BF83D23FDADFBB928CBCDABA25FE2CD26ADDFB0DACD74940F351426942F176FFBC5F3456DB7C912AA16B86D0745F87C9F45370A8456A1ADB51DB4052B5C9EAF60AD7B80A42EA4BF92C841273AD761DEDB0D34BF579600B149FCCD42AB1549BA0ABEDA57EF71D1FCA5702AAD083299BB98300189C25F3B270A87658D0B2EA56524147F739EB6C676D7BE73DD3B95B10C55AB46FD01549C5168BF7DA13A499785F35A1E3B56F4C567F54EA9AA2817A336383643FA2EA31FB1B73E10248DFCA05C04131266498E1C9491135A50E63D02FADF4165FC9E15E3E1B32FAB8337684C49193E1BC4EDEAE373A267A714AC1F909CC657CD8066646327E0EEA041AC9F2AEFFC80691BF60D3C94C642557E4299D395922216C65E75B7E1A5028960384BF816C9F7054829E7985B5841A733F33FCE2455EFC89BAE84B47990E8D0AFC6193E4AF9BC680AE24FE591E88BA6A2AE12DA3858D21F492D24ABC4FE4FD52D5ABF24BD254687B918792F0A003A5222DF45038685C725CE7579E02CB168BBC666ABF669856E10537C9291692C0CB0CFA906270AC2C7B7DC31D4F9283CB2DB8A462AEC0B9807BBF4AB4576FEC6226B4179322B67AEA53BDDF9C9BE5E0DBC43F78743068AB5BE49F0E62F8E2EB1B6C6736C05C9413D065CE0CCB790548041D7E832881A839B5729AF94AB79FD8A16DFFF78CAAA141D97CC0650F86262F26159BE8B361A4A041E9A0B6511BBE3355A4BF57AC09848847EE0243C3BA774776F7E9A227275D74E6E3101D382818763ED1E1353AB9EECCD920CD28922D559A4048F40F062164CB661C4F4AFA81A3D55933C4791EDDAA3939E5AC342B0AD1F438A532C6CE786681A870D94EC88A334CCEFC6ACE7D988A1A82BC0ACCE785F123BE23A7C92AF108E5ED4F0869E22DAE273556D1DE386623A6C3F115BBD119271D3FBA796F618B53959FB98012E7D5B9AC688940B87E2C9C065524A00D3A4F4DBF52F4B1A63EF5C46193BADF7AD7F988D4464345B2C3E549684F2F905F6F89DD641473EC05108A52D8DBB91768C541DE520B17666970AAEB506E75D8EE9F4B4455B71E0088AB25655213B75859D25F559D3C324D283D397ABE6F0AAA386815768D03357D775964902413153E3560CCEF1FD44B65FF1B287A92A9693F034B7EE668934702D7501CAF6DA4EE98AF4E8E64B0340E0BB8BDC533B0EFEE1915A4B68B93C5E95321EEDC234AEFE71AE2E5DACEC2F52F83723A2392A7F8E13BC0301CD104D852E62A7F828AD329B3D9596C58E13FCC0ED96C1C48D82A2C0F4D9D24DD8421FDCCEFD497A9B05FFC50904770401373FEE7DC73773418AEB4A1F599A4BB38EDE8D10A3CC83A1C72DE921969E3CE3E8EF2F7DA89D344C80D61CF9C5A423B1A4F3567D96DB2DA3DB9B5B5FA68156BE7452C8A0181BB9F0DC75CD9750883D0DDAE53FC156D67A74200869046B41DF4BC4396993C08AA4897A0BDDEFB55F69CC1C4D7B5FB150408427B416F73183F2B3CC16E3B7DA63CEE1143ADA1A056626A077B6D21C3DD974ED907C5A094019225737EFB93319AD3B40A4F434AE49D28391C17A999C744A68C55A91B862729583D3DA46EE70C5CC461694167D32D21DE75327732C63BBFBD7B30DBF2057A0D681519F6E4AF608D4BCD0B4750726770E156AEDE85417BD759D5FFE401CB2996F34434DB428D9A417037201FCD260FAA98084502EED5C27A8916E44F5929819D21A69CE16BCDC3CC8141E285EF897B1402C15C952590119051E369A1B7BE443FEAE6E32BC8F3D647FC5315A5200CD5238DC6677466EA86EF8D18E5A79F262483E896B8277C741F516FC040C1090F2495BF1650B02AF30456733A071AF47D7A15BD8E32A49806455D3BEA74AEF5D00906AD2F0C045354EFDE7C9A276E73D9EDD11D1CA5C297B9A6851E7F67E21EB061BB55D9E673C4A75FEB84D52629EECC53C24BEA95153051AC206C87DF55410CA1FE6CFC3F403A6D9D43EA84C60C945E642B2836338B5AF9F69E52708B2E225933DB320BB3F790D397F22D7B6F8A433CDACE9810AA0E27C699555530C562DBF7517A4162628BF10D1B6DBACEF5C9ED51E55D9A89D60E0FC378C47A21D5E0F2DC3BCEF5E05C6E0261530FB027E5032558CA2B47005BDDE99909930391EAD7F3F0A96B3DEDA54A11145F530E51DEF892E5AB0204D614E6E38AFE79CA92C28158D570120353B7A4DE0889846D835294939557ED0AEDA270D4D73ED84D3D49F9F032D43457BF59BB7D66359DC53F9B46963B21784B06CBCF04BEC1E33A33371532716C9EDB3FBEDB81999B4372D0945C10AE826C60FFE93170B6D294B3891B0D2A7B35B28A8971845DC2FECE237B80F20B379CC4D136DAB3FBB3792C63EC61F5C755BC9DB35086FBF46D2B7970DCA2A8523FDB4C7A0B8E42F8AF9ACAD2A0EFC113602A4EA62E4EBB7D269C3A40BA2C44EDD2956"""), + TestUtils.hexDecode(""" +62C2A85A6AE40091AE35068EB3E5B54803F495D49BC177F7A29282DF0C900E86F66155B4026064E7D6CF7A171F8BBB33449232EB5D7DB2B776ABBACECCD660294C25196E19FADA35E0F3524D78EDA25D614FB56DBA5BAC10D06EAEDD9644DA291DF305C1E91C82FA00EC470A8E822525895113A6FF7D1D52E7038B9CF4DB2227"""), + TestUtils.hexDecode(""" +9B829A093EC253FF3D955EBA3C0FDA29CD14089C6D699F26FC62BCD40F43D1582F2B693138AACA59A162CEFBDA6328F1BD67690C63B903F5062DCDFFA840DC2DFD4051F82A557FFDAAE8F4A4FB340D6F4AF03A19AB928F42DFD29FF8D028333A0C336D253C826175C5A194C0441DAC1C5A4C4A3E0B8394E43678DC915BC98628BF565C9E751BF9801DD6AD4A3621B50C8DD1520F0CFE475F5BF843DC2568B263978587322FD1D2709ECD869A77F054C0A45D466D297ED9B63F10020826836F531A06DFBE20BFBA0B3F204033783C5505BD82DE732204917E3DA12316559D07366600CD18EE2A329AB3B20BB0C9C607D0660044D2A9ACC5D25806F89DFD5813C9E54E0CDFC190A206300FBC8E2561BF3F23D04052902E49CD5DA530A4D2BC2E5F47EE93D0588AA66EC8CAFDD4B353D73B6C1765211405C080A614129CF9346A1593503AD75EB9C3CCC99DBCE1D937AEB7929A1B5351BE262FB2B41FCA6DD965CE596DBE39D07D20281A2ED74C35FAA474EC425A897978FAD88D470502008D9A0E08DFA2F6C33A0B4CF2456951109BF4F877D74D7681CF287F6DCFAE24D1FCB0FC69D7C4D33E20536C64ACE18F04A2AA8E767C24068F4BA45C4C49DC3B43AF803610F300D01C5CD9ED92F33BAC270ECE09EBA2CA0FBA180CD135E420471A7C6CA249D877DE616F054711B3DA2DFA5D2D3FE774F802F4880E4400FBE4D12B8D678DB076020D356769060253E5D68F665FBCE0EC702F42B94E2B0C8359CF4D6EBCDEDA9FAC8F2FE95B9FDBB9346C06300F60FFD4FAEBA01929CEDF0F15021689B6EFF9298BFB8E514D925541CE2130EE1F25ED6EA895F432987AE4A2CAE01B5F4691DEBF12129EB19C2890A9D268774881F151A06FE42656CCAFEAFFF01E3EBF52C6716CB28BCB6719F7552731C275DA226914D733AEC1BD599AED7BC0646B8E3D9E0F3B771295D43391F00293401E6331E37E779EA8914E7F03B4CA3D1AFAD797617D9D0BBC6020E1B40B431B930D19E0888518D6ED2E6D32BD872B9A416E0B47133867FEC96A88C6B67449E8881B8A455D1816BE7DCB22287D63DBBD87E571F6887AD3D6DDC08C0B710395A12570AE985AB08393BF99DF1A1EDEA499BCBBC2F2EC05FA3EE982E34814F56373891282882A05711EE9A906CFE5952A6AF64379854A4DEBEC24C22F69065D6FC392B4A687D66528615AE301C82D6C694D358B71451A536039368D05C3C240062E455A119EF5A1737D732C1079C7CBA9A05D9D8119CD94497CBE2A275C69D6623628ADBCDEDEAAA143073C6EC43C40229606E6AEB982CE1827F875FF0A6921E0D6D08F605EBCF85EAF0C4AFBD067A14BF9FA6C7A657213C04FCB93630D892E8B340217EB07EFE9CD320DA3DE466169001566373F589A4C48BE25EAB1E6A612187F110661BCED6C2FE2583F424641A420A0DE61B39026172DDC93EF444EADF8ED5CB674F0586307F2886CAEECBBF78A4AFB96ADE18F0504734A082C168921005300431BAAA9FFBCFC96D272E8FD9A10B7F963BA868A273CADA8082353C0E1D7C8BD323779D9BB23CE678B3A5AAD2B6836F65C0F79E32D08006C72EB2431FF9797E7630F27B89635F08FC92203012EAF6B009A32437ED076D66E4CC6074B1CCD0D2176FBE508E43EDDA9185A91E2AFBD235EA8944B711B8C7D0A4132351FCAB1ABC338C3419C9993FD56FC3C89A08B0D8F28914FBB4840A7D02F209D1EFD208A8E47902E11C1FA92CBA1851FF0935D3EFA705FF4BA44A6D4A675BD979947CE8FAEC565B3BAA9D441AF91F429D42C3E3F683E0202C61318344C7865957131A1F9EB822999F137C0A930744CDC698B3D41226A32268C968F576AFB37D8BB4E533B077124626535AC470D649A817F42243CB7CC73F0837A6527C2890ABE5BB762174ECCEF9B2F9A3FC77866ED031947CE54EFB0DB647BC9AB219B974E0C42A53FF6C65C1A67924C1B0415C9B9CDE4887023FDA6DF9A2F3BBD7BE5FC23EDCB6CBF5CE5C0D6B75C2048F05C5AAD82C87F5D0E9A146C3CDF01A973E85ABB5DBF4B3834BCF7EC7FCA3636EA417B92E7838DE1A8527292FEC5183F21EED1485B4AEE3541C00E36E6D3AB5563F3DA1DB962B94FE6121D36273D2813E785E491BDCFC825B0E98539B7364BB73885EDDE73CBC41B7F680BB00D9EB3047956996B97A6994FDE741AF9D0B302E99D3573117B4B537B1A3C384589FBC24156141473FCDE30DBDD305A6E8FAFCECB98800348A5DC2940A8D5CF2005CEF09F49B5FD5B415BD63222BF23DBA151A0E1925FA6DF135075E02D5A7E734AF9B92E947191E7221F1122387DD17EC8A4D3582949B58C4EE75A0A83115D936F59653592A5F86FC2B7C277DE26526AB23AE4674417C9C9388B0338F81FEAA741C446CBCCAB5755F07A195325E708256AF861913F50AC03FF02DF181E414E185DD7CBA0714FBDA807D67C938CA36AD52BE1DA9CD4FEE14BF1961CC1C20D3268C5563BD5BCC10DCC0FA42F01B8E278D3B2F549D6A1B497C8DA54995D395CA6E761D3B776C1D012B1F9B39DD73CD831F6193847930AA15A4C3B139464E3F89AF3B1C583E4E986B80C4BF117DEDC1C09390560365754F402C35B06DE3DC45ADA558ABC7EB3A63580FD8C9F29D335A8D9797D1420D4E3EC0267078F68361B65DE8F6D153F38FFE6304F0B886E94AC959E71EF2AA546DEE0E00E39A3E8DB5869C4434E862E60AF5883DC6E905469ABE8A9DCFF2BC85D14F9CD6470F8B092DD622FDEE25678887B97B021013BDFC8CA38702A7F49BFE92A3BFFB8DAC66D888A070613BD09A6B2D6C2CBC9E61DF92BB128E8C87E241E83BDDBB294AA56A5B6E70742F6EFC321CBF8717DBB5EC7529E34B21C8A73CE9EE0B7D6A62C96137A19D4836D53BC4EB8C1551404CA5804C1CE2350EC41C117DEE4152B65F9BD050E5BDD4A8EC392624EB27927D21C6F3CCA0170EA9C74534C28EF5BB45FAA789A46C703A723A82EF4297F907A20FB4B91694D5598BFDF986E517D251A401D035C5995EF8CCE18BBCAA3C4320F0F90938F7D5D9B04E187BC72B7DF045AA554544368DD90F726115A48E3BE841086889FA99ED5ABCA67683D090A8F3002C164C7C431539C1C8FFA7B871F40B0F42237810E3F603C63DD59737AA7275862DFE9046D22D59754D3668826A410EDDAEDF804E16B8E6D01D7705F611123C3F6A3822479430AB3A10F79FE2295558B60DF5A7CB1F02ACF8EE05F74A38E025C1A6FE1C02EE50C2B5ACE98528523F5C16C620D78DBDD54B0D66BB1C2E832876C304D794DC28D1501840A94FE7ECB2A62C9B68EFCD6D60E9F12E79E6793424B66F1CDF7C16B0F39D03DC0A178F850B1BDDACB3629B456F6647D0B9AD45E0A635420C1E1081D0E99D8B5E912F295DFDD262100D5E95B030CDA6BE784F6D38ABC0AB5032B0D42C85ACF782D382BD0711A7B43CB7682E908D3E36132145A1FAEB6670B26A30917682E4BBBAAC884A7306192257E9ED98A771F707A1E14AEC44DB71359E49FE15529376DF4BE36A0D00241DFD320E93C8BD8BB651132C4917229A7E5284F83408E2FAC8588E3662F4AF09D4E3A8F97CC55B507A2374754B15B086175FB593B007ECD560F7AB9E7D6611D816FE58CBFD083D144E5D0BB7C4D76A510F56C7B3170ED5A4AF94D3042073F3720A8BD2DBE40A90AEC4765371C7F27036C75B3A05E08D3A0EA4EEE0C583196952636745A9556776489A46B7FE6884EC255032CA37CA59E33399206BDA71ECCDF7E901F57F7F11732FC86CD6F6BB761F612DCE82455C80382834A2F660D38CFEC1F63DE2AF8B1779394E23747980B3D4AE572409E03AEAB7A80FD951CFD64BFC061E4FABCB4BED38F1AB19C819A797E8C378010A56C3E7CE889DB8DCC832A637B4D1E04C2EEE52E2BBE8A64FE47EC9F3ACBB73D8AAF2DF8F14D67F92D2C80373D2180788FBEC28190CC824D90DD5DE2F4A95E0CD172C1D1D33D2E24B48A0611C908812BD1411DF363F40F317731DF586F7A156418F5EAD8C06E116F28B4D0A1D1E047FA249ED4CC653AFA03DF4631C80D529F886D1393C0E763C325FC3B1DB7DE834DC7A3775C5E0A8393256D9DF355D7B173BA5C0FA8C0807F8615E3EE5A5330F7CF408848188A46AA98BD6BBF5B6925667983D4354461B43E0E5A09FACEE9E285F2872F972F7121957C5A818BF45B7B4D8A83DBA07DB5D16F96B51A46B771213FE8810D53B1EE68EA8A2EF1870DAA7E9CB8570FA04DF817AD58EC6556929AE490B09463B663D899C0F01C5A30E31991812F60A686877C254084FA73C4E28D8267E43FC873BAC32A2EEF54CA235D2089C7BD98D90099EE3512B629BC63A69EAB96D2F60EA01D293DFFC6FC355A726B0EB91D66358834B1DFCDCF5738F929226A63BC8F861740D844E47E2D3B731D03A902F7627C0F287F1863CA4E29773E966C9BDE3D6EB2C83F1FEA43227BD9B556B9773378F3D5CBF571EB6877A334C438C8071B9CA6B8F2AD85E66CCA1312826FC0428FA80AF251D13E3BE157DE900203A2B2F09CD22ED5CB33A71A10154828784BC0D9093B731096BCB14FDD8A59C06BA7BBB6F46285EB75BE0F7E5143E16FDB3B0309303392E62E536299C825293E5764040833BCD0DBE3FF00122F56C1C2364B798293B9CBE3000000000000000000000000000000000000050A0F171D25""") + ), + new SigVerTestCase( + TestUtils.hexDecode(""" +6C9E7A1EE36625760E5D2F33DF2929DA56203234069160E5F2BF039C11062273073C237566CE055D871F38ACD1A9859A824467F19BE68E4F00645D225C42C85A557D2C5ECB442B0F028A6528898EE2B673D863F32EB9EC8164127541F32519BB88E034A03F46F7D193CD3DFBADF63557926C5C8F5B766A7FC5EC8B3F948BF7A821B54C9441AB0BD833FD6354CEC706FAA500ABB5289B90B1BF917677A29D115F0094BDB48DC72E261DBA120BA6FF5E52A01B178981DD8296444656D9442DF9CBB6BFDAE56A230F6F29F94CDCC265576AA8752ACED07E99895CAEF0168BF83D23FDADFBB928CBCDABA25FE2CD26ADDFB0DACD74940F351426942F176FFBC5F3456DB7C912AA16B86D0745F87C9F45370A8456A1ADB51DB4052B5C9EAF60AD7B80A42EA4BF92C841273AD761DEDB0D34BF579600B149FCCD42AB1549BA0ABEDA57EF71D1FCA5702AAD083299BB98300189C25F3B270A87658D0B2EA56524147F739EB6C676D7BE73DD3B95B10C55AB46FD01549C5168BF7DA13A499785F35A1E3B56F4C567F54EA9AA2817A336383643FA2EA31FB1B73E10248DFCA05C04131266498E1C9491135A50E63D02FADF4165FC9E15E3E1B32FAB8337684C49193E1BC4EDEAE373A267A714AC1F909CC657CD8066646327E0EEA041AC9F2AEFFC80691BF60D3C94C642557E4299D395922216C65E75B7E1A5028960384BF816C9F7054829E7985B5841A733F33FCE2455EFC89BAE84B47990E8D0AFC6193E4AF9BC680AE24FE591E88BA6A2AE12DA3858D21F492D24ABC4FE4FD52D5ABF24BD254687B918792F0A003A5222DF45038685C725CE7579E02CB168BBC666ABF669856E10537C9291692C0CB0CFA906270AC2C7B7DC31D4F9283CB2DB8A462AEC0B9807BBF4AB4576FEC6226B4179322B67AEA53BDDF9C9BE5E0DBC43F78743068AB5BE49F0E62F8E2EB1B6C6736C05C9413D065CE0CCB790548041D7E832881A839B5729AF94AB79FD8A16DFFF78CAAA141D97CC0650F86262F26159BE8B361A4A041E9A0B6511BBE3355A4BF57AC09848847EE0243C3BA774776F7E9A227275D74E6E3101D382818763ED1E1353AB9EECCD920CD28922D559A4048F40F062164CB661C4F4AFA81A3D55933C4791EDDAA3939E5AC342B0AD1F438A532C6CE786681A870D94EC88A334CCEFC6ACE7D988A1A82BC0ACCE785F123BE23A7C92AF108E5ED4F0869E22DAE273556D1DE386623A6C3F115BBD119271D3FBA796F618B53959FB98012E7D5B9AC688940B87E2C9C065524A00D3A4F4DBF52F4B1A63EF5C46193BADF7AD7F988D4464345B2C3E549684F2F905F6F89DD641473EC05108A52D8DBB91768C541DE520B17666970AAEB506E75D8EE9F4B4455B71E0088AB25655213B75859D25F559D3C324D283D397ABE6F0AAA386815768D03357D775964902413153E3560CCEF1FD44B65FF1B287A92A9693F034B7EE668934702D7501CAF6DA4EE98AF4E8E64B0340E0BB8BDC533B0EFEE1915A4B68B93C5E95321EEDC234AEFE71AE2E5DACEC2F52F83723A2392A7F8E13BC0301CD104D852E62A7F828AD329B3D9596C58E13FCC0ED96C1C48D82A2C0F4D9D24DD8421FDCCEFD497A9B05FFC50904770401373FEE7DC73773418AEB4A1F599A4BB38EDE8D10A3CC83A1C72DE921969E3CE3E8EF2F7DA89D344C80D61CF9C5A423B1A4F3567D96DB2DA3DB9B5B5FA68156BE7452C8A0181BB9F0DC75CD9750883D0DDAE53FC156D67A74200869046B41DF4BC4396993C08AA4897A0BDDEFB55F69CC1C4D7B5FB150408427B416F73183F2B3CC16E3B7DA63CEE1143ADA1A056626A077B6D21C3DD974ED907C5A094019225737EFB93319AD3B40A4F434AE49D28391C17A999C744A68C55A91B862729583D3DA46EE70C5CC461694167D32D21DE75327732C63BBFBD7B30DBF2057A0D681519F6E4AF608D4BCD0B4750726770E156AEDE85417BD759D5FFE401CB2996F34434DB428D9A417037201FCD260FAA98084502EED5C27A8916E44F5929819D21A69CE16BCDC3CC8141E285EF897B1402C15C952590119051E369A1B7BE443FEAE6E32BC8F3D647FC5315A5200CD5238DC6677466EA86EF8D18E5A79F262483E896B8277C741F516FC040C1090F2495BF1650B02AF30456733A071AF47D7A15BD8E32A49806455D3BEA74AEF5D00906AD2F0C045354EFDE7C9A276E73D9EDD11D1CA5C297B9A6851E7F67E21EB061BB55D9E673C4A75FEB84D52629EECC53C24BEA95153051AC206C87DF55410CA1FE6CFC3F403A6D9D43EA84C60C945E642B2836338B5AF9F69E52708B2E225933DB320BB3F790D397F22D7B6F8A433CDACE9810AA0E27C699555530C562DBF7517A4162628BF10D1B6DBACEF5C9ED51E55D9A89D60E0FC378C47A21D5E0F2DC3BCEF5E05C6E0261530FB027E5032558CA2B47005BDDE99909930391EAD7F3F0A96B3DEDA54A11145F530E51DEF892E5AB0204D614E6E38AFE79CA92C28158D570120353B7A4DE0889846D835294939557ED0AEDA270D4D73ED84D3D49F9F032D43457BF59BB7D66359DC53F9B46963B21784B06CBCF04BEC1E33A33371532716C9EDB3FBEDB81999B4372D0945C10AE826C60FFE93170B6D294B3891B0D2A7B35B28A8971845DC2FECE237B80F20B379CC4D136DAB3FBB3792C63EC61F5C755BC9DB35086FBF46D2B7970DCA2A8523FDB4C7A0B8E42F8AF9ACAD2A0EFC113602A4EA62E4EBB7D269C3A40BA2C44EDD2956"""), + TestUtils.hexDecode(""" +C4F59FA2DE30C8420A7E7F096BAF6AD69B1C15A5C6E61C9D82AFCFDB6EB8F275BF5787186AAE781F487F9F88758C9C61F35D5083EE70424B0D0A51575010C2A907F49608115D33EBA0031509322AA7D3061FEC3162F96A565F98769E9A19235D89D1B21D60A381DF8EB37D58C6A2E483A8EB70736E4B7BB911F7AB923DC29F1E"""), + TestUtils.hexDecode(""" +E895DB64C57BC3C2A97F0EC933410E98F6216103E3423CAF06A671964C514A694EB6F65CBD1137CCCF8881FA403C5FA0E0B2F36B9F4009C378210D29E54A7A5A9B793197CD6D2F38D7E1F3ACA69D48881389381C89FA676DE426D634F9A157055F17283ECE8248CAF14DCF11E2D56355B047DF632A18482E79CB2D5A743966BAA8A76121BB69C2E68155ACCB0A31DA6EDC73CB09A9E660FEB20F66C7BD967ADE32149C5552EAEB2EA175B56233F3B370EDD8679269CE0D2B43F6B2F65FE957E7AB37B982043754EAC8A30B36C10004EF13C692E219AA7AF0A4C5286910C7100DA41E17BBEF2DA2AB03ADF3074BA1DA15BCC84805B89B9DA88E9B400AFB7E3BC8338D354DA953AC0BAD822756CA92E5DD9507F42BFEFCCB32B4B91A2BE5EF34C2CF1177EAAFB250AC9ADEC4BE71807589F1003227F9B76B74E07BA67AC60819B2AF766A47FFFC7B76D3A7C077F5EC69AEEA3E963859B82C2ADE58BEC2152EC8205110975D37C6505E0DC776FDE071097E93013D1004F4E1A2FD79B877ED5025F527F3BFF137F041BB9BD001E949F08B4CF88DFD32FC7CDBCECCFDB0FA2DE7823E110BCFF58A412CEA2795753E9C89678C3AE24268F7489F72974B6955EDD04E190D99BB0D7A252FAD5BBA606C1A1F3ACA733BFAE3309EA0A6EB7D07E36D8CA336D2644FCE1A41895D014D1A60CB106F3F8075F9378461738D63D115D00B024C677801050A1B0B50DE057F85DB6AEB2C9D6BB7402A66E3AB4DB05C58BBDA12F695958B8AC7B4E45EC6C952F679C1EEBDF860E348982779AA6988EFC2AD1DC1EAE22A27A5B2C61C97B3B2493CB6C13C5F6E20A67B88D3C3ACCFAF0A425742DF240634D1EE593828FE6297446C076F979055988AB834B2BD82E14DC086400E1C956CC0C30CE7BFD962223D23FE9494964A811B93E8D7B8F34C89AAD45DD4113F2AE7BD94B53FC86E8B2AE82E51EC6F3EA4C30D60B86072748612D1607056B5FF6A4500EEE78A5A639C7B74169777626864DD9EAEF0E3AD8493D831F71DEA95BBFCF81423A266DE56F3A8FE8E6C3C0D612FB62BD642188CA71CB89834F30BCC28BD178845F1F6F46C03D306F7ED4E68759427AEC2701198C3C05D385DFAFD528CCE8425BC551469A0ED681BEE4D12A843E333B5A8E0517FC61906F9C4E7809BAED4D3D16EB22F1FA9AB402D988ED59F9FED0455E9260FD627A24A17FE7CB63E530B48F5FB6687A2E8C49DA79FBD69A3400056665DD11D19A2BC4DB1D374AB6A6E42472A27AC6B98F676E8EDAADD514F6D44DEECDAB5A6DFA0F84F139A803A2524BF335DC52EA58FA50D98FB5CD55D5D50A663CF647EEE56FE8E664B3BCAF9E333978A7946973FD113E4FD3924E6C09E60386444214DFA7A4D671FC23890637EB859134D79E265C59CA3ECCDDFA018223C9BAE1CCA103962078BC5F0DD02246FA28324F7CB2FCFAD07C25B4BC2D888069B0CF5F23C761C0E47109881CD31456A64B940B4BB9B4C2C3B8E6BA834AAAE69FDFC47D44B3C96887ABED36015E7B64E8542928F277CBD2D3C512C24DEEFE590E81C684E063E7AADCF117B48943DB771FC2207F57A745357555D419C9CDCA35CC1A7100A6913A3B6AACF796FE3F94DD2F818982716CE0316542A1B957E12DA43E231542CC14FCC66D728A68326B2BC311248330F3E98F81EA38CA924A8E4DA97CF673842C759F935BE88163CE97FE4D9457176F5B8908AF948F74D5D1DDBC521825D931C63CA8A8E12242626305AB6A2E0624564EE041983C18C2952EC3D9D159BDE3985CF77897EE2DC888112721D4854E914A5397E08B54F4A54323FF820821BE026EA091ECA6B7D80D91E3DCA2EF7848B86FCA6BB40CE48271E1008368E3EBB5E395E1CCD0D178F1A6257D26B6BA4B7CE532CAA1E76CE28FA4CF9E029E2482B94D3ACF97A326D235D1BDC89F70002198451D9F1F12CCD5BCAECDDE9E14AC80742EB31E6464C83210A39F35098BE0378D074CE1CCD1EBC1C7770F778D605F2BE59DB7EA07D80CCDF55F16E985B142FB7BDA07AA7DCA5B201E1950CF9A728F21E9A9D8AC4D1327E3BC0FF339A250522F631DF2E75955154893E4A1AAF9866FEE1637EE1AA5106D244E99E6F31FC5601BB7B79BAD82860B1D6059D9B132E026418020DB06EB8391FA15B7A0F29E36D966ABD3D2A2FF3F2AAC34C8B45C7D2355EDBB80B224BC106EBC6750E55070F85A7CB6003394E5161AE26F5ABF83F0DCCCF69B86139AF8694FE1DC00781EAE09CDB421814878043DC9B0530E5545A165E39A9B7DE88B4AD2AEB90D3C329412ED2FE1D97B732C8439DF4F83D228835B538DC278FF0A2DC42F41B00CE3ACA06B05C4839B896931515D78EA3673A378279F4E89CE08E3453FF2FB453BE031C6318628A731D029FC7BEA2BA5EAC4916278B938A6A6ACEF5BFE2158F2AF43D8E56A0649DF28A250D2F2536ABDE1E008EB631F4BD0EB55573A40539A6004181A9D2BF7A1E53504F11E014840733844131AC668946E5B827289AB6B21366C5D0E2649219B92C4760DFB705F7F61A96564C9E840D14B0BB0DA82DA50F8B8E752BBFEA3B0A337BE124F72D8F8249195BC19C3E0B62EAE496D38CF7500B4F10665FC2D28B9EA935F7E316472F4FF401267541BDB62301554B2009928C6445BBD0EF21D09972F35081ABA9091A6C23FED29F5CF9E0779F7EFBAD88E62A454442B30079BE0AC9C64826B98C1E1001CB0FB0F0A95F7965FE9312BFDAEC33F95065C8E59D3950F80ADC7FB334F202D3E5F8DA481C9B54A75983930FD1E5ACD16284F07193FBCB50D0DC00EFF8203144C11EC61420FC32D7982CE896406BE769A75DD8D3CAC753ABE5A278655BF54BE33A1B8374EBEEFF212C39CE514668F1C456EAA2532828C84293F1A5BC9EB5DEDF558A9B4C1239F77272C67E1AB28E1EFEC5893E09C10662B53C8B8255B1C8DC8F8E5120A25C75EEFE79C43F7A8B37DF9D1E4F32486933DA1CB0664C5DB39E21BC227B0CDFE7A5507F07F218A7A47DEBCD9DAD7247B4D045A13AD4F75EAD2D45C339D0DF04577F2E0FDC780392553033C738852B1BE4E63EA3897D6C9C4B11AD6B58D3E2D342D32840F649DD83E759866B7381A84C8ADDDF413FAE18E6431B1EEA73A56CD889B76BC9786BEDEDCA2541E4C9B24E28F58AD374C1D93DF2D3F2C37EC594A0498C574579A7332F72C0F9750877FAD5B90B968D88F11682C4071E4EA38B816AEAD6BE54D2F371324F2475B862C75424ECF9858AA4E200CFBA412D7E3E6C308D8DE11DD185331AF9D41AFE8879965D6746EF21FD98D3ED3806FB5C4619C98E347D76B8B89849395561EE286DFDFC6A04E1D47E9F5B5B49257784C39364DFA88AD630DFA59CCA3237F4A2B141A813D22C6FFE73C2D99ADC824D93E06A54B6DE62C3125D94B49E950DEC361F961F56D3671C9925377F6E670665322B8489E833D3830ECCDD0F53F4A4F9D68F1445F3AED5C9D766409B59BAE7A72912E98B3BB57342D29B6ACFD14336B7B8B6B7549AF8CC8845E10C2811287281985D5D47685FC589F2678ED893F57B85ACED75632E50DE5E074E6CEDCF1AD499BCE67A7F498564DEEC677C708388DE8FD7B099CFC116096C45FE28890B5EAF06169939FDA35E1215F238E8CDEDFE670065F5DE3272A232FD53C250F5D779B31694FBA91B554803676E4DEA288463FE1063009E9CB76C317DB400ACF4D2D2B6D16EDEBA4108913F60AEB252CDE413690CEEFDCFA638963DBD04F4CF21AD74DDE65F0F1E7CE70AF101A6DE9A59DB21D38027DBBF76167827950B69418266AFA444C728DE3624A1C81E5B1641DBE879CD822FB2303CC3A9FCEEFE3DDF7DBD0B7057248A28D6062D76EB13B92C9C9D003B69E1842A54C09CF6B484520815E2BB237288C64FC696FD3BC45DB30CB86465DF1188BF47956E5B916A8009715CC9A9A6DCE44C54F928816B41D018C5FE652FFE4E33F352D383A9C1365F02ABFD647BD6B42AD163730F8BFDA1E2BE5F614D79597825BA09F457D3CBE7561E7E89EAF059E977D1EE88848B781F21F723890FF1F9873928412C8F11EEDD2C0C39C9512790986A19E17B2B70A4D7CF49D9D18CAA0C2023134CACD169200D8817FA321F04ACC910613DFF250EB325DBEF29EB5611B2AD2A23EDD538049B3F43EFEB4D60983792B4BF05567944AADB7AC4D3A5D80A1B9D8448B4C0C115C3B5AD3885353F47D5FCB9B7D6446F1A7210BBC667FC411415F23CD40A2A3D64061D71C67191571A97D01088A24B6711567FC89106732D8892FF985B8E6CF70163829CC085BE4E408315361BB1B2003D6413220B134506D3C304C0BBBA9C9C45D3651E0571B6B115177213D8595E143DB90BD72F7EB974D8D0A0317409D64D5837EAEC9B8D44DD7ECFF6CDA9F729382A43B379CBDD43FFB18AEA35C1A996CEF1488D3B7A81EE7CFC0B9623418AB3919A6EDDB99F222F0DDDB2F32A20C8F84FBF4C49B4CB3EB50D9C4CD25A6F7175467066D25E6437B67F2DBC70C2E6EB0BDE2386D03014A789FB6DC08EE33C0C67951DA9D74B9C94845D2A99037E095FEF7919920FE526EB5DD0BA1F97DFBD2DDC31609C1B7B45EC3ADB586FE3030A0C7A9DD034A3C2E6F9849093CEE10A181953547F8BE328720A4A5A8290B5EE00000000000000000000000000000000000000000000060B10181A21""") + ), + new SigVerTestCase( + TestUtils.hexDecode(""" +6C9E7A1EE36625760E5D2F33DF2929DA56203234069160E5F2BF039C11062273073C237566CE055D871F38ACD1A9859A824467F19BE68E4F00645D225C42C85A557D2C5ECB442B0F028A6528898EE2B673D863F32EB9EC8164127541F32519BB88E034A03F46F7D193CD3DFBADF63557926C5C8F5B766A7FC5EC8B3F948BF7A821B54C9441AB0BD833FD6354CEC706FAA500ABB5289B90B1BF917677A29D115F0094BDB48DC72E261DBA120BA6FF5E52A01B178981DD8296444656D9442DF9CBB6BFDAE56A230F6F29F94CDCC265576AA8752ACED07E99895CAEF0168BF83D23FDADFBB928CBCDABA25FE2CD26ADDFB0DACD74940F351426942F176FFBC5F3456DB7C912AA16B86D0745F87C9F45370A8456A1ADB51DB4052B5C9EAF60AD7B80A42EA4BF92C841273AD761DEDB0D34BF579600B149FCCD42AB1549BA0ABEDA57EF71D1FCA5702AAD083299BB98300189C25F3B270A87658D0B2EA56524147F739EB6C676D7BE73DD3B95B10C55AB46FD01549C5168BF7DA13A499785F35A1E3B56F4C567F54EA9AA2817A336383643FA2EA31FB1B73E10248DFCA05C04131266498E1C9491135A50E63D02FADF4165FC9E15E3E1B32FAB8337684C49193E1BC4EDEAE373A267A714AC1F909CC657CD8066646327E0EEA041AC9F2AEFFC80691BF60D3C94C642557E4299D395922216C65E75B7E1A5028960384BF816C9F7054829E7985B5841A733F33FCE2455EFC89BAE84B47990E8D0AFC6193E4AF9BC680AE24FE591E88BA6A2AE12DA3858D21F492D24ABC4FE4FD52D5ABF24BD254687B918792F0A003A5222DF45038685C725CE7579E02CB168BBC666ABF669856E10537C9291692C0CB0CFA906270AC2C7B7DC31D4F9283CB2DB8A462AEC0B9807BBF4AB4576FEC6226B4179322B67AEA53BDDF9C9BE5E0DBC43F78743068AB5BE49F0E62F8E2EB1B6C6736C05C9413D065CE0CCB790548041D7E832881A839B5729AF94AB79FD8A16DFFF78CAAA141D97CC0650F86262F26159BE8B361A4A041E9A0B6511BBE3355A4BF57AC09848847EE0243C3BA774776F7E9A227275D74E6E3101D382818763ED1E1353AB9EECCD920CD28922D559A4048F40F062164CB661C4F4AFA81A3D55933C4791EDDAA3939E5AC342B0AD1F438A532C6CE786681A870D94EC88A334CCEFC6ACE7D988A1A82BC0ACCE785F123BE23A7C92AF108E5ED4F0869E22DAE273556D1DE386623A6C3F115BBD119271D3FBA796F618B53959FB98012E7D5B9AC688940B87E2C9C065524A00D3A4F4DBF52F4B1A63EF5C46193BADF7AD7F988D4464345B2C3E549684F2F905F6F89DD641473EC05108A52D8DBB91768C541DE520B17666970AAEB506E75D8EE9F4B4455B71E0088AB25655213B75859D25F559D3C324D283D397ABE6F0AAA386815768D03357D775964902413153E3560CCEF1FD44B65FF1B287A92A9693F034B7EE668934702D7501CAF6DA4EE98AF4E8E64B0340E0BB8BDC533B0EFEE1915A4B68B93C5E95321EEDC234AEFE71AE2E5DACEC2F52F83723A2392A7F8E13BC0301CD104D852E62A7F828AD329B3D9596C58E13FCC0ED96C1C48D82A2C0F4D9D24DD8421FDCCEFD497A9B05FFC50904770401373FEE7DC73773418AEB4A1F599A4BB38EDE8D10A3CC83A1C72DE921969E3CE3E8EF2F7DA89D344C80D61CF9C5A423B1A4F3567D96DB2DA3DB9B5B5FA68156BE7452C8A0181BB9F0DC75CD9750883D0DDAE53FC156D67A74200869046B41DF4BC4396993C08AA4897A0BDDEFB55F69CC1C4D7B5FB150408427B416F73183F2B3CC16E3B7DA63CEE1143ADA1A056626A077B6D21C3DD974ED907C5A094019225737EFB93319AD3B40A4F434AE49D28391C17A999C744A68C55A91B862729583D3DA46EE70C5CC461694167D32D21DE75327732C63BBFBD7B30DBF2057A0D681519F6E4AF608D4BCD0B4750726770E156AEDE85417BD759D5FFE401CB2996F34434DB428D9A417037201FCD260FAA98084502EED5C27A8916E44F5929819D21A69CE16BCDC3CC8141E285EF897B1402C15C952590119051E369A1B7BE443FEAE6E32BC8F3D647FC5315A5200CD5238DC6677466EA86EF8D18E5A79F262483E896B8277C741F516FC040C1090F2495BF1650B02AF30456733A071AF47D7A15BD8E32A49806455D3BEA74AEF5D00906AD2F0C045354EFDE7C9A276E73D9EDD11D1CA5C297B9A6851E7F67E21EB061BB55D9E673C4A75FEB84D52629EECC53C24BEA95153051AC206C87DF55410CA1FE6CFC3F403A6D9D43EA84C60C945E642B2836338B5AF9F69E52708B2E225933DB320BB3F790D397F22D7B6F8A433CDACE9810AA0E27C699555530C562DBF7517A4162628BF10D1B6DBACEF5C9ED51E55D9A89D60E0FC378C47A21D5E0F2DC3BCEF5E05C6E0261530FB027E5032558CA2B47005BDDE99909930391EAD7F3F0A96B3DEDA54A11145F530E51DEF892E5AB0204D614E6E38AFE79CA92C28158D570120353B7A4DE0889846D835294939557ED0AEDA270D4D73ED84D3D49F9F032D43457BF59BB7D66359DC53F9B46963B21784B06CBCF04BEC1E33A33371532716C9EDB3FBEDB81999B4372D0945C10AE826C60FFE93170B6D294B3891B0D2A7B35B28A8971845DC2FECE237B80F20B379CC4D136DAB3FBB3792C63EC61F5C755BC9DB35086FBF46D2B7970DCA2A8523FDB4C7A0B8E42F8AF9ACAD2A0EFC113602A4EA62E4EBB7D269C3A40BA2C44EDD2956"""), + TestUtils.hexDecode(""" +C1E665BF7B8BD0198F069CA17EFC55B7EBBF9CC9D41140BDD0B83AA08062FFC717D3F6C22DF38EEFAA6EEC91760CAE0B3DFEAB78B03A7AB7A993B2097B7B887B9812AE2D0892B696374C034FC9E95083C2B61B09DE97D9C500FE55E489C53CAEBDB57BC69071C15808890F8A007BB5FE773CCFB729463113D93E9EC9EABE2047"""), + TestUtils.hexDecode(""" +051F8A9A5DC6D35B1485288359F818DEB027E1231DA8C048E79E9FE228AA0E9F1C0B7F4C573B5DB8CCAEBBAE8EE38D8FAEFD3B8E7730BDC0E9DE365B20E5A0F9635A0B39C7C0D6163B7876ECC6ABCD8A5F608E7253537C1C94C209C8448E02806B2B5EAFAE2483170B4E4450380C2A87A51F82B179EE0F46509404A3A9BD74D04BD75635B797B500F656ACAE5DD76B04741792112579E24081A6C88BF4981346E2B3D38291026D3AE47BDA50AB0B23B0881148489CBD057CDE9A4F6FF108B7ECCEA44D599CE3ADED82AE0E8F74DB7D604161C8664B7389497EC9F35C46FEC064BB867E867E9309C10FBC07BD5E7B8A74BBEBC1BD0E4A9B36EFE297E9F2D23DE32ED704EAA377F5C3BC4BABCCAD5B4B6B9A137F23C46C0423ABA3F1AFF00C6071CBA51B7D0A8E677F5138DB7C013CAEE1F68501430F0F448AB283692A18D15D8A46BA620EA906A3032570A659F594236F0512389E1DE63B8E40AC22DB79DE60CCB9BCF0B20EBEF676A91AABCD01D3AF882931AFF8C86A8C946E09B8B5CFDE62D53A03DF07163B081B293EA0287AEB97D1762F34361DDE654D400DFAE5B351D90742A0A269865D49C9221DD89E42FFA63EDDF449B10458CFE2EA7E1A16BD22FE73F208B4472DA8094F28CB9DCAED6E843C57E9E3258BEADA48D7761FDE0104AC6F0CE09F95E1F4AFF00515AC2E3703D2FC6D757B12DFDC044E854E50FF2D897900B0B59BED90BA4201694E29E6A830D8039CD835C706EF59E7A6B0ACA7B7D0B40D264661711E0372BAB7410A74460D07FA988A8617D31074950838411037307B052FD536822608F9D15BAA780AFAE1A8D87BF844D3A4FB31A176BBCBEA46A72BA990FCF821AC3A73ACA01E09A20AB93FC737ED4C4DC482BF9BA21D7178D24DD5D6A29633386933A3E8F28982731F07606AF28BD2D81004B044B4EAAE67E29840BC78EA66FF840031D8B2894B603733E1A0398FB0E4952B2ABC567668443581C860F87A76774E6742807C39FE99269E3199DAD02B246D7AC24E5BD9DD91F7D16A76E72318882FA21672A7D5B1A4F212954BE2B19897243F60C18D1DED2AFDF69DAB8C9B10342471C633B33C52E95A85D3142F2E46C681AF373C5E92BC948FBD31207F015DD32DE2591DF4639E4E563344D440653592EF2685E1320AB9E51837F6C06D07E5462599FC6F8BB120826E738E2223CD4B8C7CE446ECE681DC6D6BEF1D6385B0AE7E404F502B87989D969B81CF42085A7B58A41EF73EDC73056DA72EF65A7AC8E284E7F51E723102CFEF903688F870CEF1C7E5264330E3033691680050E926E93A1C0C4161A7DCA14A0FF338D431D68FAC204DA28CCD1CE7BA3B7F3C45B4FC74D9E754A1A2F7F23F0FBE8D2FF01CE4683D8842E8A1528589E7D9260368A654CB514A85DA9C2EAB74C66FA17FDFB256D585D28C1DBA35E18779D7B6DB876CC0A98CFF752A0E8DFDD532ECB04C4101AF32E689D13874B9F20AF652069C1458D7FB382E317AF49083B5870078B39221464F376EC0BC2DC1C3FAF10EA4EA87A2F9D547B535F60406E8E68AD190CD4F00EFDCD9D54D4810F31B9F68F0D95E32CDF2747B9C20FCD1694FE034EF6B5460F163AC78BA235A441DB2B3AE84BC28CEEED7B3FC2A4D63330D14186658788DFD7652E477B1310317C86921394219D75FB6FC319575745589F9E2096801E57E6AED2369FE115C2D937EBEA3602194B7432B01F55E6C9572CD0FF8BE8A4796815914D5F64D93E0E709C3CF88741C851C8BFC4CCE6F0AE60A6D2F4DC6FD8AFC82E065956971FB8B4160AD68EF7BFCB3A9694CC7EDEF64FF08011B183BEB7A2D3D9024753B59900D27F52DF6D4B2576BABA673A0E33CC57B501E1C74F63A988E1A157078FA8B3F2A143CC9D41A35412B4E0CE6B1D9CFAE7470BF4C778D026A9AF86DF7F974E2414FD7C5F0FF6D62293C6E2A62D4C5268CD0B604047C9658F97D9A7B86E1C953FFF95CB478028FDCAE6E8F208AA208A282446B2CE8B4C7E893E269FA8E02C082F82966A4AE3FD86BE89A8CC8BB3D6B105A91DCF76FEF700E5AA4A15BA0F753129D3369915D7E896527CF6E71C363EF65B2218A5FCB8D8FD96D6A63A8BC547EFC942DCE1276E268841BA00E35769B4AC706BD65B275BABDD530771D854EC38AC0529729786A86C7C4161B3E7074023516C84B4B4776AC47C2ED1587861126A7A707978F2B2B2972C20F237FC223B56A67538F9241D926DB7C992A3FDFDF999884EF83EAC7DA0F6523F53CD40E473AD370C77B30DB2FE408783D24CF4C3512E3C6B677C41A67849FA1792313581EBBDB7BE0BB3EE85330FED8B5A1915F6343F3B7C928CD363463385436038B64BAB5D055BC39D18F9A1A8196AF8DDA5A1F428434958F5C89F07D7A53CFF2118E80060C5ACA71975C4C92A589EBF5746AC92C50FC1F915C146C2DEE7531B24970790A4AA7DAC425940AFC4C88ABEB998D549681C95ACBE9F7E274521D44E9EB759C2946504161AE7FFEDAD3E62D045AD77FE8C2B8ED529843DD341E2E50559A29AE26D431C9634C4C19A84FA0257F71CDF27C33F14D57347BE8B19D254E3C353CDCA10489F06214161AEB2A9D3049B3CE4689503621C46D192C1421B4B033775D9218DD2E216600E64D977CAB0E1675666A7CA773E4E139DD4EBE94CE35A28284755C52BE490514B25FFCA4174F54E8A5F715F924949C1467A282D7F2DB468DF363F9A55E5D7858D8F95D8083D6A594DC1B07A8C4FD4AAAEA0785EA3D9B50798F0A96AA386F17C2BFB94FA8EA3B5EF71012AF9285CADB1FE330A267555A942682F9333AF2E81515969B76FDC020F9CD29E848B94F26F4B53CA5144CBCDA1AB6CD2FACBAB0A2FC0F5B88DA0AC0EC08B9EDA7CAEF502FDA52006815743520F841CFEC3B4D9AA732DE408D6FB14739E8FE77CDDB68A5F6AA215B588F1491988B4460F6949AD647DE9105CA50CFB413A971BC8E6179F0724FC28D1A7D30C41180735F4FF6167810D9E88A5F7FDF791BFB474BB5478544EA74C9F07598D038CBBA17B83228A18B2AB09A8BBD2D2205EECDF01044D5A1B2BD50D2C8E3D5511450A4E594C1CE7067A6E14128BBB36E95C143EE6A51CA0EEBDBE47E9C5A87E81BB904013DC892D03F483B1DC82986DCE7A6E10192E6743283202D78D11B2169602A75C2A688DBAD50C9FDF1A1A15A470D882ED4B5207E659A94776ABC3D3583E1D2E85291D3726E75B7AEF9344180D325583A05266C196ED367E906121C33E701D428B46865BF32AEA4A90262866A024209A7663EDA4C340B5AF3E899F009EEB5E8D5003635EED501CC02D5D11F504C823C17E961D0BF611519961BF422647D97119F5745478888BCCE367639772953C5731434B28913F3F709AF455053F6B09519AEB6B755CB02CE74DD814714A2E0B477C05202092525EC03C5B365A75086E3281D4BB5C3AD9D742806E58B5CE4E1E95269AB18B68B2928BFCF7EA683967C0B88ADA99FF35E1D5A661CDFAD76774B42F858AA54626B88050D992FFDE16FAD3A8CA496CC6BE339977BE24D33E8BAB86B421F4BAA9C12A93117E43415929F0C4DBC9737EA5586780886A8EF4E4295DDBC967A2B5523FAEE0C060468F9704509C4CB14028E8A1672609A8CED43F1B06981FBFDFD52296D7BD3B4AE68E7D54BB2405799278AE29B66E258D3B9D276FD34E192BDE869092F6A7F761C6DDB0DE9454823256C7B17ABB91003B1A3B66CBCD4F9ED068409161635F6DF9459AC382044EC14FE8B2A586FE02C74232BBBF27800ECF627AD1C6ECC93C13EDA2DC20C8D6714C519D6A571E708787BF342DBCDE10EB1BCA5A7FCD971CA52BB68FB33ECB7F90AAF739F0C5B61BFED72CDB46A712DB6928F84892D3EC2F6C7023A6B664CE9CFDC33D2F09D38B5E4D182C73FF1D7B474C8AD6E883ABC78FEC75C8A390CEA561A86B92E2A4A1950997594C29A35E4A71B0E484FCDA63E5EC9666E0A463325DBCF7258D36B85099AB7C81E70FA66F1A471D4C1593AE68404F31AD2667017C9B5B3843FBC48D831F6A9B5FAF7C73A8478A7DADF28FBD9DDF979418870AE61E94C6BD47FF2C39073AAE16FF18B161B9B21413E66E489EF9F8784E5DCBBE29127B0C51A5C1E2A04E9C8794964D1823ACEB9ED0DD555964687848629EE06B0712483CA30D6D4A91E047EA33D30A062D8249278CDCBBA2A1B3C133D3E671FACB034AD0F9AA40628C0E2288B56F7A76DCDFEA762A8DB323B44925285557C3501999CBE145D15EA82169007A97EABABBE69479E03D40F2FE9217F14664726DCEA227107412B3CC742E4ED168E051D9AD4468131AB035708ABAD78659CCF5988F70680C124468CB80BD9924B0E41CB25AA69E7877CF5EA348403AD0899A5FCF35D4F22F3A73F0207E96785F4EB9AB93B6F10EE0B247D31F3D62A85B99C88CD3B19BB68E69C51AD5B0A8E9E34ED611E24FE2644F1697A8A11B64B578FEE1C5CB31A605CD987D765FB68D833E4BE9358D869F4DE0362E6889FBE8E95B861E078CE6CF0FF35768AD49803A71E8DC60296032E50A9D0A4E64A3D4661E7C55DAFC6FDD1B18EB1003D290BE486C520A2F8F0EFC1CD2CEFBF7E2459CC7BA88695D1122A7494A3A41C329EED2A8CD2282A607F93A2B7DADF0F32414C6BA9BEC0CB00000000000000000000000000000000000000000003090D101922""") + ), + new SigVerTestCase( + TestUtils.hexDecode(""" +6C9E7A1EE36625760E5D2F33DF2929DA56203234069160E5F2BF039C11062273073C237566CE055D871F38ACD1A9859A824467F19BE68E4F00645D225C42C85A557D2C5ECB442B0F028A6528898EE2B673D863F32EB9EC8164127541F32519BB88E034A03F46F7D193CD3DFBADF63557926C5C8F5B766A7FC5EC8B3F948BF7A821B54C9441AB0BD833FD6354CEC706FAA500ABB5289B90B1BF917677A29D115F0094BDB48DC72E261DBA120BA6FF5E52A01B178981DD8296444656D9442DF9CBB6BFDAE56A230F6F29F94CDCC265576AA8752ACED07E99895CAEF0168BF83D23FDADFBB928CBCDABA25FE2CD26ADDFB0DACD74940F351426942F176FFBC5F3456DB7C912AA16B86D0745F87C9F45370A8456A1ADB51DB4052B5C9EAF60AD7B80A42EA4BF92C841273AD761DEDB0D34BF579600B149FCCD42AB1549BA0ABEDA57EF71D1FCA5702AAD083299BB98300189C25F3B270A87658D0B2EA56524147F739EB6C676D7BE73DD3B95B10C55AB46FD01549C5168BF7DA13A499785F35A1E3B56F4C567F54EA9AA2817A336383643FA2EA31FB1B73E10248DFCA05C04131266498E1C9491135A50E63D02FADF4165FC9E15E3E1B32FAB8337684C49193E1BC4EDEAE373A267A714AC1F909CC657CD8066646327E0EEA041AC9F2AEFFC80691BF60D3C94C642557E4299D395922216C65E75B7E1A5028960384BF816C9F7054829E7985B5841A733F33FCE2455EFC89BAE84B47990E8D0AFC6193E4AF9BC680AE24FE591E88BA6A2AE12DA3858D21F492D24ABC4FE4FD52D5ABF24BD254687B918792F0A003A5222DF45038685C725CE7579E02CB168BBC666ABF669856E10537C9291692C0CB0CFA906270AC2C7B7DC31D4F9283CB2DB8A462AEC0B9807BBF4AB4576FEC6226B4179322B67AEA53BDDF9C9BE5E0DBC43F78743068AB5BE49F0E62F8E2EB1B6C6736C05C9413D065CE0CCB790548041D7E832881A839B5729AF94AB79FD8A16DFFF78CAAA141D97CC0650F86262F26159BE8B361A4A041E9A0B6511BBE3355A4BF57AC09848847EE0243C3BA774776F7E9A227275D74E6E3101D382818763ED1E1353AB9EECCD920CD28922D559A4048F40F062164CB661C4F4AFA81A3D55933C4791EDDAA3939E5AC342B0AD1F438A532C6CE786681A870D94EC88A334CCEFC6ACE7D988A1A82BC0ACCE785F123BE23A7C92AF108E5ED4F0869E22DAE273556D1DE386623A6C3F115BBD119271D3FBA796F618B53959FB98012E7D5B9AC688940B87E2C9C065524A00D3A4F4DBF52F4B1A63EF5C46193BADF7AD7F988D4464345B2C3E549684F2F905F6F89DD641473EC05108A52D8DBB91768C541DE520B17666970AAEB506E75D8EE9F4B4455B71E0088AB25655213B75859D25F559D3C324D283D397ABE6F0AAA386815768D03357D775964902413153E3560CCEF1FD44B65FF1B287A92A9693F034B7EE668934702D7501CAF6DA4EE98AF4E8E64B0340E0BB8BDC533B0EFEE1915A4B68B93C5E95321EEDC234AEFE71AE2E5DACEC2F52F83723A2392A7F8E13BC0301CD104D852E62A7F828AD329B3D9596C58E13FCC0ED96C1C48D82A2C0F4D9D24DD8421FDCCEFD497A9B05FFC50904770401373FEE7DC73773418AEB4A1F599A4BB38EDE8D10A3CC83A1C72DE921969E3CE3E8EF2F7DA89D344C80D61CF9C5A423B1A4F3567D96DB2DA3DB9B5B5FA68156BE7452C8A0181BB9F0DC75CD9750883D0DDAE53FC156D67A74200869046B41DF4BC4396993C08AA4897A0BDDEFB55F69CC1C4D7B5FB150408427B416F73183F2B3CC16E3B7DA63CEE1143ADA1A056626A077B6D21C3DD974ED907C5A094019225737EFB93319AD3B40A4F434AE49D28391C17A999C744A68C55A91B862729583D3DA46EE70C5CC461694167D32D21DE75327732C63BBFBD7B30DBF2057A0D681519F6E4AF608D4BCD0B4750726770E156AEDE85417BD759D5FFE401CB2996F34434DB428D9A417037201FCD260FAA98084502EED5C27A8916E44F5929819D21A69CE16BCDC3CC8141E285EF897B1402C15C952590119051E369A1B7BE443FEAE6E32BC8F3D647FC5315A5200CD5238DC6677466EA86EF8D18E5A79F262483E896B8277C741F516FC040C1090F2495BF1650B02AF30456733A071AF47D7A15BD8E32A49806455D3BEA74AEF5D00906AD2F0C045354EFDE7C9A276E73D9EDD11D1CA5C297B9A6851E7F67E21EB061BB55D9E673C4A75FEB84D52629EECC53C24BEA95153051AC206C87DF55410CA1FE6CFC3F403A6D9D43EA84C60C945E642B2836338B5AF9F69E52708B2E225933DB320BB3F790D397F22D7B6F8A433CDACE9810AA0E27C699555530C562DBF7517A4162628BF10D1B6DBACEF5C9ED51E55D9A89D60E0FC378C47A21D5E0F2DC3BCEF5E05C6E0261530FB027E5032558CA2B47005BDDE99909930391EAD7F3F0A96B3DEDA54A11145F530E51DEF892E5AB0204D614E6E38AFE79CA92C28158D570120353B7A4DE0889846D835294939557ED0AEDA270D4D73ED84D3D49F9F032D43457BF59BB7D66359DC53F9B46963B21784B06CBCF04BEC1E33A33371532716C9EDB3FBEDB81999B4372D0945C10AE826C60FFE93170B6D294B3891B0D2A7B35B28A8971845DC2FECE237B80F20B379CC4D136DAB3FBB3792C63EC61F5C755BC9DB35086FBF46D2B7970DCA2A8523FDB4C7A0B8E42F8AF9ACAD2A0EFC113602A4EA62E4EBB7D269C3A40BA2C44EDD2956"""), + TestUtils.hexDecode(""" +62C2A85A6AE40091AE35068EB3E5B54803F495D49BC177F7A29282DF0C900E86F66155B4026064E7D6CF7A171F8BBB33449232EB5D7DB2B776ABBACECCD660294C25196E19FADA35E0F3524D78EDA25D614FB56DBA5BAC10D06EAEDD9644DA291DF305C1E91C82FA00EC470A8E822525895113A6FF7D1D52E7038B9CF4DB2227"""), + TestUtils.hexDecode(""" +9B829A093EC253FF3D955EBA3C0FDA29CD14089C6D699F26FC62BCD40F43D1582F2B693138AACA59A162CEFBDA6328F1BD67690C63B903F5062DCDFFA840DC2DFD4051F82A557FFDAAE8F4A4FB340D6F4AF03A19AB928F42DFD29FF8D028333A0C336D253C826175C5A194C0441DAC1C5A4C4A3E0B8394E43678DC915BC98628BF565C9E751BF9801DD6AD4A3621B50C8DD1520F0CFE475F5BF843DC2568B263978587322FD1D2709ECD869A77F054C0A45D466D297ED9B63F10020826836F531A06DFBE20BFBA0B3F204033783C5505BD82DE732204917E3DA12316559D07366600CD18EE2A329AB3B20BB0C9C607D0660044D2A9ACC5D25806F89DFD5813C9E54E0CDFC190A206300FBC8E2561BF3F23D04052902E49CD5DA530A4D2BC2E5F47EE93D0588AA66EC8CAFDD4B353D73B6C1765211405C080A614129CF9346A1593503AD75EB9C3CCC99DBCE1D937AEB7929A1B5351BE262FB2B41FCA6DD965CE596DBE39D07D20281A2ED74C35FAA474EC425A897978FAD88D470502008D9A0E08DFA2F6C33A0B4CF2456951109BF4F877D74D7681CF287F6DCFAE24D1FCB0FC69D7C4D33E20536C64ACE18F04A2AA8E767C24068F4BA45C4C49DC3B43AF803610F300D01C5CD9ED92F33BAC270ECE09EBA2CA0FBA180CD135E420471A7C6CA249D877DE616F054711B3DA2DFA5D2D3FE774F802F4880E4400FBE4D12B8D678DB076020D356769060253E5D68F665FBCE0EC702F42B94E2B0C8359CF4D6EBCDEDA9FAC8F2FE95B9FDBB9346C06300F60FFD4FAEBA01929CEDF0F15021689B6EFF9298BFB8E514D925541CE2130EE1F25ED6EA895F432987AE4A2CAE01B5F4691DEBF12129EB19C2890A9D268774881F151A06FE42656CCAFEAFFF01E3EBF52C6716CB28BCB6719F7552731C275DA226914D733AEC1BD599AED7BC0646B8E3D9E0F3B771295D43391F00293401E6331E37E779EA8914E7F03B4CA3D1AFAD797617D9D0BBC6020E1B40B431B930D19E0888518D6ED2E6D32BD872B9A416E0B47133867FEC96A88C6B67449E8881B8A455D1816BE7DCB22287D63DBBD87E571F6887AD3D6DDC08C0B710395A12570AE985AB08393BF99DF1A1EDEA499BCBBC2F2EC05FA3EE982E34814F56373891282882A05711EE9A906CFE5952A6AF64379854A4DEBEC24C22F69065D6FC392B4A687D66528615AE301C82D6C694D358B71451A536039368D05C3C240062E455A119EF5A1737D732C1079C7CBA9A05D9D8119CD94497CBE2A275C69D6623628ADBCDEDEAAA143073C6EC43C40229606E6AEB982CE1827F875FF0A6921E0D6D08F605EBCF85EAF0C4AFBD067A14BF9FA6C7A657213C04FCB93630D892E8B340217EB07EFE9CD320DA3DE466169001566373F589A4C48BE25EAB1E6A612187F110661BCED6C2FE2583F424641A420A0DE61B39026172DDC93EF444EADF8ED5CB674F0586307F2886CAEECBBF78A4AFB96ADE18F0504734A082C168921005300431BAAA9FFBCFC96D272E8FD9A10B7F963BA868A273CADA8082353C0E1D7C8BD323779D9BB23CE678B3A5AAD2B6836F65C0F79E32D08006C72EB2431FF9797E7630F27B89635F08FC92203012EAF6B009A32437ED076D66E4CC6074B1CCD0D2176FBE508E43EDDA9185A91E2AFBD235EA8944B711B8C7D0A4132351FCAB1ABC338C3419C9993FD56FC3C89A08B0D8F28914FBB4840A7D02F209D1EFD208A8E47902E11C1FA92CBA1851FF0935D3EFA705FF4BA44A6D4A675BD979947CE8FAEC565B3BAA9D441AF91F429D42C3E3F683E0202C61318344C7865957131A1F9EB822999F137C0A930744CDC698B3D41226A32268C968F576AFB37D8BB4E533B077124626535AC470D649A817F42243CB7CC73F0837A6527C2890ABE5BB762174ECCEF9B2F9A3FC77866ED031947CE54EFB0DB647BC9AB219B974E0C42A53FF6C65C1A67924C1B0415C9B9CDE4887023FDA6DF9A2F3BBD7BE5FC23EDCB6CBF5CE5C0D6B75C2048F05C5AAD82C87F5D0E9A146C3CDF01A973E85ABB5DBF4B3834BCF7EC7FCA3636EA417B92E7838DE1A8527292FEC5183F21EED1485B4AEE3541C00E36E6D3AB5563F3DA1DB962B94FE6121D36273D2813E785E491BDCFC825B0E98539B7364BB73885EDDE73CBC41B7F680BB00D9EB3047956996B97A6994FDE741AF9D0B302E99D3573117B4B537B1A3C384589FBC24156141473FCDE30DBDD305A6E8FAFCECB98800348A5DC2940A8D5CF2005CEF09F49B5FD5B415BD63222BF23DBA151A0E1925FA6DF135075E02D5A7E734AF9B92E947191E7221F1122387DD17EC8A4D3582949B58C4EE75A0A83115D936F59653592A5F86FC2B7C277DE26526AB23AE4674417C9C9388B0338F81FEAA741C446CBCCAB5755F07A195325E708256AF861913F50AC03FF02DF181E414E185DD7CBA0714FBDA807D67C938CA36AD52BE1DA9CD4FEE14BF1961CC1C20D3268C5563BD5BCC10DCC0FA42F01B8E278D3B2F549D6A1B497C8DA54995D395CA6E761D3B776C1D012B1F9B39DD73CD831F6193847930AA15A4C3B139464E3F89AF3B1C583E4E986B80C4BF117DEDC1C09390560365754F402C35B06DE3DC45ADA558ABC7EB3A63580FD8C9F29D335A8D9797D1420D4E3EC0267078F68361B65DE8F6D153F38FFE6304F0B886E94AC959E71EF2AA546DEE0E00E39A3E8DB5869C4434E862E60AF5883DC6E905469ABE8A9DCFF2BC85D14F9CD6470F8B092DD622FDEE25678887B97B021013BDFC8CA38702A7F49BFE92A3BFFB8DAC66D888A070613BD09A6B2D6C2CBC9E61DF92BB128E8C87E241E83BDDBB294AA56A5B6E70742F6EFC321CBF8717DBB5EC7529E34B21C8A73CE9EE0B7D6A62C96137A19D4836D53BC4EB8C1551404CA5804C1CE2350EC41C117DEE4152B65F9BD050E5BDD4A8EC392624EB27927D21C6F3CCA0170EA9C74534C28EF5BB45FAA789A46C703A723A82EF4297F907A20FB4B91694D5598BFDF986E517D251A401D035C5995EF8CCE18BBCAA3C4320F0F90938F7D5D9B04E187BC72B7DF045AA554544368DD90F726115A48E3BE841086889FA99ED5ABCA67683D090A8F3002C164C7C431539C1C8FFA7B871F40B0F42237810E3F603C63DD59737AA7275862DFE9046D22D59754D3668826A410EDDAEDF804E16B8E6D01D7705F611123C3F6A3822479430AB3A10F79FE2295558B60DF5A7CB1F02ACF8EE05F74A38E025C1A6FE1C02EE50C2B5ACE98528523F5C16C620D78DBDD54B0D66BB1C2E832876C304D794DC28D1501840A94FE7ECB2A62C9B68EFCD6D60E9F12E79E6793424B66F1CDF7C16B0F39D03DC0A178F850B1BDDACB3629B456F6647D0B9AD45E0A635420C1E1081D0E99D8B5E912F295DFDD262100D5E95B030CDA6BE784F6D38ABC0AB5032B0D42C85ACF782D382BD0711A7B43CB7682E908D3E36132145A1FAEB6670B26A30917682E4BBBAAC884A7306192257E9ED98A771F707A1E14AEC44DB71359E49FE15529376DF4BE36A0D00241DFD320E93C8BD8BB651132C4917229A7E5284F83408E2FAC8588E3662F4AF09D4E3A8F97CC55B507A2374754B15B086175FB593B007ECD560F7AB9E7D6611D816FE58CBFD083D144E5D0BB7C4D76A510F56C7B3170ED5A4AF94D3042073F3720A8BD2DBE40A90AEC4765371C7F27036C75B3A05E08D3A0EA4EEE0C583196952636745A9556776489A46B7FE6884EC255032CA37CA59E33399206BDA71ECCDF7E901F57F7F11732FC86CD6F6BB761F612DCE82455C80382834A2F660D38CFEC1F63DE2AF8B1779394E23747980B3D4AE572409E03AEAB7A80FD951CFD64BFC061E4FABCB4BED38F1AB19C819A797E8C378010A56C3E7CE889DB8DCC832A637B4D1E04C2EEE52E2BBE8A64FE47EC9F3ACBB73D8AAF2DF8F14D67F92D2C80373D2180788FBEC28190CC824D90DD5DE2F4A95E0CD172C1D1D33D2E24B48A0611C908812BD1411DF363F40F317731DF586F7A156418F5EAD8C06E116F28B4D0A1D1E047FA249ED4CC653AFA03DF4631C80D529F886D1393C0E763C325FC3B1DB7DE834DC7A3775C5E0A8393256D9DF355D7B173BA5C0FA8C0807F8615E3EE5A5330F7CF408848188A46AA98BD6BBF5B6925667983D4354461B43E0E5A09FACEE9E285F2872F972F7121957C5A818BF45B7B4D8A83DBA07DB5D16F96B51A46B771213FE8810D53B1EE68EA8A2EF1870DAA7E9CB8570FA04DF817AD58EC6556929AE490B09463B663D899C0F01C5A30E31991812F60A686877C254084FA73C4E28D8267E43FC873BAC32A2EEF54CA235D2089C7BD98D90099EE3512B629BC63A69EAB96D2F60EA01D293DFFC6FC355A726B0EB91D66358834B1DFCDCF5738F929226A63BC8F861740D844E47E2D3B731D03A902F7627C0F287F1863CA4E29773E966C9BDE3D6EB2C83F1FEA43227BD9B556B9773378F3D5CBF571EB6877A334C438C8071B9CA6B8F2AD85E66CCA1312826FC0428FA80AF251D13E3BE157DE900203A2B2F09CD22ED5CB33A71A10154828784BC0D9093B731096BCB14FDD8A59C06BA7BBB6F46285EB75BE0F7E5143E16FDB3B0309303392E62E536299C825293E5764040833BCD0DBE3FF00122F56C1C2364B798293B9CBE3000000000000000000000000000000000000050A0F171D25""") + ), + new SigVerTestCase( + TestUtils.hexDecode(""" +6C9E7A1EE36625760E5D2F33DF2929DA56203234069160E5F2BF039C11062273073C237566CE055D871F38ACD1A9859A824467F19BE68E4F00645D225C42C85A557D2C5ECB442B0F028A6528898EE2B673D863F32EB9EC8164127541F32519BB88E034A03F46F7D193CD3DFBADF63557926C5C8F5B766A7FC5EC8B3F948BF7A821B54C9441AB0BD833FD6354CEC706FAA500ABB5289B90B1BF917677A29D115F0094BDB48DC72E261DBA120BA6FF5E52A01B178981DD8296444656D9442DF9CBB6BFDAE56A230F6F29F94CDCC265576AA8752ACED07E99895CAEF0168BF83D23FDADFBB928CBCDABA25FE2CD26ADDFB0DACD74940F351426942F176FFBC5F3456DB7C912AA16B86D0745F87C9F45370A8456A1ADB51DB4052B5C9EAF60AD7B80A42EA4BF92C841273AD761DEDB0D34BF579600B149FCCD42AB1549BA0ABEDA57EF71D1FCA5702AAD083299BB98300189C25F3B270A87658D0B2EA56524147F739EB6C676D7BE73DD3B95B10C55AB46FD01549C5168BF7DA13A499785F35A1E3B56F4C567F54EA9AA2817A336383643FA2EA31FB1B73E10248DFCA05C04131266498E1C9491135A50E63D02FADF4165FC9E15E3E1B32FAB8337684C49193E1BC4EDEAE373A267A714AC1F909CC657CD8066646327E0EEA041AC9F2AEFFC80691BF60D3C94C642557E4299D395922216C65E75B7E1A5028960384BF816C9F7054829E7985B5841A733F33FCE2455EFC89BAE84B47990E8D0AFC6193E4AF9BC680AE24FE591E88BA6A2AE12DA3858D21F492D24ABC4FE4FD52D5ABF24BD254687B918792F0A003A5222DF45038685C725CE7579E02CB168BBC666ABF669856E10537C9291692C0CB0CFA906270AC2C7B7DC31D4F9283CB2DB8A462AEC0B9807BBF4AB4576FEC6226B4179322B67AEA53BDDF9C9BE5E0DBC43F78743068AB5BE49F0E62F8E2EB1B6C6736C05C9413D065CE0CCB790548041D7E832881A839B5729AF94AB79FD8A16DFFF78CAAA141D97CC0650F86262F26159BE8B361A4A041E9A0B6511BBE3355A4BF57AC09848847EE0243C3BA774776F7E9A227275D74E6E3101D382818763ED1E1353AB9EECCD920CD28922D559A4048F40F062164CB661C4F4AFA81A3D55933C4791EDDAA3939E5AC342B0AD1F438A532C6CE786681A870D94EC88A334CCEFC6ACE7D988A1A82BC0ACCE785F123BE23A7C92AF108E5ED4F0869E22DAE273556D1DE386623A6C3F115BBD119271D3FBA796F618B53959FB98012E7D5B9AC688940B87E2C9C065524A00D3A4F4DBF52F4B1A63EF5C46193BADF7AD7F988D4464345B2C3E549684F2F905F6F89DD641473EC05108A52D8DBB91768C541DE520B17666970AAEB506E75D8EE9F4B4455B71E0088AB25655213B75859D25F559D3C324D283D397ABE6F0AAA386815768D03357D775964902413153E3560CCEF1FD44B65FF1B287A92A9693F034B7EE668934702D7501CAF6DA4EE98AF4E8E64B0340E0BB8BDC533B0EFEE1915A4B68B93C5E95321EEDC234AEFE71AE2E5DACEC2F52F83723A2392A7F8E13BC0301CD104D852E62A7F828AD329B3D9596C58E13FCC0ED96C1C48D82A2C0F4D9D24DD8421FDCCEFD497A9B05FFC50904770401373FEE7DC73773418AEB4A1F599A4BB38EDE8D10A3CC83A1C72DE921969E3CE3E8EF2F7DA89D344C80D61CF9C5A423B1A4F3567D96DB2DA3DB9B5B5FA68156BE7452C8A0181BB9F0DC75CD9750883D0DDAE53FC156D67A74200869046B41DF4BC4396993C08AA4897A0BDDEFB55F69CC1C4D7B5FB150408427B416F73183F2B3CC16E3B7DA63CEE1143ADA1A056626A077B6D21C3DD974ED907C5A094019225737EFB93319AD3B40A4F434AE49D28391C17A999C744A68C55A91B862729583D3DA46EE70C5CC461694167D32D21DE75327732C63BBFBD7B30DBF2057A0D681519F6E4AF608D4BCD0B4750726770E156AEDE85417BD759D5FFE401CB2996F34434DB428D9A417037201FCD260FAA98084502EED5C27A8916E44F5929819D21A69CE16BCDC3CC8141E285EF897B1402C15C952590119051E369A1B7BE443FEAE6E32BC8F3D647FC5315A5200CD5238DC6677466EA86EF8D18E5A79F262483E896B8277C741F516FC040C1090F2495BF1650B02AF30456733A071AF47D7A15BD8E32A49806455D3BEA74AEF5D00906AD2F0C045354EFDE7C9A276E73D9EDD11D1CA5C297B9A6851E7F67E21EB061BB55D9E673C4A75FEB84D52629EECC53C24BEA95153051AC206C87DF55410CA1FE6CFC3F403A6D9D43EA84C60C945E642B2836338B5AF9F69E52708B2E225933DB320BB3F790D397F22D7B6F8A433CDACE9810AA0E27C699555530C562DBF7517A4162628BF10D1B6DBACEF5C9ED51E55D9A89D60E0FC378C47A21D5E0F2DC3BCEF5E05C6E0261530FB027E5032558CA2B47005BDDE99909930391EAD7F3F0A96B3DEDA54A11145F530E51DEF892E5AB0204D614E6E38AFE79CA92C28158D570120353B7A4DE0889846D835294939557ED0AEDA270D4D73ED84D3D49F9F032D43457BF59BB7D66359DC53F9B46963B21784B06CBCF04BEC1E33A33371532716C9EDB3FBEDB81999B4372D0945C10AE826C60FFE93170B6D294B3891B0D2A7B35B28A8971845DC2FECE237B80F20B379CC4D136DAB3FBB3792C63EC61F5C755BC9DB35086FBF46D2B7970DCA2A8523FDB4C7A0B8E42F8AF9ACAD2A0EFC113602A4EA62E4EBB7D269C3A40BA2C44EDD2956"""), + TestUtils.hexDecode(""" +C4F59FA2DE30C8420A7E7F096BAF6AD69B1C15A5C6E61C9D82AFCFDB6EB8F275BF5787186AAE781F487F9F88758C9C61F35D5083EE70424B0D0A51575010C2A907F49608115D33EBA0031509322AA7D3061FEC3162F96A565F98769E9A19235D89D1B21D60A381DF8EB37D58C6A2E483A8EB70736E4B7BB911F7AB923DC29F1E"""), + TestUtils.hexDecode(""" +E895DB64C57BC3C2A97F0EC933410E98F6216103E3423CAF06A671964C514A694EB6F65CBD1137CCCF8881FA403C5FA0E0B2F36B9F4009C378210D29E54A7A5A9B793197CD6D2F38D7E1F3ACA69D48881389381C89FA676DE426D634F9A157055F17283ECE8248CAF14DCF11E2D56355B047DF632A18482E79CB2D5A743966BAA8A76121BB69C2E68155ACCB0A31DA6EDC73CB09A9E660FEB20F66C7BD967ADE32149C5552EAEB2EA175B56233F3B370EDD8679269CE0D2B43F6B2F65FE957E7AB37B982043754EAC8A30B36C10004EF13C692E219AA7AF0A4C5286910C7100DA41E17BBEF2DA2AB03ADF3074BA1DA15BCC84805B89B9DA88E9B400AFB7E3BC8338D354DA953AC0BAD822756CA92E5DD9507F42BFEFCCB32B4B91A2BE5EF34C2CF1177EAAFB250AC9ADEC4BE71807589F1003227F9B76B74E07BA67AC60819B2AF766A47FFFC7B76D3A7C077F5EC69AEEA3E963859B82C2ADE58BEC2152EC8205110975D37C6505E0DC776FDE071097E93013D1004F4E1A2FD79B877ED5025F527F3BFF137F041BB9BD001E949F08B4CF88DFD32FC7CDBCECCFDB0FA2DE7823E110BCFF58A412CEA2795753E9C89678C3AE24268F7489F72974B6955EDD04E190D99BB0D7A252FAD5BBA606C1A1F3ACA733BFAE3309EA0A6EB7D07E36D8CA336D2644FCE1A41895D014D1A60CB106F3F8075F9378461738D63D115D00B024C677801050A1B0B50DE057F85DB6AEB2C9D6BB7402A66E3AB4DB05C58BBDA12F695958B8AC7B4E45EC6C952F679C1EEBDF860E348982779AA6988EFC2AD1DC1EAE22A27A5B2C61C97B3B2493CB6C13C5F6E20A67B88D3C3ACCFAF0A425742DF240634D1EE593828FE6297446C076F979055988AB834B2BD82E14DC086400E1C956CC0C30CE7BFD962223D23FE9494964A811B93E8D7B8F34C89AAD45DD4113F2AE7BD94B53FC86E8B2AE82E51EC6F3EA4C30D60B86072748612D1607056B5FF6A4500EEE78A5A639C7B74169777626864DD9EAEF0E3AD8493D831F71DEA95BBFCF81423A266DE56F3A8FE8E6C3C0D612FB62BD642188CA71CB89834F30BCC28BD178845F1F6F46C03D306F7ED4E68759427AEC2701198C3C05D385DFAFD528CCE8425BC551469A0ED681BEE4D12A843E333B5A8E0517FC61906F9C4E7809BAED4D3D16EB22F1FA9AB402D988ED59F9FED0455E9260FD627A24A17FE7CB63E530B48F5FB6687A2E8C49DA79FBD69A3400056665DD11D19A2BC4DB1D374AB6A6E42472A27AC6B98F676E8EDAADD514F6D44DEECDAB5A6DFA0F84F139A803A2524BF335DC52EA58FA50D98FB5CD55D5D50A663CF647EEE56FE8E664B3BCAF9E333978A7946973FD113E4FD3924E6C09E60386444214DFA7A4D671FC23890637EB859134D79E265C59CA3ECCDDFA018223C9BAE1CCA103962078BC5F0DD02246FA28324F7CB2FCFAD07C25B4BC2D888069B0CF5F23C761C0E47109881CD31456A64B940B4BB9B4C2C3B8E6BA834AAAE69FDFC47D44B3C96887ABED36015E7B64E8542928F277CBD2D3C512C24DEEFE590E81C684E063E7AADCF117B48943DB771FC2207F57A745357555D419C9CDCA35CC1A7100A6913A3B6AACF796FE3F94DD2F818982716CE0316542A1B957E12DA43E231542CC14FCC66D728A68326B2BC311248330F3E98F81EA38CA924A8E4DA97CF673842C759F935BE88163CE97FE4D9457176F5B8908AF948F74D5D1DDBC521825D931C63CA8A8E12242626305AB6A2E0624564EE041983C18C2952EC3D9D159BDE3985CF77897EE2DC888112721D4854E914A5397E08B54F4A54323FF820821BE026EA091ECA6B7D80D91E3DCA2EF7848B86FCA6BB40CE48271E1008368E3EBB5E395E1CCD0D178F1A6257D26B6BA4B7CE532CAA1E76CE28FA4CF9E029E2482B94D3ACF97A326D235D1BDC89F70002198451D9F1F12CCD5BCAECDDE9E14AC80742EB31E6464C83210A39F35098BE0378D074CE1CCD1EBC1C7770F778D605F2BE59DB7EA07D80CCDF55F16E985B142FB7BDA07AA7DCA5B201E1950CF9A728F21E9A9D8AC4D1327E3BC0FF339A250522F631DF2E75955154893E4A1AAF9866FEE1637EE1AA5106D244E99E6F31FC5601BB7B79BAD82860B1D6059D9B132E026418020DB06EB8391FA15B7A0F29E36D966ABD3D2A2FF3F2AAC34C8B45C7D2355EDBB80B224BC106EBC6750E55070F85A7CB6003394E5161AE26F5ABF83F0DCCCF69B86139AF8694FE1DC00781EAE09CDB421814878043DC9B0530E5545A165E39A9B7DE88B4AD2AEB90D3C329412ED2FE1D97B732C8439DF4F83D228835B538DC278FF0A2DC42F41B00CE3ACA06B05C4839B896931515D78EA3673A378279F4E89CE08E3453FF2FB453BE031C6318628A731D029FC7BEA2BA5EAC4916278B938A6A6ACEF5BFE2158F2AF43D8E56A0649DF28A250D2F2536ABDE1E008EB631F4BD0EB55573A40539A6004181A9D2BF7A1E53504F11E014840733844131AC668946E5B827289AB6B21366C5D0E2649219B92C4760DFB705F7F61A96564C9E840D14B0BB0DA82DA50F8B8E752BBFEA3B0A337BE124F72D8F8249195BC19C3E0B62EAE496D38CF7500B4F10665FC2D28B9EA935F7E316472F4FF401267541BDB62301554B2009928C6445BBD0EF21D09972F35081ABA9091A6C23FED29F5CF9E0779F7EFBAD88E62A454442B30079BE0AC9C64826B98C1E1001CB0FB0F0A95F7965FE9312BFDAEC33F95065C8E59D3950F80ADC7FB334F202D3E5F8DA481C9B54A75983930FD1E5ACD16284F07193FBCB50D0DC00EFF8203144C11EC61420FC32D7982CE896406BE769A75DD8D3CAC753ABE5A278655BF54BE33A1B8374EBEEFF212C39CE514668F1C456EAA2532828C84293F1A5BC9EB5DEDF558A9B4C1239F77272C67E1AB28E1EFEC5893E09C10662B53C8B8255B1C8DC8F8E5120A25C75EEFE79C43F7A8B37DF9D1E4F32486933DA1CB0664C5DB39E21BC227B0CDFE7A5507F07F218A7A47DEBCD9DAD7247B4D045A13AD4F75EAD2D45C339D0DF04577F2E0FDC780392553033C738852B1BE4E63EA3897D6C9C4B11AD6B58D3E2D342D32840F649DD83E759866B7381A84C8ADDDF413FAE18E6431B1EEA73A56CD889B76BC9786BEDEDCA2541E4C9B24E28F58AD374C1D93DF2D3F2C37EC594A0498C574579A7332F72C0F9750877FAD5B90B968D88F11682C4071E4EA38B816AEAD6BE54D2F371324F2475B862C75424ECF9858AA4E200CFBA412D7E3E6C308D8DE11DD185331AF9D41AFE8879965D6746EF21FD98D3ED3806FB5C4619C98E347D76B8B89849395561EE286DFDFC6A04E1D47E9F5B5B49257784C39364DFA88AD630DFA59CCA3237F4A2B141A813D22C6FFE73C2D99ADC824D93E06A54B6DE62C3125D94B49E950DEC361F961F56D3671C9925377F6E670665322B8489E833D3830ECCDD0F53F4A4F9D68F1445F3AED5C9D766409B59BAE7A72912E98B3BB57342D29B6ACFD14336B7B8B6B7549AF8CC8845E10C2811287281985D5D47685FC589F2678ED893F57B85ACED75632E50DE5E074E6CEDCF1AD499BCE67A7F498564DEEC677C708388DE8FD7B099CFC116096C45FE28890B5EAF06169939FDA35E1215F238E8CDEDFE670065F5DE3272A232FD53C250F5D779B31694FBA91B554803676E4DEA288463FE1063009E9CB76C317DB400ACF4D2D2B6D16EDEBA4108913F60AEB252CDE413690CEEFDCFA638963DBD04F4CF21AD74DDE65F0F1E7CE70AF101A6DE9A59DB21D38027DBBF76167827950B69418266AFA444C728DE3624A1C81E5B1641DBE879CD822FB2303CC3A9FCEEFE3DDF7DBD0B7057248A28D6062D76EB13B92C9C9D003B69E1842A54C09CF6B484520815E2BB237288C64FC696FD3BC45DB30CB86465DF1188BF47956E5B916A8009715CC9A9A6DCE44C54F928816B41D018C5FE652FFE4E33F352D383A9C1365F02ABFD647BD6B42AD163730F8BFDA1E2BE5F614D79597825BA09F457D3CBE7561E7E89EAF059E977D1EE88848B781F21F723890FF1F9873928412C8F11EEDD2C0C39C9512790986A19E17B2B70A4D7CF49D9D18CAA0C2023134CACD169200D8817FA321F04ACC910613DFF250EB325DBEF29EB5611B2AD2A23EDD538049B3F43EFEB4D60983792B4BF05567944AADB7AC4D3A5D80A1B9D8448B4C0C115C3B5AD3885353F47D5FCB9B7D6446F1A7210BBC667FC411415F23CD40A2A3D64061D71C67191571A97D01088A24B6711567FC89106732D8892FF985B8E6CF70163829CC085BE4E408315361BB1B2003D6413220B134506D3C304C0BBBA9C9C45D3651E0571B6B115177213D8595E143DB90BD72F7EB974D8D0A0317409D64D5837EAEC9B8D44DD7ECFF6CDA9F729382A43B379CBDD43FFB18AEA35C1A996CEF1488D3B7A81EE7CFC0B9623418AB3919A6EDDB99F222F0DDDB2F32A20C8F84FBF4C49B4CB3EB50D9C4CD25A6F7175467066D25E6437B67F2DBC70C2E6EB0BDE2386D03014A789FB6DC08EE33C0C67951DA9D74B9C94845D2A99037E095FEF7919920FE526EB5DD0BA1F97DFBD2DDC31609C1B7B45EC3ADB586FE3030A0C7A9DD034A3C2E6F9849093CEE10A181953547F8BE328720A4A5A8290B5EE00000000000000000000000000000000000000000000060B10181A21""") + ), + new SigVerTestCase( + TestUtils.hexDecode(""" +6C9E7A1EE36625760E5D2F33DF2929DA56203234069160E5F2BF039C11062273073C237566CE055D871F38ACD1A9859A824467F19BE68E4F00645D225C42C85A557D2C5ECB442B0F028A6528898EE2B673D863F32EB9EC8164127541F32519BB88E034A03F46F7D193CD3DFBADF63557926C5C8F5B766A7FC5EC8B3F948BF7A821B54C9441AB0BD833FD6354CEC706FAA500ABB5289B90B1BF917677A29D115F0094BDB48DC72E261DBA120BA6FF5E52A01B178981DD8296444656D9442DF9CBB6BFDAE56A230F6F29F94CDCC265576AA8752ACED07E99895CAEF0168BF83D23FDADFBB928CBCDABA25FE2CD26ADDFB0DACD74940F351426942F176FFBC5F3456DB7C912AA16B86D0745F87C9F45370A8456A1ADB51DB4052B5C9EAF60AD7B80A42EA4BF92C841273AD761DEDB0D34BF579600B149FCCD42AB1549BA0ABEDA57EF71D1FCA5702AAD083299BB98300189C25F3B270A87658D0B2EA56524147F739EB6C676D7BE73DD3B95B10C55AB46FD01549C5168BF7DA13A499785F35A1E3B56F4C567F54EA9AA2817A336383643FA2EA31FB1B73E10248DFCA05C04131266498E1C9491135A50E63D02FADF4165FC9E15E3E1B32FAB8337684C49193E1BC4EDEAE373A267A714AC1F909CC657CD8066646327E0EEA041AC9F2AEFFC80691BF60D3C94C642557E4299D395922216C65E75B7E1A5028960384BF816C9F7054829E7985B5841A733F33FCE2455EFC89BAE84B47990E8D0AFC6193E4AF9BC680AE24FE591E88BA6A2AE12DA3858D21F492D24ABC4FE4FD52D5ABF24BD254687B918792F0A003A5222DF45038685C725CE7579E02CB168BBC666ABF669856E10537C9291692C0CB0CFA906270AC2C7B7DC31D4F9283CB2DB8A462AEC0B9807BBF4AB4576FEC6226B4179322B67AEA53BDDF9C9BE5E0DBC43F78743068AB5BE49F0E62F8E2EB1B6C6736C05C9413D065CE0CCB790548041D7E832881A839B5729AF94AB79FD8A16DFFF78CAAA141D97CC0650F86262F26159BE8B361A4A041E9A0B6511BBE3355A4BF57AC09848847EE0243C3BA774776F7E9A227275D74E6E3101D382818763ED1E1353AB9EECCD920CD28922D559A4048F40F062164CB661C4F4AFA81A3D55933C4791EDDAA3939E5AC342B0AD1F438A532C6CE786681A870D94EC88A334CCEFC6ACE7D988A1A82BC0ACCE785F123BE23A7C92AF108E5ED4F0869E22DAE273556D1DE386623A6C3F115BBD119271D3FBA796F618B53959FB98012E7D5B9AC688940B87E2C9C065524A00D3A4F4DBF52F4B1A63EF5C46193BADF7AD7F988D4464345B2C3E549684F2F905F6F89DD641473EC05108A52D8DBB91768C541DE520B17666970AAEB506E75D8EE9F4B4455B71E0088AB25655213B75859D25F559D3C324D283D397ABE6F0AAA386815768D03357D775964902413153E3560CCEF1FD44B65FF1B287A92A9693F034B7EE668934702D7501CAF6DA4EE98AF4E8E64B0340E0BB8BDC533B0EFEE1915A4B68B93C5E95321EEDC234AEFE71AE2E5DACEC2F52F83723A2392A7F8E13BC0301CD104D852E62A7F828AD329B3D9596C58E13FCC0ED96C1C48D82A2C0F4D9D24DD8421FDCCEFD497A9B05FFC50904770401373FEE7DC73773418AEB4A1F599A4BB38EDE8D10A3CC83A1C72DE921969E3CE3E8EF2F7DA89D344C80D61CF9C5A423B1A4F3567D96DB2DA3DB9B5B5FA68156BE7452C8A0181BB9F0DC75CD9750883D0DDAE53FC156D67A74200869046B41DF4BC4396993C08AA4897A0BDDEFB55F69CC1C4D7B5FB150408427B416F73183F2B3CC16E3B7DA63CEE1143ADA1A056626A077B6D21C3DD974ED907C5A094019225737EFB93319AD3B40A4F434AE49D28391C17A999C744A68C55A91B862729583D3DA46EE70C5CC461694167D32D21DE75327732C63BBFBD7B30DBF2057A0D681519F6E4AF608D4BCD0B4750726770E156AEDE85417BD759D5FFE401CB2996F34434DB428D9A417037201FCD260FAA98084502EED5C27A8916E44F5929819D21A69CE16BCDC3CC8141E285EF897B1402C15C952590119051E369A1B7BE443FEAE6E32BC8F3D647FC5315A5200CD5238DC6677466EA86EF8D18E5A79F262483E896B8277C741F516FC040C1090F2495BF1650B02AF30456733A071AF47D7A15BD8E32A49806455D3BEA74AEF5D00906AD2F0C045354EFDE7C9A276E73D9EDD11D1CA5C297B9A6851E7F67E21EB061BB55D9E673C4A75FEB84D52629EECC53C24BEA95153051AC206C87DF55410CA1FE6CFC3F403A6D9D43EA84C60C945E642B2836338B5AF9F69E52708B2E225933DB320BB3F790D397F22D7B6F8A433CDACE9810AA0E27C699555530C562DBF7517A4162628BF10D1B6DBACEF5C9ED51E55D9A89D60E0FC378C47A21D5E0F2DC3BCEF5E05C6E0261530FB027E5032558CA2B47005BDDE99909930391EAD7F3F0A96B3DEDA54A11145F530E51DEF892E5AB0204D614E6E38AFE79CA92C28158D570120353B7A4DE0889846D835294939557ED0AEDA270D4D73ED84D3D49F9F032D43457BF59BB7D66359DC53F9B46963B21784B06CBCF04BEC1E33A33371532716C9EDB3FBEDB81999B4372D0945C10AE826C60FFE93170B6D294B3891B0D2A7B35B28A8971845DC2FECE237B80F20B379CC4D136DAB3FBB3792C63EC61F5C755BC9DB35086FBF46D2B7970DCA2A8523FDB4C7A0B8E42F8AF9ACAD2A0EFC113602A4EA62E4EBB7D269C3A40BA2C44EDD2956"""), + TestUtils.hexDecode(""" +C1E665BF7B8BD0198F069CA17EFC55B7EBBF9CC9D41140BDD0B83AA08062FFC717D3F6C22DF38EEFAA6EEC91760CAE0B3DFEAB78B03A7AB7A993B2097B7B887B9812AE2D0892B696374C034FC9E95083C2B61B09DE97D9C500FE55E489C53CAEBDB57BC69071C15808890F8A007BB5FE773CCFB729463113D93E9EC9EABE2047"""), + TestUtils.hexDecode(""" +051F8A9A5DC6D35B1485288359F818DEB027E1231DA8C048E79E9FE228AA0E9F1C0B7F4C573B5DB8CCAEBBAE8EE38D8FAEFD3B8E7730BDC0E9DE365B20E5A0F9635A0B39C7C0D6163B7876ECC6ABCD8A5F608E7253537C1C94C209C8448E02806B2B5EAFAE2483170B4E4450380C2A87A51F82B179EE0F46509404A3A9BD74D04BD75635B797B500F656ACAE5DD76B04741792112579E24081A6C88BF4981346E2B3D38291026D3AE47BDA50AB0B23B0881148489CBD057CDE9A4F6FF108B7ECCEA44D599CE3ADED82AE0E8F74DB7D604161C8664B7389497EC9F35C46FEC064BB867E867E9309C10FBC07BD5E7B8A74BBEBC1BD0E4A9B36EFE297E9F2D23DE32ED704EAA377F5C3BC4BABCCAD5B4B6B9A137F23C46C0423ABA3F1AFF00C6071CBA51B7D0A8E677F5138DB7C013CAEE1F68501430F0F448AB283692A18D15D8A46BA620EA906A3032570A659F594236F0512389E1DE63B8E40AC22DB79DE60CCB9BCF0B20EBEF676A91AABCD01D3AF882931AFF8C86A8C946E09B8B5CFDE62D53A03DF07163B081B293EA0287AEB97D1762F34361DDE654D400DFAE5B351D90742A0A269865D49C9221DD89E42FFA63EDDF449B10458CFE2EA7E1A16BD22FE73F208B4472DA8094F28CB9DCAED6E843C57E9E3258BEADA48D7761FDE0104AC6F0CE09F95E1F4AFF00515AC2E3703D2FC6D757B12DFDC044E854E50FF2D897900B0B59BED90BA4201694E29E6A830D8039CD835C706EF59E7A6B0ACA7B7D0B40D264661711E0372BAB7410A74460D07FA988A8617D31074950838411037307B052FD536822608F9D15BAA780AFAE1A8D87BF844D3A4FB31A176BBCBEA46A72BA990FCF821AC3A73ACA01E09A20AB93FC737ED4C4DC482BF9BA21D7178D24DD5D6A29633386933A3E8F28982731F07606AF28BD2D81004B044B4EAAE67E29840BC78EA66FF840031D8B2894B603733E1A0398FB0E4952B2ABC567668443581C860F87A76774E6742807C39FE99269E3199DAD02B246D7AC24E5BD9DD91F7D16A76E72318882FA21672A7D5B1A4F212954BE2B19897243F60C18D1DED2AFDF69DAB8C9B10342471C633B33C52E95A85D3142F2E46C681AF373C5E92BC948FBD31207F015DD32DE2591DF4639E4E563344D440653592EF2685E1320AB9E51837F6C06D07E5462599FC6F8BB120826E738E2223CD4B8C7CE446ECE681DC6D6BEF1D6385B0AE7E404F502B87989D969B81CF42085A7B58A41EF73EDC73056DA72EF65A7AC8E284E7F51E723102CFEF903688F870CEF1C7E5264330E3033691680050E926E93A1C0C4161A7DCA14A0FF338D431D68FAC204DA28CCD1CE7BA3B7F3C45B4FC74D9E754A1A2F7F23F0FBE8D2FF01CE4683D8842E8A1528589E7D9260368A654CB514A85DA9C2EAB74C66FA17FDFB256D585D28C1DBA35E18779D7B6DB876CC0A98CFF752A0E8DFDD532ECB04C4101AF32E689D13874B9F20AF652069C1458D7FB382E317AF49083B5870078B39221464F376EC0BC2DC1C3FAF10EA4EA87A2F9D547B535F60406E8E68AD190CD4F00EFDCD9D54D4810F31B9F68F0D95E32CDF2747B9C20FCD1694FE034EF6B5460F163AC78BA235A441DB2B3AE84BC28CEEED7B3FC2A4D63330D14186658788DFD7652E477B1310317C86921394219D75FB6FC319575745589F9E2096801E57E6AED2369FE115C2D937EBEA3602194B7432B01F55E6C9572CD0FF8BE8A4796815914D5F64D93E0E709C3CF88741C851C8BFC4CCE6F0AE60A6D2F4DC6FD8AFC82E065956971FB8B4160AD68EF7BFCB3A9694CC7EDEF64FF08011B183BEB7A2D3D9024753B59900D27F52DF6D4B2576BABA673A0E33CC57B501E1C74F63A988E1A157078FA8B3F2A143CC9D41A35412B4E0CE6B1D9CFAE7470BF4C778D026A9AF86DF7F974E2414FD7C5F0FF6D62293C6E2A62D4C5268CD0B604047C9658F97D9A7B86E1C953FFF95CB478028FDCAE6E8F208AA208A282446B2CE8B4C7E893E269FA8E02C082F82966A4AE3FD86BE89A8CC8BB3D6B105A91DCF76FEF700E5AA4A15BA0F753129D3369915D7E896527CF6E71C363EF65B2218A5FCB8D8FD96D6A63A8BC547EFC942DCE1276E268841BA00E35769B4AC706BD65B275BABDD530771D854EC38AC0529729786A86C7C4161B3E7074023516C84B4B4776AC47C2ED1587861126A7A707978F2B2B2972C20F237FC223B56A67538F9241D926DB7C992A3FDFDF999884EF83EAC7DA0F6523F53CD40E473AD370C77B30DB2FE408783D24CF4C3512E3C6B677C41A67849FA1792313581EBBDB7BE0BB3EE85330FED8B5A1915F6343F3B7C928CD363463385436038B64BAB5D055BC39D18F9A1A8196AF8DDA5A1F428434958F5C89F07D7A53CFF2118E80060C5ACA71975C4C92A589EBF5746AC92C50FC1F915C146C2DEE7531B24970790A4AA7DAC425940AFC4C88ABEB998D549681C95ACBE9F7E274521D44E9EB759C2946504161AE7FFEDAD3E62D045AD77FE8C2B8ED529843DD341E2E50559A29AE26D431C9634C4C19A84FA0257F71CDF27C33F14D57347BE8B19D254E3C353CDCA10489F06214161AEB2A9D3049B3CE4689503621C46D192C1421B4B033775D9218DD2E216600E64D977CAB0E1675666A7CA773E4E139DD4EBE94CE35A28284755C52BE490514B25FFCA4174F54E8A5F715F924949C1467A282D7F2DB468DF363F9A55E5D7858D8F95D8083D6A594DC1B07A8C4FD4AAAEA0785EA3D9B50798F0A96AA386F17C2BFB94FA8EA3B5EF71012AF9285CADB1FE330A267555A942682F9333AF2E81515969B76FDC020F9CD29E848B94F26F4B53CA5144CBCDA1AB6CD2FACBAB0A2FC0F5B88DA0AC0EC08B9EDA7CAEF502FDA52006815743520F841CFEC3B4D9AA732DE408D6FB14739E8FE77CDDB68A5F6AA215B588F1491988B4460F6949AD647DE9105CA50CFB413A971BC8E6179F0724FC28D1A7D30C41180735F4FF6167810D9E88A5F7FDF791BFB474BB5478544EA74C9F07598D038CBBA17B83228A18B2AB09A8BBD2D2205EECDF01044D5A1B2BD50D2C8E3D5511450A4E594C1CE7067A6E14128BBB36E95C143EE6A51CA0EEBDBE47E9C5A87E81BB904013DC892D03F483B1DC82986DCE7A6E10192E6743283202D78D11B2169602A75C2A688DBAD50C9FDF1A1A15A470D882ED4B5207E659A94776ABC3D3583E1D2E85291D3726E75B7AEF9344180D325583A05266C196ED367E906121C33E701D428B46865BF32AEA4A90262866A024209A7663EDA4C340B5AF3E899F009EEB5E8D5003635EED501CC02D5D11F504C823C17E961D0BF611519961BF422647D97119F5745478888BCCE367639772953C5731434B28913F3F709AF455053F6B09519AEB6B755CB02CE74DD814714A2E0B477C05202092525EC03C5B365A75086E3281D4BB5C3AD9D742806E58B5CE4E1E95269AB18B68B2928BFCF7EA683967C0B88ADA99FF35E1D5A661CDFAD76774B42F858AA54626B88050D992FFDE16FAD3A8CA496CC6BE339977BE24D33E8BAB86B421F4BAA9C12A93117E43415929F0C4DBC9737EA5586780886A8EF4E4295DDBC967A2B5523FAEE0C060468F9704509C4CB14028E8A1672609A8CED43F1B06981FBFDFD52296D7BD3B4AE68E7D54BB2405799278AE29B66E258D3B9D276FD34E192BDE869092F6A7F761C6DDB0DE9454823256C7B17ABB91003B1A3B66CBCD4F9ED068409161635F6DF9459AC382044EC14FE8B2A586FE02C74232BBBF27800ECF627AD1C6ECC93C13EDA2DC20C8D6714C519D6A571E708787BF342DBCDE10EB1BCA5A7FCD971CA52BB68FB33ECB7F90AAF739F0C5B61BFED72CDB46A712DB6928F84892D3EC2F6C7023A6B664CE9CFDC33D2F09D38B5E4D182C73FF1D7B474C8AD6E883ABC78FEC75C8A390CEA561A86B92E2A4A1950997594C29A35E4A71B0E484FCDA63E5EC9666E0A463325DBCF7258D36B85099AB7C81E70FA66F1A471D4C1593AE68404F31AD2667017C9B5B3843FBC48D831F6A9B5FAF7C73A8478A7DADF28FBD9DDF979418870AE61E94C6BD47FF2C39073AAE16FF18B161B9B21413E66E489EF9F8784E5DCBBE29127B0C51A5C1E2A04E9C8794964D1823ACEB9ED0DD555964687848629EE06B0712483CA30D6D4A91E047EA33D30A062D8249278CDCBBA2A1B3C133D3E671FACB034AD0F9AA40628C0E2288B56F7A76DCDFEA762A8DB323B44925285557C3501999CBE145D15EA82169007A97EABABBE69479E03D40F2FE9217F14664726DCEA227107412B3CC742E4ED168E051D9AD4468131AB035708ABAD78659CCF5988F70680C124468CB80BD9924B0E41CB25AA69E7877CF5EA348403AD0899A5FCF35D4F22F3A73F0207E96785F4EB9AB93B6F10EE0B247D31F3D62A85B99C88CD3B19BB68E69C51AD5B0A8E9E34ED611E24FE2644F1697A8A11B64B578FEE1C5CB31A605CD987D765FB68D833E4BE9358D869F4DE0362E6889FBE8E95B861E078CE6CF0FF35768AD49803A71E8DC60296032E50A9D0A4E64A3D4661E7C55DAFC6FDD1B18EB1003D290BE486C520A2F8F0EFC1CD2CEFBF7E2459CC7BA88695D1122A7494A3A41C329EED2A8CD2282A607F93A2B7DADF0F32414C6BA9BEC0CB00000000000000000000000000000000000000000003090D101922""") + ), + new SigVerTestCase( + TestUtils.hexDecode(""" +6C9E7A1EE36625760E5D2F33DF2929DA56203234069160E5F2BF039C11062273073C237566CE055D871F38ACD1A9859A824467F19BE68E4F00645D225C42C85A557D2C5ECB442B0F028A6528898EE2B673D863F32EB9EC8164127541F32519BB88E034A03F46F7D193CD3DFBADF63557926C5C8F5B766A7FC5EC8B3F948BF7A821B54C9441AB0BD833FD6354CEC706FAA500ABB5289B90B1BF917677A29D115F0094BDB48DC72E261DBA120BA6FF5E52A01B178981DD8296444656D9442DF9CBB6BFDAE56A230F6F29F94CDCC265576AA8752ACED07E99895CAEF0168BF83D23FDADFBB928CBCDABA25FE2CD26ADDFB0DACD74940F351426942F176FFBC5F3456DB7C912AA16B86D0745F87C9F45370A8456A1ADB51DB4052B5C9EAF60AD7B80A42EA4BF92C841273AD761DEDB0D34BF579600B149FCCD42AB1549BA0ABEDA57EF71D1FCA5702AAD083299BB98300189C25F3B270A87658D0B2EA56524147F739EB6C676D7BE73DD3B95B10C55AB46FD01549C5168BF7DA13A499785F35A1E3B56F4C567F54EA9AA2817A336383643FA2EA31FB1B73E10248DFCA05C04131266498E1C9491135A50E63D02FADF4165FC9E15E3E1B32FAB8337684C49193E1BC4EDEAE373A267A714AC1F909CC657CD8066646327E0EEA041AC9F2AEFFC80691BF60D3C94C642557E4299D395922216C65E75B7E1A5028960384BF816C9F7054829E7985B5841A733F33FCE2455EFC89BAE84B47990E8D0AFC6193E4AF9BC680AE24FE591E88BA6A2AE12DA3858D21F492D24ABC4FE4FD52D5ABF24BD254687B918792F0A003A5222DF45038685C725CE7579E02CB168BBC666ABF669856E10537C9291692C0CB0CFA906270AC2C7B7DC31D4F9283CB2DB8A462AEC0B9807BBF4AB4576FEC6226B4179322B67AEA53BDDF9C9BE5E0DBC43F78743068AB5BE49F0E62F8E2EB1B6C6736C05C9413D065CE0CCB790548041D7E832881A839B5729AF94AB79FD8A16DFFF78CAAA141D97CC0650F86262F26159BE8B361A4A041E9A0B6511BBE3355A4BF57AC09848847EE0243C3BA774776F7E9A227275D74E6E3101D382818763ED1E1353AB9EECCD920CD28922D559A4048F40F062164CB661C4F4AFA81A3D55933C4791EDDAA3939E5AC342B0AD1F438A532C6CE786681A870D94EC88A334CCEFC6ACE7D988A1A82BC0ACCE785F123BE23A7C92AF108E5ED4F0869E22DAE273556D1DE386623A6C3F115BBD119271D3FBA796F618B53959FB98012E7D5B9AC688940B87E2C9C065524A00D3A4F4DBF52F4B1A63EF5C46193BADF7AD7F988D4464345B2C3E549684F2F905F6F89DD641473EC05108A52D8DBB91768C541DE520B17666970AAEB506E75D8EE9F4B4455B71E0088AB25655213B75859D25F559D3C324D283D397ABE6F0AAA386815768D03357D775964902413153E3560CCEF1FD44B65FF1B287A92A9693F034B7EE668934702D7501CAF6DA4EE98AF4E8E64B0340E0BB8BDC533B0EFEE1915A4B68B93C5E95321EEDC234AEFE71AE2E5DACEC2F52F83723A2392A7F8E13BC0301CD104D852E62A7F828AD329B3D9596C58E13FCC0ED96C1C48D82A2C0F4D9D24DD8421FDCCEFD497A9B05FFC50904770401373FEE7DC73773418AEB4A1F599A4BB38EDE8D10A3CC83A1C72DE921969E3CE3E8EF2F7DA89D344C80D61CF9C5A423B1A4F3567D96DB2DA3DB9B5B5FA68156BE7452C8A0181BB9F0DC75CD9750883D0DDAE53FC156D67A74200869046B41DF4BC4396993C08AA4897A0BDDEFB55F69CC1C4D7B5FB150408427B416F73183F2B3CC16E3B7DA63CEE1143ADA1A056626A077B6D21C3DD974ED907C5A094019225737EFB93319AD3B40A4F434AE49D28391C17A999C744A68C55A91B862729583D3DA46EE70C5CC461694167D32D21DE75327732C63BBFBD7B30DBF2057A0D681519F6E4AF608D4BCD0B4750726770E156AEDE85417BD759D5FFE401CB2996F34434DB428D9A417037201FCD260FAA98084502EED5C27A8916E44F5929819D21A69CE16BCDC3CC8141E285EF897B1402C15C952590119051E369A1B7BE443FEAE6E32BC8F3D647FC5315A5200CD5238DC6677466EA86EF8D18E5A79F262483E896B8277C741F516FC040C1090F2495BF1650B02AF30456733A071AF47D7A15BD8E32A49806455D3BEA74AEF5D00906AD2F0C045354EFDE7C9A276E73D9EDD11D1CA5C297B9A6851E7F67E21EB061BB55D9E673C4A75FEB84D52629EECC53C24BEA95153051AC206C87DF55410CA1FE6CFC3F403A6D9D43EA84C60C945E642B2836338B5AF9F69E52708B2E225933DB320BB3F790D397F22D7B6F8A433CDACE9810AA0E27C699555530C562DBF7517A4162628BF10D1B6DBACEF5C9ED51E55D9A89D60E0FC378C47A21D5E0F2DC3BCEF5E05C6E0261530FB027E5032558CA2B47005BDDE99909930391EAD7F3F0A96B3DEDA54A11145F530E51DEF892E5AB0204D614E6E38AFE79CA92C28158D570120353B7A4DE0889846D835294939557ED0AEDA270D4D73ED84D3D49F9F032D43457BF59BB7D66359DC53F9B46963B21784B06CBCF04BEC1E33A33371532716C9EDB3FBEDB81999B4372D0945C10AE826C60FFE93170B6D294B3891B0D2A7B35B28A8971845DC2FECE237B80F20B379CC4D136DAB3FBB3792C63EC61F5C755BC9DB35086FBF46D2B7970DCA2A8523FDB4C7A0B8E42F8AF9ACAD2A0EFC113602A4EA62E4EBB7D269C3A40BA2C44EDD2956"""), + TestUtils.hexDecode(""" +62C2A85A6AE40091AE35068EB3E5B54803F495D49BC177F7A29282DF0C900E86F66155B4026064E7D6CF7A171F8BBB33449232EB5D7DB2B776ABBACECCD660294C25196E19FADA35E0F3524D78EDA25D614FB56DBA5BAC10D06EAEDD9644DA291DF305C1E91C82FA00EC470A8E822525895113A6FF7D1D52E7038B9CF4DB2227"""), + TestUtils.hexDecode(""" +9B829A093EC253FF3D955EBA3C0FDA29CD14089C6D699F26FC62BCD40F43D1582F2B693138AACA59A162CEFBDA6328F1BD67690C63B903F5062DCDFFA840DC2DFD4051F82A557FFDAAE8F4A4FB340D6F4AF03A19AB928F42DFD29FF8D028333A0C336D253C826175C5A194C0441DAC1C5A4C4A3E0B8394E43678DC915BC98628BF565C9E751BF9801DD6AD4A3621B50C8DD1520F0CFE475F5BF843DC2568B263978587322FD1D2709ECD869A77F054C0A45D466D297ED9B63F10020826836F531A06DFBE20BFBA0B3F204033783C5505BD82DE732204917E3DA12316559D07366600CD18EE2A329AB3B20BB0C9C607D0660044D2A9ACC5D25806F89DFD5813C9E54E0CDFC190A206300FBC8E2561BF3F23D04052902E49CD5DA530A4D2BC2E5F47EE93D0588AA66EC8CAFDD4B353D73B6C1765211405C080A614129CF9346A1593503AD75EB9C3CCC99DBCE1D937AEB7929A1B5351BE262FB2B41FCA6DD965CE596DBE39D07D20281A2ED74C35FAA474EC425A897978FAD88D470502008D9A0E08DFA2F6C33A0B4CF2456951109BF4F877D74D7681CF287F6DCFAE24D1FCB0FC69D7C4D33E20536C64ACE18F04A2AA8E767C24068F4BA45C4C49DC3B43AF803610F300D01C5CD9ED92F33BAC270ECE09EBA2CA0FBA180CD135E420471A7C6CA249D877DE616F054711B3DA2DFA5D2D3FE774F802F4880E4400FBE4D12B8D678DB076020D356769060253E5D68F665FBCE0EC702F42B94E2B0C8359CF4D6EBCDEDA9FAC8F2FE95B9FDBB9346C06300F60FFD4FAEBA01929CEDF0F15021689B6EFF9298BFB8E514D925541CE2130EE1F25ED6EA895F432987AE4A2CAE01B5F4691DEBF12129EB19C2890A9D268774881F151A06FE42656CCAFEAFFF01E3EBF52C6716CB28BCB6719F7552731C275DA226914D733AEC1BD599AED7BC0646B8E3D9E0F3B771295D43391F00293401E6331E37E779EA8914E7F03B4CA3D1AFAD797617D9D0BBC6020E1B40B431B930D19E0888518D6ED2E6D32BD872B9A416E0B47133867FEC96A88C6B67449E8881B8A455D1816BE7DCB22287D63DBBD87E571F6887AD3D6DDC08C0B710395A12570AE985AB08393BF99DF1A1EDEA499BCBBC2F2EC05FA3EE982E34814F56373891282882A05711EE9A906CFE5952A6AF64379854A4DEBEC24C22F69065D6FC392B4A687D66528615AE301C82D6C694D358B71451A536039368D05C3C240062E455A119EF5A1737D732C1079C7CBA9A05D9D8119CD94497CBE2A275C69D6623628ADBCDEDEAAA143073C6EC43C40229606E6AEB982CE1827F875FF0A6921E0D6D08F605EBCF85EAF0C4AFBD067A14BF9FA6C7A657213C04FCB93630D892E8B340217EB07EFE9CD320DA3DE466169001566373F589A4C48BE25EAB1E6A612187F110661BCED6C2FE2583F424641A420A0DE61B39026172DDC93EF444EADF8ED5CB674F0586307F2886CAEECBBF78A4AFB96ADE18F0504734A082C168921005300431BAAA9FFBCFC96D272E8FD9A10B7F963BA868A273CADA8082353C0E1D7C8BD323779D9BB23CE678B3A5AAD2B6836F65C0F79E32D08006C72EB2431FF9797E7630F27B89635F08FC92203012EAF6B009A32437ED076D66E4CC6074B1CCD0D2176FBE508E43EDDA9185A91E2AFBD235EA8944B711B8C7D0A4132351FCAB1ABC338C3419C9993FD56FC3C89A08B0D8F28914FBB4840A7D02F209D1EFD208A8E47902E11C1FA92CBA1851FF0935D3EFA705FF4BA44A6D4A675BD979947CE8FAEC565B3BAA9D441AF91F429D42C3E3F683E0202C61318344C7865957131A1F9EB822999F137C0A930744CDC698B3D41226A32268C968F576AFB37D8BB4E533B077124626535AC470D649A817F42243CB7CC73F0837A6527C2890ABE5BB762174ECCEF9B2F9A3FC77866ED031947CE54EFB0DB647BC9AB219B974E0C42A53FF6C65C1A67924C1B0415C9B9CDE4887023FDA6DF9A2F3BBD7BE5FC23EDCB6CBF5CE5C0D6B75C2048F05C5AAD82C87F5D0E9A146C3CDF01A973E85ABB5DBF4B3834BCF7EC7FCA3636EA417B92E7838DE1A8527292FEC5183F21EED1485B4AEE3541C00E36E6D3AB5563F3DA1DB962B94FE6121D36273D2813E785E491BDCFC825B0E98539B7364BB73885EDDE73CBC41B7F680BB00D9EB3047956996B97A6994FDE741AF9D0B302E99D3573117B4B537B1A3C384589FBC24156141473FCDE30DBDD305A6E8FAFCECB98800348A5DC2940A8D5CF2005CEF09F49B5FD5B415BD63222BF23DBA151A0E1925FA6DF135075E02D5A7E734AF9B92E947191E7221F1122387DD17EC8A4D3582949B58C4EE75A0A83115D936F59653592A5F86FC2B7C277DE26526AB23AE4674417C9C9388B0338F81FEAA741C446CBCCAB5755F07A195325E708256AF861913F50AC03FF02DF181E414E185DD7CBA0714FBDA807D67C938CA36AD52BE1DA9CD4FEE14BF1961CC1C20D3268C5563BD5BCC10DCC0FA42F01B8E278D3B2F549D6A1B497C8DA54995D395CA6E761D3B776C1D012B1F9B39DD73CD831F6193847930AA15A4C3B139464E3F89AF3B1C583E4E986B80C4BF117DEDC1C09390560365754F402C35B06DE3DC45ADA558ABC7EB3A63580FD8C9F29D335A8D9797D1420D4E3EC0267078F68361B65DE8F6D153F38FFE6304F0B886E94AC959E71EF2AA546DEE0E00E39A3E8DB5869C4434E862E60AF5883DC6E905469ABE8A9DCFF2BC85D14F9CD6470F8B092DD622FDEE25678887B97B021013BDFC8CA38702A7F49BFE92A3BFFB8DAC66D888A070613BD09A6B2D6C2CBC9E61DF92BB128E8C87E241E83BDDBB294AA56A5B6E70742F6EFC321CBF8717DBB5EC7529E34B21C8A73CE9EE0B7D6A62C96137A19D4836D53BC4EB8C1551404CA5804C1CE2350EC41C117DEE4152B65F9BD050E5BDD4A8EC392624EB27927D21C6F3CCA0170EA9C74534C28EF5BB45FAA789A46C703A723A82EF4297F907A20FB4B91694D5598BFDF986E517D251A401D035C5995EF8CCE18BBCAA3C4320F0F90938F7D5D9B04E187BC72B7DF045AA554544368DD90F726115A48E3BE841086889FA99ED5ABCA67683D090A8F3002C164C7C431539C1C8FFA7B871F40B0F42237810E3F603C63DD59737AA7275862DFE9046D22D59754D3668826A410EDDAEDF804E16B8E6D01D7705F611123C3F6A3822479430AB3A10F79FE2295558B60DF5A7CB1F02ACF8EE05F74A38E025C1A6FE1C02EE50C2B5ACE98528523F5C16C620D78DBDD54B0D66BB1C2E832876C304D794DC28D1501840A94FE7ECB2A62C9B68EFCD6D60E9F12E79E6793424B66F1CDF7C16B0F39D03DC0A178F850B1BDDACB3629B456F6647D0B9AD45E0A635420C1E1081D0E99D8B5E912F295DFDD262100D5E95B030CDA6BE784F6D38ABC0AB5032B0D42C85ACF782D382BD0711A7B43CB7682E908D3E36132145A1FAEB6670B26A30917682E4BBBAAC884A7306192257E9ED98A771F707A1E14AEC44DB71359E49FE15529376DF4BE36A0D00241DFD320E93C8BD8BB651132C4917229A7E5284F83408E2FAC8588E3662F4AF09D4E3A8F97CC55B507A2374754B15B086175FB593B007ECD560F7AB9E7D6611D816FE58CBFD083D144E5D0BB7C4D76A510F56C7B3170ED5A4AF94D3042073F3720A8BD2DBE40A90AEC4765371C7F27036C75B3A05E08D3A0EA4EEE0C583196952636745A9556776489A46B7FE6884EC255032CA37CA59E33399206BDA71ECCDF7E901F57F7F11732FC86CD6F6BB761F612DCE82455C80382834A2F660D38CFEC1F63DE2AF8B1779394E23747980B3D4AE572409E03AEAB7A80FD951CFD64BFC061E4FABCB4BED38F1AB19C819A797E8C378010A56C3E7CE889DB8DCC832A637B4D1E04C2EEE52E2BBE8A64FE47EC9F3ACBB73D8AAF2DF8F14D67F92D2C80373D2180788FBEC28190CC824D90DD5DE2F4A95E0CD172C1D1D33D2E24B48A0611C908812BD1411DF363F40F317731DF586F7A156418F5EAD8C06E116F28B4D0A1D1E047FA249ED4CC653AFA03DF4631C80D529F886D1393C0E763C325FC3B1DB7DE834DC7A3775C5E0A8393256D9DF355D7B173BA5C0FA8C0807F8615E3EE5A5330F7CF408848188A46AA98BD6BBF5B6925667983D4354461B43E0E5A09FACEE9E285F2872F972F7121957C5A818BF45B7B4D8A83DBA07DB5D16F96B51A46B771213FE8810D53B1EE68EA8A2EF1870DAA7E9CB8570FA04DF817AD58EC6556929AE490B09463B663D899C0F01C5A30E31991812F60A686877C254084FA73C4E28D8267E43FC873BAC32A2EEF54CA235D2089C7BD98D90099EE3512B629BC63A69EAB96D2F60EA01D293DFFC6FC355A726B0EB91D66358834B1DFCDCF5738F929226A63BC8F861740D844E47E2D3B731D03A902F7627C0F287F1863CA4E29773E966C9BDE3D6EB2C83F1FEA43227BD9B556B9773378F3D5CBF571EB6877A334C438C8071B9CA6B8F2AD85E66CCA1312826FC0428FA80AF251D13E3BE157DE900203A2B2F09CD22ED5CB33A71A10154828784BC0D9093B731096BCB14FDD8A59C06BA7BBB6F46285EB75BE0F7E5143E16FDB3B0309303392E62E536299C825293E5764040833BCD0DBE3FF00122F56C1C2364B798293B9CBE3000000000000000000000000000000000000050A0F171D25""") + ), + new SigVerTestCase( + TestUtils.hexDecode(""" +6C9E7A1EE36625760E5D2F33DF2929DA56203234069160E5F2BF039C11062273073C237566CE055D871F38ACD1A9859A824467F19BE68E4F00645D225C42C85A557D2C5ECB442B0F028A6528898EE2B673D863F32EB9EC8164127541F32519BB88E034A03F46F7D193CD3DFBADF63557926C5C8F5B766A7FC5EC8B3F948BF7A821B54C9441AB0BD833FD6354CEC706FAA500ABB5289B90B1BF917677A29D115F0094BDB48DC72E261DBA120BA6FF5E52A01B178981DD8296444656D9442DF9CBB6BFDAE56A230F6F29F94CDCC265576AA8752ACED07E99895CAEF0168BF83D23FDADFBB928CBCDABA25FE2CD26ADDFB0DACD74940F351426942F176FFBC5F3456DB7C912AA16B86D0745F87C9F45370A8456A1ADB51DB4052B5C9EAF60AD7B80A42EA4BF92C841273AD761DEDB0D34BF579600B149FCCD42AB1549BA0ABEDA57EF71D1FCA5702AAD083299BB98300189C25F3B270A87658D0B2EA56524147F739EB6C676D7BE73DD3B95B10C55AB46FD01549C5168BF7DA13A499785F35A1E3B56F4C567F54EA9AA2817A336383643FA2EA31FB1B73E10248DFCA05C04131266498E1C9491135A50E63D02FADF4165FC9E15E3E1B32FAB8337684C49193E1BC4EDEAE373A267A714AC1F909CC657CD8066646327E0EEA041AC9F2AEFFC80691BF60D3C94C642557E4299D395922216C65E75B7E1A5028960384BF816C9F7054829E7985B5841A733F33FCE2455EFC89BAE84B47990E8D0AFC6193E4AF9BC680AE24FE591E88BA6A2AE12DA3858D21F492D24ABC4FE4FD52D5ABF24BD254687B918792F0A003A5222DF45038685C725CE7579E02CB168BBC666ABF669856E10537C9291692C0CB0CFA906270AC2C7B7DC31D4F9283CB2DB8A462AEC0B9807BBF4AB4576FEC6226B4179322B67AEA53BDDF9C9BE5E0DBC43F78743068AB5BE49F0E62F8E2EB1B6C6736C05C9413D065CE0CCB790548041D7E832881A839B5729AF94AB79FD8A16DFFF78CAAA141D97CC0650F86262F26159BE8B361A4A041E9A0B6511BBE3355A4BF57AC09848847EE0243C3BA774776F7E9A227275D74E6E3101D382818763ED1E1353AB9EECCD920CD28922D559A4048F40F062164CB661C4F4AFA81A3D55933C4791EDDAA3939E5AC342B0AD1F438A532C6CE786681A870D94EC88A334CCEFC6ACE7D988A1A82BC0ACCE785F123BE23A7C92AF108E5ED4F0869E22DAE273556D1DE386623A6C3F115BBD119271D3FBA796F618B53959FB98012E7D5B9AC688940B87E2C9C065524A00D3A4F4DBF52F4B1A63EF5C46193BADF7AD7F988D4464345B2C3E549684F2F905F6F89DD641473EC05108A52D8DBB91768C541DE520B17666970AAEB506E75D8EE9F4B4455B71E0088AB25655213B75859D25F559D3C324D283D397ABE6F0AAA386815768D03357D775964902413153E3560CCEF1FD44B65FF1B287A92A9693F034B7EE668934702D7501CAF6DA4EE98AF4E8E64B0340E0BB8BDC533B0EFEE1915A4B68B93C5E95321EEDC234AEFE71AE2E5DACEC2F52F83723A2392A7F8E13BC0301CD104D852E62A7F828AD329B3D9596C58E13FCC0ED96C1C48D82A2C0F4D9D24DD8421FDCCEFD497A9B05FFC50904770401373FEE7DC73773418AEB4A1F599A4BB38EDE8D10A3CC83A1C72DE921969E3CE3E8EF2F7DA89D344C80D61CF9C5A423B1A4F3567D96DB2DA3DB9B5B5FA68156BE7452C8A0181BB9F0DC75CD9750883D0DDAE53FC156D67A74200869046B41DF4BC4396993C08AA4897A0BDDEFB55F69CC1C4D7B5FB150408427B416F73183F2B3CC16E3B7DA63CEE1143ADA1A056626A077B6D21C3DD974ED907C5A094019225737EFB93319AD3B40A4F434AE49D28391C17A999C744A68C55A91B862729583D3DA46EE70C5CC461694167D32D21DE75327732C63BBFBD7B30DBF2057A0D681519F6E4AF608D4BCD0B4750726770E156AEDE85417BD759D5FFE401CB2996F34434DB428D9A417037201FCD260FAA98084502EED5C27A8916E44F5929819D21A69CE16BCDC3CC8141E285EF897B1402C15C952590119051E369A1B7BE443FEAE6E32BC8F3D647FC5315A5200CD5238DC6677466EA86EF8D18E5A79F262483E896B8277C741F516FC040C1090F2495BF1650B02AF30456733A071AF47D7A15BD8E32A49806455D3BEA74AEF5D00906AD2F0C045354EFDE7C9A276E73D9EDD11D1CA5C297B9A6851E7F67E21EB061BB55D9E673C4A75FEB84D52629EECC53C24BEA95153051AC206C87DF55410CA1FE6CFC3F403A6D9D43EA84C60C945E642B2836338B5AF9F69E52708B2E225933DB320BB3F790D397F22D7B6F8A433CDACE9810AA0E27C699555530C562DBF7517A4162628BF10D1B6DBACEF5C9ED51E55D9A89D60E0FC378C47A21D5E0F2DC3BCEF5E05C6E0261530FB027E5032558CA2B47005BDDE99909930391EAD7F3F0A96B3DEDA54A11145F530E51DEF892E5AB0204D614E6E38AFE79CA92C28158D570120353B7A4DE0889846D835294939557ED0AEDA270D4D73ED84D3D49F9F032D43457BF59BB7D66359DC53F9B46963B21784B06CBCF04BEC1E33A33371532716C9EDB3FBEDB81999B4372D0945C10AE826C60FFE93170B6D294B3891B0D2A7B35B28A8971845DC2FECE237B80F20B379CC4D136DAB3FBB3792C63EC61F5C755BC9DB35086FBF46D2B7970DCA2A8523FDB4C7A0B8E42F8AF9ACAD2A0EFC113602A4EA62E4EBB7D269C3A40BA2C44EDD2956"""), + TestUtils.hexDecode(""" +C4F59FA2DE30C8420A7E7F096BAF6AD69B1C15A5C6E61C9D82AFCFDB6EB8F275BF5787186AAE781F487F9F88758C9C61F35D5083EE70424B0D0A51575010C2A907F49608115D33EBA0031509322AA7D3061FEC3162F96A565F98769E9A19235D89D1B21D60A381DF8EB37D58C6A2E483A8EB70736E4B7BB911F7AB923DC29F1E"""), + TestUtils.hexDecode(""" +E895DB64C57BC3C2A97F0EC933410E98F6216103E3423CAF06A671964C514A694EB6F65CBD1137CCCF8881FA403C5FA0E0B2F36B9F4009C378210D29E54A7A5A9B793197CD6D2F38D7E1F3ACA69D48881389381C89FA676DE426D634F9A157055F17283ECE8248CAF14DCF11E2D56355B047DF632A18482E79CB2D5A743966BAA8A76121BB69C2E68155ACCB0A31DA6EDC73CB09A9E660FEB20F66C7BD967ADE32149C5552EAEB2EA175B56233F3B370EDD8679269CE0D2B43F6B2F65FE957E7AB37B982043754EAC8A30B36C10004EF13C692E219AA7AF0A4C5286910C7100DA41E17BBEF2DA2AB03ADF3074BA1DA15BCC84805B89B9DA88E9B400AFB7E3BC8338D354DA953AC0BAD822756CA92E5DD9507F42BFEFCCB32B4B91A2BE5EF34C2CF1177EAAFB250AC9ADEC4BE71807589F1003227F9B76B74E07BA67AC60819B2AF766A47FFFC7B76D3A7C077F5EC69AEEA3E963859B82C2ADE58BEC2152EC8205110975D37C6505E0DC776FDE071097E93013D1004F4E1A2FD79B877ED5025F527F3BFF137F041BB9BD001E949F08B4CF88DFD32FC7CDBCECCFDB0FA2DE7823E110BCFF58A412CEA2795753E9C89678C3AE24268F7489F72974B6955EDD04E190D99BB0D7A252FAD5BBA606C1A1F3ACA733BFAE3309EA0A6EB7D07E36D8CA336D2644FCE1A41895D014D1A60CB106F3F8075F9378461738D63D115D00B024C677801050A1B0B50DE057F85DB6AEB2C9D6BB7402A66E3AB4DB05C58BBDA12F695958B8AC7B4E45EC6C952F679C1EEBDF860E348982779AA6988EFC2AD1DC1EAE22A27A5B2C61C97B3B2493CB6C13C5F6E20A67B88D3C3ACCFAF0A425742DF240634D1EE593828FE6297446C076F979055988AB834B2BD82E14DC086400E1C956CC0C30CE7BFD962223D23FE9494964A811B93E8D7B8F34C89AAD45DD4113F2AE7BD94B53FC86E8B2AE82E51EC6F3EA4C30D60B86072748612D1607056B5FF6A4500EEE78A5A639C7B74169777626864DD9EAEF0E3AD8493D831F71DEA95BBFCF81423A266DE56F3A8FE8E6C3C0D612FB62BD642188CA71CB89834F30BCC28BD178845F1F6F46C03D306F7ED4E68759427AEC2701198C3C05D385DFAFD528CCE8425BC551469A0ED681BEE4D12A843E333B5A8E0517FC61906F9C4E7809BAED4D3D16EB22F1FA9AB402D988ED59F9FED0455E9260FD627A24A17FE7CB63E530B48F5FB6687A2E8C49DA79FBD69A3400056665DD11D19A2BC4DB1D374AB6A6E42472A27AC6B98F676E8EDAADD514F6D44DEECDAB5A6DFA0F84F139A803A2524BF335DC52EA58FA50D98FB5CD55D5D50A663CF647EEE56FE8E664B3BCAF9E333978A7946973FD113E4FD3924E6C09E60386444214DFA7A4D671FC23890637EB859134D79E265C59CA3ECCDDFA018223C9BAE1CCA103962078BC5F0DD02246FA28324F7CB2FCFAD07C25B4BC2D888069B0CF5F23C761C0E47109881CD31456A64B940B4BB9B4C2C3B8E6BA834AAAE69FDFC47D44B3C96887ABED36015E7B64E8542928F277CBD2D3C512C24DEEFE590E81C684E063E7AADCF117B48943DB771FC2207F57A745357555D419C9CDCA35CC1A7100A6913A3B6AACF796FE3F94DD2F818982716CE0316542A1B957E12DA43E231542CC14FCC66D728A68326B2BC311248330F3E98F81EA38CA924A8E4DA97CF673842C759F935BE88163CE97FE4D9457176F5B8908AF948F74D5D1DDBC521825D931C63CA8A8E12242626305AB6A2E0624564EE041983C18C2952EC3D9D159BDE3985CF77897EE2DC888112721D4854E914A5397E08B54F4A54323FF820821BE026EA091ECA6B7D80D91E3DCA2EF7848B86FCA6BB40CE48271E1008368E3EBB5E395E1CCD0D178F1A6257D26B6BA4B7CE532CAA1E76CE28FA4CF9E029E2482B94D3ACF97A326D235D1BDC89F70002198451D9F1F12CCD5BCAECDDE9E14AC80742EB31E6464C83210A39F35098BE0378D074CE1CCD1EBC1C7770F778D605F2BE59DB7EA07D80CCDF55F16E985B142FB7BDA07AA7DCA5B201E1950CF9A728F21E9A9D8AC4D1327E3BC0FF339A250522F631DF2E75955154893E4A1AAF9866FEE1637EE1AA5106D244E99E6F31FC5601BB7B79BAD82860B1D6059D9B132E026418020DB06EB8391FA15B7A0F29E36D966ABD3D2A2FF3F2AAC34C8B45C7D2355EDBB80B224BC106EBC6750E55070F85A7CB6003394E5161AE26F5ABF83F0DCCCF69B86139AF8694FE1DC00781EAE09CDB421814878043DC9B0530E5545A165E39A9B7DE88B4AD2AEB90D3C329412ED2FE1D97B732C8439DF4F83D228835B538DC278FF0A2DC42F41B00CE3ACA06B05C4839B896931515D78EA3673A378279F4E89CE08E3453FF2FB453BE031C6318628A731D029FC7BEA2BA5EAC4916278B938A6A6ACEF5BFE2158F2AF43D8E56A0649DF28A250D2F2536ABDE1E008EB631F4BD0EB55573A40539A6004181A9D2BF7A1E53504F11E014840733844131AC668946E5B827289AB6B21366C5D0E2649219B92C4760DFB705F7F61A96564C9E840D14B0BB0DA82DA50F8B8E752BBFEA3B0A337BE124F72D8F8249195BC19C3E0B62EAE496D38CF7500B4F10665FC2D28B9EA935F7E316472F4FF401267541BDB62301554B2009928C6445BBD0EF21D09972F35081ABA9091A6C23FED29F5CF9E0779F7EFBAD88E62A454442B30079BE0AC9C64826B98C1E1001CB0FB0F0A95F7965FE9312BFDAEC33F95065C8E59D3950F80ADC7FB334F202D3E5F8DA481C9B54A75983930FD1E5ACD16284F07193FBCB50D0DC00EFF8203144C11EC61420FC32D7982CE896406BE769A75DD8D3CAC753ABE5A278655BF54BE33A1B8374EBEEFF212C39CE514668F1C456EAA2532828C84293F1A5BC9EB5DEDF558A9B4C1239F77272C67E1AB28E1EFEC5893E09C10662B53C8B8255B1C8DC8F8E5120A25C75EEFE79C43F7A8B37DF9D1E4F32486933DA1CB0664C5DB39E21BC227B0CDFE7A5507F07F218A7A47DEBCD9DAD7247B4D045A13AD4F75EAD2D45C339D0DF04577F2E0FDC780392553033C738852B1BE4E63EA3897D6C9C4B11AD6B58D3E2D342D32840F649DD83E759866B7381A84C8ADDDF413FAE18E6431B1EEA73A56CD889B76BC9786BEDEDCA2541E4C9B24E28F58AD374C1D93DF2D3F2C37EC594A0498C574579A7332F72C0F9750877FAD5B90B968D88F11682C4071E4EA38B816AEAD6BE54D2F371324F2475B862C75424ECF9858AA4E200CFBA412D7E3E6C308D8DE11DD185331AF9D41AFE8879965D6746EF21FD98D3ED3806FB5C4619C98E347D76B8B89849395561EE286DFDFC6A04E1D47E9F5B5B49257784C39364DFA88AD630DFA59CCA3237F4A2B141A813D22C6FFE73C2D99ADC824D93E06A54B6DE62C3125D94B49E950DEC361F961F56D3671C9925377F6E670665322B8489E833D3830ECCDD0F53F4A4F9D68F1445F3AED5C9D766409B59BAE7A72912E98B3BB57342D29B6ACFD14336B7B8B6B7549AF8CC8845E10C2811287281985D5D47685FC589F2678ED893F57B85ACED75632E50DE5E074E6CEDCF1AD499BCE67A7F498564DEEC677C708388DE8FD7B099CFC116096C45FE28890B5EAF06169939FDA35E1215F238E8CDEDFE670065F5DE3272A232FD53C250F5D779B31694FBA91B554803676E4DEA288463FE1063009E9CB76C317DB400ACF4D2D2B6D16EDEBA4108913F60AEB252CDE413690CEEFDCFA638963DBD04F4CF21AD74DDE65F0F1E7CE70AF101A6DE9A59DB21D38027DBBF76167827950B69418266AFA444C728DE3624A1C81E5B1641DBE879CD822FB2303CC3A9FCEEFE3DDF7DBD0B7057248A28D6062D76EB13B92C9C9D003B69E1842A54C09CF6B484520815E2BB237288C64FC696FD3BC45DB30CB86465DF1188BF47956E5B916A8009715CC9A9A6DCE44C54F928816B41D018C5FE652FFE4E33F352D383A9C1365F02ABFD647BD6B42AD163730F8BFDA1E2BE5F614D79597825BA09F457D3CBE7561E7E89EAF059E977D1EE88848B781F21F723890FF1F9873928412C8F11EEDD2C0C39C9512790986A19E17B2B70A4D7CF49D9D18CAA0C2023134CACD169200D8817FA321F04ACC910613DFF250EB325DBEF29EB5611B2AD2A23EDD538049B3F43EFEB4D60983792B4BF05567944AADB7AC4D3A5D80A1B9D8448B4C0C115C3B5AD3885353F47D5FCB9B7D6446F1A7210BBC667FC411415F23CD40A2A3D64061D71C67191571A97D01088A24B6711567FC89106732D8892FF985B8E6CF70163829CC085BE4E408315361BB1B2003D6413220B134506D3C304C0BBBA9C9C45D3651E0571B6B115177213D8595E143DB90BD72F7EB974D8D0A0317409D64D5837EAEC9B8D44DD7ECFF6CDA9F729382A43B379CBDD43FFB18AEA35C1A996CEF1488D3B7A81EE7CFC0B9623418AB3919A6EDDB99F222F0DDDB2F32A20C8F84FBF4C49B4CB3EB50D9C4CD25A6F7175467066D25E6437B67F2DBC70C2E6EB0BDE2386D03014A789FB6DC08EE33C0C67951DA9D74B9C94845D2A99037E095FEF7919920FE526EB5DD0BA1F97DFBD2DDC31609C1B7B45EC3ADB586FE3030A0C7A9DD034A3C2E6F9849093CEE10A181953547F8BE328720A4A5A8290B5EE00000000000000000000000000000000000000000000060B10181A21""") + ) + }; + + static KeyGenTestCase[] KeyGenTestCases87 = new KeyGenTestCase[] { + new KeyGenTestCase( + TestUtils.hexDecode(""" +38359FBCD79582CFFE609E137EE2EFE8A8DBCBAD18BA92BB433AB4F09B49299D""") + ), + new KeyGenTestCase( + TestUtils.hexDecode(""" +29B4987C62218C19C77D695EB904AFFAA1BFEF6A52F138604CDAB1534E66DC10""") + ), + new KeyGenTestCase( + TestUtils.hexDecode(""" +9B54B9C91E0201251489E07D1442A42D0BF32189D0C0CA8A2D4871DB25F531FF""") + ), + new KeyGenTestCase( + TestUtils.hexDecode(""" +A5B67695D7DBBD6A7B25146E30DC3F577240AED2E4E20158D1E24143698D1178""") + ), + new KeyGenTestCase( + TestUtils.hexDecode(""" +1B87631F6ECC4BC8FFD14B2792F3D1691A46C22A26BBC98DEB2554D7FD2522AB""") + ), + new KeyGenTestCase( + TestUtils.hexDecode(""" +5C3E3EF0278EA9197F30C4DD9C4C06425C05401253E77DFB3E1D5315CB00915B""") + ), + new KeyGenTestCase( + TestUtils.hexDecode(""" +E3B2350AF8A1817D936FB7435C4C0CC758F79FF4696C46E4642670C5A78B30EE""") + ), + new KeyGenTestCase( + TestUtils.hexDecode(""" +75E70362235CC7CC4A08053BD887CDCC4E3D88F77E1C7DACAC972A9AF83C0CB2""") + ), + new KeyGenTestCase( + TestUtils.hexDecode(""" +45CCECBAFEAC42F2D9166A879175A6D6263C3F7F9B5F39F27A1578C859CECF89""") + ), + new KeyGenTestCase( + TestUtils.hexDecode(""" +4A74BED90EF52CF135555B622A50D1A4F5C53D97D3176A1B184CE55380DE6FDA""") + ) + }; + + static SigGenTestCase[] SigGenTestCases87 = new SigGenTestCase[] { + new SigGenTestCase( + TestUtils.hexDecode(""" +13FAAC5CAA1C92AF31DE6C25B147014BD7FE589A649FA0089AF0D606E4B869EC1E4519E3AEB57924B329B085EE7C80501241FEE198F3F41A94AEED9BFFCFC9F7250182F2FB7F56C145635D81FD4981B541AAF62A572520FE29FCC0AD050545BCD377EDA950D1DF476FD2B85C8C9E749807ECA53A51D6D0F4F42A339AA7C48181C83851A0A830D080651C3741E1A805D4324624272D21366D403652024250188488CA24804C842892360462109258844503326E13390E02928CA038044C348A52A46054082DCC329204822D5C9869E2246918914462A86560080A0C372010B9890CB92D63126D13986C21B02D20C52560340918C641A20872048684824026DCC26418165219223158928940A8408A3646491061E396690A2690CC042D41302119C06510872141400C83120D831205109905A42844DA06201AA30502150C04282521A430E03601CB804C1AA2618AB621610410649450E3C630C4226880343210C09021944589248118C7458B904402126250B400E2866800A2041BA68558080ECB228E59803192847159262A04216D13A00C0C452D518845834402C42846199345630069E2060E084528CB1271239484E2386E93446D1CA26D21C60561B228DC1406D19870DA9211CAB48DE1A20503376262B6014A284259948D80225010108C18354D13982912474DD3B8209A40120A398A88026A8B2280D99460E0A80491246D5B060D02012D13272D04154240860520948D9182215890688084115C0248C12012D0B68DE438666306258A884C9B0801DC087083445222404109252AC988851AB7491B899114244A8A043103408ADB3680593488410690DC084AA04830C9441198142E1B038124B06464209223B484A49631CB82648A9669A1C230C9A484A18420D9226A99A26513C168234404CB224940926C61066E83C8418332254AB48002067102007213A57123842908326E54828101920D83344A5020251B84718A182C64B064E31049E4C090243592A196308CB89109C3109336812399415402101C196153A68000022C8B10011018914318705AC20C1801665B341109836811B78998C6618C40910A430683204421284E41368C94202ADAA66541141213B9605B442901102499904C41342E24C28DC9082E11382E00018A9334455810009090316348610C2860D4262981280DDA10519C140C1B2308D29208C8464E10322E44A848633490810022501845DA420E24097162A04908194453C06144482622C42188320A01C00952046A1B25511BB185243809C2A86C603689608684448065D1226223C98DE400468CA0504800804A283044084A220640D800724A0062810425E2A22804C04C0A408E891089E0868DC2B4850C274843167291220C498061640488D1B605121721D1C231D4C2811B8271A4422A414212D9982589069110220C99886002B7219A1262D2C0219BC28412496A4B089022824011106603A749C1448063A65160380D84460CA4A28C9B162A09A388522426C3A25119A6802410860BB3888BC66C20A028D2A664A416721B05119CA42113932C1C86491CA30953380C92A67020C7244216280492714332221440406492514C448C8AB40188308611346560100CD0302D24B460A03870A0968920842924A88D58002010286EE1204C14286DD3402DDB38251C1381E4B465CBA645E082015A022CA01612C3322A14A36480124A01042A0895250C8440809051A1282524B86D08318AE0220E210692DB966C83124ADCA0692127065B1828C1882D133209434411C9462049C48481146C18956948C4480C492603080D18942000130901436118A60120474819111018A50023019022882818054213069191062509480E11456E8A00449914010020122092480B8320E4321210B429C290512139049BC411129890DA14661245048322049B442A942291C9A845CC408203C77181429223B670D924218BB08422392C4B2860A012905A807113462992C068CBB68D1C8064840482D9B82152202A1B0565018545D4462DC8B620D3404003C42051380AE3228541086C04C62C8B20051B091008A420E0906851B685083825E4428C504866CC98281B1171D2208E4C324E13424E02044984B20513B9059AC86500472E9220710A300CC13620DB8808803840188810A1A84D043582E404320B048061345208C5201B92401032121C426A231904949090CB9810B0D16BC03B32C91F22E9DC32FD1369B126053CEB625567AEBEA42D32F861AE27857C24814177623EE402427442714970674EA84BD573741F3ED9C297758E0666F718D5E61117BF138734FB56E3348CA54F05492294F52FC90C243BD836DE2D5B9797A189C7D38E6E35AD95E1533A32B5B589AB56941904BDE66124FA6CDFAB90C80A05A4EE8E50A5DE061DA6E11D3B40F218664631444651497AC3AC3E9A9114C9BA1E92D2FCEEEC9168E27296AF943472C8B4E251F753EF79F80948F2ED5BF690E0C0A074E8E0E4503410E8FAC6D8B022BCE3FAAD1C29681FE2223125F43FCE56DE461BA8264DC83CA1E690BA638E49052D0D05EC5176D12458159F2FABCA6556F15914598E014A4582C678C0F6ADD2F2AEAA330E816B0AC0BD5457948FA49FC4C954020070451143D8B4B4602BF9616BBD1D9F76B0EDD63F186BACCA0C0F861822E6AB56F771C6742106314D54EA9D0F1BDE66F4A504C6902D86B815F46F47E6D69A9DC16F290A8A9EFB06695670196D17E096543CFBB6927E25191B9538BDF5858B54EE4F69D35CFD511FAA422B6955F0EA87EBE5506DB4E7871C7FC5A2F974C736FF12AD545CE507AF4E430270E47EAD8663361CEFC3FFA2E3CD85982ADF648DE6F899056672D6CDC6841B1F2668CCEE9CC630AE9A91CEE7648AAABAFB09E4AC7ED0D7ED8165D851627A01919AF56FAD39CDFE838B5CF60E8FF5A2A7C91EE43F1AA3F81CC853B178E3481C32C2D6FD40B0EC924CC1887FC6DA4039FA0BA82D0A57472C9D6003BB3D819A0533D3FDBDE2CB06BE052AD7E56B92B431652D6D5991BBA6B564C15C1BAE95360A07DD76F0ECE8532376D0B71EB865933D3520EE7B3B35B7656ED684FBE914D01502EC4BD7FF39FADF06F6BB002B882213C4D42E6CA651BEEBA228BA93D825D618084917ABD3130C31B3B935A253D8D28BD45C5FAC4B05A42BD815B9CBFB6198DA4FAAB4DA6E9E95194E8084D66CD6B52BE2DE2A86DFEB25C254F59C4CB168185E00074E9CBF060639CA6ADDB7DE514CAFD5D1D3C74777C11957416932E8745C2B01AB7DEBE2E20FBA37476C0626140FCA24D3EF4F53148C51CA78C935C6C89233A6D4C57C317A19712A8040C1C4D3AAD221C1D375DB372FE07250FC3C1BEA8ECBA24D781492425702F35CEDE709AB063EC0804E71B8669B87DAD1563606E89EE0DD2A0B11B8836F5A2D375AC4B7F85FC5F80268FE26121210A4E1CD24BE3FF9E6D92A5437BF9019002140A42C317906D61D862200117FF0F8B8EE8D4C289C3950D083B5E5670D4ED32DA5C691F20CB648DDB715977ED6AC69F64DF8D5C99B4177E8B98876E7A5D29ED0C0F972CAE6256528233E15B13C69AB592C3AA260C77BA41BC608A57CAAE46AD240DDD5C2232E2297ECC90CE628DE5B83A551B06BB68FFCB152785B5AA6D1702DEAA8E92F704B0D31498692C537249D71DC6B1247948CC07413726DFAA43F53058807B77C4C73874EAA526EFDDFDD9116C98B0E2C5B7CAF9A25278761E2EC3B34B766877319243E138DFE6A3A03038D357516D9BF64955EB8B0A4975E026D0915BCB8637C769530458F242F65A68DCC78157CB30C4632938AC32781259BAA48F11B3949616E06C4D4E63F15B96E203D4B4A8110307D5CB3552810B9E1F3F4DA4209CF1BA98359F40E7055C7538ADD0AFB326E5F865B3F69E3D6C9F9F18358C0F6A47777B455B8CCE6C514CEB2235A7B376EF92482E2E86F42331511FB94A9038FF41FCFACBF353F3A43F3A79997167306DDC94A6D0628FC346B06166EE9D857D4B0C63990259AF271CDD8479F4B08633139663A1155340109B5FDAE255D1E4E21539C07249AECFE8E6AAC44A772B39596946BC8080D84453DBABF1E62843D179C1C38F1AEA5CF15BEC4A61810299632A2F3B9422DA99CB13C852B1CC6933DD52EA336A5A09D7D9F568CEDEF14CE1AECA48D92996CDB2CDA36A3C8E95F62DEE742CFF293037273E51F77BC208D5B345331E72C26BDCD0F51C9711BD899EE82128F834BB0B2A3DE473358F47EB2F98FBCEB2624A5D2697B86C7559FF40D14744C93AA2DD6570CC799C4B5669ECA0463AB0B4E1228032DC19A42E4F6C64D9EFB26E1B4E622AC06FD0C47B5A39123FF8F1085E4EADF768FBE9D5E12CBC5F380DBB414775E2836AB19CDEB19A0F653E7CCA9DE567D18020D19D24364E03C762EB54701E1893FFECA6D23A2163AA5CA9FC2DB681DD6E8AE2F42985C2D7E477225AC2F9C5274A5584E0FD90579B32D2143B89F9AD9576DF10A8E82D91C4987AF05F3E720D8557093A1DEC1D2699C2305651CAA0FD621EB48190751D74478381A499A61732B917E84B749A0465408014D249DC7D5C247AC0BF404B4311A25A55B2EC1301350B76E3F953EA2E67C90F1D5B9FC29BAAD30D07946AE1C2976A4FD32BEF26A2E93818913B36B237BE40EB7A907595B27E7BC80039683B3D28323F53B5521D244E3C87798478A8F9ACB55EC09E97BC5220F955057A889E7003B9DE288ACD5594AE65777F36D6C73FF5A17C7A8FAF039F60BC9E3EC54284384429C62EBCABCAE2E78F5B58DC7132994DFB16602A54B444B9A9C0FBA6F7AC3E357308CE2570743B8D2B5DE5F9FEA05A46307623E579195D6B5C946C47C57A14D5A6177636025FA555F700BD61FAE9822ED336AB21DA9E67F9E81CD815F2EB79F25AB194E8AFC564C43CB4CD8D681CD8F1BE41D9376668E45EA7E707EFE2E58BAF0CBC091DD427009B0716B819B857FE9841EC48248AA49EBCFAE706E5F8FC65076E6E871D6958EB1C7A357019950146CA8AB3821317C289C744450C293D3DB4B3006EDD727B5BFE7541F6817CF5467AF94232BAFE06E5AFB845C0216491DCEC3D603B32EA59AE651739D0E26138408A5E37A6E0BEBEE2956269A722AC36D7A3D2732486EAE6F8100C9A278988554895424EC080E282EAC6401129F51148DA16ACD7BFF0C1CAD9516F189AE1D1F4EC79110B942C026C6995A0AF85445AB9DADB1B2FBCA7BFCAAFE884AB6BA0717D3D7BAEF75D9A4507FDBBBBDBEA858EA7975118B94AF78E250F494205715B0EBC31755A38C1AA944F0D80452AD54639B2701462B2D82E522F8752110F44BD381E23C1EA52C15BF9A7DDEC0AB0AFE725B5993A0351737C1DB72989F48FB41AC479C777FD2E7808FDA72790640F9F741D643CCD0C1ADFDE90B9ACC84345E0B0739768ED8265455AF008BC09970B18D52D188AC387CC1DB7E47EF83A0108D39F7057BBC02E611DC34F9DE364B7ED9664A9C5C9D691DEF8E8FDE6C61484A097CF8A937FA55F353D439C380357BBD108933B6CC49CC5C5042D6E5FDF8F85BE9E4315E094EE569C5E3F38CBBED68948FC95226CE06ACF6D0C88408F3AC265B6B10BE10EF0467E011A5EF8F10026C7C54F8466E9E574FBAFF13FE9988E783BDCCD4B02BE46EECD77443F4CFE8969BF3551F2829FF2C0F8630DCF7B088C5BF1FDEAE2E81143D1573854D0D6D6F70FBB5ECB7C6E60F91B241E5543BD4F316C66A7F3C91491320587DA5CAA6345FC0D2240530BFC19AF88B43773FBB4A6369F540486BF74E3DC4DCDC4CD265C7C0D37213037CCCC1FA81D21EB4081C254C4096E044EB6BE48D07CCE2F460718164AE3B68B7298BB1B267FCC0AC3D0365437ED45C742A3FDD746910C1610E6CFEA9A17225DF2B577E790EB870F5A2190ECC166EBA09C171BD825D5E8EFFB3703746817908D299426DE95D605B368AF04D27B01FF5CAB91515096DE2986A0C575D14CF4224AA9523B661128740F19DF8072C917483746547EA422F8A3B40CB67FA87A7989A13C49262089A80B1E4113BB1EB9B469275D8BD336DE344318EB3310B3ACF8201A6F5F613CE0F2290AF5A8B9DD9A5B64AC8BB94AB56C36157C8EC8DBA4125321F30F753D489FA42C4881A3450DB8720892A8D3F52431B960A2404A748220A7305109A2E80EAD78B8D5C1F79D265B00C771129A2117DAFF0D24BDCEC32D53DF76A56CA24B6CFA0775F67614186D7513528FCBF2F7CC47D60C52580BE1797A62C17778DEE9FDC0B6D32585BD35C86276B363915D3D2E5A4BF58AA483891025522B572F4B635CBE94FF014ED19A017EFE0088CA05C54BBB6953BFCCD8D6F867769CFB02280ADE6C39BEE714EBBE252AE5AD84027F8F9C2CFF3FD01ECA4F051591B7FD9164C3C64386D177A74E17181CDD3C55C98AE89CC2C1A26B88D6FBD16DFB76742B631DD8F8D78B308D606B486071C30E81C25AEB864A822402CDDE0CF27FAE8B6CA16500775AD44733FEC8F10AE6677114A330E59FD52747B992113C53EC9A09AAC1C3646FC3760CA6024BF39B7DA597F8902CD605599779509E3F8CD8B03AB66C1993AD4B3317949578351B74055C7BAED3D7555B315765F1065414F39A7848DBACEA596C51D10BB0081381F7D5601DCD07D719BB9CA9A294E092376F6D4CC32B26A9A8FB5297CBE32CF4356EA70225CB302693A6DBD36C816AAD475815E9543F7DC8064C34870A799C32A6BF76D472797F1DCF908FC994604407B59C824AA76BAB6334CDDFE8D0227A383B0CFA2158CBC79DEFA98BC93A38DC0A0420C99B920BBA64DA16819A78F8BAD42355EFB42B4BF17C68AF75F7428B687334746245F7C5145B5272B9C504A9A0A3A985A9738BB1B42FAEEBDCE7E7962CF0AC6EC80F77CC5C9733E49DD1552812957E1FE30C4129A702E23DDEC09FD"""), + TestUtils.hexDecode(""" +67D7F4FE3CC57FC8BE9A3D06BCA0FE4A39F39E3A6158D3E4ADA9CCBABEB542CA67CAC48167928336993C569AB5AE55BF95C8291AE1A1AB2B595C90C0FB19041435F3B411609412630D80DB0C832D413D69C8D3C3CA78BD1BDC24167AF590B67449DAC7F6ECBF87698BF3929FBC874F6FD68551B28E4EEEFDE9A0D0E7FE9E569F1F9893D39C17C3BA7A6211B875A7BCAD0C14194C30D60CDDAD640EAF7A02CC9DAC074779345B83F0D282899B2B9B61F8504BEACA3C02A76611C82F2007953D04FD3C54D7A00DF8F6DE554FD83D1EA5DC841645B706C9D900DEE7862D526245215AC6B9D178E60F9602F1931503864D97F582834DB797CAB60DCDBDAFA3FAE8726B525E8BB69B5E0763FC4ED17FE7CD9C9629273AD5B073B9516F6CD7EE729351C213FDD122E3C11DBC58FD2A501B267AA4AB21364BAA856823816E77B81B6061279FEDA6617247B86073E55B19973BC0E725F34ED4BAF0AFB95E436A9B2290A2B316C18CDC0D9F98F9F6F13C5A3FC767EC0A9A49BE1378E92BC9B3010B41AE52AF409AE0FE27CB816EB2614DA41C796D5F4FAC4A743FE34EF7C0B3A78E0E4A5B439659D4AC27B698550E89A1626FAADF71420F559DF2E808144707B5C02090F754C3BD4EFCEBAF6FA4493C5D48F895FE7674C81F069E1F00E455BF5C965BE2926BD19AF76E20533A6115F4BCF2CC5DD3A49E10A2B3FCC9EEBB2B6E4F25118599062F2AA6CC3A9D86167B1BD08DDB2C53A5E46E1BF4E8C1967866320BA66AB67CE581981F2003B812BA058B75924254EE3715BADB8E6B1B9E4F4AA9844D578CA2F0AD12E1C964685FBFFC87108711E022EA7F63330CA72AF86262838863780F4115138672643E6D9B48C782B8637E01D3D20CFD5C98A1B57720762037FFB12742B4EA8E89E4B32EE7DBFCD5C11E4A6E839A83398ABBC32BA39C6A25922649971D88A102D1019B560C96B820C44551E14509468196CEAFE3B7BC8F253ABFC59FFBC01A13008F77C91B19083A9E7BE733C1A5E558C64557389CA19249CAB77014D0569BAC7812862A610DC6EE074C844A055ADCAAD496F6976C932587BAD9D7E2080F8623C5ED8D9D4FB9EFBDDCC4CCC1284D22A2997824577A619905B0D6E451CAA3B2D30DAD9728FC7623F9ED71F80599D65D9F2AA285BAE393D05C15891472B2DD2ED5CA669785EC4D441F3308EB4BBDAE8FC449962EF9787C39A533847540965601D8BCB6B4299AA636589BFE371D3904E18BC9AAC9B3B6EB8B7E8F322C22A6E01E6B26244F9E39586F124AE4E504FBC9D860A61B20B4C127FD0C55EE810AB9803D810233E6126488A6E95F8ADBB3F8E06D113DE6A3E361209E0D36B326E042CE9D2698DEE469DA15464AFF82D5603434C07CCFC4D956A7D55FE79CC127AAD2A56B34EB10E8B85C3CD5163C4BB8C1083BCE5E5EF986AE028837809641A6AF2B8295B743DD9B03931E755673DBDEDE56F6294270532D685DAF1187137CD7D29248F21B290EB8317E3EB28B62E45E140F4AFC6D1438F81E9EBFC6FC0F1A4146AAD83AD1F0EE2952643E7B6872CB2823AB21A155C281ABCD19E20A52611C6FFAA724578A070935B1A0BFEFBF061101A81227187E14E96B016242DA269FC91253FD827A73743A4BC49FB63E2D830D0FF409AA1C73706D7C2297CBC552CED567DFED72CD15060A522F9B88EC910B03CD2794A9FC07A8FFC5CB97817DC769E64D8C474A305035A49D05B1C572363913A315932E391B62AF291DC203B9A40F04F40EBF26A4AE186056CEC45EB7D21D88CF50258DCB5EF40CB2ECF949B18C72626469978FBE0964C8A25E8C2D27149C2266748F2B06746E8C9E7E2F0977BBBFE3FBEC7353F583FD5F7C2B0139EA928AE1F67004706F6D4ED7BD8D13BC68E0F4A49877C0B2F692936BE5FF99544B2B19B23A97EA6B5F585ABC9E69E689EFE25E15804C650444C479E0DC63C9CA2AEC41A316039EC7F675F1FD7C0476707370CFAEC9C3418CCF30B5D85FE0E15056D6C015DA59F9BE9028D9C2D93434F99DD8C1BDB41FA1EB021BFD0FC12EF0D038CA32B0FE1449342D83CD6BAE43A8CC4077074FB1191A8887BF29238D27415D93880682017470A42872D6CFA729AA2B3F8B37038C83583E4C33256FB871A704527594596FE858777A93D3095767BCAD2FE295352C93D227E1766A59ECEB38FB7C2E3664D6DA0DD4C063975FAB3AB4B68D125AF16D233389D96A337DBC18DA11F37F430C1E49BF8AD30258601CAC9215F32771C6FC2B7BC03B55AE9664E0D719C3B40C3E4FA7DEFED8571CE8E46FDE8701975D94319DC5FFBE93B4FC4898E2EFEB3CCFFB3494AC50BBA364C22A3953F052F62E46D0C35692AF40D2FBF899A23C1A4721375F307E2FDE2E588830753F908FAD96EBD5FC360D742E2CB2C38A7E142C95376ACAE29DE8E1034207D1CBC1DBF2968677AECED152B1EC1AFC195F3320352953F2503227152444BAA74EE8F98F2B4512F7ABB43D7F87889CF1F8C12D9BAB91EFCA5AED21058E322CEB4E59DB4DDE13BE46FBDFB225F4AEDF7137B548503008002A36D7A3E98C0ED65ED9322D66FAD4A741125EA4ABBB26A2FDD7AD136590061E7BC0D5228555D1A59F8A6E4B97ABB61F4B1AD9564E84C000585DF8BB31AE61CD25C9D91D1A1FC21A69AD286CBC7E00F592DFC1C65E2BE755DDF041486F3B52C8F72ACA97A149FE0CE1378236D99EF099A668F6847659F7EF617B66192CA452ECE3010AAC18A65D8964381F561B48D044096DECC22736C902D7E23EFFD26245018D9D7EA9E2F907932A1EBB405BCFD29F7A397C71A5E08962ABEDA5203988A81F787B25EDE84A7D85DE92A2B19974EF7D0378877B82BD7CB28B67F45F7EE625CCD054B44B4CD51802B4FE2E219315CA9F4C24065F5578732DC671C3004D31830DB435C763143CA209D7DDF3F5EA42244E68429102F4D90297B7C987EEDFF0DFA7F31964B76432E1DE27FA38570F2BF64D5FA3F12DD9772618ED2B95F51AC90410350320E19084F1596F6B791AF1EFC24DBFA2B7E30015AB14FAF43B568C5149A1152A47D278B5F01786F242858C210D28812147646A1A3A7CD69996809B784BB2F0053CFE18446F060622FE3B9181AE9175D6CFD8033AA752296016E7BBF639842DD4073AB282FF50F94B9E116C63DDED805277D4FD7987F740EF8118946851A5336A9F6F6E2FE3ECABCC518B31E741AA79AB500D9C6DEFCC437569966EAB1D4BD6CFF8AD0E5698D15F1342ED46CB6DA986F0C4B2B427752C18ADC5070043FFEEBA98569E90C79A3D5E0434119A077A097D69DA6E9AD7E32C6E8875A893F6D69424DCF4C0D4EA12605E5E8A9853E4B58E5659FED6D724CBAF582A89A228F99BE89D88F55095D0627B40B29365863C57F82B9EA22FDE731D1A2D8A9037665213F2C410D4AADCE12CF888DD4AF53FF839E962F0F53BEC60F97133D131C2C8EB588AA7D25EC025B9E821DA8E8FD8E550EC5E4D5923BFDDBAC522D1FA64C503078618B52F452B57874285AFD3F6B182CA6C979734C94F040EBAEDFEB547683E98F4D13F12A252E8839317A827CD97A7C3D81962A25DF7D8C62B57812EAFEA9EEAAD7D6A9E755AE4CF3AF42CA2152F663C1BADA0E653EB165F6FB56D86212378C0B9BD5733D4C37178FFB58E7357487B98DEA35127AB58A804B13E61E6D3E385C96884EA91C744DF6CD44B3EFBEFC79ED19C406AA6ECE144A44F1E78B33046C33EB17E3BF61A17D849493D08F0FCF8232AF2922D96213647A47A05A9A08D28AADD3B3BF412F29063C9D78CDD3385BFA9F8BF06DCDA23FF79A5912D867EE1B0D526718EAFA6F0E231CE6C51959BDCD8D201838A50634F1C6BEBE2E4F5235FD01A6D27B90C58C12D8210692BF68FEA5B8A8651E64EFC1DFCE07EE670D473F29AFA63E080F7675F23E7D2866E5F2F9A525BB657E8BE5933FBED1E206C7BA9FF097EC95B91E14612E16F0F4082F70A1B01EB6219D47C716455F4C1C60948CF3228557E787A3186B4758AD35922AF28BDB328693BAED15487F7448D1796BB9DB5C931EFABB4BE436B2710EA280368A8E20C5782A7FE986417003236BE9CADC560B3D7C2CA92341536CF67D412E855B92D0229C45B1C518D8BFC82DFC9F413D3FB23D37EBD96AA0CD0B39EF88B23609AE0FC2BD16FA9E934329558759F05C8D4C8F3F8728335B659D3986E44508322E47121E592C9DBC6F49656B473EF7DA53FF8EF7BAE07D1BBC68EF4AC369D7F8BE60948F34444C0C443A100443EFC444E7FCF0BC4DB6A2C2C64662A538D1F68F4DB95B0B83DFD744ABCCBE5DA343621F0E182CB9E915B2097C186F1B98E7D8F297C347B60EC26D04B6D9C1FFC01EDB2551FB8D11D49E52956F69CDE0E49E2E7DCC8E7C8E78C41A9B2A01483BAB11733A0943A9B765A5811451C07A195D87060F157D114358E478FBA2F2B755A2A455E9831B77EA9D33FAEDC1C562E1CFBD8DE156FAEFF10AF655713E36FB508342D9B4A239D6DB786CF9F57E1C39AE65A7329E434AA88C68F82359E6F057873968F9FB63D898F24BC13C0F7748F92E404C6185CE24C98D4E4D8D4B3C129CB46C614E773A89EAD73CF0C30CD7E6C9F6435F7C83A4C3F877E034755EAFC5F30ECE03F6413F4C7DCCD01649B6ACA9C1C3AC3D112F216AB852A27DB3B846CAED86B76FB699AA7623548EADFE6D16AAF5A3ECCC298D5CAA7E84ADA0B75290FC6ACE736051924DAE8FC5BA6DC9AFEF65F369D054A4A18950E71901F4483A4BDDB2584DEDC31A04C5F8916DA2DE33B37078E5DAF3304344A8AC368A6668464FFD7898A18D10685BDE6D0097F95A3587717F6A3A8827B46653D56E461EF861D6908AB7D865B532DAB37E02A7A6A72A06F25572D83ED6DAA540FE56BFFB2BC9D104A74F135127ECE457991152DD0564BA955971E8C9767DDFAE190052A98A63C4C0DFBD1B51BF60643E4C5EBCA678CE5150F03A6EF09AB0B1C2A0D2C19C2B30A645C7DB9B56B5AACFB862837A38407070DA9C7DDA20B99CAC7B03D10C8F28D6B1C686FD26F9A8FDCEDA6B188D472BC593AD51EA62DCF73D32EED5444484853AD0EFCAA60DD42DD2C50F5AD15DEC7B71BF585581B9F9C68C7C94C154CC7E0D19ABC90508C8EB2DE93F0BE4295973C1F443A1B2419E20F3D5F883912BBD5CDEB938A4452FE0BF2361A9E3B2ADDFBF000DB07EA19B2735CDF0E8E5C7EC5CC7CCE1A9C3E869718272E54CD9875C21DCCBB06FEDE38A4E787D111DC6A253A4604B314FE47A9B6F6FEBA3F8F013A456DBB78B497C4CA7F90CC6145F47C96D266BE5507DEE27E968052CAC85EC87049CDC68D723D8CF89B0C91F67CDE2908C0C71808004A070CFA2EB6408F5FD6108749406FFD3D5DEB6FBEA00FEADDAC4CC0E22A9F6F50B9893CC4CAD028FBB73C1B7BD4292AEAEBEB668859BAD444D0C5FEDE3C469CF28C5C726B59E828C473C8787453BAA3AB2BFC29C691FCAC2CF496ADF3949CC42FB16F3677D456E614B1F88406E6C9DA7DB9937B00764D61C3D347C140FDDABDF8CE5E3E2D385C3FA6FD9F13F3BF8073B5D6AACD5294938DEF9C6ED414FDE4B3C5EC43865A7FB02787E50F94033CFE32A85BBE24B09FAA3B55B8BDDE60E325B691A350F2F128CF74FB5B6DFCD0E946AC7BCFB839B3765616DF35AF29F3AC82F4E2DF7D4AE87A016094719A07B5897105E2B08AE3D807960FED396CF38863E69662238541EE295C06B290404985444F4B28388DD942E51867216C734580B3F1D5BB204B05D4993D6F8ACDC8F16FB77B607FEDA67939A2B6AE285ADB2C98E7D37A81AF0101A5CE39CEB2C67CF99441C1FD980C2C542E7284BD21F1D30E68EF3606C65D3230B5146DAB41D4ECBD5FD89FFC68441BCFED9AD8B4E0B616127A7AA39E84DBD1343E2A41B4DB1AEE0627657438034E890C8EBAE19791705BF6C948C630DB1423D310A34BF151AA8ACF3269253BADDF5B40AB7EB3A7AFE2D7891B925F65EA206F4CA121175E8F348B4162917A68FA768928AEB0504A60C4F42802DA25DCECEC60ACD21FB236080AF1FCC9146BA30AD964416F4B524ACC416B5357206980305555CE3485425EB8F87401FB1D8CCC184C486B5B563242BA9531147D6A2E7C0BEC1A56E083F05344BF97A18D0CE0FE56E8BE869C746D4AAB365225D8871D4F99020DDB1CE2B5D7D2E5DFC8A0DE780CBA0A9B9ABAC87F19C73639965AC2382488387F06199A08F283794E1B8D3580E5CCADE811ABA6881908277624D5395021016DFE21C345B9A21B474043E187403E5B0ECFABE43991865A424BD33D233AC4BD30A3CE73DCF49B58CC4A3D2CE25C54FAB3480FFE0D51A43B71FDB7E1126E66856D263DDC3BF1A31DCDB935DECCF858FA2CE5AC89BF32E36D8009657F11691201290A243B5680E060D2CE30F1BF2444D67DC94A24708F8F9261945D1B5275ECFEAAF40311CED5C3770A1C194EC44501DD25B7F5FE67BCF62D1BF31119F8EA7DEC1CF536C1026A8E72C7B2E167BCAA8673AE5506CF6208F3E1B6057B5D488B29EB84D6F94AB8AF322B8657075B9EAD3297505AA521D601C21540EE71349614CACE0E7F14EF42D6CD5377DDD0241E34CF273A1171135A376B98C53B218503A908577C268F6DD46CA9C26DFF5942998851627474DE9E6B46F49DEDE85CEB993A52D01F6AAD6F96439C18B0DD5A4FD559812227BBC0567A28C1299626B171855AA0C74E2F9B1AAA781D34CA58C72C708AC49F5AE1453902A1FFBB8458E8B4786771780ACAD999F8DB036CF4C3F77AE345817EDA2AD8F7D2AA9228C994F6AEE512F7C2D2AB72F2099EC932D818E495CAC8507B06CDC6702944237DBCE338C20EDC84D958C14233C1884BA09A023BF5284F0B0157048B6AEB508415DF337A553F6435140D0CE5D5CAA77F9137B2C1AD5A02B13738772743F192E53E970DDB401983535CB096F7D98644797F487CFCD18F1B22BA7494D892C1E5AA05E66B1A4326C70E348350C97DBC26CB110AE8289C97CCAAB150020827B7D7AC7913B4FF515583677018949D39CD73BC7DBB90696D5EBDBAE6BD6FC78E3826C8218996F079A387A17456875952B268211891404E80F8360F042EA3D9F7F7BEF772E64FA1EE8B4EBE0A1162A46EC1E9899766BF4D3099AF712A847CC86291B3D6FBF51B3B3CFF87D7DE71E73069619480F6056AAACDB9ED8E228BA075622C2FF242CB050342DF8F02118D071D27D1FDCBFADFF49184F5A100F95E1BCB019864E58E0F02672C8F5FEB97EFA06FBAE6EC3D57A10EC712BE0144323292A2CB27F1B1FCC104140F556D09A6074F853AD4328B00E6F2F24A61A7932311BC999805F2E774DB44ED72ED244A945928B9512556EFCB2BA7BE0E668C41AE7601339F0162CEC0A1AA91C3FEB6A8A40158D7A3560924455B9AFBD4B3881F6C08EC2895C84CEC30CB0F5B499B4A66267C719785F94A9B9F96FCEBEE939AD0FCF42D0E65DC241698DED0EDF1A9BB4147898E6E83851499175105BADFE4CB00B9000404DC92EFB4EBF41D9A9262EDA550DBD0B99353D001F90AA05591100BB678634FDE4E0B1C174222C253870DA3B8A797CAEA9B446309DE5210F9A932D6AD48A4A7361A943C1BC66BFDF75CAF5409034A8768BD535B20996A728A26E28340191E03DB17A7032FFF883EF664FD7351DD37DC2D72F0CC4B80BEDD1DC33BA3046162F5D0003140DF78FA588A9FDBDF778836C6CAE7E5A20FEF030C57867B295712DED14474FB87A301C31214FFBB4F8D166498ED93B6E233A669CB88D441A38A0E5846EF68F5DB20245980CA184878BA8BE1992A0638B058CD3A3A501CACFC818D2B5D7876DB6EB08E9F26430FB06EE0B9E834D1C331B66CD0BCCAD7A66ABF4A9D8F7A872932A3C0B25C5BBCA480159711E0BADCF69A1107B286AB199B210CE95BCBC4244780C074C42B6BD43869F27BD666F9B2541B1561B4C207E9A667EB1E31942697FCEBFD0B920EF80CFBC5CABA6F528187403D7E8262C110458B5382BC376799032362CE57ED39F0D29D7822C408923C29242385CA9749FACA43EB4483E095851E89D24CAC7BA5AAC60815CB5C8C5331CFD66352BC8623D5700F49FD98FFF9E869D5AE173961138D76E00CED6DBA09144083437CC8FF5ACDA10BAEC0081C8BD2F5838666A093B412532C521753C4E11ED0521923D1EE6BEF3B4FABED7467B9C8F75FB24FD8D96759A6146B34EF951C4DF92228C2E58231A8D25E3F08ED5A27BF6041AD7011DB41F815FEA503973D4E7B5798489B261A0AA4D0C32A19D17C584B1702713D1174E542BE4EDCEF27016BFC78118445A63FC1D17FBEE5F71DFF46F1EDCD050239C68DDBDEEFDAE7EB8963B5BB4819186D45191C05AA049E50C4319936C8788AB72744912AF28BBF5CC77C835C35BB4F987DBA6657BC2A7E58B7CE69AF37AF680DC0EA7797B29528AC70D92F295C561E2EE0D0E530854AA19EDC43C01A383035F6A5DFB354E9306962EAECA25EC85B9B78E8A1DF6CA50EEC733F60C81BF812981337F784F8CE07D0C03D8B3E72BEE1FFA55FB92DD0446CEE29D8825CBAF1A6ED295E613FC700FA31167224D99338C4F59B1BB9C1E63CF77476BF84F2001D42E4161F7737B47C1A5F219F6AC8B8E3ADAECA827AFCD6BC0CA09615BCE15F1BD0803BDCBD41E68F781517907EF3DD8E8A33A1E30ED09D7EC1D3605DC72C9232EF9F92475743164E92D953177B98906DFE5E414E134EBB63C79220D4907869CB2D93280F60DBECCC81B532CA336510E2A7F1D631F7BFC517AFF223430F9804C4A4877D8B7A385ED48F390ED9666A56EBD62F6C943D0E52AB1EA247BFB07C05908E99358A51E6111486133F4A6BE3BAF6B2D4C01529925ED911CE728B4CE4E8CF8379BD216108BF964496269BE76379912E94A4984B890A4BBB9692107D56AAADAF27ADE475E98A566C0C9E33DD1970A3DFF0E2F79197F6315E320BEB5E2CA3E3C904B557075981118B363042BA687DC682F13D213974B1647FB43DF7FA168C9D4F599C5BDFF2941C111C6C43FC75E69C290601EBC9F23D665F944A9B75932DF7792CB8A005A7CC83DD071376DB11F9C950B38B270E06C907FAA102AC76722325934755F53F3650B42D0FF293FA37086241C00E99B9C03FCE21F8D7555CFA93D09A0EAEE3733A8A5E4C45E74DD5EBFFD2F75EA60942BE34412BC82FC9959CFA155DC87FFA0AFFC1E7CA5057EE016B9751C16DF25610F1981A08B8E3352254AFA433E9B86D3CC13FE9B5B7FBDAD83CFA0FFE511E44412DFF1636BCBB49E9769FC52B302AFC7A96A3DFB233831007CFD6C302CCABC119DAD45EE63303DFA1F11C39C702AAAE00FCDCA913371F158BE5493A9B5C3B06AF66C8D5DE2BF9563FB617D1490FF6510971203DD25B27E1AFB289DF894396B8C26548BD53B320203AAF053B19CFC815C5D37E3115FD6CF8231B88FE4C330545F131A01124BB2487A3363B3E534BFD38B1D5138F8887EA63776D78783AC45675ED598617077AEAD86206B9FF61E3669C93C3C3A3A8F39E7848A88C0F94878E5D359C22BAE891FC7478BC8227FF320B047D0DFFC8218C1110136FA803EF6395E52DB8326CE8E3AA928CE42FBA04B1E7F1AC7B73296CBC1567090B9E92238859A87686D8E623B780F0376B8537F41B1BB102CC8C480C0B6C069F562468D4E1FE111B24D51F63E9BD38C47F35D8C2B5BE2E737274229974CC4CA63BD0E1F0446F6C4448EDB2498F2376EE26BDD8581242703715AD434E425908D61EAF865FAC5E82578EEB0525F54320B6C264F37DA36B55C2308D4FC6C7FB2F4D12A88CAFD93953193B7CC46804A0C464740B4972A71B7EAB5F6098FF78BDD452540AC5BAA894C10CD69A992217B422C88CC7849B4D8357D86234449B452AB4D49EDB1D2769512CF8A797F5FFF4E1E0A3FBDE292D91722D71322F0BD48C68A3CC998D03F7581EA7B5F5150E7AF58A076D09D103E9F64E61A2D375461007210DB511EA89FC4EEA75FFC71F7BF31400E7783F12F69A1EB5B7228952E2CD1D6FD57109237BDC024780006C229EAD71EBF4B543647FDD9216D98DC78B43CFEAE12166CDEDDE09B52BDCBFF089B1F7427EAECC21CCAF3FD5A35EE72C3107DF0670891E1AE12C1FB81581F3A45480F1FE06BECE6A494074FF3C47F90C961E371E8014707AB0FD004D19166140AF7B1C9D6B7E4B6826601AE104CE18E17939CF77C2A31F711D5C7D5126F4CB642178CE542973466696FAC1A0858ED62E4F2741E47B83B97DCF4610B1E4E262E700A06FDBFC6709BB1D4AFA7C20EFB72E0D623389DCCB049054CBBB322E63B09176E2903DBCE49083B01EB07F140D498B793E149573D8CA91DD2BBF8DEABAD9CECA0F896A7B306C22F8A761A65CE2BC1358A6ED07327AA0FF4C0B6E2906882A12C50D61D021A1316646461013D8169C4B54C61614CC9EDB2CE0AB0BAC96B36908BA3ABDF92D11D96EBBB9A60DA780AA58B804DC6F91E54D82068FE2FB10EC1FED54B794836F54503135A7F91921E2BBC2A61C99B6A0BDC04FBD2D4E7E430F16B5D3C7F06243517452BB7D2D51340BAF550D260A26A2F3B5451AD7D4E3A70CAF63F92E25D137C9E9B1433CAA5502DA269211F58AF2720FE3F899282C2C02B78E66D3302C5B9DC04B98197D3685EC4E6D4603D79B357282932689C2928361022E79C197A470212A69AC2BFC7505366CBB2BAB8D2E31314FFD77A04E85076D76948E836CF2A87918D43208CD856FFA33740FCAFFF9F690B2E6B33F1D89F65C71"""), + TestUtils.hexDecode(""" +6AE10E0133138AE0D51C77B5667D4C9180E04D0935EB5F282E696BBE794C8B96EB6A21A232C9366518132BD8EDFA9AC38142BB9CDCBA77C729BC4D1127A13933DCD44630D3CC6D1CF0242355A0DE121D15D7D4618F501E509C4E0BA296BC956571AF19BA6C8C2A75110DB6ABC3E7C682E87EB280DC29066E5D45C5D318DC3F14396AD3EE29A772117429E28A7B423B54470508A48D67CB6395190855A0D92B30E71B34CF7F508658E7268A27E2545E6B79E48F7C69ACCB09DCABF5BC5CCDB8CA8CA8CAA2F2869773349C666583702F3BDF94C40204514DA2B43A91443B119EDB0B421100AA587CAF238A87F916281435AA6FBF00BF16AA7BAD080D60B35C53792C438CA39A4BDC72BD7CEFCCFD877F82AD557B176DD5C28E78563D1DE719EBEA1099718B0F4129A493C11CBB2378F989D18A97074A2E0F3338CCB9A8A36C1B3749E7A99E7A765C70E5D60386C71BD4CAB64BFDB815509166D5F55CB4A380C8CF24E6BBF61AF3FE7BA3529D84B11FCD6BA6E18B87121857B00A737B0F3D9665720C38BB54C09C8D3917C5AD646E3D01359724534BC1910AD174761D64AE6F796900655E0B13AA3EF2282DFDCFBFA5B0F6585D33455D7D86DC6BDD252B040B66EC6A03FDFB4C06E54C734145817A20C42E408E7571FFB9D6D258E585D5904BCD45D16CA6E44FDE9A25E06CD3645A302EF8F3589D897181450C178E4DA1663F2F5960B4755A0107CE43A265E6EB0C9C267929CFB1A93ED1881798E9B8A1D91CAC83E63537FE0182D022548B60CF0BA47B6A7F90CBE86E1E5D39101C0D2FB333A82E2E99E9E0C1AD46DF3FE876D144FCD3B1D78424C6C5CF0F6E0BCB447A6E9CC337481F5C14D4FB74D764FB38B8EAA511951A50F41A4CE248E13E4694704A0554853A0AAB9405E2C274A4FCF8B5928667DE041E668B17AC577173B0F4CE34363A7C2AC9C3E0A45A39A46F0248BF3D45DBA806A230DB1DC7B0BEE80EC18BA8F042BD6FEE173177FC0194124AEB21BB06FA079A1BC80758B347E4B129D69EC6E8416BD89062BACE16F2288076469237231B6FF4902FEAC3BA7D884DB747DA6371E792827017778E43708A421931115EAAD9E4CA316814904009F1CCD36763FC63038641BBC4F6F93235E16884F8A12F8D71621354B0AE4A9EED64DC5462917D4B35370AD9EC8057ECBE3A6221FE8C39B11444D4BFC380F1F4D5AD18091059AA5089E109181247DE78DFC231401A3D517E9DB655EBB914385BAC1B2888E3837FDB08A9E7AEC206406B848D045593BB837DFC41DC283CAA753D8CB64CEDA3041B2330BAEBA2F1450F646BE15E0B2A46578B1F54A73FA4DE57FA1D632F3FD410C0E8B17C11E197B7A17C522EAC6FBB78001DF9F96CC5F6116635D404AB454BF4450D536250B80E813C8F397E038590011C66C5164E05FBDE695482185F02C4B6B566BF3FA564E9232F40594AF96C96CAEF18CBEABB292BA546EED3A1AEC1476A8418B25DCE79F12D7B4F89303688539815E05F96BEB3B1818472C7E4DA7435652DEB5FA4277F2A810831F88098899FE2EEE35C1B0E6F74DF159D0631C5683C2D7B86390BCECC534CF69F3AF74FEE59EAB25B634333470A55CC49C28C7252B1CF4C293EF500589805FBE5CC056573A10F188A02D050AA34289A21D8B7D587C0A288114E47F346DA3772FCAC58CBAC669DA616C9976C56D87CC275AD463F2131DF95460A151123C964B01A2B908AEEEB7DB3E2FE12EBA46321D7A3FCAEBDEA0FE11B78605E3C8390486CA5D484E6C413847BCD8C6BA1B00BD2322BE537B173647BB63BEF929223C6AEA687F8ABCC4A8B81C44F0FE24588D2C40BF76590AF7157E2E4409804A28AFD25E36275C34A976D22213D457C162ED9274BF52E20842ABC94B2A1D6A4A3F9C2AC544060974DD687C2BB96AFDF8C27522C0C438E7E0DD4DAD7AD640A4B3ECF50CB6250C0A97FDDF15D8865421E490F84650144AC489AE7920C4941895D7B2F1911513E428127562F9446BB706FC06F07BC6C9922987A970D4FC21937BC09F072BEB132BDF8014281BE75BBE6F8C74E337EABAA16A064EBC956C188787CB34A83D5698438AD22CD4FC80781AA1B66E5A2AE0180B50B77FBC07EB6EA60246DAB074494CC9381F6011C2ECE64F97B2F5CDA92FE91B5533518A7DAC9828FB33ED428890A7FEBD0906095094576CFBA1048665782B07194839CB86719DC91EE8C2F64D4576605C2B55804299F314DE8571D0C58C78F071FE810B2FDCD3D7AF0C635303B6ED0774637B1E563855D54D2A1B0FEB5CBF84E693E512F59A13A20E5FBDB77510E3356CF211DB09CB471DD1043D9940DC1BB6A26CEFFCA03F48BABE03C15226EF29E0DEAB6108BDDEE6462884F8708E79709775AFFB39303D78BC51C8B9EAB5D91A56F8BD1518708EF243AED01A637F525E25F297E0FEDE03F3136EF23C4B33DC1D256CC92E3B6AE64C368542AAF553B1605C94C255012D605D1291098D1F0B855D137BE49D198CDD3EBA0A9D9E7519B8A5BFB4DC3F338219CEA7C97251166B5004CEEC23606421A8F9248359E5346594080FAD04EEC15C56FAC9D55EAF4C399B1FC8D68501B88002212FC0E36DCAF5016371696AEE5EBE4396C36137C535B13F09D490564D38D1E0FFDF13902F7678FD06EBF8E34E81BF712D918348728BE21965F5956EC8AB1F5A8D8276E6A72B4A69FB7C5AF658C5DEE4C8BE285ABAFFE0EF41529AD44B31EA310C3665F2EE61B5817C1191549DA070A2BD4BC790E283BF81C11EA05A6E4652823EB3FA05283E784C4143F4C029A6A7D485A1B892F7462CC26B1879B4668D133DCF6B9827D3A91E069B25DFC72EF00FBD6FBEE4970E26222D81874C748C746DC5564732CABCD0FD99983034E4F5523A43831ACC1E6F3989FDE186D4BD07E15CEECD8E68375A5EC130AD93C0837A27F5EC5810F6C87CFD8E37BE6117496F7C283AEA1DD30A5FE5AF6F8A94867A5A7B336B4070B1B5539608BE8D10BF765F6984FB2D0AF376A7DD4E5E25922078782B77C4E5D5E086669D265C6306CB40BA5755E6D83D93D33C89F548FABB20DABFE7086B9E658F4A8BC22C11C8A12A106C534EAEA38F46FFC84C2A4D96C5DFC31F6F21B3FA32F988FB86A38D7103ACBCE69C5D143C33D1186C1FCA80A13C642487D5B221DC76556249EC81E42AD4DFF51EF86F2ABC45274AACE72A79A7B985412A3E94C92CB824E3B54F328FD2F06B49DB12338284DCCB5E03D063CAB73B939FB59A569E4E693E53B446279281BEF3637B55FA1C77DB77A389F43CA7E00B8711B32F98C9FFB2FA30D66075DA836CB528CDAF3FCF65B6EE3C0355E05A46DD0DF6B3D71E8C705B6C14514A537627FFCAF805F8545A86865D9EC83B243BDD4A444D6E09A7F26F5C30D824C39C65E1596BD506F70E793CD5E703159736F7A7C1B1A08A88E348FE12D0D74A190EE4C8CF1E2FF44B9FF40A28DB611296835E251E8451068C1016A3EDA063242D1DF3DDADE57998C1FCBF7B9F988392916D4D405F82ED894AD693FEB4206E1131911E3617F5A5325701D01AACD591469026E10585C1A73ABDE7ECA706C97F48B125A8E101E55D0262334750AB98A8C4D33F98763684402C16BC7BEDF35AC349AB471E3EEFF92A79AE0F11F3CF17EA1406FB6DB669537CC0E46F0A7C42695C4595FA2F0E604F048357125EEB01AE824FFB63B70F10DA410EB93933398C13B485493E4DD5AC42744B00D2F81BDB3C7030C3DEA36BDA258AD26D4540D1FB83C7E651E31C0A2F7D06A328820D85321B24E4B798153885D80111D17811D5ABB97C69B24E3E82B44649CB8C5E828A3D532DC8EF2C317890BCDEB43571EEFD97780E68E03C1F751F5EB823D75965ED7714397112774934F465F61C25271F1AB2EE80BAAF7049D1E0C78EB59BBC3594202F002E883B7B579B98D0D4865ED783AA0ADC84A4A37E73C3CFDB5F464812AEFC6081EF899B5F4C9F903279E77D39B2DD0939329B3C5060990BF8E0BBA6CCFB6F7BECA77F48585F44F8CE7293D121335939E3AD785BC66AB2C9DC955941EE85DB9D2A4F404B3F45C7A68452E6AD108530A1FAB8E35C9EB0AC7F647DABE0E0D50358A007DB71B6D76B9922797F9CC377D675E70D9E166B750FF457A5D3D649153C81CC1B659ECF3656BD864FDDB3C430AD6FE44B21DF23D0827D56899D8F0544472298FF1E12FDA44466822409222063A8BC27A2C2DF44B1C4F56C47062E7D717705967F8C10E0F1A35B0C4F1EDB14B4E3A2ED44163651179FAADB643E602F2C92DC144FD96871AD3CD194BC83951F18C77B92518F8F3013BCBB49E57A4338FDCEE5000EFB89A3DC2177ABEB2DC34C094476A8844CF072A17FECC8E87F8C3D85B776972CDD5EA7F8ED6DF4A123197F78150A2E9CF2E3CF88617E82FBA29410168DC261EF9516AD01187ABA8E189D59DE5E243CB019E5B7C34F5BD158B5E11E9D7BC75BDFC71B040EBFAEEAEFB7639355AD3BDD27AB9DD799BEDFA24D2AC5566DE15F46CF601E08A702B133D391B0E236951AAB4BBA409C5B8C49EA0D1E2DD2EB9D6EC67F76D12571C002C1E3448FDFD0FD6D5C070E6B749E9C3E6A86DE347E34A72DD2B19C51F405B8A4F4DC04E7A7F3E0BFCB51EDD253EBCF47171E0F57E7DC04C0B1ED1054D06B7DD2E8E6FBEDBB16D086E1975676B0B3D34F3D290495051DD8EDB5C6FD727C8A460668FA7EDDBAA5AC776727EC2A155770B5C98297C45F192C5817C0942C62FD9FF9BBB5085F7B197AAF21173E1B2313FD94DAEFE9B76E068E8D6A46F25D6E81E09F34D0337F22086EB2F32D4917A6B5D685E3FB94D919BD8D513BAADC61643AFCFF3B1DDAE63FD0562C3F60228C951217142269183F4D9BF65F438D86739219161F9C6AEE0F65244E85758C0BF3B137B30536129FF7557E5C52F05AF64883FEDD419DF69DD8B9C9EA6D4A6B018CF676E91855B58B37120D84D3ED06C7173BC3BFC65FA01CA02A01E2893FEFC9E0E708506C84698BE652909F0F9793C443635A032CDEC61C5ABBC097997A62BF2894133BC991A19567C9F4549B30EF4C081FE2FC52724CEA974DC6CDCD4042D3118AFFA2A7EBAB82ACB14BE405FD6A764C8405CCCD0D1BE12410855BDF950747EB26E948C7FADFD2089D26824F7100FE574815B487865090CA8D8307D27276C8C5FE813A22636672026C72B81290AE9917FDD5A314029D02BC37EA1C39B592EECD57883952907C4A2A4203CFD6498C19328E55500BA395947B0CE523836ADD259F92C358026CA86169D73D17044AF5F4B7EB42348764488FFEB8D34237F17BA80D5AEE6F5DB8977898B2BEB745B065FC20DC567CB4090D65D82003B466C21921FCC13C6291CEF5B18E6F6F77B8E07FE9F803F40EB4A015A76E18C03B40CBB8C8095AAD7AE64B52D6A1AAA31EE00C5E4EBD04597377DFF1037A0B12D2585E8C2FF784659F3A57CEF7732CFE93DC4A7F11E5124273A656CA234AAA7503246EE53F430A79A0F9ADA4B6C0A5AD6DF6054883339C013FAA1B6BE863DADD11B5443B5E4686C5CA6CC2BC43415A116D2B908F8949FB594A470B2D6017FAD537F066B8F2BF20AD2F376B33633F90BCB9D262EB23B399E8CC8D7632E17B49C4792B2217BBC020635CE2ABE63B1039463C7D069B2B004D0CB650CB917311A049B97560768EC46A793F19FEC3ECBF9493AE80D16FE24F00953348E522E28B2668FE430454AAAD914C385490786CA7D98E6A1CB345ACD0A67A6B57A175D8A51C2B51F8763861B027D29181655D5548E2B15986DD3835404A9A282DE523A045E5DF42FF092144ED9392D589DE70678FBDCACCE10C956AE96987A266AD001EE70422549F7F27BD92748CC06E7D24483CE0B83C3F2067D522E789D849250E7F7588A2DB9BA9D5F439D9369F04CE59A12474CB5FDFB08C2AD9E0889CB0F2056A7170428778D3BEC8F9084072D6C0FAA922400D8239119E44BD7266A43C55A70CFE0984F60A482D08F9E77426AA875AB50748161B48390A43DFF04534054C2A2D5E4A84C804C03128A0D7134BD3AB8E0A2BC7753F458A38B9B244FB654F9DA3C2784CCE6958DE3DC806DDDD84A8D2AA24A8382AF4D11E52E1F47733FF61B79895A9AA426BD060B4761EE687F1134A23EEC3EA828134C4B8108A6C5B9E3AE6913E955299DFBCE6488FE32036662FFB0CD451A98D97A1538F5BC34D527ACB9CE6D1DFB5862FA889422FF32319E35AB53102E566C710D4884BC3357280112F2C694D957D26BD3372D99CDFD00CF55098238994610D18A247BBA60650EC3AD7FCDB208B15C4AFD35A25735844D66A929037EAE673D66159185E4B2B79B48746BD9F046BA5828595CC6820EB8A860EC9C458E7AB183489C3ADA179C40A386B1F33F2D41C8B1AA5D571D1E7088B0ED0372C95824E870D63A4B95D87222C121766B270A3F5523BB6B69284B676C81F20D0F37418FB0B40240414E95B7CCD6E110658CC41F343F4F56BAD2D31A495D6BB2E9141E374AA7B2B8EFFA3E41434B4C4E6385BD0000000000000000000000000000000000060D161A2228313A""") + ), + new SigGenTestCase( + TestUtils.hexDecode(""" +6639A514256A8CA2D510FCACD916BDEC6245D3AC11A035B7C7095BA4DBB92C62A8D0C518807AD496B31228F96E1A2A23096EEABA09D37E615E24E5965E1073DD0192B175684B4F326189549EE36FE38AB2CB29380675306AF7FEB99B2BB8A07D5BDAA761EB9409F46E70EAE199F0B3A72568BF6964E6A58DDC6CC223FC89E27C104004C328694148109306900C0085913042D4B211E2922D60A80C91008512101118C04492344863824C81C20DC8200819C051640444C10470E42286618424149040C2344292161009400ED0203012B10991A404A4B24011A848191800DA128D83803003182C03A5201B4066D9462102442484880C09A20C1047689B140914B70C84B068D4282823885081128222326CA24882024150A4B04C44264059320498926924496950C0841910840C136E1AA10954A2889006864222665C026122304A20A36D12486181306992368509304A1416210B064EA3320403014D918885012051023701101411D33840E4206CC8A888582484444486D8A06C03C6499AA67140804518216024850001896522483222932D18052922344954900DA49890233351C434852025420B230122044D9A26604B266E8430011A2889C120240819461AB76503B50554B2605AB429091591E2122E1A320EE43808C8880D4AA264D3960042C06C24C92959C024A220208C942152B06513286D11B440DAB20104B84804A50D088650A4386049988488A28108490A81328442388EE440021BC811A1B204A1482E13B2842007501B288A24A9092109629BB465002966C44682D140459BA8400381108BC8051B826820466C40301111C77140C89112394444B60020992901178D624202549405D1320502872D02164598104249A0114A182ACB3802D0944552A441C11641C986255AB864D1184EE4B44D821224E3086A0CA30C5A18100BB3900C022C194780DC126264248801B9880A265110272C142025C4328659124423262D0BB590E28090A2385010042103876D61284618C38D08A10D922684D906501A33611B8468098830E3844C0A4424222640CC388A1C05110B460A24004C02132408067224C4611AA62409358AA4C6112322629C464E20964D580430CB388603B44C64C42C0000095A220DD206655040415A2864102510C4300E24A46DCCB28D89180D1407714AB8451413409B323011396C5882005890911293081122850BB94012050018C905C3248520B34D08964003852D8C220D109270D8464ADC34301424840CA480522282D1346D8CC810D4000C22850491B224D84688C084450AC30C1987111803618CA6644A384D09C8012092040301121A4722C1844823A1858AB24DCAA841A4160E8B34889C249280208849A0851C46290B1260D804604B4451C1C2911C0729013381E2C44019962062C28CE39220031824234202C24006C82264483466D2B630DC90880199054C242804424A5B0628D3866C1200896424492025050AC680192921E088812413204988448A368C20A36519006C00410E23304A18A04C0CB96C8A46210194105B82251B05840A15840A185059420E93C289D04611CB0242118100004606A4C28D1145114C186A922260093921A4941154C669534625898208C0080E4848061197411AA36CDAA80C0890655A2284DC380823A44CD04680011370C2840C8092249B1648C134801401445888215B4620A1A84D0BA04D4006061CA769D9380C1AB78D0019669212911C020E91A0909232515C224D243662113242CA081104A950E4C02020C069E3242E0C3109E4188518427261B84C840422A036605B1486120022D29881A3900542480613A54914228D4CC44D1B112994403112C6894C06665A384411499083904864C82D8B002DA3142CA2320261303044342CA2322E83464A923885C424690CC60C0926528844300416600C0741D0126244980888228CC214704B9069C1C84CE484440093449A226108850102C2212342282234650046698938660B371160840D58120C09102110B4451847480C434D1B33111C990459480D90260C0B464259B82C9A200D4416062139310BC38188120508806113396604318D8A928509372698380E21C925000384CC4228933031D2982C5332461BC10D5894451A47118490691B386083482D0A8921D8B82941928120156AD212414A90250C248202310DE1346950807101106864808004A5604488712216244FCA3DC070EAFADBB8E253BE1E85890557BA06F6FE596C9EFA6CADB19A6FF51D64B2F169E1FCAAA7761B8E4E94A6DDA9B390A96D7C0BD5AB3282F4F4E310FF1A7745741B15A80D1DB35B18090B1C35467939147179082650854D3481AC46C4D5F372ECACF58B439D2C8E9BE32AF5F647C4D1C8C06C5FBF01D95D35E4D7EB2D0D0FBA5B152CF08525006714C6A1DCC41281FEA9C16F1950B66DF989AD4671296C9BA6E565227A47EE10536BCCE94ED83E57092ADA82578FF23FE0C01268FEEDCC0953EEBEE12BE828BE36415712733E973D6A984747296AD5D24CB48002483869BEC1AB4AD0487BC6AA09CE9138577A5CFFAFE08119E3142803CE2C88D83CC9A102560B8A2BD01684F0C7FA1480421F4372F88CE04C3BDEB9A09FD541C17C67BF4D06781B6B8AB45A7C1DAF153B5CA37C1736A12B7999E05D213A2501AA67ECE2B92710749BBC902E550C33FD2A265CED7D3A88A961503E8C4A586867A9A2AC605849FCA19DDB92ACF22D481FE8A16B6BEA0E916119A83B8826B7B64EBDB9A8D7F5517A8812B9369EF1AF29818940FF4C1A41A8193BEE2685866B887E48DADC162929938202BBDA46D7FE090A185883192E45464E88026AD24C12B37FADFFC15956F0A2BC1AB5E4917EDC664D3B35E3C9E2CE2A73E9CF319AAE5A1EA8161B747989D2269B80E82086B677D417FACA39B64DE63AF8DEC028ED2713E7EA645A9367DBD8A4BF6E52BD45082712BD30A12D639DFF1069EB150941EB3204FB5F7D12C655F22594A70AABC428131168179AFD776579865A2BF65988276B9337B553EF75BCDB793B67FB602583A879747CE0169B72E2181C6BC1569A7353BF0476F7DCC04F7410F1C94C6C1E164E2ED651E90A3288EF61DC18B89BD8746C0491F680EAABDC51B68139E8EA42ED4CEC08CD60093D18EF38E26B1615789EE6206F8996B34EEC3773C098D61C0B4E4ACD835C98C16B0F3DD0A8145E1A74889297FDAF7FF20519A6184013E9773BACDE0705496D3B4103E5240759EDB954C9E77A05B20E4833F446F4CC447CF862778E97A388312D7AD5E0D2626B298BEAB7D27F5CA67EB73F3CDB03ED0239912590C787F9C3F4B04B170C6582DF1FA489C7F8FF48E78C3AB63EEB5CA0CAD4BA17AD57EB6181FABCE3D00D31602FC3ABDB1231EA961A5F64558D2678F963E603343FE35B4B97B60E102B95BCE07BA525F4122692A28F891A77A87F07C6444AE92C621875CCB9A973961C55D920BACE5050C42938B6FB81663DEA18FAE1625B13FA3225CC80FE23D557C35619214E140A55CE2ABE8BE2D82122BDD702B5263498B9C2957CD3B2D933F3C62A0696A0CC96D99BC106872F0E2B6E70BF9429530ED9B97E68C4ED660456D7A79E37622C0C854187985C9928850A15FCAEAB8D8D9A3A7CCA7C13C400458DB650B0B37C858F52B04FF135B6BAF86E4D91DBDFFBFD6CA957B3E1CBB1381AF4118D9FA13B70692030AB19C8D068ED620D8E7E150236B8B988C38B6D4002A3B4FD078F58B96A3C4A996A13F0C6190F783C6E6AADB8D69BA275D7045E1646C56C8024F8D1CDA3EBCDC42877674E480A070BC26C118504525595F034B4485CBB9C4C48E5B5AC4A250EE8A98A8D0448B5581F9AA1F92BCC10199A0A63AE5AAF39D6C2F82D64E6165C9878B3FDF4F3403ADA84A57202B94F4B65B4EFB551477FAC6338DEA7281962698CC54110B8F15D4BEB4C091B845306024445EE008933A8FFBE63AE3580E098A18FE33681D926D46AA99F5DCD9E9C6AF4CB2737036BE094EF63C0310A42DE5CCBCFC75AE57EDF5DEF3304BFD6854405781FA983BA2B582B631E4773A62CF8E3B222F9FB0C484653E7DC89851C989F62596377E35BA2A05F544D6C2AA1FFB71365BE259FA6AFDBB797D70C2E40474C2697A510E9C277133B26C2ABC03786589859134F5719314F392093125F15EC2334A2833BA6F4E634DE374AE5EE93E7C6FF37D978117122A19F5522E63D637E6109BBB80C95AA807B205B78821DE56BFD0BA9949BBF0A58E2D3803B89AC37DF91955536C5381D81377AE430C261992EF2501AB8FD653D715C93F63A98C7A00667AD74DE5548B685BAA6D301D4C6BD9E40F7B50434D8E88AFA19F73986CF55E5F318BC5264F909F8DCE692637FC09F62E9CFF2AE21FBF37698736557ACADB9E782B6E60A214216FEA674815507A12933B0A9DF9165180579072283F7351FD9696B1C7EF7713845B3EA3F618A0E52ED23273484EF1307E7082818903C5AE7A5EF2F11E5D1E813B8B2796D2E134C43EA733DEA8EC94CA03E64B0C06D7A52C38FD63658F549E49872BADB78020B9DD64055EF006D5D92FC0642EBBB025C44F436B9586C9453FDD9DF65B94ED020A5F647717881470C0C27C266AB56C3115E4336633E492893DC34359732740E954B74606232D2F6E988CE1FE565527395CDBF66F1CA04F42B34DDA2937857589E3DB5FAAE2B0CC97A68408B2D73089AD0098CBC66F03BEB12FF72A00AD72C5150BEB7760D700D634A0823988D20BBE9237B9E1E60737CFC7A97CA65AE467026E3664D2D2242E73C3D43AF26D33828358670BFB69A3480CC4483114FF22D93B452578CDEC1B93C732910438B66E30CEB14EF03CD044EB6D51E5AE1242EC49F176A4D888DCDBC6036163160D404B5B17F194BEC4A1A8FFE396B6A1E3500D2C1B17CC8CCA3F105A397D62B4462D3C09638B01B6A60AE76D93A4D7A204F8CD381C7ABB9C06F9B4F835D89A69A5F0424052C19D5AB4FED48B4CE549976F68BE60C54BBD5CD80E8A0DBF80A75A961332ADC8377CF2A286068B8E4C7F9BF85B2FFBC9FF2B9307BFE33070764C49EE7B2DA597BAA459C4C0C1D5BDA7DA4EDF5DF2ADE76F44A2C64576CAC913BBA0059027E98666DC03610189BD709BFE88F0AC93224DEF65D86FEB422563A83BA823F9F312CD13A7707275E3701369CB009EDBF95E966DB3DB9645F493852DD1F71B025102D2B5CBE6DC315DB57D4E47C9FFC1B65E0CFDA0FAFE7937459DEDBB5983FF57ECF7E1D38E9B67A0CEB91FD7CE01DAB9FA9CFF2A4DCB19C8F74A4DE51DF1D466A44FABFADED4CDA52FBA424B312A873D29DC420F8FF3C94DA1C896E0D54F8C882BAB83573716DEADC439904093EFB720A1120A7CD9E18DEE7B6674466737C36948A4EA961AD122E3C461FE6D5A3843262A3845CBC97E37EF41BA9274D0EE4E77CAC71DE5AA39E860959E353AC28D1A545BCDF977BB4BB7BCDED646BEED12A6E03ECDBD2FC3C1D845D5C9299882D15A295AD1D39888EC943216CC0175AFCC605938A2F72EA01F1B7BA77A954FE1CDE49A7B7E224D1807E81BD09634346DE0ABA64C0F5B3D2E6A9C47C497D28CD231A70347DC9B9713E1FE77CF42DE2AFECDFE081395AE1E2198E2C8D5FC05606D648F18D3B5E0D96BA194C1D9E4985506F6A96C48F1CA647D478EEDAE301E86DA2D916A41832D28A6315A2B95381632A3CFCE232621C8477680D4DC096A57163E4B570DC6AA475577A60166AB550437AEBD5810B523E4053AAFCA5D5F702F26C6FEFB18637B23606568C43AD1047AAA51E84178814319C6FE2CDA8128B7156F84ABF9D11D201390283801BBB87FC2AB6B050539D1DF5511893F809CA261303C54A7C8BF4D433E330ADFD495E3D36D61D469BACAE8F1F8814777B3D20B4F98EE5727C1826CFBFBA2E5BC624C4ADBC32519B731A666EC67D082570B1739066312284C1F560A9CE45EE0E576F5269EC5C325667D13C3A62EFBF24236A0598F973CA99C53DA3E5D4130FF8F4791E5A900B0B2FC93364B234F85926BDA82286AA1B04A2EE280357CB6D2A464E8DFE9AD6780BB2A6937F008DCDB8B64A904E9CAF6B75A4A3341D068381D6C8646992A7AFFC4C2749940FC7A51D4C7195F291F8A1E3C4E0C7AC189669269036A2996B9A7A1D696C35CEB82DEF7B4C19151E1DD8AC8706E38FFB945907D2D825B06F65EB460A5F51CC9B17310FB878D73A436788DDB87978BADE32BDDA761EDB2CABBF9D44B9E7112BD8D158B502AA34F7326244E2FF83C778B5AB05C2A8CAFA7E218EA97045C658152A21D8015B4A62B27ECB39B72CCAD51F52D3F323EF61F35304BF52FF7940642C38A0643181A6DC6042F8E4D87BBF40D04770899AE2165B39C2ABE3D00E41311FB1B3DD865567F9C60F5FD03AFEEFAA9EC299B50C1F378EBBA3700DF56C4EE64548C29A6ED299B8392DA122204FCB5CB990E898379DC6CFE26B6C37FA4F25066BFF6E296D1EDBDF8578A5E939CFB07EF8D5040DD3F46AA3152D5CD76285F9F864664E465FA66E338CCA55557467D6E7B443478CA00900A6E14FB8C7FE7F27984153A3A1CF070E91C8E520D1F6DC0D627AC966D6AE8B3B10B61BA99F642C0945174E3D62A3448A0F90C3B1F7104409FEFC05286B4AEC3BC389698D500E199F70F8374AFA60D2B4F83A22813F8121FD99E37BF310733F61635E4690B0C6D0498563287FFA83F2D677906A4CB0630CE3A768FA827125B8E37A5F5C855192762B8ABDB0DE0C94538E441620CA1B3F24425B37F7C13A9A55EF08117B8E5D2624A670473741449647E2997BB4F7A1E08A2D58ADA29E80F453C271BE545F2939E2F95342131C2C9C3E4FCD52C24F25D3D3C6B040BDF0B8BB0FF47B0E4A6EA11A3F3B10B68E4F2225D5A5E4946E6033926EA55A21531F7C344B06E42B49908C8F3D43439E949FA1"""), + TestUtils.hexDecode(""" +36DC7A310D995379B796EB8F9CA346EDF60DEC7F6C00AA311B3E09EF96A6795C4B077C1D371DD8D4A538AEB78B81927D08008E817A6FC6B3F9B14FE56EF9B2664E76112F214EEE848E67EF33B4A4E26A2378E9480CC7D25C369E6C25A2673B946B635B6EECB5F5F1499B484DCCFD5165D6F14CAA8E1EC9A9E4FDE417403720D7B4BB30060AB95C6F227767D671B75A1BB5AC5CC33EF0509C69652748251869B072B9042618071233B48A9BDEBA330F0C450A2FAAE79291B9E2480D1CED11FABE56210A80C39F25E5574356CFAA32E57782145920D6C0D27C3AC7C63DED6A770A5A45119FAA92209F2A066AB90FCB81A886FB87641C550368C1B412E43F4FECC2FD659B2BDA6B7309797575DA2893314DAB058DD92C7470F570EC0B1D9C9A149FE0934D40182CAD14D5B3D98C4B7454CDD2AE7E54EFCD554AA5B458888048BD5201C04E7D6004FC2A597DA781BF15AAC9748B6659EC16602F10AD44145607917C3599A1F53DC95839086A6A4FFD66F8EAC8AF8F11C4F2EBA3B58C46B93D0494C4CDA4E8B8FF7278049D2B4BD7BA16BC57678219EBCB5E211D51A168B5CDF66453412565B9BD606CE29A5A70E60F3D451D4214B0A258D6E9325EA5196C55125F0E115B14FF34FF6B172471C2B4917FC36B0DBDC82D0475AF56249AB9297790535C0F0265D2A853DB0B41B418072D0ECC17CF91FCA86F6E10762EBC520F0AADCC3C79EFC25E9692FC0A66389B15ECDD1377A9C3D744CCCC4BD160FC65A45D4144DDCA04E5408576DBA6D5C875BB4071729361B0514E8B96405E2F48D47138D2D2DCF4DC865F717428FA1262DB0D2B7B1A356E9E76301D38BA506456B4AD70ED09B0D5A1375AA6E132D7E06F8745E7A5B5E4F6455F4282A87D2B372C40A34C09699AA8C2B2E060107BCDE0F9D99B64F17DA5FA01B6DA87B1738882976B21AE12D1BA0AEB37644AAFE5AC20E7F3F631FFC2A24EEFB61DC37485DF27FD9045BD9BB5D3F00B9B2694CB94B01E7A4F0D909B8612DD28BD64E6C1C5A612CB30DF6004276FF58491B8129FCB0B539CDF891A97AB58DDF04AE40BAA5781C3AEC65FD7E84DFD0369A53CF36303270DC80E3E428854D82B08C7AD022BD99AC0851B16C7D8D462DA21126F70D661A59E4D0FE4441806DEC48E37AC4A271F15D916135408A2751CAD53564967196763B512D52240B2B0D3D924B83CF482B5316B7988D73A16B773705097F5ECE0027CCB2C2EFF598B8F61ED4D6BC015E56D4549432A6A95328FE3122EAED0149E2144E4CD2262C7FE7495E41E0AC9FAC9A11E21AC940D25E74AED8EF6FECD21747FF8166589B7038EF1DD504F51E01F1ED911FCCF44949638AA6E8526F0B9DBC5E536FE2AE7D4DA9DEE66402A45CF55D0137FAFDA9207AA7E22FE396455F2F43108961FA6B0339D89EB8ED7EF13B936E3D2DA18E5EAE45B05DCAF5D845DC62CC55553E37CB328AA2C649ABEED0D862E8083962B81B84A85EC12D3CE5B600123AA7CE4764139BA7AFE5CD02F70D06DD9AB0BBE868070A9AACB951D362E2606FD940A8F5BE632393E0A179C2A62151A094901F5625D952D39D7CAA87B77C4919A8633458AD9B6DAA16D1B1CAEAA8075741094FBC0C08D30D9956812C1D3A75926C546ABD78A2B9D44C1B6EF8D6EC2A2EA8B7C23D0EA57E1320ACFB576FB9C575DA98B714D6B01F03364E618A2C03BA84BDF0E5D2A0403B1379416D87B5E022BD958B0C9170E82F8E9A727D39C8F7549E34A14792776AF0D72A27FCF63EA985B3882A717091EF35F5835D4DA127554B6637AC313BA3BAE8170B9E70A6DDA2DBE813A49F045D8C3A65ECFB4D5F71FC75AADEDAA91A81A958273ECF0CDC4512F0D0ACCF9D9D001A30D0B6B2D50BD216D6086AC5C9DE7388A7B1319F2E9E6CE128B1F72F765804E060A8A92C93295A99C66D6D79BD7DD4F7F02317927D60B2E9FD59EC3F95A874337228339EC673BBBF53BF0FE1886A4B14F19CD7FA9B771894377F904EE8BE48D64EE5D40882C684C81DA3198604FA599DA8D4EDEE8EC3294620B6555B3BC9627D4514DBD1F7E3E9DF7B56BDB4CD395A8CCADC184B2B8DEB2AC7CBEC6C96001EDB67E6CF6F872469B110097C69EDE1121D22FB5B5AA4CA540474630651A4F9E8F7B0ABA5DF568D882626BD158F925F8DCE1D81668EF7CF770DC615ED0F5A807E25991EC97BBF2F9E997A532A1BD82A2A616250D2232F72067A17550EE516F28940D8EDA9CCC0E02EEFA496010E499E62C50B03F1D3C1571342DB8A5BDE1F432F7B6163BA3AEF35656434937A42C4E1F473331E38467DEAA483189902364463832ED8C5E04E0195D3435A6FCE75EA3BDBDDB0A0319262083141B1BBC0C278CFD40319647E90BFB51374B0AA5EBF3C564EE95B7AF618669C935756AFF3150A93EDA92F0ADC29253758A6C8A83EF55F97F1A4C0DB566668F30DE59D93D8185BDC1CFFAFAE472E0B0FC4B1E16F0B748220EB2EB85EF127838D576638E738E9F93A05D41CC1264AC6BA03B202D9E3B06946CCC68DC15261A029B0C5E91DD81EC1D79BC51F74BB5EF778F00AC091513443308410F60AC1850F2548C8101DB3B6B4D453541E36F0ED57C2C14F465196F8F1D0D3ACD49CE3252BAA0C10521311B8B8366C579A430526ED58BDE92FED3F0B359ADB31D67BFD212BEDA7236DEE4615ABF13C856CCC93DD02AA28D1CE1F12C2DD69FEA828BDB9F4CBC9242E1017D1063A7BF842B00C75243303EF9060C8EA501BC73B3EE470919443EC91D1F0D6D0F23A899AB86F2E8A0898D318BA520DD15D9B24F4F10A1B9FC52457714A151E075BBE419E4216857500B8354A8445B5FBB526A6E008229F33D8DBA14DD42F424DE3675E704DB308048B2D17904DE46B76622BA08C62F17EBA3E9F414A1B10921858832EEFBC282755B319E176ECCDC32A25CC5E76479AC112570AA86518BB1E6CA3F46E010E8132C0A1E8273403C5C4D7046A05398D461CB6843D70EEF8C94DEA5DF53CA1A4C7842AF5DBBC6451554FC7F9913E56957C51E0A602D882BC389C5E5C7899539DBE6832B0AAB5EF26B2C96CB03D1795179A62F748CA501CFA34D5ABBAE3271AC1F005112645F10863AABB062FD2C781E4573173935B5392CF9E88A1A31989E1B8E94F77CEFBEC591DF6529C6D2FAB72E678C534C4EFF40177C41D02AF0EFEB6371835CB55AE0AA99C0653876CCB56ECA127A0A1DFC0F9EEB49525C9A5786F618DBF57C41C5CAA971A9505BECEA8969D9DB28B0E707C659EDC42280035254E91C522300368F49F2C36211E455FD620DC956AFEE41A2493BDB2B0B8AB78E0B838DA6584FF753BF88CA6A523042A285F84ED90E0FD5E28F75A21B53F618145C16925486DBF6B1E7D76585D0D117EC562E22239E14A49ED714814F01DE2B250E9B3B6A1C99D1A71CEDEEB3ADADF611C4A4F97E1B26AF9780AFED5783129FD58B1232C7E2DB9050AD3D494EAC254DC46B0461A1B4B63840621D45ADE97EE5663C9BD8FB7261152545AE35536611B5C65DD6D66878DB71640EA429F801D6FFE291B06062EBAB9B416DDA7D261A46E58B154684E86176169CFDC4A60EA38300C3D44F9A4C9DCA0CE1BF37DF8F786F28B5B3CC7B0199D3322CFDFD2CF88C5B794C69F59543FB985890471DBC93A313992ABD33691CCF69B96A9396E5F55B54FF7BCA82A31199E5E81CE94B6B523EC5C3E2F2884D8BD744CF0C072E29E4B542DBB370FA5966F68CB20ABF40619E76C099BC7A9A373707707624E8999D4CF0A75D4AEAE113D7823D7D2ABF54FB4E68B8A6A57A198B128DC69584D2DBA473B6725FBB8EC9561D6614D606ADC4FD9CF449008C0D54BE4F62EC1441FF79EB59442AEFBDF1F0976844B4FA3969EEFEA10794FDBE35E89EA52F50AB26319BD1604D3FF5AC660431F1073575ABFAEEA00E1246DCD1D9399939D655C222E19E9DBA5FF42709FC11E7E365D7F7CE2274FBF1738DC5CF5631547549F2BD4DE896C8FE039720F5E0149BD81533022DAEE22B93A3AAB9AA9DA15180EA071D98E9FD176804A5B04D089E9C2D386271A8B13E7D668AA74BFFFFCDA3B4E528937C41D43A87DBB46C2B49B63BEEAAB978415536A87D845F6C2484F21D71D0F904438C46E7B0A3C6DE5ABC01C6F7CBCFF21D3E74AEE96C20C32884DE4EBA0F282C0FAD06BD9CD6B7B5031F149E4788F102D2AC2C99FD09B14A4AE3BD6859CAFE6F5A494EE8CEA29F49D871B79BB66AA6E6EC3718B97E83765E96D5603B209027BBBBCB09EE6FDE3AEB65AB1D73684820AB1FDEF88086B93B6338BEC7088E04F5F6E520E3D715C6C5E5B79E73B9E7AE1C5EDEEE4015860CDB9FA21FB434C3F28AD865042284A7FE9A5FF47E8C6158DD83EDF28BFB18DD5AFA07A48BD5AF25B9644400CC976A9B0FE9D9071E708113802A78CFDAED28378AA4FD6FBD9390D8A17D6500A0E1835652C7E0B332A382576AC4381CAD51A31E64E5E24FEDBC62EF9D0CABA0C8EBD8B94625207D0C8C1C6DF4EA2B20832EE44D1E2DEB799BC97B7245EC404F10764296E5BC4A919EC24B4F5F7D18692FA8DCDD5BBC170A81BE7590B7BF4058DC7BEA0C545BC85F0B3F0936386C37115A333285451CCAFB8397F1AE1B56D0A8F884BC968E729D622D21FA26B89BA2726C91E6886838DC9912797FF2BDF6800665C1D1DADFA4A240BB9BBE21B6DD750389AFA49C5C366ACA5E9C3B31B358FDEC42B0032D9E2C22112E43BED2023B364DAB334BBBE2C3B669EF700702B5D1837A6EC15CEC2B2036D56B8760129F593A669FF00237D26BAD9F9C2F4ED4018D998E555D2C3CA1D53EAD6A1E27906353983D4408904E5FD9D79AFEFEC26ACEA1F39218C36637977F6E2F3F6211AA06AB9D5F991C76F420B152BC95C4BC10047E107CC82E3B00B2325ABBFDB0FFB2966D5FBA0EC7E8DE1DBCC053C4186AF23A6BDF3F14A7186665AC2682FB94B0E10516D500B7F67BE4BD2523E194A1ADD8B5564FAD9105C86B6D16B08AABA604419D55F571F11F4989197144DD12867D1636D12800D54D36FA88C620008095560103366711B8E3AADD5624FBC7FF51318D17311F02A807770466AD559CFDA0AE1439442E4413944855D4D0074D529CA8DD621DA02FA98F46327A7BA600387EAE5E724D64A82E94ABB760C891EE39F27F0CAE8D1AACFE20629DEC5DD9BF4CA91E65BF413FD2A9566B7DCA9E500C2C328F533AF2A957E46D9FB11F0DFE99127656B1D4BE20C946BAFF58E5FE1A9ED282ABEBF6EB35A35AF324DF0A858CA8AF507CE43D228ED81D863F7096044A084DAA37ACB6AEE98E5A94D363963D4F852B955C2F076848092E6199E07990372E56BA1D590BB83D0C7F834C852CBC39B666B801CD32A0C36B034264F3BA6911A719001FD0F4B63D2D628FD0CAD34B4C9355534A8A38512E758B110F48E5A09B504D20D178508E09B1423A1E61164E7D138B4A9455B95EC8EA786F5FFE67806781F1E619505FD7DDE9A904E9003CA7E5EA1077C94C228D36667031502D78B3B52C3B5A09FC398D8B5497B6E3F0C5381BC99DD7B11DADA2DCFAE352DDEA2C749F8CF5AF39587083C2C19576EFFE871AB94D1C7CA2183FABDB74B27A80FC4F20CB86B46B0B7F86384540EFF1C888168F74634F2C0BF7FB54F7002EBF90B6C4B2B25DFF068DFC7D087A27749D6C36AB0A33423044AE027DCA8C42678987005FB9DE5C2774924AD2A5A8FD2E89C288975F89B5C0EF70A20EDAD1925060A12606A9B03626039635BFF332A0E6BDDC4F5DDDA209AF8DAA0FEF045FBEA9523D04458FBB0BD81F65396938436AFF5FA66E997AE58D64E7B5C1B589558B3DFF6D035E31008D2C76CA426B07F1644F609945909DBD16559B36461CE882A361D0415A9D93CB98A5370C56913A299B2DD1AA372CB75C7E590A9629CAA6C439CC5C7D94A21F36F998C6FDEC1C1721ECC500ECE1214EFFDE65E479D38C635EA223286DB326EF9B19B3CB862C96C162D3DE238C2948E7613A0FA4843E39EAC51EF293AD7EEAFF0F522934C982890F83E922B2BD52815136D0A758B33641C54E7D4E0F3B19AA85859B750E7A7FB80892C3DAC5048767132E2DAC5804709B8560A4B3828B1CD25DAF263A2466AF7FE328ABC84EBBA26902FFD92B0D765AACC0C0DCBEF962E1B35B1195676E8A67ED593B23B2B0305B611F9E16633E77E3F31794C58C5309BA07DB5CF9AA1CC108186318A3F16A7141854C2FC8B469BC0F54BCB22976A3CA05FC2C8E23F1B6A891E7527F204ECCA0A5400B68565906E795FE4DAF52ADA95A9883676F9110B14CEEA389CE9BFFBB5D040E60D3D03C4E6D6CBE9ED53EA44B1AB6ED7EDBACD0AE0613DBA5A5C673A534D48B539DC85F48175F13404016C5289348504141338FE958AC28331853AE80ADFEB49A6637936BF82FB26B95295B2E46F4F9534720A4E86FF18B31335877C9CBA96A9B450C1C8C9C9862E51CFEDBE3DE5C8B901D792A179AF9A782C330035A14CE6A710D398BD28416CD72373FE216744F6237B38B97351A77D5D0DEA1A26A0A9A24FE15503240933E1CB5AF458E6FCA8624669A0DF439CD7FC13F7A1F10A0CC7DB8C6AFAD9C99B5FC45A7C565B5DCB74FF0EF426FE7C260D3ACB1E9E83DD8E6E11A642145BFBB7566D582D0540D7931AA28B7F8F682E6E2D90B6E6812FF8B7F15FCD3DEE686DF06E8E6C456C99C6B4215C4E874BCEEE3B4F94BA825C6A45C2A2B4C6DC04F8FF5939C74E7DA37E02D8230340C6E2AB7CB82BD226DDC1A7C7BD0C0FB36F71F9C772233132B8871A0D76728C2A141741C2662438C5CC7B129A6C8FC587A0E475545D176818B51190F0F19E91E05C04477283A0A7D4D646EEDA3BE64459780BAC1862D83E6B99C5731DF91F0CAB454E70A0D94D934D0CD83C8B8301DE282F9A1FFE49E73EDCB520C016FDB4AD02C261DC1A1E73E38809E60F91A4E38C69EC70D2A621DF0D21588F24CCD59D331C69E16F0F6BCAA8F24031DD5718875BD9EDA5B420C116E4316137D4B77623C9D73D182900BD7A0F90A193CD16107E692D469AF09F74702492E22C796B6B4A960D47FDC571B4A264EE3528A0F5A9D66DDAA33FF20C3101D50299EDA3225834C9429976EC8E590C6D48A721A14972BE70955EC1A0348D2F84347C1E8E21EB0C1FE67223B42A6BCCAC43648F3BB5464121180F8E3E682B4B664D91584AF55FD1C7D2E6F79A93C680238D29CB7FF36D259CB703DE03B2EEF6DE0CB77AAA8F49C61EE482A8DAD30824E603411D5F09482DC84BE794BB6EB65A7BC1DA92C8BC8364AA88D4B8212561745BCF3CBA0D6AC8B8AF80373DE3F44EE39CA3CE4C5763F422CD4E8827B1E7BDFF79DB990A52530E4A1E21F6CCDF50A322A086AFDF24EB5FE4D99F1D1BB4D6DA965D168E9726FF7A4C82F327A748DDB1DA5A3D0E9C8E0B060872B009CC9F913D35D94FAA912B0D6FBF233DEA3AE3C2A4E35BBCACE21CA3E5F7A7B9A486AE9D7A7D2E0B79FDB11D87072F1B307402BDB22746B86A1A0E6B41433D5BAEB2048ECA53A1ECF895E9EB9BC5D6AB5D5DF72353566BB90578F12C6A16A163E95CD35DA27C79379756141DD05C315B466871E2B726B8821FB6FB439B49430CB3CA47CD211D03DF40AE4A0BE87B6000BC9C75AD23552E2129F47AB64BC9E5E1620C99405CEDF7BC059547D547E2868A6D470D813AA5095D0AA4BB18D91964988391EE6F05DD47CA1DA0423CA238C5E50D43CFB0527973506B9F1DA4A8055C47D1FA1E0DC783CE3CF75FFAADF574EC2849631E2551368291AFB5F2C40A4F1A184E37A19E511F482B7920F6D51B13065E6327F3C21DAA7F73986F2D1FBF375DFE2505C0FBD35F403D253BDFD0BA1B00CCC5A20B683D4F1E1F2374FD914C7D674901A0F01BDFDC007E8021013BB9A2F885F0699D16805F9F2511A0C7D3CDC06E36679983A2A0F12662C88BB7DC643FBFFB58CB51AAB3CED28553910D063ED8FA37FD756B79AE4151521450E552E4F2B62EB6F6BCC8086BBBD30331F3F2534AB3ADEEACCF2A6E66F205935A167FA1D5C747936050E276E8E4CCAFD9E0A056E4AC2AC08738BC3A598F07E933B0ED285BACE3D24AE6FF7574351758F983FD7EEB3944473EDB4EC9A9828A5FC656BBF04DC623C75F8B8038F3699BD5F255CCD3EEDE4FEFA12AFE8F64436DDB1FF2DF100B09BEC657DC5D2B18E5722D5AB30D075D9A52A576B6F9FC8C8BA3ACA6A92E6596F688FF5D2A7E3183B696AB277B0B17F004843E58760683F90BE0C61DD0D1BF9099A865CAFD1BD1D8AB1B7D4AF2F86D51C18D7868BEFF3F6C53EC68FC46EC9F23D1AE1FE85CD97D8CECFD57A562E7E574ED1D0A7005813EB980C2A46A98CEC602C0E022E87D4A6EDBFD7DE9FDA8C02EF85701BB1CEF6013F4869D32CBA56B0AD6EB007591D03C76A839F9D01985C546C39E49D59395B10346820324F3E298C5CD977FC2FF83BD422CA550DDF2A69607BB8125647B389246ADF0095F22692BF907EC86BF8D70D7E8F2C50E35DC6EF34FD1258E1FEBA0B254470D43C77CB0073AEB2D4CE5F6772D49A101052D8CE943E1C7760F2994071644D27D26BACA88EA07F29B2F2050BAC5E05F2226F1F584D17DB80E4056B7F9C60A5D9DA0CC577C6BC802FAB26E570BF017DCC7236A1173E273397E373640ED02B4F9863C40D2A2A7828C3875D8081AEBEF349143BAAECF9089EE736EFF0EF80078D2CA7942FB24A92071D229A1FDD0F6A87D362E5165D57F62D927757BC31964B5DA63B90EB3591552F2B9902E2269A163FF221863ADEADC9BC92CAC0087ABDA02004C0B9F34E5CA8599DC3C4261489F7527FD27AD2B6501E602FDE47DEEBF3F3EFC0166B1EED95116CF43C8AFC0EF89BDAA9ACFB6DAC613770DEA78960C99C9628C0D21FAF63A0FF7A3F2733EDC0FC07B83F107A811BB3C1DFC6CFBFEC105193272A4BF915B1DAEB232E16216E40FD3F9D9399B15CC4C073BAE8D08A4EC42D91609574EB009A9B52F06D3F428F6EA9B0511D8319A1B1299C154C94B103CB586370A58F18F04F5D21AD3B638660D6C04E99D356A7289E37EFAD643A5EBB488D54F4A0194FBC4283A8C4ABB8D9A1D70150AA50F991204C038AF54B5B74F722CD6515045D62276A9E936476F42B282C3B08D9328089AEA259510240B95BD5E81FB9D7E006DCE0DA832BD9A833799E05CAAFA6305D16DBA4461BE13D3CAA95773B98F09230F2DBE13936495C2DF5BE3A8F3EEB4FD211810F4B07D3E2BE1A11CC87079DF1B32D44B6FE7942DF2627AC19FD9F584E771D7ED98AA4C074A9DA5B7C156F83D90EBBDAE78D636D51EB0CB30C7C7CBC1A96273C0AE0ACAD8E15D1196BCB2EEBDA332896BABAEF76B4275F863732D646C24627AB014AB602A47594D6031795B17144E6E2C23F0341422886C1E2512222ECD530017DA02FC015EBD5BDFB319F3AE942D75A55C21BF347A44B300ACCED7A339007A2527EF4499E3BA5DE334BE58D59918DD0CB55B2F478837F71E9CEFCBBC90808E0BEF8CC7712A3B008B69476C61535FF0787B7833B70C69B1EF506EC4F445B72AA12FAC2589815874E9123BA13A17477D61E41163CB21ADB8151658C99F1422C71A8183B8D0B1D489EF436564C47ED8482A0DE9170CD1BC34D88CE76E1B47B84E770020125F718B4AFB1E4587668634FC7464114762A9D74A93E33A5C0CDFA824CACBEB097B5CAC3B554BC0D41C402812D8E43DB37C730A6219AB6F0BACD096BBF261C78E991DE0A2278DCA7D1BE0E5F2FED72CA38BAA86924A84275BFED3B91FC8DCC5024316EA0587C96E030544F631076DEF65F05F98C7641A958313686B8580CFC20221ED50DE4D2CF32461FAACD0174AC46A6949EF8ADEE6FFA3F537228AEDCFFDB2250D7BDBC848AFDFEA67AE53CE9ACA45F349557E81F70F9DB92926FD0CED8C104E6B7AD180C7B3BEB86171EE84A8DD2C243F6869E04C2DAFDF0C938C0768415C56330C9BB6EE756BB335BAAF96EEAA5CB52E554E39E2435B0731B0062376F4730108DD2F05824A798DA24C239724D19F12C6F2FBDB52652352021E0167F31E0F5941C4687DCD13A81A20A0AF05A55D2533280941865DB4D5715AEC293A64AA2E5151C8F44A14B72C0879499027E67E4E2B487612216F6122361E8D34E92C2163B0C88583E3887DA93A3AA0E77FFAE3FE8FD5455BC86AE6D6D5AC7CB7BDF156A960C98B0BE50E1370A43E7D183636DEB2C64B264FC5922D4BD46A8206F911E7A742E72E4EBDBA39B6151AEDF5A6CB4157B375D9A59899808F1838C61EB4388B923423D3879E8228AFE0CEE9561135849A89363F84B41BCB166EBCD0E65A2A74FE710F2B3B55CA9DE2FA9DC163BFFF4BE91F10493936FCA15F5F39422C75233DB22299456D1EA3BAC26F6671557B2A5FB0E9460997DCA797C67C49DF109CFD597BE34C8E0FA0353F28B815D0CEB31DA93E49EF29CEAF20FEB0A8F5924DCC62E830353463245899900304A8C8DB5830BC0E97AB83853D8EB05660D6A9303833D170E138FF6F1C30D9DD64574D5F875F974225DA81ADE3D97924A38F552276F46A5208403AEF82D1E92959675EA6B353E5C6091034A295D9C12C288241055A2334C30DF0A37D2590626A7D1787A4F591A6E494BF55ABC76842BBBD508FE54C5630D11C54386A487A756ECBFC0AE8957E7CA8678D5B9B044117365AEBE79AFF2E6678001D23624"""), + TestUtils.hexDecode(""" +58BC36248443BED9F1FA12DD93EF6FE7D89828D96315A0FBEF047B5D57BE38BF2BBAE0DF7E983151E879479E00046AB12BA8354A6F51F9C286B83560DF391BB7B1B2A495FF27E582D3D09412950CE565F2A800D18454C0C17181153091B57657ADD3EF44C97FDD8DE557FA590474BF804E569EB7FBC36357710A307F3D540F3457FF382730910BC41C20402449A0CBC5A93B5FF47DDA2D39E59DD58A862079FD60B24E8FD43BF8750AF3A463FF810E43CC4E84D9B54B716C8EDC3B00BFC0A8FA7210E30DC6FA7B8668078782643404736A7FCE53A870491E3CF91C38A9E761426FFE7ACA6D1DE13BA213273E899DDEBD4E0BAB8CA084525DBEAC382D0155421B800A1AA921BC4EA1990E19CE090696E081AF1D4145B5C6DAC1277FBC483500B80F1CFCF40F49F48D2D86531E98EB3D14D1F54E435E976F0C123B14A4D8111927C2B425A43316FB10F9DE9BAEC23D49F7CF37D2369ED11FC3801E84C981472DED8DA4D1AACE2F6F4050EB94A483F79F2551CE179B31D753072D02642873DFBE5C7E61C9FD32701C10847C6AC35F41A2DBD695DACE401814743B88C579BA7B188CC878150C71CB5C8AC5763A805801FDFE267D812F65FF31D958B857C41B06A738646E93AD2D9D0AD0E1678697C494FBB76CBD41FA63719A3331A96A4840F0DC65F890F7F81BE3D22CE8500CDA8E3AE5A6482DDFD749F363882353D2EE9BE0784BDA8BB2AE75A011869108FC9736E6E6B08D9F6F42DD42F4C06A561C5E8B585ECAFAC49BE7B17299BBFB4B74398D8A300C6447108FAEF5DB463454010217F01AE45F0282D4A3B9EAF23FE092EB750EC081D6EC0329A9A537A5C270C31B1499983A7C293EF72F0A4FD91CDBEA3F029DFB35FEA766C475A07BB4EB7297A9592A20E3FB15119F5A7A9E658D18C4EEB3E35963C122A1397456DCAC9DE8EC08DF9873C751A10E189B9C8DB3F63721910E930397C4CDE3D475AA7E5C56FA2B139690C20418DC40F9AC14BC29B419A45ADAD66AE2790EE4CF0233EFEF06E75CDCAD7A594BD9D64F0A030EAB8FD2C77B3AFC4E4737FB5682FEA678FFD75A794DA8E2A0348088A48D1321C9828E0CBE6F15A746DF22248B360F51B501A9BEDA1F7263D5BEE948C72C9ED854EEB7DB56E5885F6892BDBE019B8FFA9CA30DB9D1C82D3E13AFF7D75B0D0A713FCD4934B559A80F4F32062BC4883CBFE4B4F905B8B8E639A203D69AB8CF33B61A3092B38F03683EC64605DB4585C1E30021294BCC7C98D8DFD80940E82E65DDE8621A38638D6EFFA26E19CC215FDD0A305E6BD731ABA1CD14BD397ECD52BBE7CE7D84F88323A4C2D709D28333BF97DF22D24BF792EDE7B5F5DD1FCBEB169B625E36D2DFA95539188CE7B7BAD539C2BE1BA1971648478468AA3413DD6076A213EDDD1AB0FA85076B6D91DBFC858F1F935EF31DA87A24E3171B30AF8F03E8DF50A1781FAB6E3775E5D14B3025492B4E0309228AD41B68B278ADAD656EF83B0F8B1ED030835255A4A07C94A35D27B256AEC0381C35E640C1565A80D55D8905C7DD3BB69801DD362AFA95EE532714BAA8FF701E8F8F30A6165DFDF4FF260C6DE1135E66DAAA7EA771FDB07E07F818E4B2F7334850789F8FD0E385B23641F0D8A7C754A60B35A76389F5920A4DBC0E890A7207827F2B6368CA95241DB5C6664397D5A294FE3CADE660D80F69F0458171684A997B68E6CAD05417DC192638F9275DC093FBD4A72925DF8FBFC7B6777CD28F13658B4D3745DBBC82C88E42A16C31766A9ACBD13DE946054131FBCFF70677F2FE91078D9593F12423A3ACCCA5761830297971F6AD925455B9313683F01541B53543808D1E8C6ACBFB93D3B4C715880545B77AD0E7F1CFD6A3426815BCCE1F3E7EC720BA259046B06803110F12508B33D7C04C567BCB2069DAD995C590A2560C766185D7F2A186AD1B336A1A5BE702F6691F90978F1EB6F3403E00A2464F19AC7C76D2490CCAE4C0D117DB7543BDC73E6DCCC6AEE86D74984FBE575C10E6AAAC0028D61BBDD001BBA9186065A7BD1E7A8C13CDABB33F6F2FD03BE5E950793212CEAF82829142E7BC7E97CCC4F774892456870B23A1D6CBC5E1D2B797219AA1D4AEB332F2B38DC3B230E0EEDD600935523D9C05D7C750B485F32DF4BDD932676E6FA4A7AF63E12AA149AFA49ACE37B03DBEDFD502B97B36238DCB412E5D9C6AD0E8209119DD9BC5C22ACFB7FF53827CD2CBF259DA76D48CDC11C452FFE69D73354BA70D9CF566872011AB6D06D027C9B1DD93B97963F964B33F8F4FE51EE4E1F4436E5B3AA240320BF3CC6FE63B219553F6923A134D843C9B49F913525B4FDBB87F5F3235461E8DEBE849449BBDED39DE58BABF6BC66DCEA2115AED2582504E5FE394B9C2C346C5251E9F058C6447526CB3786A8A66E86747129EEBEA89F6F27AADACC5A97D6D9EDAF5533218C46BE6C8A108F8723F78576133FEEF95920D3B92CFA38B2547CC48B97087EC163FF9C244343F51683E8B1B7D29968A81423EB1346DDF5C4E638D796C8FFFFF6C482E47227327FB87885F52EA0840B06252E5DE252577838D869B074E6D0FEF4811866467B82121967283C2E47FF209D9E3860FC43681E0AFF54E6418443D5B3F769ADE3EF026F7E96762E1018326A0CBBAEF233996322E495DCC06693729D7C744ED8B7780161EE1277AD7C9C4B40481869AC463653E1E7F7F60AA5C352BF1F1A9CE483446F13DC6A26239A6D784B9F44DE97299ADB3CDCE3896081A7C93445C45D9ADDA1ED9FDC49E63202FA99D02B240C46DB1DABFD69AA70822333264064184BD583FC949B5134902767D003E6ED1D05581C1D6AA5AFD9A119B15F745E835CFC832011829AD48530C7C51AD17785B06748230985E77E2A2C4AC40313EF394052AF472A74044B8542261BE57136759FFCB1F42F349A464066BB4FF963D9517D4D82181B1851654B73203B16E302E7F7875067D2198E33F819270183ABC0AACAD3ADF227AA20314979F296AAE763E9934F15A6544FC5CAEBE33B6D51897ED5DD4094B377C51C931E9E62E5C05F340507C82C4E2788DC84E6B719F0C1A729AAECB019946C9DA7920DD20A7E7DF89EBA8BDC8E8EC1B03FE6ACC18E855C02408FE1EBEDB17066DBCFFDD0B1948FA53A45AB7A892C071EE692454D94453E2D5E8DC33E7B6C304154D3843C6FFACDCE3358F8D845546E2DE5C1E9641646702E6CB83AE5CBB07B35E9CD28DEE1C6CC88D8A614F262681FE0AC38B86AA792CFD0509A76928FE196ECA25D9A8A231A1DC659CB37C2D7EB3B7702443D879D6725FC633D503841F43B4EA7AE7155074B4DE876E2918339CC2BECA755F757183748F1E9FAB045C3F22DD5DC2EB5752A4EAF055F64F9BA6B3AA65EABEA3F585B72D712E40FD2B9BBF5F62ED5E9343D613A59A81B8D4172ED8837137DD07FB77C3D1B2095B9686F9ECB15E37C6C1B19267A5C0D299A1DDF368559F615733F451532554D0250D52E4C56242FDDCF6DF7F4C5E0F372B04AD24248687BF21243FFE82ADBF602204E9281C2BB4F47D5E3233A6CB0FAC7854BF4B298EAADD9242C085856126A1806D7B063C38D2D6F13CC617D22626BCDA228ACA22B798C0BBAD8D3BE108DBCF6ACAA304EC51C78BF2D06CFEFCF9B279B7677F78AE5055F77E0C8BDB8DEC635290D154F59E13DD6E45CB81BAA882A54B26D2447C8DCE935FD0A9E5EE20136C3FC643ADCD342EB901DD8A0C9A652DE28E552A73182616FD7AD0F662A465EC1D947A0442F5583811B7A921FE210DB41614A01B880C0F811BD74325967CB5361235E92C6941B4E5EFEBD38DB1F22A084C2AB64308BA1E47AA7223962DD65E7152C840AEF3B0607827B6E99F6037FFF6749A9B871ACD998F719A222F8ECFF7B060F586CA9CDD6D9ACF769DB558352F7ACA2A2CD8BCBD91915835D96F0B1770A88097C234D5D46AB064D9AC7B3A387280C9C8A16FC561A7585F6FAC747FA4091BDEB5AF963E9AC134B948FBFB32805C80FC5DA7798061D0B26CC8675E2FAD9AE52DB944FDCBCA68870B29E270D9D51A113B064FC6273CD3F86AB72CF31B20F0B72E1B964A2B2E42CB71129481AE61536DCD409B431E2859BCFA5734A47A05F149FF91181F081846D376730E4D492250DF165A2B542B39781977E96802A4AC38F450AB89EB87BC19E5F8C323F29F13394228C985DFE60A185728ED95DD62D764EDEB4F46C6D5F24EC9B105075ABECFD0A27A24D52DD0826B18F89BBFB55C27A42496F5408D283376C20807922609616B07425B4E180CC6E33BAE22186AC37E3775A6786BB6E930B928CD682632D687A2915094F520D76CD439DD125B3DE7295C5C3D1D1367C49954CD0B2B944F5CAC8CF765F39BA61B89B007CDB7D46ED1AF4ABB6E219C67534DF7AD50C422A0A34B2204633E4763A386E7235DA77CF46CD2388062028FF8832FFC74A4612886B0AE4554BFE6D82E604978101B413B5AB9478FF79B39F49ECC91FBB639DAC7A72B97B7693DC8647FB472AAB87CC9B28C0CC91AD51C557ADDB3B6D864903B98793C0E80AFE5F02A2FAD2CEDB1486BE609832DFD285D92E67D46FE19AE445F4FFD7C166EDDEA185666FCF0B4B9F75D169B440056DEF1E376B0F6166FBE07BFFB1925B69A2E85C25C7737F9FB48B87E7F66D2E1432E12BBC585E3D4E6C5ABD5E65326A67D1C944C67DCFBCBB0A017666187E71D2B1CAEDE13DB5A4576F2F0606E892B7C57296B95B009CB92137729786672E11E66CDAF1081E167B0AA0BE018711C8CF7D285359B6961CD04F79F95559801D1DFFD3AD1E712AACB0C121BAD5604C9A5B95782BFDE6F1A2DFC110579197D1C6E6686AF1CF312B95621C6B72B4A57CF8B1FC47B773EAC6392B6CE10F6ED1D9A0C2827A0B12D058FE72F99EEEE750CD4D41BD4A3D95B1B7880535F78E4942A7D83D3E2FB8C1892DAA7971E4A0092CEFC9786D69D689AD31D7AAEAD2CEFEA23E0CE14305BC745A472AE0782DD31F8F5484EB129696950B2CD00A8F401C19441FCD6A16BB2AC5A9AB36DE2B75EDFB5BFFEC0AFB37886F415D79DAFA24350BD01FE8B0824FBE6FDBF6B34DF81F0A75B5F5F87D94011014AE543B1B7F5C1F7BA542BC3F4B134E1D9EA6345339F4606D132998969FDE118BB0F305F2753D1D63EA33465199C5D04D2ED4889C19E180B68D2C5CAE8511F9C69A6539B1BC24EE28DA9C9C87D7C46887D01740262F7F2E76447C5CED2C8E23A43CF9B5A9EF603C14BF4FBF4578A1A316029B0C036D085EA7AC855516CFBC6F658923D54AD182AA66F6FC62812C49E0A209F5FCD343B1BEED407C74BD4499024DC312918B45FDDB307A8DCACE261D070F84CD26458B62D7F3E9BDCDF3946384AC7AA1C32A34A218EF6C9FF835FAE4508485D2A3F4E9C94425A5B3FF0422EC098A34CFF4583C722389ECCDED9ACC397D53985F362DBD0DD401CF830E206BC956439BAA66981F2EF63C30F9426A389CF72F144DB8FC4F7A245A7DE66F1594629FCBDD6CBF44CCAA2C4E3D45C0137F99CC69E08FF6BA2E835DEA3D9DAE61DB48E684BBAC10562B6587193DEB0E6980EAC9877A5F954E1AF915D02C8C394483DF6C8AC9840DEF57D7885E0A38E14E9D3B85EAFC94BBEC68BDF2CFE33C08CB3CB7A8530E8759D27EFE663724FAD3F23F6CB10655C0AED09BFFA78FB3C671770A2A9B928C4DA2B0852836730C1874F7A027C861A805DDCE2CA765D091ECDB3CDA874165B5B0B87A6D6B64A73A47DAC6B255AE65BBF445E1633440FFC2882D487CD30D5BE629A4DC58DF086A4C62116A64AD799E34BBC46CDE85EB71E7A7B279B6E50A13EFFB00EE7E86FB19541596D7CE82F028A26DD5C9D0D807F686492E0DD3FCEA572A1D1E544EF62C282A904803CC2C7B2CC0FF7804FA14060A1B7D8E06A61F5DC2FA43179286B4DA6EEB8065C3D6397E6CE850562DA4E614A44BF81C3442D00AC3AEBF682D5B1A9625BA462556CBDBE75CE951C3FA91F83105887C24AE3EB3ECCD05B4BF4D6C910A718C6BAAF44BE750CD008C2591638CCBA780807D02BC462B9A16967D2A5A927FD75AE048591B5CB40B3DF6F092469BB30B2939CE425A190847B904B631E08323B88E11958BC5C6FE6F97DEC18B7EB94D14089F9EFDECA3D20958780998A7DE03881BD99B7315465BE6CEDABA61F0D3935694D1FB6610E00BAD93E96ABFFBE51F653FAFD2353F3ECA0A65FE4CF7D5583A19D99CCA53C11A5E8E5450A2383C7222880062C1315D81C705F85ACCFED53B9E46DD9CC544F588BB7C7594E4EA2B7720984C23347BAEE26C015C065F732ADB6B71C772FF539D9AB8458917BFCD3D8B8F6F9A495A942DD429A91DB1BBBAA2CBFF201086B14B8104D6CD77655510EC4EB8C995B95B1939BD0602A893F631499C81B0DCF7D02293A839483BB697E7AB5B364B8A386D481648557206AF32F4C96DD05232B37536793BBCAD81B515E6E7D92B8C0173A5D8186DB189BAEE053B0DD4B4F678FDAEEFF14295C719EEAF1FE00000000000000000000000000000000000000000000000000040E161C20232A32""") + ), + new SigGenTestCase( + TestUtils.hexDecode(""" +5B62D37A8591CFB588DA48B3B1AA1570C3491210EFCB877AE913F5C98D06C5853C78D526C61C387FC6E15BC8E612762899056F844B324E4829E5DCE6E2144804682D4F5D3CEBEFA61305B64386107BAC5022DE119038F94F656ABE41A61717532E374C1196780C888EF1F7455BF502420F61FE9EC389C1BB6B75397622374EE00AC0856130828C806CE14840D9322440B02923822D53126A0221108B988822A191D43231D82831E2C80CD4A8705B086D83B001A0A64183180681027040220D223269DB940802958C8AB6500C056E2222311C91491B9451833064D4280A112750232610CC088054222ECB344511B90063128119C04CCC942914C36114C1049B1290A414460893242316665B184262B211E330868A280CD9920504009162A4605A926C1B28100C002E1C4491C3A869C246860200050B1888588664520625A0102158409090022288A468484685C3844CD428919BA0300381300C372191B2001C086C13142ECB30710B3021840864E44465A4B061E2144184808118B70DA4161201398C0436810C2970DAA029D840600282411290898C106A19140A6394711C256D18C08DC488249A881123418DA33491CBC801D010680B865090104161B0511A15501C0104C01605D2B825E02226D1A0708B98248BA22040426A529220941080D34006D3C86458B4651C1440DB168DD1A66DA0B67108325109128A92C869833400CC842004064ED9340502132D1992800424309B260E2319105AC669481061994028C3A29163024C52462A5030221496846280250A300862B26523282922292410436C10B11001120D993884A34661830430D0100A00318589444C5C28802330884C22445148248A083223C02C442682E3C86C5A0088622224C2444C0A854554B26D18452214214898464A1886610B26205330310A9840443669C3208424380D94C62911C445528249DCA431DB4211C3824CDAB885D800655C462E238288221980D93468118441E42609601488204486623445CB02411A266DC392514C142D1AA8515CB60DCAA22819286522368D4A0630DC44491B036641C231E0064CC08430918460142670E0000CDC10624036852348819334308230458A38300095319B082D608268911868C2C2109C048D9C084120B16C82804C14C61120C071D1B850930245A48420D8142A4C302663B29103932521466023094A0A076C14012190180E901012C2B62458C809D0A004429885834010820629D0102462C624D844021C054CC43841D4082D0A498C2425600047621B90001AB78C63A228A1A229121126828820D224028344285448640A3104CC166411A52520B0205BB61052422509C62912474CCA226289261222812D4A28428888210CA9210A0965CB948518929002C56D59C04DE0C04C54360063426D62206420C8815C484511037209100C14122964008508A225C8068E80062A84C89198A411DB302613851023C6681BB54D49066041268501B970E3B005C424458C8425DBC469A2A45011914DD1064261080212C9010AB1240035658C164A10358621A38050284021196543000C03174800394108B448049571912481A4982D1CA669511090928845194642094226D4B42842800021028423294A51284DDAC690D0262401B26161C0250C8265199290A136680B0689C9B84D02948002227053386A0C08885B962899988419060490964DD8C86119370C21986D8848515CA6294C042A2208441AA93111C2905218220C454EDA1404C42488C8280C20433259C668803891DA8000249301C094089A008C53321220C468CB928D623881E30426011505C2145181488D008244A4468011C38499A090E0A425133510D14088E394000A271108C44822362D8C004D4A86512430242405818C4624C9348598882CE0B841091612204968A1C830A096108348106332068022610CC491803062082301D88045DBC82510C18C6486601909910BB3480A244A8A9870813031532881C494111A88605B828C0315022017901383641046890103668BA451223840C002458A8011A032101C35514A481091488021990CD8949148B29112282A224440C3127281920C12B889524024C3B0655C8209D104712143710A326112389213042C9B00820431000CB344DC1010E2B82859982C032602CAB00CCB843113C6200331280AC061D2848C1A4110911430D3388CDC005262C0858AC660B6B814546CB4270B543A708AC86BC1CE481601287A65C59BE8D90379B0CAA51F6D98723C5BA4787DFF8F095CE307869084EB4783EDE6ECCF369F923E9F435FBC1E5AD11B5E20159EB53B41A0596BE86945FA60133274AF288DEC348188C166BEF153321723169E4BBB7CC6CC2DBD6158374E10891EB82EC47383F1BF3A103B912FC2A929461137DC00FFBFB8D5A8884B1702D329CE3EB967FC0B1847DBBD06C3CEF44CF4EDFDD34E9671A3B51572A7510174D26968B869F044919AC6CF766250953DC9F4F3D0B28FB6D7D0F973BD3944B6ADA312044A09EC59E008EE8F92329776708916B1301D2CA52F9F571EE458AB13D13EDB882305351E3A1B41FF9BDB54D1BD5B768B7AE758EC8CAC4668582073FEA7BAE86D6ADDA4A4F582E7C4C298178DB1A5038D9D337B1AC18BE442865444D24B0D2443D6200A6C938963A812F1600D3689D8EAE1D668A7A0C2A3745CFF5484D0E1AD2B25A9A70CA3FB16D423DB83318BDA289478A5C44C5F81253AF25A7EDC4B35BD73CBDF3C621B0DF2ACB9B1D9C5A87CFF528D0C04F77A31818BB36492F3445E250712BCD2A0C2D3CC3B1BEF6AE9D1F4653EEC35E2C34F14CD872172FA46ECAA5824507EDBC63A5D5E8222308044C6A0647924F9D1B8AD7584EF56467A4531004AB4AE1D48203E032A1B83CB53C8BABC556AA6163E7DB321E71E55DE72EA992BF47E0F70C2180325559C33F6A0F9677BB801D99525CCCD1738C19DE9AA91A85146761FE773255D8B6BD41DB2515C23444463616F14459536703096F595E841B93AE455B9F37AD2E1A5710C83042689944C5C4A39F944E98C07D898C59F4BBB9DC8A4AC6F3789286D8B61382994EEE1C7581B3F2D12309FAC0A1F5B5F02D0C4978231D52D57D3D56D8F12075F4145270A3DCAA543A008F8A39D95FB555E1EE9D2C9F1FF557FB6C38BF4050B6F59C51C02203046ABFFD51745EDEE1B5BBFCF7A9BE1017839CC6A4638F4316DC6CD63009360ABB2B6B02818C542124B280E18A74BAEB9273B3F2DB8111CDA487DB87A18DFD16D380B037DDC8E60B5F1874D37F704E1A8743D51259D9A778DE571EB1962ED8A07B641B21C274BA9D1385B6406CC3D8ED00B697FEA1BD10967FE481EDD332EA30619655E0A454D58E59672293694DED52C791ED09E2BB3126EF1FF977931C0116B67C91E038FC70C382B28DFD692B1ED75A3B3753D5859A46AB0159C7F9FCB7E6CE9CB91C13A0A3D243D53956E444E7EA734724D45EDA455ECC7C3C74B2A2C4214C7D2B6B66B1BE97C7D6057EE64794EE0130001CFB597BC8B5C0C3E4D159E76F6409CD2C8D6ADA7F8BE816992B191B80FBE9835BD3EDD60CE62A79141DDEE46673B189A0F1CD0B103A66A6B42A3D9319B92761BC8A54F416AA8942E780BE5B70262426B11E3AE9EF12B3FB3BB884E3E230471C020DE7FCB92091396817AB83B9A7C40D53F580AED146CAD8C64BE7E0B5F84F0CB35A2731B710A10D784874B5CA4FAA3FFF38536890F3E48C5B6BA96BDFD22A8C02FBB2668D16AB52BF742D79ACAA94893C81C108622AF5B4B0D1DDAA009A2B1205B02D1B8F754134AC4A92E0669278A0FA2119C62F9F75763FD76CD4712D04B00042C00BD8E4DF2176918F97D83C03DAEA19FA30FDD16E1F9FE534B444C7C4A3E01C2779135D773AF35ECE0A3CA8CD3F3530760059580980DCA09DEEE0740F5D83D69DAF36A5A92D9F4096CBEECAED0816CE1326EC1804C54584E8C28355E5D00795838907B20CDCFCA4FE18C0D3D6E0DE96EC0A6C502057AF96C61A265DDD8D874E4D42289FD04F9DCDA6C270E7C53C3A2B23B20AB13AA8E3FB8B0DC77C0CD0F00B6C2FB8A36D935356E10D51A20E53739A5BDE93F96B49ADC09AEEC0B35EBFEC815880A56DF5B1D110839A9BF7946576E33C226964F6075987489DF3A7C0B574E21A219B670E074713ADCE8E401969B6D1A5D2EDE0F725C0FD829AA435EB3F4B9E689061C92008547F4AE3430B259F557E1A2DA041643FE2FDBC8E03286B50EF73D6DCEF0B9C6C75AB40F1D2F8D4CCB6725AF56A37044A3933923FC2F32378855CC0FBBC0327F25C16C59285BD19627CEDA13CE715E35A689B67DBF61C3B45C48FE507B02C4C2689ED5CA3D76418E3C2FC5269E3525A7C122A0FDD0E00CF4F960D45513C049223084BC5519B028F17F94A3B7CC1C407618935F248C3FBF0678F2A7A05E8A1911059264409A8801BBB80A3AAF8E0B6D86CFB3775F7F9AE87152371C6216947E89BA04EF44E8AC304B876028DAAFB54C3FF067029F15AE768235BAB8F854009110645AA801B2904F6939014BD76E5AA510BAB9D5AC17BBD536FC32CB2B4505A47D8679AE67DA0304E4982F03E22E77068A23B32192A24569D40356FAD23B1D79E40F17F5D2B0DF23EA437EB2371CE2C7278653A884FE38AE0CE9D9C60F97CC88E3CFE5AF1AC3A1D22079BF9FC2B42435231F110DB596581B44FA7E31265BEC9FF7C86EFAE208B898F36302B66E409184EEF82DF40FD60D6A4796C071C088BCD95E8F8AE857047BF83CA41EC4A845B48E5631F85192FB998067B0B7172E575D6671917363064C08CDFF23CA8499F240738D730DED8A79CF015FD9FF34D53A0B6BD0D1DD38B32AD0B3585FB99AEEB5C11547B8AD365269FE96CC855E3E7E5508930A639D82BD105867396D6074A6C2330A35967B1914FB52AB94F44E3DE354D8349DBC86E444B5165ED20376B11DFC9FA5F51F6069FD743804BD04222E22A79B54603AB0983530E1101227F8BFFA3A24E084D452E1DBA5B5FEFFB23B9842395658C38C7970405E17E0E8451AA188BC920887B35917159F83D7B187227B26B659D168EA4A2C8FA6330D372DEAFACD8854852F313618DC847C56832CB2A3C8029C5770F7D7D63CD3109EFD2725F24016232028CB1666DC9F407040806AE63115BFE51D2BD2D74286B205557C7F58F7EFD4755C53E2BF24F3D9F97E48ED86E2B7689B385BE82849DE6CA634963F2782436ECBD35F58EA3CEAF50A452EFB16F6072FA1E9A10B3E948E5F2959C4DDDD89921D4CB0214AF3149B7FE5E2DACBD9632720CD06B4B210350435F663C4562424927197703D7ABCF4F278C4335C623C55D8021B7A5766854DA7AC210F25A326F84E0BBDA83495D44BB923FD32AF32528A68F11C7557F4DE631DCFD8C233F473ABD54C6ACF3B3E935CD6942495FA61211CC158B7C2FEC84F923D6C4F902A8A19B46A931C68F420260A477A6C3A28B3B4133634EB5751E3A7CC46022B706BFBE01A3E062284C2D4A8758ACE690514B137FA480676B09EDDDD309D6F52F94B2D0287270CFEB1A6E663B762080ED4C4769BAE6C168CBA07AD79B1A1690C5FBE0D9A05656D4E52466C906271CB7C023A72A2F015BF869446FF35E9BC1A59E23D9928CBD1285512AECD6C904CA47F63A8747FE79AC8438D6C26F13FC4549453349441D959B66DB25037127C036AB356C8CF79F99F10BE8502734CD91CA6ED2F543F2C2D5412CB6D16DF798204510CF5A17E6E33397B38BCF4BC57546AF7824C0B4DC7D107392B97730CDC0F1528648FED45BCE3443A44BDF1B28B31FC8FD17A1B4A737CD28F927559FE2564A3018DBE808D3AB4A4440527825D2013D487293AA875E5E911510CB8B56B04099F96CA23C62E72C2156EA08B6C7CF5E45C869BD2468AFA718C7E3B73C6D02C7FEAB0AE69C233F0E46E57945C4D4EFF7796285E8988B51280323A8E89CE7BD8C068B0828CC0BEB77C0F44E28C5E75A21853AB9D8159B0E2255C5DD8F5746F924E237A4A8FA3745F5CA39814EE64E7EB1C94DC7B4A2889CFE7A01690A89285DAE12AA6CEF45805714F05BF0FFF97ED82E51842B099FAFF2F0C0F2C608FB3CB6E069D276714A21D1AEF73A870159CF5C56CEB3403D96F4AD1D413D03583985068349F73524D66760A17AAAD749931870581BA8C576FF6549661A43529A2145739AFCB3BADA0EA472AEA14986670A97FEF749F520054CDF4820C191E5D94599D95A9050CB45B6E8E5FCD28816D331F21FF06EBA6C0DDC495AB8F1BC645386AD1EC65EAC1FB4C4AA5FB8A301BCF5A04A7D61A8310804475CA128824C767426E55EED148C766181E2F2573149C2AA36496563A4497DD9244F9B17791AF92489B0BE38BB5A778E679B93BE4BEDE0C06B60A048955A0F598FB16256799ACA1CFA818863EB852A7329FD13BB9177B8653E3EB32D6C40601AC61F69FC91468737480C6C8D422755D2AC35E410D7504E07DE414A7FAD9A00CE495C84452ED9EEE7817066DF613156995D4132CBE14F1607FF63BDCE71849C7E3A20B5F728EEE14DF98C950706E97F6C2E340300431EF2A6E0FDD9B2EE45139C2DC66FC4FCF8231A86B9F498FEBCCC3E87F19DA17D09FBC476C8CDF0870775891CDF0C94411FC686FBB54C9EBB8AC22BC43AB8A72528DBED5AEDFE87CC534E3127CFB22784BDB2811B39D20C29A0FE79061A0CD54787EE228013EFA979413F8BE983F7D9EEF5508DDCFBAD3F4AF8526291A1840BBBE247969C8EA5218778571891783F16D84E517B7CC7F1A50999A23085AEA463EDFA3AC16AAE8ACF4670C69437821C57349A12F561A87218BA746065666A7B76EF92EA8ADA926BEDC8F25F809F4E747F92B7F16FAE68EA88BE10542DB5ADD7042E8B26115E2A587C5BE310684AF723C6BA4BAE47725FA641BF4C0218F5315E5B2EA0D89F0EF"""), + TestUtils.hexDecode(""" +CA0104B9DF99E87474389167359968A307F63AA32F0C804A96B18FFBE00C748B1D6894CBE2B7BA06EF17B6947ECE31DDC9F614348F01995FCCE77099A0D88B2BCD1035667631991C2BCAA4C86B4D31074A2FD46C38429B52CF0BFD7CD3E5D194DF22E2B0D57C0C9D624C772B54686AC963447E716C6B4DAFC00AE383CFFC69A2F6F931D616954BC9A140D785F15C5DB28ECC793D88C78D11F8F8452046ADDD3AD26988B21BF895DC810739FA7C45A8062B2931AD363B0C7EAB4CCFAC71CDD0DA3B54CA9A6388DCBF79AF799446395DC7A5B7ED1788188E9D03EB3BF7B80F8CFB9B7F33DA0D4DBE1840B9C6C5D80F6AE64487BBFEC86C596E2ED8E721A11D783F7552A4B01FA24F60B5B683E287BD75EA0DDC15314E014D402F527C5DAD74CFC49B4D824EFA77C359B90AFF15AC89C1AA35959570E2148DF7A09E27E2FC096AB5CB306B4868AB80A24DF745DCF9EDDE57357866182A9AF50796EAF97A1A1051FFE6F9038BE1F6239CADBF0BD81B23E2991941F34D0851AFCEBC4D3F8B472D6259CF61FFDB87F79928C66E69D969B254D57541A87C692160E5D58A837A1FE90A1799758A70F958DBC1BE5D6E6836845940C75E745245FBCE59D1F83462B9578534D7A05DC3F21C34EA93ED78387B32DE09ED3CD2A51EE2B8F7387C8C2D426EAF3795E99B158D467D9A039234FDF207D65D2577D1688E1B1E72B5EB096FB6377DC8EB6B3F51900380BEA561C03D546EE242EB4264C0369AA2D53B2B190E0422FBC4CF896CD549C2A08A37070331F15A9ECFFA0E91B1FC4D5157418914308EB8C6A992B197F33DDD517DF4610E88F2E35E505BA7C7CACB8E76677CA9B39A4094EB4590F6154FAAFA76C1D95D4072B5CE01F42355C47AFE569FA80142EDB49E2ADB34D3C356F4D882A52021C5216B3678AA6A5D52C51CC8BF09E7EAEDD2501A9886FAC977EA5F385F46E8718D39073D8995D392074C2525A4ABBE228F531E6B16AD5BCD5EF5CC4C3C71AA77EAC1747E2B763D0B3D66C7F35458BE43369BAA0ABED23202B733B3C7A111F9CF407A7D62EFF5BE3A5DDC3E49AF130012BC6D5D3641EBF268236473EAB09BE87BAF7707546B7AB194D2ECF5B03A56662B1D6462898DA94747CEE9DDA08A9026538D799F163E1E771EF7EADF8833C0510104FE7AD7EE75F44F8D4572E299A87FB17429718C576B29983B50FF81F8D48D41CC764809429A7CFE05F68168B6B36FF66CD75DC0021D774D07BC716A74F9450EAD2995089FEB89D1EA73A9CEB83155ADBA737B3DE33B6B617EE7F5CB6C6672AFC439990B612A6AE71540FC6D7FF535FC88DED0E6A80A484735F63209D39F12E6E129C4ED2EDD8C8B5A24472B83A058B0F1C86B7F4C53D88927C7E9EDB5C40C5D6C7F0ED8A626C5F35E1D3981936F0F1FE4E8CEE0FC7F66F0016B14F3D1EAA993A5DB9B92C03D99C0A867FEB343D9F43BBBBBD85F58B2380811CF153FE66E5B5DD07D5A87ABCADBBD472692358777BF17AAFB622D487A100062465D9BFBE0E63B9D862A02F09E371EE820D969B29B4E6F6A1120CDA9F9E3FB804B26E2E9C3DE219044D1D6E62A28CBC90C262B76914B8929465FD901777F6F5C112D196A002A0F4C4FFAFD2578B5CAEA21452968400DAD6490E313D32A708A42F64E9CF412EC0E358F6B833EB0190C5933037202C266ABAD212B570E609FB7D338AD3F850EFDEE9347EBCFEBBBCE90E7F27372E244C3F035D4ABF1008055215E573F0C4001FFCDA5E6B6C5B29B7F59132CD86481FD0E1245EE4084DCA3D44A0C9E6B6B14E1BCBF56F470F15609DE76588795D5CB62BFC9C253EEFCC155C116D70CCF9112D8E0A801A3C640C7D16634EA02DA9DB9AC57DC2F7D43F48ABE631D3438C2BD3EC97832244E81223EEE47054878BB2472F64E9ACA0D5A8B0B04F783C5052E0ED6AFADA5274C94084621E989084EF9814128226346996CEB6FA07FB957C7432878505442FAFC4D945A953336F9C92B8ABE4E4A092DA65E2BF1A7A274E1EE9D7958E35334D9B7CF8B314F0AA5C45E93111460A8F5409C0BCB842DF9C9887FE4643BF8958CDB40EB66438BA53972E359EB712BF4C553D871ED702F74C41D1217D7887C891E49043C0826FCCEB2897BFAF9F217DC9F566DE1C416DE9118491162113E2EB56CDD4C024DCA4A33359D88CB0247BDD6802455063DE9666A4C52075359316B3B557D42B7C99700F55CABCB2B802AE4209C6B937C798433AF94159A4EC0A7DE00C809F6E6675A4213A1CE8A7099FB7FE6A0C7FB383233444B64AA120BABA1C4E61C6426001184E897A3C6B0BDCF9759A72146EF848EFA65EF09076A4FF2E6DA518C5A08F2A2A12D904C893297234E53CFFA04F285F350412456C9A13E153421D65DD30B236653AC13CCE3D5CF1EBCB8AB46808414BD3725987D6E464EB4F97321595153DBF9994F7E19AFBD19E9BE929D18563789567B28B1AF05BDB5D2C5C289FCBE8EB159D0017E09DA8FE5E9D49D3A231814778370DFE703ADABFB175859A895A6ED86F9B6B52CCDBBF936622C5E5A01D50E2B6D5730EA4588680EFCCF390211F211472F9E10314482CFB45A24706BBCA8CB515B6A9AA6EE1D2509E8F9AE9D6F545BD3971A02CC26699608FE1F076A925008AB6CA8576CC5A962326A369BDA8ACED3618F02BBC55337FAB2D66050514F904083D4386B43B6EAD553DF5603201C6D684F7156FBD2D3DDE3D7EB0D569AFD42886E57B747F21D44B88AD58FA2370FE6BF2DFA4D94D8FF983A1C2B89876E75AAE3828D1306DB9A639D052EFA6A0EFA0F61737CCC45E0C516815E92E256BA49E7853F9E9D4670593BF9402E59EE80F6CDFF8244D156FAEA8220D483601794A3CB5E1D7B60DCF991A545D2C72F62E5EA05BEAA77FA86A80400A07B97D8159F0EC170913ED885B578767CCA7A5BFB8BFDB7AC99002555145D9DF5011654700D6FBF2EC2BA609C969EBECFCC0EE346FA01B6CF07E6855F3C832BF1DB6E247448438BAEC055FD41CDBE921E5F62D93F4E7964258A9CB3991E8084BFFC2E5B29BD1E32A64E32BF5E27416CBA7FA3DFC143281F3797E1927AE9D9E07FB424833A7911C23F231D676EB0FB061C179C72FF0038E48068D43A805D56C3B6A16F5A2E5E8457F1A3E0F927A8880CD261F0D0AD8F82EF0E52E1BED003661F1D4510F7BCCE680CE84A0181F046366126A53EE67C7309C6982C28966B6CA1F324D03F5E09AEB111486C44B6551B1C36E84C2A72F78AEF5CA31AA66EDFB0792C00579C0C7C1FAE501735706CCFADE03E9A0847E498A24AC1DCBC7DB8FFC946B8D914633559B63E3031C214414BCC1921D2A53726695340648CF6C2BB4FDF132C77BC39E9CEB2E4D22EB138D807D7B79F78CD9713F5BE7512FD32E73E886DE16A9B1B19026B91EE6AB92DE4DE663D9774344B283149AF4890BFA57ABD1C9DFF128F9F169E4CECEBA0FEE1C33D4E34B877EF04DC887F7109B2BA65EF5732ED4B7C6B33131EB5867811D4A8A3536102F5AEFCACAA681A6A45A3BDCB24C4FDBF49A134244044E2B424996CF6F3C514C77EDF2AEC177B8F80A1AB77F6D3D920E508C76EB71ADFE2209A132839E9BB16BD9991A545AA0587B7594E0422647DC84CD355B20983AD582324D4F19E33E9CFA5CEDC739B26F43BBAD1F165720306F48CB15B23B961E5990C2DCC39E5BF58A9BFC10829590A7AA8F60E13EE1DBA85EF5EB9B1F6DDA891ADF7357E16CEEA4ACDC00E20F8F364AE3EA838CB4A0FDCCF8B439A242F8D18B8E0B9FB8E074922E0C25922CBEC46C98A82E93F0E95884BA9853CC738AFADA3F08BFB66C17DE7977EB7CE5495B8620B537B49D1D37EA4B3477B79759EC7D9AF17EFDB2EF89945D453BCBDB349CFC623FBDB8F125EC492CCBAF30006523B543B6A17245CDC5EE7E28EA895654A5EA74781CCB0F30343C73B4BB88CE07BD37DE9220712F11748EFACCE925626FFDD8447D37BD9CF2476437C093BA4CC0AB674E4CF9543CEA67BC25B9BD56946C0D077F0849796EFB74C7F66D5B86CD9A38B8138D816F677CE08DE6A6A911BA4DD1834751548578CEE4CFAC50C11D685E52DECB77A475FF5468C38DB23853BB2118C78AC3D52079042FB7F370B3D0406E402EFA6432D3055C572C81DD999876E8306021118BA87D5D430E4AB9C24670EAA1274ABF4BFB8149D9067C427DCC026A61C5B724CAE1858ADE366FB42CEE52C36F0F99AC02E8BDF784EBF311334B83B2B277982519DFFA3AC35D97F9F30635CC17BF8E017EC4E209EAD104B52C58E8762052CA62BA7A82FD011860E4F298D889A11F6A2BB1B4157CDA42AF9CCD0B5324329A92CB9FD6EB81DB3FC58431BC5C9A6DC1B07F7D2B00B32E5A39960C5E2CD69CA2914F23365B518ED746B27733D713E8ABEAF9D1FFC6D3D9B601FB386A6911F24CC818C0353658CB826F43FEEA792055720065601F1364BB6184699F16E3EE2B359CF0642C85E9115B18E55482356E2F91121C5884578F3D2C45462E47A3D477B3D63448A8C1679E68F9B7AE509100B7B2B142FB6BA20179E599259414520B02B745E592FD10D0D40D780A95C164D651E96A7052B69BBDA979216989A57506638F891336E2EA123303F997194B7AAB4F22CB192AB59A8BDA7CC88D0F43E4DD949146006CA3F91CF28535ED42662A61F630AD6E7319A7B98FF5C7200FECA768F14BFD43BD60DBEC814E22C26F1A8191ACC869A6BCE61991E4F36148908A5B1557A507C407D73A6FE75A548CBB8CACF13E57BA6B01FF0DF900051AE7C0C346D5DADE5F1C1BBFF967236BA5BAEF19A70FEB320BD76035F3A6B11383F13E6DCB8D1533A6529C98334A3F2A9105A5CF1C940659459C405C197130EBA44F0A2881B4614B7A0BBDAD5930DE5C3389A7349265629E29C0123CC89F3F540FE5C9019662A4383A38248F22201967D908EB48D530D17D50A08B35FCAB73AE8ADFDD72A8A7551EC28C7573E2B33EA4F61EE84C3DCA33DD5861B8FB7176C4AFBC174250D51F86B1452903191E39EF099C0CBCC15B3FB5DD30A2822F68AA37D59583BDC1CCDAB1B2E0337BF397647FEA9111A5B94C6A3369E90F3B86C266F4C11C9A7D9E24802B31B5F93B8EA9AEDC6C2944965D6B54601311D251E81C77AC1BB2159263D0A92F377F111DBC8D554C3AF747FE7E82A6E6BF0E4E3743B7AA42C3B5B8D3E5D9C3B427B3290452136E61592609826F4B61D4960B7C3784D0E2508363212AEEAE624489B739D0573CE23B35D30826182DB5F4D09772582E4D6B61938041344EA434614C21B01530327C08539A84F03275D0C4A77FDF230FBE6639CC7A12C34545C5CAD34AABF8E25D64AFCA8206948737DBA643867A146F17ABF81A926294E2368A5A2F0C381E2C244B21843E3ABBA680CC3F1F0509DFAFF4C70B68C82D3D7EF8EE053DBD154376FAAB5D561A19362314B037CFE18DD03BB817444FBF08D771A13B9D745DC066C89C10ACD53597B74916BA719F9EEEBA865252FE13EDDF97978092FDD1524CDD865FD6AE9C14329EB62B322F46905804AF1CFFC13B46B6AF4ABCB107D44DD27B460101F7A38DC786239E34CA9D1A444898673BB3DD92EE88478A3C539A563CEAF5CF499AE8E07BDAC0CD5419DEFE2977105B5E0138D84A8F9BFAD82F58884377B803C8B68164A3E678648C18127A832FA994EBEDCDE4FECE85DAFF8CD6F44F4CE57694522DC30BFC492BF62796D05A9B87BF13A7D538EE5C55E6898D50ED127E8C12F87D160AEEBD3CB126BC4144A51F685079E962DB6FDDE3BA6D0C8038BD6FD8377C4BEFC2EBF1A876833516D206C2E309C61E4CEAB5F86ED83FF20C8723BFE63D8E480798292E6EC6D418D3CEB623AC6983A3F8A3AD568F73E408F15AB88C8F56F3CCF5B32C76BDCEB1FA41357C42E1215CC503A316EA0A83FB341ED6ED20B1154E5001A754F92E97570F9DA7EA8AB7F2EFEE7B79A1DDA705645ABC5B1E04CE4F922BB03435D11FC83EB580CDFF7EDEB78F2CEBBB6053410E84477864C16D4CD7CD9D16B932372FDB99DBCCE2DC3B5CDCCF7DB86AEC9BDCB8E4F27B65ACA9A3FB985CF95C5BAE253797C8474D0C25F0FFBD151E6558E524C6E96267677EB7A3E128C918CD3B09F1DDE311401152C62B4C59EA1D408ACCC4A12A34664D7C0858D7E99A0327724AE9CA55A9322D865EFB4FBFD37FC79F8D7B2BF08B1824D44777153ED6604E05DB1FC9B1ACCE05F8C53C32594A84F32D97AE49E819029204AB7713AF2AF2C281448A34C69D5F3DC76345031D2CC05B6B26303198E182901FE65710EA95793DC8495F1995F0196DC9473B7AB922786BBC61A91868BB0BE05E2034EFFB288502DDFE2595887CCD144E98ECA4D1E0C044C642396F98473BFDEEE796530467F6B5EC0D5B79674EBDF5D1416F94A8EAC7F4833947F1DE610029779CD436729E55AE3D959F99D5438E0E4407D0A870A38AB31E08F16A06345B7BA730CCF55CF1FDA1E9D04833ADE5FD74A34E2629DCB75A3482312860404F7E75D94D7FD2C8215C6A21BD5FCAE81CF4467931A984AA24B927039526B95C2F5F39AB2040A23C76B64CD2D04E95DE6DD9B8EA849F9F7919A619EFAC498E7E3F4A70432E28B1C5DEDB08D122AE503E98D34D13A4E8A69FA267C3E20671077F977F71308D3EA1AAED5DC33B3F41E0ED981050B3B915EDA07AFD71CFD3AF13A2063813039BE85EF98706399299118D2427A7912A131DB7BA731D18DC2838A116E05C4CBC660895294A73D170C060CD83C9AA0884C5F3FE52F4891C2101997D688709F356A556CE202C571E1170BC339F3E2A75A5A13810E3A2F2133438C1705895523D03F00BBE4F4FA9BCE6D7A14517BD54E281F202BAB40DF35253961DC9E94DF5C2C5C3F0E420AC67A85BEC2ED70545B94202AACE5E58180104E42C5AA6F7F59915BEA69AC10F678D40506AD2B502D77EBE4D05CF8253B4795094F04BBDFCC8033EA131BE83F3F647D22D1212C16895F52FEA576EFB344A476D2A8EC74739BA62632C4B5B08076905BC0103CC9B2193EF6C4785685F2B3F79FC39B5ED09B258E5E9BD346557F24CB542B69A3ABE367123179879A02F941F9781935D44BCABCC563BB1F31C44BB77D5E7A4FC7EC2C11D597E7288C6088497DCC97910CFD8245A4F255CFBCB8FFF95905E8224B770E910A253356916EAF1B3277D831BEA5BD6681C6C7D57D363608EE78973B7BBBC156FE5536C963030B6BC8D306F3C1EE72F14163DE0DCD0CE741EF975A9DDA77EE386B991F3096FEC95FD394E26578269F491572B36AF42CEF1D86CDC82D63DF00AA397E1960378763F5CED239BD2A6D0EB7C5BD7CDA2228B684FA57B7FAF497310D510CD386DE6406924CD592ABB1E9753EC8BCC594ED52B70C04F7C53E19B0CB607DEBA79FABD6748A52692CDA34BB7CBF95D1ABBFF8AEF8F8AC7E5D52EF58FC79B0C7662DA90A0F737CBD42E64B648B624AB497162A7B27E41850A9BB4AF0489550773EBF1EC6742CE8D53A20921149563AA74337ED4CF1EE8685F41D36F748B6DED5F894BBC50A8DEC84621B6AAE690D6EE0B392A7266A480CF985295361B14AF0A5CEFC1EB737ED3AEA5E5894FDE80CAE477FE742395CACD1174CF2B345774BDDF71853BA1854EDC8F5CB03D33C5F58EC386ECBAC8E4209F8881473A4FFE306ED3194F455D4441D132B7685425435E58AF1F2964B657C71EB6E28FE3568183F7A0E570821EA49DECFBA3128002E77208749DCBD3F5E15453AB6DE9EB313D7445377B3BA74BD2F67AE31F560ABB628CA0DDB120CAC6CB62EC9CCC65051F70FC41BDCDF29F885FC9A558929F58CDE1200072F96C3D8F22032A0AB3F705884F0D827823FBDB62FFAA39EEBFECD9F57DA083D1ED541CF36465A999558F2299A865456C94D67E74F1EDC7166F91F4CBAC8F89E680BDED946A174E9260DD50C6B0A980A4B886850797149FCAF8871AB3080A76B645E333290A0DF319DE058981B8CFAD7A54FCD62345DFD9C3E6F7A26D212C97FA6F09866E23D5A19EB9CAE760E876B2AAF43BDF9004D5CFDC41570EABACACD4B57662087B6A91B6249CDAF905BC2B1AF5934F1A05D20E6C6784F0FFDA0A3E79A2C0939BF36C55EA0E31B1AE614D44CD413118EA165FA549026574D1549FF7D63B4C464A896C5C0E8D5569AB2B10D1DC56458FD1E069B5F91B1D084F7AE34F67ECDCBF33299B12C102F953CC48B0661AB4EFB493F7E4B2EA8F6FE59C3D5EF7D121B26B912B86BC0AE987B6A3543558F0B935AE62B4711A586DDAC9E5960C48B99CB80191B11F4053527905123D20C549457BA87608948933442CB06BEA0E73FE99E3C4198E9E7C51BBB7074DA46E752E46B3E419FAE2AD60D180303D710C0A59C6B980B24F0BFD39959368B5F56AB3845A2167F4683AA82A9613257BC801F5146CFCA857F2DF4FBEA85C54930D4373F70C083F661077567F1173819EBAA585EA3675F97951CF8C9997887BBEA9B99E17A1E0215DFC2B9A66760A277F68E747141AFE5CAB6B25D73D562B91BADDCC7938F2EA75F1C990E88311549F38FCE2C52933498B22E2810227D1EAFED4BEABCB153324622E107A6D96214F3C6D5DB91855005056A8D1BC5D5518867C373709D24DC1FCE21537C58999E26CDF4FE61ABE5E1225DE80F98D02253999F39A145FF3008F12880C173A7ADEE15025E3E186FF0C2090872A0A51505A09094FA2946AFA1840B0D6D526DEEEA95FD8E259E70B2E794C97F50E7833B165E7BEEAF5D3CAB7C3AA1CEF00003B94159F0F6DCBC74808E3FF237D5C3E94353FC0E700CAF48DA8BD94B991EFFF2DACC9E423A2AD63824CF879EF838C784C7D4C0CEE3DACF5884941BCC14E043082D382AFF598BBE0321DFE9406434DDF558EE2BDC272C2B04CBF8CEF92EF8180D0FEBD3D62E1F73F3B1E7FB0EDF9B50538D49C52CEE53F3000E581FCD7E6FEA1CEEC9DCB4876B3F1D1B1A301A2D395DEAC54D68181406D7ECA05A416D3D8E0EE10228483D8515A0F662D933C53F945B50C65C5B8D51EC45360661C92761A1F74EE06FAF8889244620DABA05593DDD4D6A82A30F34DCEF50B1B1D261CC357AB0673370A38DFEDEF3D591377CA29DF609682EFFA212092ABF84FCAD677DFAD758575CA35046467C6925B6185F9B734D5E194F5CA48DD10D0B84B7E9096703A9EEF0D3EFEFFC0F58C4D38D741F15AE766D06156B26E9C82B464C9F609F0A4FF699D52E0E11E054738476456CB81859ABE457F3595E9D7F1CFEE5D0437094CF093F468C79C093CD615F7409A505C610169010F46E148F3D264FEEA1DF42B3E78D1C4B33C92EE9BBD9C508E89BC4CE0BA0C412F75821EB54730FBB627C6C93694810CD741167D5288768165A68034CE2B16B0E73ABFBF75A905C9A9E577024EF2070EBE8A68076AE37BDF3507C7CB10EAE13D3A05BB3DA33F873F488150CE67AB892D61A11FAF5850B6A26862FF0CE85E4B0AB3EEBDC81F68BFDE39B0582185E4322404A0195BF5951BF7CDDAA6530DB0EFA0A2E6B2A9CF8DCD8B0D15447448847D1EB5FCCDC80EEDF166988D55DCF3BCE37E24A0A5F302F820C2782849E70BA47523A7AA1FF12F144148E9B5A1E05035A346FC4028BDA824B8D5FDECEC4036EB2C3A7DA612A703EFBE4D5E5E17CBCE1EBF546880C227EEE2D9CA4113D0ED61AFA70171700F0F9A1BC7CE7807A081EF09E9CEDA5DFFDDECADAA7CB5ACB2DBBE26550ED006C5B7DD89A2585EBED5995F8F76F3EF8F13B6AE77084727DC894C74268D4D91000155FDC94DEE049E54F4E4D2494EF926F23B73E60EE16CC3711B67B6F6B3A3BA6BA8CE602AE1BA87ACAD58650AA8F7F0F36AEA21080CA8DFC618AAF865B14BBD69FF7B413FFC81DC6C8BF2A7B122EC2C13DD7832610DB9E6EA0E5CACBE1703AF551997E6C51BCE7BAD4B3EB1F392EE12C5691F795090C6F1D6405D0E682F279B3DE64A9F45B1853346D8D337FF8037370CB4DBE5B241959FB8DD985A4F154470833E422AD9EAD7A14EC1CAF6308FCF7E9AAC13ACAFAAD98011148A2D52D40511CF13C7CF0ED1E320617B908BD1A6A442FAFB2E543703844B0D40FCBD1B392CDF5DAC9CE4C2CA69C8F04AA033F5D6D11DC1A5667FB352BE6BF88A9978AAD37B01BF8652A2C475E8516AE1A6E56F8CD596B9A780864ADC65A04F615ABB2BD4BA97301FB0CB7D9AB5423BB14C29030DCD5345C54D556ABB116051C04D79C81402B70AA9F32CD01B6C06FCFB416C4CB7709CEB12DF3E8BC541333C90E6D991B24D7D1D98D0839AA86614F3D91ABBEE5DF138A9DF2C0591204FEB3D9DD546305FD017B72FCA4DF01A7C1728606EDBA07EC101D7172971C9F4ACE7D6D09E06BF9E8552A4CB3ABF6FD84FD350F60A3E1826BBCBA484D4B5B284E2E1EF2A164FEDCD0D22AE77026C4A6596ABCCEBF6ACE68C11ED108BD3C"""), + TestUtils.hexDecode(""" +3F1A9B8C87C0A08481C482D90D252CBC687B25E613C6BDC311BED7FC59BCABBE5353E8094DF52017277C5EEF17A07D65A7DE47EC40E127A745EBCABE4E77AC5781ECE95BBEEDCAA01914F00B98F04A6147222843A4F9A4F4CA0DBB5C26B530DE04D304FEF6AA5F3EB1789858760CBCCD9AFECBC45E02EC93827149960F8EC0867CE9D2F2E46F6DD8AF4F959DDF9DF7177BFCD67C43CEBC559037CC88772567E6279CF261CDB891631CA68FC3B88F7A5EE03C964810E29943607F890FCD81F4AC0554EC8FD304741DAC4A0F156B66DDCDCC7D12BD563B2D54411891CA94CD44F6EB127A7BB3C0FC51A06597639C97FA4787D4C819817A8100D9463FE92ABC339426B7C57670962575B37934E890F6924F95CAF81E62D42821B1B4E669320B4DFDFD8D213C1CA405F9540D3AF7776A3265A717468685F0F3A08A22E60517C6DAADED6AD1365D90E7D91DFC8F0415810C7F98406CF0C24A583B13531B52F3F492969B198B4AFDDA5340F059D21E8F5A830E1DE4DA51E17BEBFE8BA1E3B9F6C5222BFE154516C1C1143B96A49E04DD99F56F047E781FE925171D83B3755DAD89C361CE5D4A11A7E9C37C245BC6B3315723EB2DD15DF385A108C719EBE636ECB6529D6B9D4817EB011FD6127270831A097ECDA206519842148B029A1505849118CA06FD01FCFE100B1644C44379AE47442DABC2BAE7F342ED79B26379D50C0E61A809EEF8B7EEED4B403407B44FDB7E683EE3F85881BB715266F87A96E6E3DC1FBAC1715D1581CC3691729979E97D577D8691A9AB21769AB550C258A15F4A432EDC1E18669999051A7594950EE013D95E269973762E66808BE560D9765A104D4351F118653BE7F425D0FA9D3581724604028FA8A4D35C6AE687DCC0B55C915D75E5C590366713AB78A2AEA5C1515F36651F85B2997D6027C8AD330D914F3DBDA26A1ECBD1A34125342A32B5F432ED6E8EAD0E1BC5796108F5784CAE34A3207973A13044699B496753D7CD4420A8F45D71017C2439B773771229633E08E076F1AE5092ABBE3461DE11AAFAF154587342D3CBF56939B19DEDBF0A612FD3880A5B6D2EC518BE04D81B9F183250D9EB3949EF4B7A7EEDC4021B1A4DE20AF1B5A1633A26F3D1789C1DB42F379E4E16F1C87922B095B5751F8FCD4E9415438AC7F546B1BC000927A06A4BDDD18AD62B2E829C5C2E464F178D1FD9CFFE82083FE84CD61F5AF373D10B0DD30B151BECDD8FAAB9E185EAAAD459EC55E905B56417F5AFA8024B6D5B971D3F070F5CD513E85712B171D7DAAD6A47351279D4D204E33D6479BF0747F7F895117DC9EEB22552CE829DB8AB67A44E035748BF41C5663A17A1AC141DEEA02C990858508C62BB05D8ABB8825713C954C509B67D7A56259172F25E3EDFF8EB356A818233DE470F543152FC9AB0C0F2530FAF9B1B0CE6BAFCE2FAA46DDC76FC90F6B658DAC93263CDDA34294269AFD2826B2BB6F71E1608A6232D3CDD09BD5201FC7589AF0059ECF3F0EE167289A6C7EF1F414532BC981AF7D44B1F8787C4446D9619505B11E6F60C0C861C66291952A054DFCCBCFBB0DD75C9A74B0CCB3C0AEDA3A6D1C1C1DE0E494FF26133CE52A64B397A7DCD547F88F4F327750039B2EC77AD56E4D1A793A539C0EECF501B8E8186CC5AE6DC5CCF0A14964D2CF1BB83A974780972B2AF75545B9266DB1B3E2F052E15758086BEDFC5CD42DFB3E1F2DF6DE49D9CDFCC990174F52C66993AB07E66B2658C9B430E92838E38ACDD02CB9302756EEC3CFD74D92B0D89C90281A93ED479B7A37AF9D37A47F8E04B5B261669083F97062DE23B6C52EDFEF09CCF65B8F32920E5586BDEC1634009D42EF43640C26CE938B2BB5A5E459B74ADCBACC76A2BF7712509553DBC30F9D73EFA20F95B225808F22101CF4A068D6E1C1C64EC656EE535C57785296755F757722E897A53264E63A0311A13C6E47120C3850992EC703E98AB8029B6E29EA7246882D9083989C093382551663C570012FD42DD97EB86FC434D359B85716D0084844D185A1FE8AF8C90F17510F0E1264EEF6709A2C0E9A840F49C6E7E2984241DE2A50DB152AA9D43CAC0E7C6707B55BA44D18F36E2F5F89BA46A5C1E195E0860CF5B3CFB1C4C71A0A53AA1A1A83DE888D8EB9CF7354B361EBC37DAD4F9D0F96CDD62D108DA793BBC84761C5F29F24910D736C8C9A70DD467DFCB46A53F880414CD2634C2E8AC379F2C29F52167894B6E9BB41636F93653FE4371555E061B711442BFF93D04E0AC20D7B4E92A23D1BC77387A7679C688436D34CF37132FE336FE29B57F8D792BCC76C9B4F2CF048A2C8F9B3AD2EBAD9DFEF954A55978078AD5DD59189C25411717BA0C59AD2C89C7D58C6758019B3A134EC32B8DD5A7C90DEF509DF31AC9DA19BF136DC49CC8518CBC0B193D2A8D7681A1A8A6E1B4FD96896CEB085374A81C082C3EA606C4113C85E78C7C72945EB436497E5DEF79340B64DF13AC56123980C2B4985AB0F3DC4F1AEC2CBCD47B4693AB4DBDBB270F5FA2B7BC4A69D77B96164DBD43055A930FE97296034718569D3DD151CE0440B94FE8A2656195AB1082BA64881CCB1B196BFFD86584BECC610F9751DD29B0985BAB0DDC4D0583C2A12BAADE088C6A021A437989BAC7B72709340B4BB12E6FB9BACEC05EBEADE26AEA86ABFC225121672F2687B08E8C6CD87C744C62F65AEAD52EF3063F8492CC7DB1FEF69CFA96532001430BF131064FE5B2EF71BD65FB69F2E1187B34EF659AC499FA178B969E49F494A9FE3D0B3DF5BBBEA9E852D4A9587815E199474DCD774F5A1A4922E9F403EF9A56D79BF8D20BFBD3D3296757A29EE30F3A8DAB3CD909E8A50A775EE2BF33D136DF4234E7D44A2F5A4B8EEC945C6BAE494D35D24BA70122CD9071F3F7B3B217BB4B0C1035301D4BDFA7FCABED5E223CFA7C5420376B53EB97FE945BAC67CE84DA6E9E3A6BF44DCF46B5FB35957A30E922793FC47FB59AEE2808BA559D422208180F437108128C741F181E3ED84742A122F30B420CE3063016D0B8B8EE07293DF269E5B4A427EBC108EC22FDC33BCD7F02230A49B6433BC4E981BA5C72027398085E36BF72C868D3FCCE0CB15C8AEDB801254ADDA850EE2AC97392E36084A8456626131441587F72CBFD1974C3780875EA246CE93FDBA8757591A30F00900B9B9E07A77469D03897DBB6F52F8D6ED02F77469A825BC1F1C276D75DAE5307C3A72F09825C761CF44A9F78A2085B7F339549F0905DD0413211BD3A82961C5AD4FE88B9CD776640E38434392DF1510FF9F416541502FF9C81D0B92E5F6A6265A982DDA7A457D943F05238F3EAF3EAF88A6C300F1E6F800BAD8FB08CA1EB1C5655A5ED869F3BB7DDCCE5EC591A2D19A043342D554EEDE81242A9A3F0FA55887EB621684235398C15C5AAA9962361E94C223BDAD1D69C87A684390771364A87FBB854371AD33E80AD569753A389D7496A1A7682F1265C77DF9AC5B629FB576A4C0FB7954EAC01F5A94E213D1ECA6389D8F4FF9C4B768812E675A38870729756A14A7A17EFBA62981F03BBFD55248E515BA5913B770576652CE2836471C0A831DB7ACB9CF451CAA0CBE56F6FE0C84EBC5A551FA3C68C9C444D19552697E65B7A5D9535E7A6E5B1D322CEEA4F7DBFEA175EA716E750FE8BBA057FAF26D03F83011E92672E4BF4F1336FB883CD21A2AC3AAE4D81731DB30D794B04A25CA4EF2E389C54C237B1B142987383AB6F6FD7C527E8D3886ADA4F3DA08A20F33E252BF946424F058BDD055338E9DE72068D5BE75A06A0371102C429E980233157BB1B0B5DD1DB65248A9AADB3DDEC4EC4563E6353CEB01B8991D7E9A6B8C80519CBD8B06380F61A920395E4D2AF2910184870619F5CCF4E8D4E05F81068D88834CA0C64D5B91147A876A569BA0E23D430DE76B1A0CFC70B22CF4110423328196D2083B03D5791D7D967A82FA7DCFDED446518CA4D29BFE3A9B0CDCAFBBD4C74A5AF9445721EA1798C0219E9041A2543F31D8CCE862454F0BD361FFE6BD0B95D51C777C430D78E226E124C7A0908895C78A55ED6B0E841DCB6B42C8093958699DFA5F0B82F0C94697BDF822B7A94E1607FE85A801DC9626117E3D2FA3D9D828706AD8FAF1FA130B65400A5256EF7A174953D2855BE3FF62633E0C3C533A322729D5327AA103EF255AA3FE75A173224085BF3984A9C0E1DE30D08B04FA841BB0CB0C2C3C63BB3B8BF8310673200F2881AC80A621AC51DBE999B8561164A3883F022DE646A95DF2EB6ADC8A773805A009FD8BC5F72A758A109E4C3A4841BA80F27789C29E23FDE6ECBF23DBBC3C12556BA32737A2D625045550536EDBBE859D02279DF1A8DDAB731E1B2AEBF3F84588B21D109D9351BAF83E1AC61F990C564E34768025FD6124B0D8007E5D4C0D00521684EDEB739DA51D3A793C6DB364CAD8AE59C8D479E66843204675C8A6A76193D5BD690E349A27E6E55FCE7D20BA1460DAF762A0033CC54D42F1F387DEFB6D5108A3153FB43E425471092E882A06D34A226EB259667D6C85AA63421048C17B2E4E0488F5E4038EAE9C5D4198ED477470E4E4C4D4734AA77DD93F7172009E4583857501511C9E40C6D22ACA8A16A968F3C037ABE0E31437A82150EFBBFD7251EABAD03D93B2DE6159CB2B432802054AD2615F96552AA978C8F8F5CCD0626DAE79BE0BEEC69BD34C6988F6056F4FFC5DC3989F14EA6A486BFB4ADD7DCB960D25F71EF515B024CC9898EAF414EF07744A98F0DC3C3CFC91C4BC381238DFD67A29BFC43593D3A38C245E5E2077034BA8A646202AE547115BB40A4B4CBFB7D47AA6CD628243768F2E2A4A3B47B96ACE2E8C3E23A646C129C9F8885215EF0F7D13AE8E64D613E84366653A5DF27A55D606F95B1A44C56F40BDCAA60405E1C02D42D72F391E7BED3C7455CB3A26519DB1AE24D99BE9DEC4AB2119A6F05405C026AE30FE263AE13623F9A81F746DF4A0563DB49C14BD19BFABF1FBBBCCD6B05B565D9BA16B86C1F61B24CFAAEF2EAEB52D92CBF130FF5E49D834244FB34D478BB20899FAAFDB97C8901B11E906263A3F353AA2F87D66BA6DD41337D2C1D05819BEE7D215CC2B3ECA5E0A3A3A71F7FC9845FA2751F25FD292C37EF96B0017101E3C250AF43DC4307C449069E9257BA1BDA5B823E2343A7B1AD61EEB1BE94EAC4E410D7782AE9E8A75BB54849C5764C45935C6E4B2948BC6F72C620574096D57C14508719C21B02F6F75291A669740283303DF20ADE6A5B3038E82DCB3EA9508BAA297D8E39C56E1E1F98A20D57AC893DE4C1B59DCB35F1B15D2B923CB2ECDD2D793DFD3254B4CA3F8878E04CD301A1AE8177103E2012D17314D9BA9DCE0A05FAB6A7E23740E713DDA18574C8BF8AF2D116A16BD17367D5FE9C0C6375260481AD70E31FFEC9F8B9F63E5BB0FE6A4CDEC6782A5C62779B0B1ED0956865D963F89541D0508EB31EE26ED55557687934D2DC9A1093A5ABD5D2357672578D1E914E9329BE8CC1C6ABB8F82F1A63044C3119AAB980C1659FC7CCD04041EB8749AF7222E4626A22DF729D0B878A9FC434F7AB431041EBF49963F7F283BB5CB3FD433BD75428AD445B281524CA08E5ABD1AF6DB75208F70B06036399AB66BA84A014377685275BA2672A5016CAFBEA373C6176987232967F81E97156E1057F45ECDD86FE18BC95C10B3EBC7665F879B100ACDC4989427835F9E1A778F3A1E39B4FF2BE81E9B30B4F605C4144FBD8312A879436C532A72E6308BB794A2D69B4A6ADE42EF39C484A494A624909AE942BBC0C36B0FA7EE3838459B3C829F8A636FDD8750793ECFA500D04F10E9075957EB063776CEB14048861912D60DF85E43FA2FEDA98BE9FAD55E1B5A177D82933AD17C5B5913816C90FEB8509C91BFE8199AC75D66AE907430CCAE09CB2BDFFDAF40FF4341EDD45F7EBB55DB6A8691632D06D1DF6AF6974110322BDE9ACBF7E07DA4FC7D6C6D300B4CDA1AF21CF5EF780053BC38C17D418411AB6574D4F3F5E9426014EDD74DBCE26C76A53A09C6666B399DF95307F82B98264E45A6C158C7DE95567E74D67E8AD591E296B67EA01AF48C01FF3A7141F817C9B12C2A73BAD5B36694DFBD15F7D98DB91848A373946D9A1CE2955BECC1AB0801FF4B2F00256E3F62AB684B7D5F251260454C97FF6979E8ECA36F2956876009F7FD24A4FFE9276544C40044CFFD26C7579734AEB496F4E10DB0C5664300684D5D8B84E7466A4F857560F0AA1ED6916EAAC996412B4CE27DF2D877CD899DB377276E500E89533A9B70934365850CCE9145811379B924846C45627521E34AB03366EE128EFAEC353C695A1D4F13255D1393722CC03252B814890F7281C5A4BEC52A39AE4AA2F07565BC810DB4C32606F6864618E549E496F8712D45BC2B289200776958040B6B47F8A93F341DCB375994474059F46767F34021E3F424768DDEE1D2C3F949ED5EF3D42568597E8F309171F2046B7CAF00D1F2C88B2B7BAC1EBF61B36484C71AAB9D6D94C4DE4F900000000000000000000000000000000000000000000080F10161E283135""") + ), + new SigGenTestCase( + TestUtils.hexDecode(""" +B6A445DC4F4638D109DAAB0B266BE84079A7536E8CC0598C04202D52A38D74A2663D2C880ADA729C99379BA01136A54B662CA0448D19740139F17FCD3D713992C3545BEA8BF149CC7EF5555BA739C80A9323261BD623B40C7844CC3B513FCE137AC51138544AF6C55F90EF757EA51472036D12F01E5D7EC3109C3E04C91E4F78209808DB8285C104884884019802924A9690DA0046C3A064600631212700E22264CB008191C42552422E100671A20884A080458288511CC66411B4315BA05121232024968192069010124859202583C6881132651B991041A668091871132322CA4449DB38021338622222869AA41113A73182100C9344808C107002A429CC1251191220591800828268093711480230A4221009271010B741190941C8924000822D88842941846490322CC8B840CC000C5B28908CA85124228CC416908A228ED0C445082760C9948C53C44C40480E8198515C8864C9B6200C172692063000004ADC8271C4304A0CC9250A098043040923002899A291831266C884640205000B94859218905AB0081C81491B156A0BB8401300119334011B26050A445092100D0245091000924A168980182E14244504446A143366620849A01400A3348583904D514480C39864483446122180A2484C1488095BA400841484D2248C649425D188690BB4519C181224992823316E194320110706839809CA30850C960150464DC3962CA3A471CB462C9C448E59C230D9C40C18972008C41018C7300238921217911CC3445C025220390861482164A26911C18853C24121130544482110306DA3A4904A462D20352CCB264A03985021B3055942681117262120716288705B024888940D99A061E44091888051E0B824CC086C2140514C10449C04002236820240104A082CDAB28D8324408C007120C589E4002DD8C08C9A24045382298A328060445122204C814871830628C416099AC289CB408E4C9801E0468A2011451834240B0790CC1406412882D146311B398ED3108C12A221DBA6201908861CC5400B090053367119A27101964D1C857012A605C83232A33861403490D8C2108B122958248154224693022E484060D24672223552C8120910264913802998926519458EC81864118688423022A14232C1880420454089288644064680C28DA3C0800B078012428DDA200E1B2080A4B691D4486A5BB4004BB85161B44102B32C0440724A209023822C4C46695344219844049C367019C1111B904814C605884289DC820D50946122B591D91009CA164ED3406C0C936D4C181001C4014B8824002112CA042809146A1C920C6244842034255920458BC671E4043150948458A48811C38D9C806504C9012016521B9821D93051884081232201D3488812014CDC9221C2183120006012995104B00993824123158120960C80C02D5B062108382219C72002B10099C424C21402D4000660306E0CC32DD2383113C9840314024C06490C219040262911382182A048C222724C28898334220C2846E30802DB4442221229C326111BA808208644E41620D8400013C80D83044D20283260080401074611018683442EC31804581206132342C998901134815A44901B26415A480A8430480CC89014B7858B002CDCC061122611C1422C44363199360420A9804A04605AA285E2B431E3086251166191824D41C02990046218B270404608221381C3B03064A441412292A3B0680CB80C00256AD34686919240D88029C41681001380D1288C1182811048690100301AB5901B0406D148425BC26523B08110152543006E8C268924A28CA342701140800C0126004406D026465C882DD148914A420E9100500B02318CA8008B38521C21520934121A498640B2210C9991222308E4B0314880699A8630DB40051C41259A32049314815400529094510A396811A68083160D830001603664CCA6242182850CA7600306661AB84993208560444E51948442122AE312100C0472E2184002B921C916464C868990B42420C20D03858519A068CC34044B308943B20913236524178548B060D42662DA0642604604110070D2121013C750D148716100099A049294102C23146D9BC86C848260D0B045C430222289695BC24C1880091B322D91A408440682A410641A256582C070A380298A48285A406C62140180486E083780249284A10042808888922082C9808840160551406423B16D24896DBCAB7827992C8BB6CB1790EFE735E25FA69A53857EF72C747691D235BDAA8FFB682A2A5835AAC37E5190412ADD9E5B91DC9513D2DBB8768978D32D3743156EDD38082F2C93C1C82994969F6719035478DAC4C0CD00380FFF08A9321B2E3A14B6A4CAA808A562B0D02AD7BB4DB593B318E55DE21EA3EA6828E15F150C0780097D0C576F3295C2E27B63139127E4302D7460D6443E1D5AE1B9B5B3B806F956C78606809347647DCB91331BC57D9C81B48C480138EC80A7EB9D623850C96843D604FDAFB611EB92201771CC4AF621C4CAE9A8D0CED827C6936BCB0CEE6E82C2A097CEECFFA25C62E713C9D9AFB571E42F1145E1D618B0A1395DFFF5F07291627EA5110185EE11B1DA3EB2DA29EC38596B47A70F34430C373E3A947E8848DAF8C269049C551FB61B25C704E5B98E44B39D34448E50DA0522F290328EFAC7BF9AD912579AFE639221AAA177673AC83563770A1DA92977DF8C7AD850437F0E77DA98747DD9968E965D5C1EDB47645907F0AB59C4374C0791C60A8BF3C447017E45A9BD4F2705A9598312B5AE0DEEB5C4F9011665BA56B733A2743EFCE0C9199D575EEEF740AE78C1254CC6D486509A26711742B5022DD0FEE1F440DBFD5C71C11FABA95006FB234E648395CB8B7F047D4112E08CC773043B848811E916520056F19198904B38831ABC6DE68D5E67AE340C08C1BD05E25E6325F5D0A38523DD12731F9FB134AA252376E24EF10CD7348BF0C2859257BAB1D09AD45023CD569C8ECA23C0E8C8F9159DA852A9B09407457F3AF0714C849D649275CF166344E6CD4367812C1ADB0E11F3DFE6A28FBADCA7AFB683E47A8FEFCC018FCB4D51061C8854E07EABBEAE2E0CBEF1F8D6302230982DAF37310E9D21F84C2D660C9D3C5D09DA8777634BDDCA0A1E720B8DC8132DAE59C3CF64D7EE262B49888EDBF98602E55F5B5A3D2CAD14438EBD8752D6C93579790860D47D5EF94567359A77E56B866DD04B77A86CD4A2EE6A21A476ED56B8A750B47907D65DE6F0FAFBCCA5397F125D519669E55BC5D03445594217141ECB649B0600FC257B8327F4389ADB0D6EB9080A444713CDE66D2509D9D8AEBDB3D6743580AB42568CF6D65D4F26F494D9F12AA89E5AE3146FF08A4EDB569E77CF7E7D238AD9F5FFA5082CD024676B010B245306582999936E9CED1DC493D8DF09F553A7F4E71540F10F75339E63EF17CCD3F9E857E17FBED81485C5F21672194DB806A66E4CEE58CB4BA9CE150506A8D139B044BFC1B985235AD526445F067BB4B458DD652475CE873B16BA403F4D2357825BF8F98D45DAC29376670C925616FF8FACBE01323607017A48E6D3CD18C78505BD0FECD7934D7448B5DABFD7C48D70A21B89CABA42ACF2FCF1C3EDB44A9E9C3CBBFF2A0B11330CC5E03BF8244F04F97A1014677BEDE221EB0E5BC64A8ED93224D517D8F525340DD0E2DB0227A56A3BD803E078285BFCB40B53F2980E3004ED1284D60A604D0FD420B83638020987E42433B52A31F052E5530029FDB0F52858D41D2DD6DFB85613D7BFC3413015CF544494A4EC1F21F5DE05EBFA829FC6811544F4B38E04BE93378F981006EEB92DFD62C58F2B8E89A8FEBD5F26C58B4D638D404382CB0084AFE425F056C6CC44CECB80E2247C51C20CA4AB9451060626C594CBB3CA5B1C3506E8D52906C0B5C064D35459B1D17CDE9B0A3A55DE2DCCEA8B71D13BEB28FAE7122F8F92355E247698FD95F5B954945D4DD7A80970C443A9577BABBB8886D7E08DF0EE7CA01935F46396061B3CA9126BFAE452235B04358E9574263FF5F0E052CC87095942C556C8C03A04FF808167780CCA0F0D9DBB9656BA066ADDE5BF6BB87DDDB4BB86E7CE778BDDC9CF467D621C529947DC47740AA21E275186F4DF83EEC4126590EE026C4874D67C60CE074E0F6CC3817965BE4BAABA2D4EB77D42DF37B792DB71882F5B10980F433B9DB158DA15E5EB9587AB568256342D82C1B8BBD4366730CE414AA25F7E97E4A0D27089C3A53EB451E51484C257F65D82A7F64D72267468E45EACA3BB5180694F842723E17901D4846BD5138F2F88DAAE1C79D84AC7C24E3CB72476AADA1AD0792DC4B031FFD4A35FD3F23960CE912693C67E0A3DB404979ECEF172CF8FE7D13D03D29CE3D57CC8D1C51690791682F68AF6ADDCE013D085107BF2674580D44E88D47B052576B6769607B7C285E85F5C4A18A3EC2CDC93C7C74289F769FE703D0D66231AF23631EB88411AB57E21FA1CBE2766B1DB69A6618DF0D9E85CB0D4D0AB001B47349FE49A23AEFCF72783B6FD9AF26F5863587CFDB320376F094D5DCBD6CC32631C9C564AA6A585C7F1CF2B4FB30F8ACB2A4C433B896D1FE2236584DE464BC17D680C1D4EEF6B561BE5516911299D7C7346228A41106A3DC9E5B4E75C8F04EEBA3D36227494B22B06D578DC99F8ED068220B4C4C791F6FCC4C8D9C2B94A7B3FD9930735A00675549E648CBD338157FF5163002E99CF94171849FDE5FF7530F552AF54A95E6CA4061A6556B30FB1385621253CE70FED7BDD09872165EA8740BC1E303E34F69ADFBA16CEA146C7ECFFD12906DE24947CBA94D068DA7F51B5E854CCC6DE513405A28D9CD3E409D33B70731040A7079CC3AFC2E502B3AB1C4EF1B2D514EF445EC99A530BB049D4F8AD7F58D55FA3909F76608CC23FF704586AEE0AE9050EE5F2634767997FB39D44688E949B9C82C3B605DB878D7E51941F8D9AEB66097FA206462F5CE7F17093389800B239B86D0ABD79B66DA99FD0C65E3A3183A143FE9B45FB85AFB57F2A101C9713CE6C4DDAAD90BE6731679DE7C72AB1EAD6CA954D350B9361FD143159B45C803420AE88363C327EF31BDA33D2B869857403615F20117AE708DB5235583E06B82B9A5E7B81AEBDEF1E696FA96D76C3F6388C4D1EB88EF3F9F7A95D5B9F446AC7C27D1915717FCADA4F22458FBCAF7D4377F2E743AEFA5246E840A96F017E139125851055A1B98A91D9217207DCBEC227D23666E76BCA0266566EFD0E2D735498A2102E4D52C6FD758568CEA164E0A28B67E2E2907BA6F63CC049DE87E61771B2095C6BD2D58D4A36055FAAFB51B63C3F9BC06F3B27F5514A9663950A6804A5D34C8E1BB6C924C8BFF44BC217423C5FAEC7CD56B61B746A0AEA7C37EF6C6351969AEF292178B75DC8922DDB935717C897098CC41E150E7633C91F6091969F19525FE257268AA74015EE2AC93163799B03785E14E69A87FD0776A438C01DD829348D6FB825DE7D2B01815C115ED418E5C132074904ECF4FF06775ABA0A498B1627CF49D8ABB68D3CA440517FF4B08B0C4B4845022A2462A0C1C5B706B061F406507094311D311ED0A5184AABF03B0B0BF06C3FF55D778F280E9F3376504DCEBE4B9FA4C4A55D93D7924EF9CB5849364CAF92DC3C5E198A3D1DE5B139C13AA39E9545959D6D738C1D88288A908A1E7DC3ADB26DCBF02D9F98BFD8FD61A6A96FC4534A2D212B208C48DF6BC95BB415932AF801B5519E8647AEADE54B68539484302C9B5A416848C2F10952D1A66078997E56AEF14FA8078FC8E35E1BF3BFEE35C3D91C31B0940E8218DD83BE1E633E649712241C61DE8FDB1B84C0BA60836F95444EC81A48E591BAE36FE7CC449C9B88F6298F9E9588FAE54C40F661A6914F001A75D4BC6280E05643F0A114C2DD71EE8FBF3D7D4FCE18CB8F61A6FF8B08FA1D20378922EDDBD2175A2F2920F434919F0F9F1AD7C6ED5E0FB13EDC924410708F7973270A03604A0043AADAB8F0368871040B418E74158CC4E7358BEBCDAE696EA38ED155E3599D06F86552D9556C39F6A435770AE62878C4FCAC7E8E558BB85EDA22D0DBA818AA3A6BEB5958D05520AEB2ACFB1BD403047DF27BA63B34A42ACD3CCAB700EFF0B6906D18672340F0B6E2842E8750366885E148AE0E5546D013427ADA215A4809C11590ED8A7547131880460A3179BED70FBED4A1C304452C1AAA8B0F6C5575C2F60B6E0AE93E0D7ED699A3B039A61BD63AAED95E4822D8D55452056A266D391E444819970CFB4BB767C6613CD0C65B259DF532D58B2E086BA9A36BE37537ED0562515B6AB8AF615ADDDFCBBA355363DCCA60F5EA2B07E59174053D6F29892CEBC4A44AAA4971D19171D2029854FDD977BD357D54E8DEB4DE463F251DC566DA73AED7170C402D3F4DF466CA5BCD8BD47AD1A499B176E39F4EE2FAB9C7225A3B98700787B73CBF36C42E934D0EF96B3859F980020679FFD83F106D609278C3DD780E2E5DBC262D9DD8250D7F4A24DD27F3937382B8E7B2C3269B6CA09B522D0DBE4CE098418E95C17FF32EF99F016AD4EC8EDFB7028CA9F85ACE4976A6D11E90E2990C762E7E4845CC7C447ACA8907C94E81CD6E7664755D378030DBA0208CF039005F433083E1E904F541B036E03F7C2686630D0E5F8785FBB33E03566E8CFD19056A4E6D1D277584EB20C8727D2C79D910F12610C003F90899CB6B5231D2B3A5EEDC0355DFA7FADBA5C949E9B9274E9DC69579C10DAD85552CABF32E90870D9D0CF579348F46874BBA064E918BF4A279F55984CEA32649111EE86059406CE0B0D50E4F52C7CCF110A5E34E01C414075CF5B31AAC9F504E9499BE75CB3EC35C2C19F7794769BBF34039F4AEC85C48E772075B887B63A5C81595EB4D17F2F25912C120623439E93482032C20F7CEFB0CDE27B2799EB945DC28EEA9B94A0C4C5592"""), + TestUtils.hexDecode(""" +D46F4482D570F26C7E9F0F74A354174CA145033097CED3896350DFCE8200CB9448F522B118698DAD51F6C672E1B12A412DB6B7B95CDBDAF6205DEB631E44634412F026CD95440258FE5F0C72C5F3E64FB3FD13E545DD856EC2B7F51AC28C0D5D698C66C700DD3E409BFD96E14A9DAE1677ADEF2CA2CCD178B826AAD3859E569541561073095EFCA329B5B216563D956D8B7BB918224FB479FF7025FD8168F54D14ED1FDF0B399130C6117B5645D0E8DD242C3C7AEC6A8361361CAD9A8FC3B5A40BF7E73F1BBA9AC7F5A583A5B0EB95AD0AB4C1360D0145FC2C3A9AA50186D649B72B41DB7EF392E663497B3166AF9BD0C1AE21650D6CD04DD36532AEA0FD1071D6E9554CBB575B2C1ACEA3DD4E18615FE83AA211F8AD330C78FD32D920ACB40627CA4AC80F840A64C019124079484B053F525A5403383C21B164D0C6BC1B462C0E1C269A1EA0B2438FA64934CEE47149C4EFF566D9C2234E656969C1C89A0B0A4DE124EB920FF534B934172686A18A1A269960C725940D3307B8A913D56B78A6CDCFD559FF97E225B61AFAE7F62B060E7D3E2D4040D8D9233A24827434AB4EB31B0D528CB0085953D9A1A0FFB748588A2DDEBF241F93B41F5C856159EBBBC6571AB12F4EB534ED3C624CD3F5F836A99C7E6E2FFA0369654A5C07C19D44BC9FAD96983660E4D6F95DD9C38D84DE11271D23A6158B685CF050121425AF91C6FFEFD0B2061F54CC4393F99857F3B9775F81B6526444AB705F9CB88A2D276AF2F530B646FC3D93DE7087EBC1FBC7F9A8DB3F3C8FA186F7B636CCEF99FDC4532E54F560519C94B79B1158D85BFBE23D4F36B64F8056BEE7558252DBB3D9A43748E2E6A338162F5E2BC0934E89DC79091180C93D340D3615F82E7780FABF782E5FE2B5D504F3BD1874EB5DB76CB616CC034D9B2B080319FEB8EB97F62FA4498878FF049FA97C56ACACD2414E0BEF018F25A6254448F02E64815E525AA06AEAB53969A66D453B732891E31C36679B5C0A4637611A5983F21F6D4ADA1DA5E890C909A9E968F947C686C17EC73A0F9BAE5C7BF7433133F35F22D2A0B40CC135A7591E2CD216F7D8018969940EB9A5C4BF21579C524C41AFF5DBC0E141FBD02F1BCF376DFFCFBD06F9CD4384E128CF1F03139C853CDD04DEC61EFB8F1DF1A6450E4ABDDDD8A9D85BA79479562A08CDF06BDDD2E740DE7AD9AD1016D72A649A73246E8DAE183AFCD6FBDC64B6B6B2EFDDF525F3B764CAB39BF8D617D47FD3380B4A30081AE6C3165E9437B2F37A73AFC5E596AA626FE5A32D8873712F99910DADD0DE296577D4749F88639D07F83B0F6A05B1668D8008EA749580EE5A629FC2313FAA2F8ADDB5764B242B6B595A39AD76CED4CE5BC34C580069071BED1F98CAF4BDF740A5B1DE3FD30C29DAD808537CB16D0EF22D937F297F50E1681C898375FE0374ADD6EA1B84C10261DBECCCA8E1D224A4709497CE696BCD2BC1369F4135E815A781EA26A055DEA28AFCFDEAF6AB1117085EBF6B8AA6845FD4763FF9274BFE5FC6E377B9F9DA8263DC1F3D53C83F446ABA5EEA4095AFF91F3BE30022B9BBC2C74FC52A3B15CC76F29E541A84C5BF42D499F9B5EA134E24F01E8D866FCD20B7F7A302120B13DE636F48FE8EB99F17ACC153CE4371B266CA61D13E19793CBEF12C0EBA9C728096A3DC6A6750DDB0F52E3807C22EBE4DC6B2407593A1B7BBCED799DC3EAFCE50B483818D903765A63FF572F5D4481357CD6ABD89EC260417306DA1CCF71DA568240D4FD6858BB7833B2C9C98B9E7286FA491F9E318F25D0459071848BBA0D3DB8D2BDDFCB7B8E9C64ED67B4A2B5E1E49B55C6DCBF93394010A078E6F52065AB777C7F6D831DDCC115CF316ACF3680BE8766B4E15574AA383030EDA83CA45B965836FB2374695B50472C4159CB7980FE48B58B40C6CDD2629FE3C6DE6E13ED6728FCE45024C96402B78BAF37E74A1C071F4BCC2A1B84933C872FFCD87C02DBE65438A3E770903A04DF96C569FA69828CCC32D13A0A419FCCE454F06EDE43A97CE5A9A169C6E849F075C66BAB418791778ECB2C158FC19FF5927ADFCA90BFDB3B4216E19BE11157E858610BAA373237B42F811EA97EEB93D735828B2ED092518160A2ED894BB108AD74AB0113A8D5882D99A06CE2313BEE3F902D5CE9CECC835974A47FCF6FD1648C635FE56D1B2404927C49EB53FBD625E0624D5AA04D6C0D5A082C37BD67F477850458B8672C408CEADD9A55CC268B75BC51D7B3D75668D52BB701BD980ED22CC20611EF618277B82624A1192287B46BB5C4468F94C68D96F3CA3ADED476A18BE6CCED70924139F2E16C8A54FD6C9F6695E624499AC8E9AF86A430AB856924A0899E75C1FE4A51DA0DE1588E66044B2465C04809272B2A5C8EDBCAE42B47E439FAE06938810526DDFF4B64C515787B41885BE369A31F90E2D6F6C71528412572A67DF6E155C3705929EB28B80DF15345E0E32540BA9AB7E1D1CF0C015E50C9180372C678CE6C34BDACADF45B0172A1D3082565E16938F57CE6B55D9A711CF72E362A2ABFD45B7B56D48E89A0079E973F597D2E457EFF423E229AD439C3193C264E0BF9A8A1FB50266AE4E0BB671817CAEF10A3BD43452A2FD2DCBB2481D63BB539E0C81F6986400D3A619AA92F250ADDCF661FFEDE7617162B532EE2088A87F58E1FD071F5D720FF1F72335A5B4582F1BEB3BF19DBC9D51A62CDF68A855F7F6DBBE5FEB226C9918E7FFBC8A38079E411EDB44177F843EB8CC1F73B9765A0EAD825B3C43F6760B5F03BB75DC7469701AE555C2B7037952180255612DCC9CD35DDB31F3A9218397E1924791D29C410D2E4C3F5549B7EADF75045EC78D579EA7948D121E8297BC5A3A9F7AA2E2EF5776CAE3B9CB73316170F9B48B657BBE365B352A8129130BF1E718B386AA27E493016ADA86C4B3D3D116B7252A747FD50DC14AA28676F1C25150A86C9F4547189523280A3A897F80FDBBA073EC645C9953B7F8CEC3BD08BC0CA5640545B08F728AA38A860ED38C068F0D"""), + TestUtils.hexDecode(""" +216B7639BAE886F93D92D1BCB33B6014E962751B281796AA6DB6724C8B546AB7D62CDA401D6B651C4BFDC699EC03DF4018489EA99B8BE6A2D2CE3E442AAB604A02FFA0641523F3EABC9BC8EDBF7C19CF9DDDAB6A81E4DD5EC6754DE75CD071CAF48AF49CAB50FEDD7218564A02EFB0224957FBA6115544ED19FEFC7AEDBAB4832C60B454564957C0CAFBEAB5F71F4AFCB68458A503E800D6807155E5D61D78EA973FBC45CDEE09F5503D428F547D0CEB07E42118D0537712CB2554F25F0EEBE0C5AF76F9A5E88B9966D1504B92EECFB267121F1A988EC42E675CD605D6E58CAF7E9588E7306F64C6F81BBCB0D7CEE234AD2595932E723123EA215AC877FBECAC9D096BF307F487B0C7648A678CD608FEA23162D9F6FF44DB6D953CA947EB16CB90AC9D156A8A9A60EB7781837A71FCA2F9D9835DB909368A5252C050051BD72BC5056797E866F041EE2221836D4BF341683977FC992270D3ABB95AB3665EF002467A136CE28077C9868680E4005EDD8FE15BB499DC2E95846A9266BA44ACCE9E425E6176149F17EAE5D6176651D2ABD7C1B6538A8F26AEEE04840EDD165C8114CA55D500E1B260B2F469D3AB5FB90F9E198ED5A5A7845BEC24C3DBC48B06D6D211941BF86018EE634B3CC7D060A1FC3A38662E704338A197383526D4E55F5C09B78FB7DDB9A38424130D0D9BB3487348FD9ED8D0181BA9DE43EA5B5701C5F9DE3FC88EDF84846C7733651D5653F75B7E6A5C87C4F236F64147C3361E790ECEB6E20CD2482DBE6F2CCE55437828F4F8E1AAD0307947FC33850E27FE568761AEDE63026C167830A20F247CABFD0A2AD01E5799E0D68FA5BC25F0D2F9B42A2B8411B995636D472498990C549E538101D0CD0E29A29FDD5913FAC1B40F8D9B7655B250900DAEADEB417FF471D5B52DAD310FACA606ED22E4C98868BCA788DFA0AA030EE3637B39B3AECEFFABA6B14C733E997C2130503349E6F4A5CC89431B063819DED0C718BB8F78FBF763A64B28D315B6B0B90D48F94B306F0B42A41242CF27315FC69A83DE094D2CB11FD307E1268F976FAEE2053AA41CC2CB6A8B878407076E237FCD378699F5E65856356FC9363F4202EBE78483C4B2C730DA86473CBE588356F353B7AE64AF874B824B8060EF6E4CB302AF8FB027A25606B68CC4B3803EC2FAE996E8FAF2A6D52FA226E684D1EF4E950FEC819515CE9EFFCAAF7B277C5247ACFB57DAA0812B2477B4A18683B98D2BD11143504BC181397ABCAC048989ABF0386A17B79BF73A12BCD2DF5CE96BCF5FB6904D7BFD5283DCFCBD922EC508FD8C591EDC5B34A123857EAE97FE3665B8109E4F29F5625F475199B57F425947F37069CF30017935FC68272A1B18DD7502DE0798CDDA5A0B21E0C24CC9D8CC15F1F774057E77A007BE721343DED110C56E5E80596273BC9507B392051CF19ACB15A3606C452DEB350056CEEFC12A4467813A37386B99C966FB508D0C2FD757E9C10DF490CF600DB6FB3CCEE68376BD7092C03A3F3F60DB1EDBA925FB5FF7802D9C4618E53DE0DE1D8397330D1167D63AF0545534DC5644C16E6531ECE69579013D51C7B98497100308C1750629C8DF81B45FBFAD69F37102D36308AC63AB2D78D2F711DDB691D59BF4C3483652C260CD1A7EDF1E01FFD4E5D8364C69CE247B9F0924E6BD35D358B63B18DBACC7CA1E8C786D1437A730CA2D24FCC92D59E90F4552D490D19A06E11B1AEDE338A3A8D3207688FB27D581FDFE28C42B66240B6C8F5A24D50403FA2FD34DAA370F0504A87F28A4DF44AA86AFBB6D67C9614CE5CDF5C599CDC2C6294B25B641DB59DD7D73DC21923EB8AD68EDB4D0B16B7C16F3161F7C8C0EC493FA9951251D1C5394678B656B332A9FAB7477F32BEE65407B3D2EF6EAF70C1B430B45E104142FA2EF72209FE29558485DD26BE8E1B526B7098F252F58046B6EEB17D7F0734201AD865E7A6B838980707AAC9A05DC8C34E5B36AB03CCB74570670967C3AECAA9800106ACFB0B8EB38AEF82114C2036677118317E339D19CA34BBB68B30E46DF3136481AF7EBBF8C45951C8733C0CAC97E518AEA69A41C641C14EB71D6DE67A5F7C5C77F75C98906A3E5F2A6E875E2B6D7C8BD2A54554E19616FE3E8C39FC7360749B5133650508E8254601A7B33B82C1BA537623D6DAC9C4C3006968EAF3EDB233453EC8DF00D02D022B6A552FBCE8F3694EFE49A7C6088F3080421D45DE8C2F06C312150FC0CC0DA4DD35D25E7F446932406269D45A8358CD1E2736FE2E1C366F24D5A6DC11016FE6BC73447B1562B1C021AA9BAEED212B0AC8AFC337E1CEFF1609EE3F0A7AAC747E185E3D860D1D828B6EEFB93B31C7D2386155612A9815DDD2411541D91B0F99DE4D762F69C91C527F6B5A1BBBF6C8D65E7437F0FE9CCC669EF9D1F36E6E0CC47B682449258673A02B12248FB784AA2B7F15FECC3753119AAB9F77B3C5C677EE4BD54BE29CA5722E37D744E145F9E08A8F8015BE8A56057ABADB987538C0A1E02A9DE66B7666A0F4061A4DECDC2179E3613DCFEF4AE67C66E8F6114AC74CD9464EF29BEB0830CD2E64E9E5D8B547C0DCD1D625FDBC87E8FEC987C5F5F5E3D0AF5BEB341D62789F77851BF2D7FACDF815E101F335944D6EBD0F06BBEEE92B5DA5F8F98B1F41A2463C6569834ECFDEEA395D6D26B6EEE7EA08D261970D2493B86DBEA68663C042FF7791725A58F6B062697AC0724F09660E2E630C39FB7E0568785158CE9A7EF643CB93026131A9EF900E16DBE4E5E286AF8CF89C69F75C6CB32F3BA9D3B779DEDA8BB75193DED6651F452EA9124947EE70D43BDE04965F5A64DACA8CAF2B5885FB75D1847DC07B4C631E57843EEF344FC4B7A3AF886209D77CE5841BBD664E898F939704B7AF6AAE6D55BF3243E7E85991BA8F0C40E843E50CBF16A34A4E67B0C115542D93849F3C511D977B6B916D59F2DC7FEF38542B6B24EF7D6AEA82263C02AE73BFF5DF8110BF1DED037CE296AC8AD076642EC79F76AC62A1B3637BB4F3078BF453ACB2BBD3A9F30A77D01574933E79EF3C64A316935E8B69BAF22FBCCBCB10A2AEE120FC9F15FF537E3C73F2B3E561F5F470311BA00528AC575DB40E162DC23B9BEB3BD1C916D7E83860557DA21EA6C0E55AFD0903FC9AE08011716D67EE6B879EB7395B6F791B6E946DB867F6E9B1F11EE9BFE04D6AB7F294D8CDC6055AF46AC33BDA8808785DA377DC45BF488A7257C1E7AA193438A67E3C667342FF120FA076DB4057E8AFB443C07C72610BAFF2359CA8269C1795C622B7FABACE8599D039593832B46473E8A823F79B973C67183C8ED8F9173604CBCE4F6964265B93954FE916940E540949950B72DB4EEE74C5EB386109C99537D1B0E6DA10F12977320CABCB53C47F62E89F2C275C8D310E078FF098E4D6550CB80BAF8DF93DD77E5B3D32D94E13889C2146EAC717C7FD4231406391ECBC51E9161626186D475AF3EEC30A3FF8D6458D01980BA72AF05F03DA6DFF245DF4D23D976DA87D1B92663B82EBE0DF8A104ED77BD121357160AFF118D76D5A232E92AA1FCBB93038DF7FF9319481E03B768B68804B1BFDFD0DE0E1C58CD7FAA6FAE5D0FDB51E594BE5863303216E65D27B1EBEF55B77E08B4B485576A1A8FFEE4FCF29F71783721B9A4D8BB50D26BE513CBC62C787C7DCCBF0E2601AFB6373C69FB4CF3E50F4542844A266CF19207389C833AC3A03728A4E70C5AC3B4B099482B1999550BB8A1D25DBB941B51B872422FA57DAC6035732CA3B2F30F947D7B8FC5EB53808795695A295D7BA74B558BD0175A8AD7F46CFD6BAE928DB33A9E3B7D0AD554CD8FA09088325E5620A06C824A809461C378823293E0E7CA10A0A1B345EE60780FC1559CA354126F30FDAA421DE4A3A21DE4F96D8CCAEE2E1F2F99F462470F8215A6BCEB923409CBE4CD24D37252A6950C4B12DB6F2942F547F8C646E0B5F4C1E614C5B6F8EA0E23B249ED920DB9DE3E001CCF5F99FB3B88EDF9391833B510DEFA73F26F9155909773188557E57BA3C5268B45933DF9ECC4381377F2883FA121BA0D11CA20F989E16B43BAE6FA5B0D9C74F8563CFAEA595DF4C887E7970CD883A95D9017C08838D81559A95490FAE1C3CCCA7381EFDACDDF486D158704BB8EE0D9A388487566712736FA9EC72ECCCC5F88348D39D07D38ADD76788B96716C5008717C0071C413C3618727C48D0956DDD43876B50BD63FEEBD2692A01A1494AB26EC9B76E428242973AC66E6221D7404223F8AA8DBF1075E703C7C002B67FD49BDC253D604FB7BD38E27A56B9D27E96301EFA75AA02309336AA79D83FEDA510055C21D3A167458E883D260E11ECB2FAF4468D7D648EEBBF4C48397EC3058C163B76C49729BBEF4AA88B37D9989CEEBF3FFF400A1B05860D921440B5AF5B58554E6367743CF61246302D2F0A1EE3BC26038FB52304EE8E9BE69A3E50E7076E17E2462B44F76D3EBAB9761013371436F2564B23BDACC1134499DA39C276ED99603288D6A0FB997882C3257FDFCB71304B942D77987919845437F7BF114D6FBE9992A5B38E4ECC366888A9AAEED48504AF753CB88EE458C7FCC54045D9B9165D2E052DDAEB3AE8F8633174A22231C0013135D824EFD8D4DCA97A86A46D4A64C9E046B6DBAF99C3047C06AA8C53F19283BF3D649819E8E86E749D2C74C740C0BA0251D3C77C6EC2FEB3153D09900C7198569E66D96F40B566FDCE24B09964671E1B150E2C4C587DC97D3DF2F03AF69D9F13B3A387D1FBCD8A4848D9136BAA520E4CD55D36BF78CBAB778FC8DA179B7E8FFEAC21E3A3BD2ED16F332C2A39841A825EC138BBACAA19AD846A01F15B07431DC989F3B870FD27FAE7DF63EC34319E95304CC86EE8C978DEA85A8ABD84F839F2563C7FA7D1C7198DDE5B40FFBAEE7627AF62D7F57E2DA0C08CD02A5DE110C7FC04DF6B493D4656FD03B80E86214AE5DC00D9BA1F34EC1CF95FDC16732422515CBAEA1051879B87C397B10B08BDCA1CBDA9B10A53DAD9B8A13AD05478A73E88A107C0AC73F6C4CC08E7038AD4E2C7F918CC0BCED92AD77D0CE9C7543B6BB8539D0E3B99A7C6BEBFB4F90094BE399DA1ACE5668F5752859388D796B0FDC2161EC01E64EC17FD22C52E6FA14E5D057C78CDC060A06D0B9DE3A4E46E7EFFBA743AB83C14C3CA19554B1AA7232B6724048EEB80A256C7DF100ACE744CAD137FFC541D75FBC0EC762DC9BF26CE87A52FFBC2DE6C079A50F4BCC209EF47A53D6CE5FF88E90DBA6BDDC707EB93501701CBE6263CB7CF6A6A2B69E25B23658CBC94889AEE51D6A16EADA5C84181CC35257ECC21D60D8CBAE2B46E3C69C48325E4785BEF9A119BAF392CB0469B23C75BDE002898B6896ACBCDA44744081479F99CEF23B70AAB1378AB9F98F76564D81565B380D8A994AF696ED2B317379227C28F880CF58ADD23F0D49F829C5D23865AB87A237FFF17DBD23E34E13848F5F0B4AC551D4865A50183751419B67F30E3292F96DB6821D1B788B21880B5D6F0F88C1A9098C5F07F06474B9AADD76733D329355EC6E4A4658C81D4095B8E1094BE2B1EA4D1DADD7B4877F144EA45D102AA0AE7B9962F7BC5B11CB3ED7E9DBF83BE020EBD4D733C448426E7549A5225357C0319F8A690E2FB2FFE33B73F26DCDD461BDA2EAF1CBDFCDE7CC90A5F94769DE9ECAB066CDD158E55F10C1CE3A9B3793417F85AF871AD9BFBC8B02E3A94200F2510C0E61F5DCE3638E6B87F2B299FF627F121CF8DBCC94479A2CCEA282597CD59BDE0294857C98BD6D9066741AA6E4E8BDF83E00911B1BFC947778826022F6AD5377ADF7495F483FB01D7B83C7319E08BC13E6F161A534F5337395477FB7F03B5051C90FDD486B4B6FBE0C963E9650047E32F666FC3C4F9C9B391FDB4FCCF24EC379639D65F676BD686C0030A5946F0193C11759275F23F4AA242F6BEB1BB7C6FF4176F589AAB96C1D8C2A8F73F1D87213CC2AE134DBE1A5EEDBB6155DAE672A01BB621CAD4E32507D00DBA534173F6207441E65118459303DC8510E996A854015C50CA5508B3D3E9596F242FFCDF2440AA7DA52BCDB0CBD6B9578E0CC2FDF1B880C0187E280C4E2FDE44F2365A9E858D6C5197B56588B89131387ABA1B4845E1E515B4CF3C92478B50933F3CFA42553011DB91B47B16B2151DDD6014787F7AB7DBC053AF93468DDE606965BEE41FE7ECE2EACDABBACC069E426320AA26353F6CAF896D024AD9C5C94FBADB6BC93C5579CD1D9F4CB3F195C919D985E61B56B58953BC69DD6DD3D27B7A943D6BFBD86F41334D82E9262F86FA58006DB66433F02284796DD668D27E0E6B4C97D8A6442502603CC859210CBDECA85DA3CAE4D7CF080F9AD820C6CB8B54222A71A13864754518DE2CDD0E168DA6E601AA863FE4C05B08B4FD4DEBA3508552AC014FC3D2C35D264B58871B92A5551A033E40A9ABBAF2066580EF080D2B49899411393F556583869BF11D2E7BC2FC0C263B4C7FB9D10104353B5E6D9BA4CE0613535DF50000000000000000000000000000000000000000000000070B111A1F262F34""") + ), + new SigGenTestCase( + TestUtils.hexDecode(""" +2C242C2E0E18E6E587ABBF3FEF52D5156E92A73F58F15E88501D7F6DD793D6513627423FCBD68B62D99650E4D4859A8562B9C868E08F2836C1DE1493CBD8E24937874DDBAB2564E8B6D5EB098B1A53F1117594BCD26FCC8A464843135BCB424E6AADEFE7FCC8DD6B27A966D7408C51872CE114D58FD4DC0F31EF954B71C322B8D2106E604801D8320A54B004D480500B179144B864590245C236660C064C924042E0904514282CC34482D82245D18290E01640DB428D1B1781233360D3026C12462501230A83084E9A088D0C299019388019366081360A14266E540648934206D1A28CCC300E04352018212224334888282C4832481A1272DA86519C4289118049C2C0411B484E43082D03934081400C01333153302100116E4C402C49268ADCB28022955140240614090188A66801A60860C46DC3A20D9B129299108A8AA668D8986CD9042C1C276C0A16259C4226108569D3866422A729A0240C9AA04804428189C00802C74014C75120B24122A56509058241B451141749882411E4A22118A40CDA306591C28419442D93B481934064000729CB86898AB06920148C0841520B3412088190D2380604B380D0186561904C802045E0400801A07008250102C90D82C4081221620436088B3845CC20664190402429821A458CE430051123251B250220A16D1CA53003244C4C84410033684C984CA120520986481133249BC271513682A4808084346E60004D2194650146501044611815029102405236904A3649DA168209364E5B8889CA120800308040221104A629DA30650C2329499829A0444DC0128E0A106A019028613850820611D9020D13C190184149404430CC226989A24C99343122082004B6098320296098891C30620909880BC7650B847021A0705A928198B05012261120290D2146281930460CA80844B049C0202684C04480A611C248924C140D9C260444244D50A408C8265281B42118A22449204598B8009A9848233400A24288A2360240368044B26981A24D58101043902543B4919CB60D1C414A94902D4428228B368E64048AD4188A9818281BC830A4402A1B0308CA8611CAC405C2C69121204D208460C3180E22264653961119982000988011A51160286A23037109A584C39849E0188DC80651E3127112A88102158CD3868D50020DC8422842C809D2246EC83888DA82812101609AA28DA242651C1205C2042E08830884A26D420608D38888C8146C90C4440B076CE1824C08394618C63181046409418D0C002A231041A23482003408E32051D2C26904B249D1364943C6840AC2245802319934495C106208310C232384C1B26922B781414641E1860CC4180E2349260A094A10031103926CA2A00018130120968DE3366518176519284C50126203296841B0211B04920497116388099334448320880B444E9B000CC2A6518304650428205146898812444BA68C54882409088454400C8BC20D1395915C260918328552204D91B0442029299C920022208662C6810C95291A466C9AC871A1B02D2049098A123118A20C9B322E5388518B387211820109022010390019337249C04113305061046410094420C568C1C48CA3C2489A342D9AA460CC326E4C30450AC90193462ADC025151268444000993A08100C784D80262510206A4046EE4A6481C29609808319328215A289283222524378449B66D64C4450C179101B54191226582824804A024018329D2004593A64064202513B42510200D4C8410DB901099466ADCB845CB46114B208210802DDCA28821A88921920500000AE4A84810B66D18A269E484814434728A244E82322204C270010324E234504C428111220600460101218A20274D1A39259442098C1405CC8660A2B84802300D093490D3080A0080688A2029123008D49891CA48828A82411C002120460CC0B8214232818C482A9308800C928C89082920266419116210454E61104CA0348AE02404A38410D9007080104CD2464921B304C4B02C9BA80583304D8094711221506420925B244944C49023207243202593C60521234243B04901232E5CC60CD3460252C669A0A04D193809101130C9466D5B324A09230A4B168522056612B97004C96C08178D13916CC232001C469082143183220418A76D40C4415C1001C8180EA0A684E2A2411128918B02450CA6098AC48C5A0890A1A801C1428E04B041803452D9A22152B86CFEEC2BACC5DD2E71A2B1C8A14D54A95430380F6D2F08A08E638EA94C74186CCEC154CE3B78A6B0E275C08A5979473509BB06EE8FA6A81AC2995E8373933A5BE90E0BCCB82D192BD1847A7319F3D61D040C12327370BF046773DFBDA9943C3B35CBEA6AA0FAFF2CCCA040BF38616ADF6EBD43D5DBAE2929DA15E0E26EEE338FDBF503D5F6681692C199A67F29A5938CF32E69EE7516B0C57F73C8C4C686B2AAF8350FD84FBA13AB611DBAD7728353276B0DFC78022BEAA249E4EB008447EE55C47492F6ADB6FA22CA3F924CDD0D2AFD8E4C5427DAA832192A3E36EF85808836AB4FEA9E5544461625A956CBC30B086D0FEBF21609361E0E690563DD39BEA5FF7138726AF93D868FAC9FED7866EF2AF190F7D3173ED949A76152993DBC8FBF3DE466A0C56E0AE069B8666F02EB5D7146718769DD2481E3BEF3E5F54B9F900AE8533090C904CB08633CBDB01054D6267954A315BF0BF748824BD7865DDF8C70A6BC0B47D4667C059F75C758AE56DC9939AFC7D71C2F7D12C4AD0BAF3CCDE9BDF0ACF2739FB0311BBD22B3D62381C64C9337EC0A735B7A02EE3E92939F63ED1A290F3D4A495682A3804C3587855610D2DBA663FB73E220952B6C1C4024E4A9163C853C4686C508B600C6022A4CD7793DF69F3F323807E4623302FF751ED61877221FC25D763A18574F1E0D11ECD755E6883318187D621932E0B30627E023CB5EB88C50D8642D1EAEC03F8FA7FC0179F602AB147522F818B993EF6938C02834E8D328B88D304CE8BDD502045888D337FE490CDF2AAC5237CFAFC3308DDE202F593FE3816B95561BD774F25A7EB0E302D08443D100C28B9EDA8995E5FD9C739D348C01FBE2A4DAD5038C052549010A8C8BC4CE40D76DB2CEA946775C5E46938AB65199ED491FF7F57956AC842C4EEA2A19F50E13FCC7F7A5B71247FB7C6B58F1B244EA25472321ED86A5498F914B243C135C8438E26859063201205901F45ECACDC37105ECA9606164D44A6EB2C9E26FD0017E7B6669C08BEFE43EA0F0A737D2A2F375B21E076BE884689477DE6507211BF8C34BD92D54738E7A41F33332B33E6655B66E4EBF48E415F6D6724272A232F85F59AA9B58F3B2E6F43DA613AF54872105FD116F4E24AB77DAA2D91994B45F89B7B79454A0FA77F1B369BFBBAA873D7DDE82562854CC987B45B3AA38B746F05E30301DE0B9E799B4976446D8D08469F00E9D64EE9D7A38854D9C9A6E6A747E77A9D2C526E6FF2678920B8F35C80BF488A87CE9053DDBF829E409A5375A4DFE0AFCB9D3D4CD8555E66E8FDE5438C234A579C631C7190D875EC6FAB628374018A31DB01795761401B45DE5744F86AD954474DD783B37E4942F5D90364DFE365A38F0566322743313F3E75299635E70B7C02EF7A1D36CAAAB4556C26AABC654E9BC194DE867C3DD89F8EFD710ED04AD115F5EF4E11BE33B67EC709DFE2D4ED3BB257624C463DBB5B24F0653ABF18736C6275E716A474F2E48271A5623F80F89EDFED811E5D0F807B3112B53D3E8D8BA71B7AE531A005B1A1BE3CBB87931E7DF937B2A78AEDC30E9543156074434F390BCD8DC83C43F7858750AC113F360DC1B73C7BC3D61BFEB2BA1D417E2A4774A166F3AE220417EA7DF29CC53ED50A1477EB003D3C00F95EEFBAD9D0EEA92AAC088AF47A94D847F79C5E43D999AA75728C9D80A0BEA59AC3407F1E41A0D46ADF15E51AB89A43056B1F578B31FD389C29936246266B7CA17706BBD0DC7678B26C199ED792E0D8488C5E79625018CD65564A77E6A9CD9838F066E431C312E17769875CAD6B77829E39D42A7A0AC220BFE22987D8FB3FABD9955F94965DCE2F5E534D87A1C2CE9962A6B346953651240A005E6D7A3919DDC1F34BF3AEDFF39FA895C842D33BC9B3C86636516F6ACD063FF512121E4F175F4E3F7C5E3449E6CACE385E05814F0B80831757A93C2C680F5682D0441892CB440BD50443F2EB3DDC6C76AFE8919D0DA754FA617F4BB3F07375AFD8BCC6D06E7249D6EABAE6F46226CF9FA61AAEDA3C85E16835E65556131B103B7CFD32FC1BDA2685951418FEE53FE2D0E13452E912F5E53812642DEEE6043C1390D8290D01EFBCD6E49C860BA552F993902277EA1A1C276005504FE5FAA377D4BAE7A41EEBF2EE689A7176E64D3627C8E01BECBE180629F63625D070697F6140F175CB4D61CFD527D3205BDDC38C2E5E3CA1C64C8F3023B172EBDC9C43B228E521584EC2319567DF0736A2262F1E4987981494AB775856D9E382B6A011B61F1FA4C14F4A063D725D5EB1059C3B10DD8108A689268B5A29780BB72499D758D70ED2548879F3223D410F098127179B3F8AFDEBB8C92E7E2E9F5BC3CA594752DAA602179E25524550D55CE8EC4B819B54CED54AAFB27231FF1FBE701CADF649B4CAAB181F786DCCB6B6F9448CCB080F47B58FB209B135B96B34A95A0F29AD629315205EAA1510BDCE86F3588E981FAEBC2476040B2A255917347FEF6BD984163360DC13BFA71642715CB6D75E3B06EF05823F827591236ADF211FD12EA3E9EDF7C33B95266BB4909EDA767B4312DDF1085E3E687E2A5210CAD2F1BFCBBF9D1098D4843B16597D914F2D17807D4743ED9530FBFE3010D834A552146A928B5142C427131EE73E8C1AEF179E70A05B1214BEFC391287E1D2F63F8FF12A5440129FD97B11FB4263CB92E54DACBB6B692CFC93ABA5D281DA468B81A607EED89B02312607648D35767DD52A031FDDC3787660DC772A3B1CD888AE7775E10A483AB1815C6CC07F7C4D959594B2B81010153D242AC9E9E77A4CD4A14A6F2E2A193EF320AD28F718745E3B68B32B97492D1D690C7494430F24EBF7DB4F1F18F94546DAAEB9CF43A2695D420582EA5413A57E2E03C6A276CF2A6E65CAE1D338E3945BCE4477BB8A702F584EB5DFC68EEAA082950878AD334F63FB91107D7763651622179C732B067E1C31B8A48559CB70FF7C31A7BA0A75671882D8831A925289E394C8CBF0AB0D001ACDA20D010CF4FDE387995D4151EB77309B7A6B6A1BDAB20113803046A48AE6D94F0C5CCEEE406315B4CA43D5418777E3C76DDA4F2E7C7A987977107E26F15238220BEB5EC511E749A6296C81DB3442C6E404E085232FF5B412357081251321337770C376F6919FE30C25EEEC062CA4EBE571D81B2A8E5E531971B7EA917C739B81658BD70F00A7A0F19C2CFBA5F2880CF9A311E4E67B3C54C0652D0834C3CA7924DCD9B82AB4A4B3B2FCF87409E547FAF41F40B95D7310CA5ED638E1CBCEDEE449934B222F189D19A653D9FFF4C567EFB366D614AEB8B4B885E401285154BCFD9D3207F166962C25475184B432837E698C4E4F6E7683485291B1E24A0D8A7F3316425BEA502F4DC9D9B4ED205699C92BAD86AB07D6F94A07D9DFF43F6AB0048942DAD6007DCC146DFF6B54DF61A21C77DC01E1F5C06E8B0C72C72DE39ED01F215F7C2A4D8DC15EDF2C26A7D5EF41876DCA11690032A756CB240AEBF823052E450415A957970947536D08A4481FE2D59507CC1A875F3DB2A1503CAB2E10D47AE301B86EE4872DBB814CBF04A536771EE820590434D066CBA98F05E04F067C12C5E04215CD68260383BDCC210C6CF84518BD630C2690193D69BEA8EE69ED4B1743B5F9E9AF874B37B6890E6A0A7DD660F4701E726D323A77A324F80CBF3800AC10A4CEC4AE1C67C65F5AA31E141DC3B4BEA82333F8A75417BDBB8590BAFC66384574DE632740E5DD2B393A4DAD98AA275D14751B7E0CDD81A651403F6B8BE9ADB0B5E6B1E02EAF0A6C0D9AD0CB7D2A3044872B124CC826834427951C48AF0C81488C046F7668528C7F53A322A9285C93F9B2E15D1A988B213827BC607FA79F6136D4A17BA580D4F16ACECFFF037B8C692B32818F5943479121189D2C8BF01674172B7A709E798FB5D903BBF93827887328865FBB40F247EC85D953714315EE33DA40BD74C0BD805E0C3A180FB5D039493730698178BEA7E4E7B1DDF9017835D8F00D5AB81B9F4C81199C5672E54F0FB9A81004F4E7C3FDD51F5852F72ED8F7003718178657A1688200375E419B47021221F6C0DFE0670DB8D6A9094C9D74A1C335E394809ADB6C101CB7A6FF49B894BCAC5AF8F5B866AB8BD50213A2D43F4FB1606AB30642546D071F38AE5DBFC348A8C8B9B606D493FB6A4B0E3833A52CE308C5E0E659292DD69BAFCC5FC8BD480A53306E9CB8CE71FFA1EB96791A18DBC6FB1DE53A3CD50E70225D1E5A386226F3A83D0630DEB8BC954DFA6569FDA606C51150D741B017BEC309E7B6BAB57367DE8CE7526F19C2FE78BBD4091E7419BBF7CFD94606B6C89FC9ACFA3D8D9E1A404CD93CE933A45A920AED24562CBEDB34D3C117361E7ECFF847D61BD8B46E351569B2561BA7EF25E4C9B2BF562A0A97B1105B8664F6F5408D4109632F23862267867E41CE805A1CAB1226CBE7535D1C7A155D03F3885BB1077E8013EB8B685291CF3355FDBD2F1DB43FD6D8E33320BEC59C6C7AB34FFAACDB152CC01899713AA5B6EC98743F8BEBE45A095B0C67F1FCA064C6727A509C79F2FD46F91972D17B52A192186F7F1E6E58654EE8585D2DAEA8CAE2E8900C598A8AB10B56D66A34020D291F21A8A41AFAC85BB5FB10F10B991F772CBA37F7786DE37172ACFA8EBE6C57DCE0A8DF0C44FA5968E2295B5154922C142CA5E2B7B45CD102D33C260D6CCF0DFEF41C26070"""), + TestUtils.hexDecode(""" +78A2B7A4C8441C36E0A9831F65D41773FE6B81B3FA6259A320AB03D460D7E38F4AAB2B93C6142FB0F9584E4D47074670B07F3CC4513675A4367EB8F7F4168F2EF7CA26AC45C8F23B2FD3E970068F21D9A3F7EAF005DB5A7157715CB94F5E83E3C955DD68E0EA689B6F419FACA7CD159237085678FA5883D5330796AD64627CCE7F913D1C2259E1F970E44988B08E78ED1EC01CCC2D0274067100C1C1E3D880B9CA4F3A1FBB345354D4837A6E5FF4D5F5C87985E51C471EB9B0F85075ADB57DEB53A87D85834167A4A538134CBC24FEC2756F7760C3D46248D5BD6022D8F88CE7D037935DB74A6440DA49B97E8FF376101B296E3A9D4D22E70634CFE88142EE5FB6A33F323519EBE3A915AEE5BB687DA4A5E264C657438B0F6AC977A22D0E56882F74E70D981CF37FF0C57D285D8CB07ED7FDF6D7CB1DD39EB0D84F2999DBA9273E0B716CE754A29CBA2FE32BE13BE8B9F2117DD7359494A0E0CE623AB9ADAFD3F15F644545A39055D42C6C5FBDB46D121308D649AF9B86A350B70F77A977C8268FA1E04F4EFBC2C95A2D72BC37E558F0460BB281D33F75D2AEB240086CEB8246E8A44416A5B31EC58AAA88246D355591BF7C622CBEB1CAD3B785026CC04C73E352DFF28D77186CA93870339E132D57B11F0154E0CED426DB31BB2E125C5635BD489B52C5E77593145D3100E48CFC8FE6975FC3F60ABC7FA4A4D9030A2CCADA3854BF9AA213EF11E2F85E9D4E79CBB434C65ADC378F8A7DE33E66B4F8588B73FA7F79AF4130554173975280879FBE0A59D25B969FC45AB20401CBF85463A83578E63D0C8324878F5CFAA191428E7EAE37BB17A18D0459378CFDD4C8C0B23B1429950F054DF5C67174E99AF9FCE6B0D8C98BAA9078D2CA87EB8A014995FB79F7F49D78F2674839E14C8F74588B45C28E4769C439A930B2A187764D87D71200E841263EBF74F7428EC554C12A7352FD3912D95C96E4BB1D325DECEAA9D6FE360DBAE7AB897ED467A300A8F4C6630F8E721F24860D1FBBCFEDAFBD94DC9B4237B91B243A01C41D5E98E67B52B4A8CDF0F1C985EC0EB85131F5E970A6DD6D4E1F525D9D94530157F70B333F5E50B1B95D569A012ABA959456AF773B59BC2891D745CC036D06238AF3F34081A20F00A831422CCF6E4593EB56CAA3B7DDF44B388CD54E5EF9E3FB8A260847BEA5EB5FF9665530A4F4B56726A4C5E669904A933AB1E56C020967FE61E72185D56B38B03D343302712FFC1DF9D857C6F744E3ABABDEB3F65628932D69C65FA112AE3F7D6ABD2B4C3CF572EDA73C959637D0C5C188343415E9A26E698170F8E31CA45A8E6E8E96BD066BDFDFF49C98C491149D61AA7C456D3DAE0C017A32B81CD5668A400127ABD4316F3DCEA171C3F6A3E99B398CCD4AA7E45BB51963C82C43398050B8923CAE2D4E2A2FF5232AC8F2C770C9A775F29C261E1C7DAF54F9FF606560F869638B666C90112B29F469C3620B0912622892A432EAB443F8A93E3E7953235EE78CD3FCDAD3F1391A2487DA621526EE92735284C347853D5F65395ECA2B50B0CFCBD988F99C86B5AC56ECB82813A93208096ACA04F22AC015CD9860889E9006DDAFEE0B472FF7FC3D5677EE089B0AF7C6C2FD5A322D60BED621B8F099C30C2344F453320B6FF405639CF764B101E1CDBD312495C2D4FB30E2FA7B3C345B9935BB28EFEA69C829EB57BF2E2E5E42B8515DED4C32F9C84C33DEBDFB345A4BC592CA56A769533FBA0A631D5D0E07DAEEDD2FD588FAEE648B6391422924D28D08B4CE36084C20E827E6E73A97852BDD7508E1CDC1630094C9D3A2C8517A25A244FBA388EC7DE2CFABF139888EB7372E2BE3BC4FC71788AC3CBBB3EA1CCBD9616E76F2CEB356C13257A8E5490F3C4F7DBEBF942BDB941937C956DFADAF3A78903B49C5DE34F5EDBF0E98E3E04E51021B686325955C14AA335427C4A116CFCB3B89349B1258B8E0E354F13F86C86E5E8EF8F57D7B7501C5D75B1D9615D942B04E1FAC4EACE0FA10E6DE9B9721EB0651EB3C9DE4C61EEAE7D7E17C0D699EBF7EEB122B8C1A599A2CDCBB9B665DD9A653698735D5572EC379ACC6A8470CD7CC8245F871C83E6FD92111F5128A9797AE802889E4362104775CDB69FCF37AAC22EE4532FD0B5ACFDC4DBD56D9CE8B9EE2A8B923F42FC512B54204CB971BBC9677EBC49D287A3F68A31DB8AA49D6477B287285B88AF298E68C6EAC3C73FDEC94F7062D204AB310686144168C155281627F78C883AFB49DA50C0F5139E2A0ACB9A9CEFCCA39C6F4F0F5356D2898A4F5DEA78FDD20B79662F4D066E73EA4069DCE6CAE300B3028F15C98801912A86E0CF34DF53F7F6E1868DAD92DF22A238C710F471596A49843D3E60E4C381F713C21C3910ACB1515E5E30252C94F040F00A9D1A08A4FCA329DFE190B5464521BBAA32932022BCC5E119A96DFC941965CDF3B739F53DA156553C6BCD72927B07CC3CC945FABE44B7348257A9FB41EF85AD5423304E016E74E03D5164D9F15838C3A4BFDC29C6B9F134054B53B29183A6A145CECACB3EAC7C18E31CB4BF78BC8FE60A3B8EF880CB6C1EFE7EFA8D77580CE200ED96713E32FF23B86CF532D8EFA2FFC8DB1A9E65A78EDC30090E3DC02475D84F8D9F2BBC48B114C9E4A01FA79C17FCACCAB1FD304C7F901942B9EF57C918588C9CCEF0DC5FCA7AC84ADAD547982EF9E855F6E88D02751E8E7B8B76C3796F94C9F7B7C6860042A3A33EFFA55AFE1B94C97D68B76DD240346355012F036DA9C7E025C3633CE867510D54CACD36D8638FAA8EE47D315FCA9D5AE4BEFD6150086DFC368DCE8DC623ADEAAA07287F9B291252628F1BDBA5FE6DE45129509651FB048D3A686FFAC5F2299AB0133FCDBEEE8445555F5C649598649678847FFFCE6E0DD9C4E75E2F6E77B1CEE3A1740A94E678C1191EF46FC4D9648887DE6277B11D4C242DC4A427AFAD5459BF213E0A20EC74EB0C210D0A922B9E690EFDCCC2C160E011AB94F709C174F22629969B6332738654A133E8A13EF7C914CE75ACA1C37DE05A84708DA741161EE4D23C025B405CDEBBAF9040A1CB7492294C381FD069C4622BE1EBB0113F25F4E1D5A415C121055CDE5616662599C2364481BCDD35F7E498E80D2350AD3B34C205C5EA73F1B923E6197E07C502BC6F4F4288EB46013BBACC49A5DEE5071ECAE62B192294E904BF3FD7BE08F0C43E3EC6E23A7F68115FEB285AD388A0F8FB94126EDC0331834179C1F10CA5EC54159FC256D7E0AB3129B22E5AA5D662C6A03C7D9A6D066400859EC2D5B091C37E35DE31365F5125793E7F653013C722045F7292C014123246D611A7FD59E9B09EF24221C7EAB249330C91BC9F4D3A223D9C2CBF7130C5C057961BE89894221AFB1EB27A4604BE310EE3C395E479D852CEBA4C2F74D4DF416C8836861BC13D0692863667AFF8EC89BB9194407222589E1C27B9D59AC49131765273228E79C2933445B83D07E48A789FD6E406064593EFBAC4FFEE64614C5AB34E5C2A717C50AFA79A96161203531C161E46D71F447FD28CE4AEEF197A3DCA6BCA306AF09086D6BDF35A861820C469A40958923BA824F3A95CCAF8531E930210BE46D66CF7156EA0728F3448292F47ECF20DAC7C5E78A2A0AD5215FF37594D37A2AF4778B15BB1B5C4E0A44AD5910B62CA3FAC5BCAA4CFF5BF97C8B8CB239126CA09E92492121C9E6977111E6E5248661AD122C87007318BD3D98ADDFA1B2CD60F12AD1E072643FCF82C630C2093CF4A75B2D3F809A0496727E04AD60F14CADC7331B23D9CBE28EEC92C68C97E597C2EBF99F2B"""), + TestUtils.hexDecode(""" +9DD91BA5CCF4431DF756B1D23F47C0CCF24F869A2935340E59CD015E04D6F524A0F40C05247F5C8E4E0EC6DC0237B948D25679FB1BEF9435F248A20B4C2449409FC6E7AB855DE8F42423C83192DFE5EAEAE504ED4A490BC1FA3A84E66EB522327AB8741605348BE8C74040FAAF4F4B63D17B2157C3B216F20774412B70ECB568968BCDA52B6D3823DA6126FCDAC3837395CB0A22A6F4C704828ACF0E0B48A29400973B9C3567A0B4C0453F875A3DC82ACDDA5106895EB2B7AC33CD2982B1407E0259EB05E0DF60EC4AFC471D9FF5A4FADBDFD82FDEC3A3832A8F2A0776D650620B1DC4BBA31CD1EA10A93AC38DA5E22D9A0BA83FDB8C8E0F1C5751A11866E5C3E7BE5FB2147D7F67FAE52278BB4FF1486CD3BBA2FCD0544C71C1A5717AAAF6D1BD279CD97530BB1BE3D692CEE23A0069138D1F7AEB88C6A7A136763C132CE5C6F036E703D91FD76F3BC200656B61912576CD729540616FC49754E3371624137E39346BCD74990099A20A32FC20E7C2A8E23A3C0B3FE200F0402B2F79B825B3636C4746A283DBA0072B8D77CFE67B9EBC45350FD96B6F8C94247F98B90645A06166029C4B8F44DC998C0FA8DC5A0915CBC0EC139DCF1C75FCC68FA18DC365A198F46FD5B6C6FB69C9CF6D57586A0586511A16E4E1F94474337D31F97AF17C49E2283BC610F65E3AAEA08FC8DBAAE8A7D5D9573C46EF3445E46207536F57B7D69D5D0B61FEC95C883288EBFDD33947145FBA259B9C2947F7B837113303CA88DB7E0B8945F0ED413658CB0B1A200991D28D69D138A096803D964F2BE8E4BA04705F5F7E8F805871B7CBA8953B24DAFB9C1E25C272430B7F514DFAFE7A5194186AD8FD464015E09BE097F257DAEEDBE5CAC479E517A011E7059CE0FF415B42524F7CFEB49A5EBC68B0A44E54AFD136CB6EE143A2C6E8001FFFCA92AA4EF2579DCC06BA93A921DC261003C6CFBBFE4A8FFE70442C5652137FFB849B383022702FBF3A6197E13996C323D385234089234634777A9CED6A9E97DE805E78FEE580BCE6EB074B1174952608E05EFA173EAE7E929DDDBDB68985040775946BD70223D404E427ECD91188AA0632BF107EFD0A7296C4E100DBDB8EAB415181A4C12B43BAF42EF14A6B6ED171CFF05F96F919C0A5AADF18CE68381571250E59630C0D0967CE8B90FC4E075F03CAFD851EC009630001034D81B1CF2CD864D6CE6B4741B056E1E3769C34E82296B4B856B8523E5372DECD8FF62E289EDEB8368280D74239FF203BD4EE9A1D05438BF325408E199D28980DC8D3847B412D0CA652E419DCE0C42ADB52E5F33691304C0CA16551A4224E9ABABCEC514E0D183230937ACAA3125688F7F47EF9FC7BAD92DAFEB157EF880DDCB4BD1E1F8AB5E88641B1C087EE49824C2EFE263F149D353DF8FDB8B784438E74A17180A66792E02D84F1E7BAD76DAE2C5EA63E76C31CDEF083524912C73430C21E2A8E04509621A612FDD5DAD1213424FDC2518D116E93795F726210AA627AFCCFA7CFE3E563C5B97E5B0C276001325A13211EDDBB19017A0E8F0DAB523B5ACDD88D4FBA45CEA00ABD38FCFB98910A3330438BE4944EDDF55C9F2A3AB31406A26392340BD9907F1CBFFF78B320B1F9DF7150B215401B65DD46EF1A5912EEDD90ADD53F43E44FA8AC1BF010BC5130DFE9229FC93F36E4121D0E2767A88591001408D60C8507AC3315C74B72AD9CA05CA4CE9B81DF98771693A6CA084F8FDA0BD556FBB15F76D179494892EEEA3F961EC47BFA0826CC936451E66224045C82ABF55875F02658C82AED63E486941D37144E1CF3386844E2CA24C469B4344775C0A59FD2CE6091F575A260260395C52B3CBB0E65F5C3C540A8F9F8438370B57435A1F2FB465C66797B0B03F874FDEA6700C0831A18A7B50AA7B18D424BFA9887B3AC955E97C80FE176DB27EFB6E8FF0BD4172EB49D984B12A210C30F5D4A6AA3B28460EF2A32F8AE7D057D76E7A111F8CB2116F266F3070EDA1BC98AA52BE181903C2882F4739DAA06C21B4031A732375FBF23BC51A4E9695118113723BB1BB1C351E8D72D9A847A434467B90ABA082556980B92A146BCD3E13D9BEE551C14863AEE87CB56F7002BFF857AC9BC5E2156CCCE21724DB781179564290392CB47CB3148844F3159246F39665B69CE6F52316D0AFDBECBF8BF2B2A5F9CE79821B2E7471E97748D190268E8BCBEFDADE82F3D5C8F75768269EC41A4648C5BC86B267E680156D41163BF787278F3BBD9BD2AD483CEEBB9624FE531F76906C12AD16D151FB4AD5F08BD277C2B55650A86C060D38EF3C54DBAE10B65345BDC4CAC61376A5D052ED0D930E6BD8E9F4C08F257AE7D2ED672E82DD8FEBE17CAE8F3829D353638B2B104D49B7A7E62DA46C642CC3646CCA36DAB8D9D65AF695BBFDBDEB65DC07FF7F6599D5CAA6BB1F6694A8FC62BB3479D1889B2663CE704F4099C99186D504C3651331CE06E627FAB29B1B254B159435AD6A8CB6A678F6CEFFFA7988512328D8D868CC439812FDC8C4BC7D086A1C6532A62AC517D0EDA6005C16EEC0C93BDD9223AF2CF5D3E272416DB60561DD0B106AD25B23E00232BE30B9EFB7C82F97DA6C564AF92E5E16227CBB94EBD50E06CC34A2D22C948EF264E5A1B4420A36AE83901C346792FF99829A40714454757FA1CB0D7681798102AA90BA5D37FE7C29C64B86005713711D5890279CB0844536C0F974A46802320C33431588E42CC0F35D5BAF2C828441538843B185C4D93F57BB90ED1261B980C6B33B121D5C8F1B87C2D05442C34AB56512F40B06D326F8F7EBC5FB29D06AD907E687856D558AB423C72CC3B85D683814824DFD9CF34B810861B4E33E41F15569159FD4C6622A6FC797CA97E8D0B0D2824B199A2EB5B6FF06976A92775FF8B66763C1A430DC452F0CA701357A00F3A7C1A29412F1C308EAC4896F55EAECEF88D89F6BCAF7A02714F68E8D412C591A2C5F11033F7FBD2F29A0DB8B4171AA8D4C7E4A708B9742B51F80DD6F9DBB7242EC438CABE48E39F1C12AD886B7750FEBC9C3C4CAE1F6D016C412EB6812815267590F94794C90FE793DB920A4C6C0ADA4E80D2B64B81F04084B65A8251076073A84C2B4B1209655847420223A0A87C7612CE67C1B9540C8ABE46A0EFA9312C0C1FE5AD3165B90E6973F0FF8DB7FEAFA2E01EFA3ACD58AABAA0DDFB30AE7AA819F5D5E9FF72402117FB8CD9BA3CCA0BD2B8F52AED5A435E1F705ACE8E18D60845B8F0B13C967C39AE8D1A6D1EF3BF875BC32B21839077DC0FDF2A4D02A0D1554C2128E55A370168D0698438B21D02DB8C3A5691712B439D4E51E5E31DB45148977A8B184AA5FB63F41C2EC48A7C9C64EDF88E6B480956D9B0A63FC1149D85966D045312A3BD3AF480FD4A3C3F09DCAAD041427B3355B4C1F072A6A12301A1F91880F16A3B3B425BF150E01C6F369C84655D6F167E94613C052D73ACDB2A04CBD4EDC141E9633568485603E5D0339743E030066AE49FE5AF1BC28CFD6F4053348FDF7356EDA04AD72F17376339FF0F7AF432EFE60F3B4325E7C692A79C5099C29405ACB84DC6C991F70E73E1F93B4DCF749B5776A8D5E4A34744192D48E6450B39FD74F162BDE7EAEE2DB13061547169B627F3209B4D06E2C0F71C8D05F64A6245C9097FB0931BB838DDE1F26A211C27710900DCED962114CD51646E5DE093C7B4A3D18FC99EDD501DE8EA5695DBB9581322F903BA408E74D859EF91CB1082EE68BBB997ABC44BAAD87C51A82FFBADB819743FD0D06341666624FD88EEE897168E2EE35CA6DC71FACD98E754B7AF4FEE2B77E4B49E718877C5EBA1706EED84049DBE7019FC42698BD5E0696732C61828FFF5D15DB72654595C2F2B90D12E79691B69F2EDA1C137D2E69E396AD1862F1625AFB9ABD111D495D8FF41CA4896D2A83AD8D00D49B15F1BF0D160AF3CDC637BA2E32015ACB2299A13FBF43D054B420CE97361CB38022C684B695C4164D0CEE286DD1E6E34C483BFB5F91049351762D9D2609580B64425C06084275AB7ED3C3CEB8863F713FCFC091F460DA2351D54CD4A59261BA01B3A0D5F97C04A4A598DD6BB45CDD6049F2BB52D68A9B219F6474751C655F404DB8F75DA6AAA2609BBAF77E7F67BF27D721517A7E128DC4180F0612EA7FFC343501E048BC030A85089BD2F2542FFDDEF0F4B98B7A45376D9B33EC082C17C8815042C5DDC3DCE0CD64CCBD3E8AAF9AA70475E845E8FB4C0EDCDAE5CF67C2384737D602EE1CDCA0238E5F2F0D676E3C9564F9C1D4D9CCAA85BA8B1621C8E3161714256D6200A61642C1E3034A2E072E6D32FD941B87BAF22DD2715FDD8B50D0D366E20F1E9ABF312F989930145FB158D4A1CF607B507C1D3C43C6FA130F36B2355F24DDA2856149357AD1FB9D608E6F25C57B61CFE450EE9393042952AD2BB04EB4C1E7EC92A19BAF7FFAD5FB4CFAC804A0E18AC98AD1462E384DDE80F22E457FD9DDD58615FF9FB4A731F85B1510FD18FD30FFC74F56CCB569002B85AF3B593B4B117E6927E8475AE2C9406C383F686B8E79F22CC4DABA9759DDC9B1CC6BD91C13E451D5D30FFD1AD0D1BBF5F888AFC54783CF930DFF4EBFDEC0B1D0DEC4F781966BBAE1B9D0358F23BD5A83F0DC43699F30ABE458C7FD2E1B3B5B04DB570C598EA1C9FCC0BE0E607418FD5F2B375DDE950CC9E416868F0D582268632EA4F6777AFD49EFEBF7DF61B1F6AF5B8915A3DA8A4BD5D7501426AF0C99795BDE3D65317175FDD10BA8BA957824D45EC0B2653FFAB6BF4207798833D6CF875A87A181CE8B7188F09A69A8987C836EA923188D59B02C0CD2483B03654120794459B92228A8E029D149D6854DA86AA59C7C906F06E314C193C5BB1E94FFB4101B2AC1AD22F520F6E2D1B877E2CEF0CEE8FEEBBCEAC4DC6E66E270250FD77ACDE3E05EFAF41029645891521C0A471F268173EE36F5A6DCDA14D1F5D30CA8C2F772AD1CA92A5AD9C6B111793F38D62FD5734DD9148308344C5EF4D2D7F524576D3DE03543054FE8AB8E317660BC23513D4100FC1F3479984E1F8BD8D18F2097640A1CA2DE7956BA400AA5F06BD13AED8D54703029E7B927AF48A1FEB1317ACBC7DA9F3B0421611252ED708515FED233615C98943B9B1D4337EA182CEAB73B704C162812677B9F96B41922479DA97BBD7C83E6A588B0EA87B53FD80024877037FA98C058E3CCE7027A425957F87B0CEB5129DC8DE0D14461646864B7E69C862B9C4EB1C2240F35FCC0FEBB3E24F98A182737515BCC65A95E53ED42CD15FAE2F3329D61BB0CEB24FAA956A33F358C8E29BC610D02F1F9F3B92C5A6B2B4F1E00B3494DD37814CE79956CF2706BD3B1F92D6E262CFCA492FE20C2DE75D1B8C20CCA8146237536BAC89DBEC536F00B780A906BCAB0F3669CF0CEDEDF8314E3ED4811B2C8336A7CC94FE79D97E4B65CB6240820C88B785CA79D630C06E9575C9A2EF67B49A150B481BBC873BEC1F07769808953695AC1B4A2F971233C9506827E439C37040FD31FC49E76EFF585E9157F83798FF4C7CA1D95258BAB04AF860805C554D44584A478D3274E0C564594EED9343E3349370D30164EF7B2E2D104B7978E8CE758CE8C086D8F108BD3F925040552CAB65853B05A51B3510743B70F4120150E062773071EBA75E5DFC774CE13261DDF18FAA0A7741FCDBC1618D1874C8F7876B200F8A8E5158B65F8E015970B0C3C3283778DCED0E2FA6255BC5E0BF24CDA13F6A47CDF2452783C46209623A7C425DF9845EAD1E854BB810183512043A66046996C19AD1D89C1E32C1C3D9C697E7405E6CBC0E5642816F8D9C72E9DFD7222A6FEE81C9971657B6F06F9A0C8E9550CEBBC44C2593C60B1EC54E5DD2D93501FB9EE42B8CFD29DE790CB8A15A6BCA3F61163D39F186E771769D2B7BA9ED1DC0FEB03DEE86834038116C5B00D117B2EFC56C283436EDBE48A61C2C7DABF5DB3CC638F14D28AEDFF375AE638A3E05FD871D56D86413477BFB8D902DB263ED841367D29C4A95B03D758CE9F2E4781915755990A4C4D5CE8AF77376F7F2CD050CBE42BAA3DB923CD90665FACE9034087F56115858441C9E060B05542053324A0722FF12E6DFAC3330C12F20679466CCE4C4A24D7AC09A04302B95509A42F5538EFFD1BF3DBF1E9537614ED865CA9390854F286C243F2E7AA7311B40E5B3DD2208156B37FCE086CF064C41593BAC8C6B00DCF6386BED761551315BEA7F4E1600FA1FDD2D0B20B26613A312E1C03D82D3FEAA24D3B948730698C1342B4FE97B7085B192573FAA393BF62437C57362706B17B22ADF289BB31B32079C9D9DC9AA1E8FF63B25C8EEF97F13A628FA5CD151596E67AF80A4B1A71443501F6B6C8B6825F8AC7B5A6520F056D589E849949E93F0C2E52AE89CB81F3EB7C31388A56D15B25EAF35F9570379EDF4E8923B4F1C6666BF646DE202359CFA3C8E10434A5A8DC3DEFF104298B3C0FB507EA1B3C9D8F300617487C3E93CB6CAD5FF4D535E92CCD1D8E3000000000000000000000000000000000000000000000000000000000004060E141B21262E""") + ), + new SigGenTestCase( + TestUtils.hexDecode(""" +CBCA46632F51931999369241A839BB7E57DA0237BC70ACEDE33B32FD3A66B20FB4EC73B8DF3E9EEB22782E3359A9CB10EB8CF52422CE70C71824C705B7862DDD926DD53A787E5B80EACCFC8BFA1BDCAECBBCC0F697558C85BF745C0741CE0C818A1A2159B5E2D645CFD5FD8A7914D64095C4B2EC86549121848871229F27D91D58847013928851224411090690A28493166A994460490891E4065221B98942B44C03850564C071C92472834244E086650B377010102924382922458601B224149085D44622D43231C3284010182DA2288C1AA10990082A542286D4042680400103196A019780D2A86DCC062AA422680B492854327123C36440180C61B070DBC02DD2300A644009A2922548262658200C14912994464813046D0842008B989144400511474DD4180598C67142B42880C62163C020143265C40241C21624DB420D03068A8A382448484DD0A40DD3924489306D09A52012856C1A4450113125412820421692D34012583481092912028684C094040136451C200C84B48C00932512190294A07108A388838064CBA88484022A13418299C48D5386848A4692188890233820DC88519B16469398000B046D10A45012B14D81A20454468E9C240ACCA028DC420611295102A4608A968DA2264E0C2931C13272614280A2A28C9A285288B40150A28118024919970814A7110891680A8644E048921BC68DE3C04923C261DCC00822C08840A030134972802844D3920C1C304620012500C64DA33485134140A12406E1226022130648006022C309543491A20881498425804240C240640A456D04226112106983C22D53344C42902120048192B80020238D23022ED094901C33685B16500CC7440826720081481294200A9148C9C0050C13109130650924300B0889110461C3908481B06C22044AD1B63181021091362C54C60DE13691C106084146508182240B20020C416A53340A132822440026C92089C48660D4300962B0600A274100C664E4A084098788D11646E28010C0444924444ED32471C4A851D9300DCB884C81488A1B3025D8802464982411C42DCC022A5C38869284311A1610A2164A0483601C33510B336020180D4394441B07480A21104940321C28804A402A81C840C3106E12C8456288819C10654294715482082045892048461439864C068A0AC585E4148AE2B02424400288342052464C53064A84226C932850C2187061244182487011061180A668883649C22220D4982054420E1C070194C04814A72D9226268108810B03651A210ECAB44D0020026140122202308AA48D24B74C0986416388804C1871C8226624C249003971A0164401246002810DD4C4845C32701999919A90702297712348019318025AB429029785E4B4080A300954B80923434E232888909268DC92440CC525508680621069143989C4282E919248E298059C308564201208B520E43225524668488809C12868D928442193045140401903095AA84C8148288B224A04B369C4028452360043442A004800C40445CA304418181292320888C690C8284E20B101A310268A1490E2464DDB260609498E1930260BB58D5A3866A0C60D4998619BB06864300483226D194071D048520AC829D4903004246010258AD428860A320A10C3091C4661E3C0806428686480815A12024A4610C8360A9C2442909489140401190409142721D8020998128C5BC84DA29409A28271CA322DE226825B16080CA00912384E8C84891B3748C08848DB980D04A84808982C24A59094246C2113669B102611162A13C96890485220B96513394CD2A26CC9320D14952C0202651C3980A0B62C18988483242A623269C20202C8446A82062A0300255294880C18259A128618C6401A310684066D18430D88C06024416281C06000380622378D02096E83440621372E50C629E148819C882D03400C5C48301B0384221061921490D446858944110C2431144051CAB421198444CCB284538050A1006C23418C8896298C300C50A60C8820848CA2509CB43124356D0C21120A3749C2C06014B44844108A41146E1281045B32080181088400054230900B344E03A048C834450C3290CB88044BB6844800901C946D1192100C1600E2366AC04866504890C34892A31830118600528871CB26400C44684312665B380C19852010228C8B928D8B40308A900C03C90D1C036D1C2652922032030120928248EA7FD68A0C62DB31279B2CEADE3F558AE9E6AFD3849A6FDF95B9F0C219B6155FB29921A667B0130D8B21493847393DE153BD4ADEEA031270DB812F827F974A2CD6520E7BDB2ECD99916FDD5C439EEB41514044ED8F02361EDEEE74F03C183B6E3F3194FD522321188ABA2B3D8C7B6BB4B6F2473ABB3E5337BCA906E716A6DF660DD51B543F02D35CD9A78B9D58312F62AA96635B8B65844500413B3D52BAF6E671487E6D882ABB2473AA4F321CED5A1F57072AEA093A6D51EA0C701FA0B915B14D5EC6F16E4C559C85FA9DC465044097ECC21498E3D6F919D75F8C364BE6371753D2CAA90166BEB726118266D8D7C5C3AC81307E74C0F796E1B038F7660E770D1707F10EECC95694A2C17A6306F661855DAA243033E624D208268461860E39936BC6915A86CCEF098B4D687AE1C1B22BF476C2AB753C8F5F528C7F749749372AEABF9724FC7E3F554B483D10EB78F3099A7ADF6CC4CC03E4EF1B6D0219DECDF5AF99FFE4B2D4CD18BA98C2D62B93555A2989C753BAB1D4BF34A982A71E0B10328E165BFF69A18F494F5F40DD2AA52B23CE544F7FE4B5632A0FA4C879D221A84CED7E097DF3A17F4E4731F87EBAFA97428C0CF9B51200A0126ED983C6FCBBD52C64E109A809C1353C3ED3A214C07A29BD3047D0E69D00B8BDA5242BCEDE709961CE83D1112F19BFA1C6C68FBCBB1B3045FD681E3EE1AB7EA91BD5F501F2D9CA88F9E6E040516D1DD238ED79A84C3E4E8318427A41ECDEA73CA4E12E575403FE4BB9AC0CC9FD8A7A1877F09612B8C8746274117D7930A0DB55EB493907822208DD541CF3BDB71635BFA364B01F293A3439AA6DA458ABA62F063500D2222A6CFCA9E545BC61624E1097031219D61DBCBF8C8D32E345058DDAFCE284B23BE63B5F3AB979C35F4B5AAB9BE0CC37DCFECD168298B744C37D08CCC0DF515AFB01461ED24850BA5D84977D4352E0838EEB9ADA60BF0862971A83A0DE929C06F4A4513E3E01F93EDA9CA7408233ADEE110DD0E1270AD957A296F8842134178893D39C0AA07496EDDBEA015A1E8F42F4CCA571D1AAB376556156863FB00BF1F4B329964B98505B0FF71D39D35EAF9D23A8589188F872D555A55BC37E364C0BC41468130B2ABC8F43EC7F3C39BF0579692CB04DF4A29C4E71AC4921A79B7D722A005C226A4CEC49967AE22E2FED24CABA43D915522E59778BA66F5D2E3604AFBD076DCB7ADF9CE9CC26711EFB4EA190A6660F5F7BA77E2A165912E2AC8C6A4756B5A305EBB92F00294F771B75F1B005E7E042D4FE23EF90C564E385A6968B0A61CA8940E8C67ABFDB4B57F16FF6EAB60ABF48866479C6B891C5A7787AF18906B528F8CCA98EF2D1CBBB5516B95033CCB060B8C66FB1B0049AB88CA15776971FAD4903639A1B354923E13E1322DC220ECC967C581334F8FC2FD10B7B8EA6517427637FD2A967DE71C49F24ED2FF2A72A43CA839D8893472CFD453AD66864AA73C002875C4A09F631321485D3E8C3403406E2462030EDBCE21E7BADBEC4774CDFB7914DA8099E846D69C6A7D58451864F5205D1854EE420B2915B84A933DD381D9152E4FD6C0795CBB90F506A4234AC4128A4AE863D68B06DA74EE36BA3AF8A35B30AD5AC6CD7DC29C467A088CC733AA88055F2246B3370947687E2F6A825555C5E8C6B6577EC2C3A9777882BDEA26F8F8E1871E1664F702DA4B580DACF7DDCD6E29763F5737B000BA424528D197937EAB91CD31504D626A3C33ACA17757DC65C7311AFFC35731272B18AA49CD9452C7497958089FFD021A8D234F80CC693B286C12AF252C9B32C8884CAA75569DAB60F2E3A0CC8CC9ED8615FC67866B54E2762B69F3F81DB13B510208974897A62EF4192BDDC9A7B8AA27DA597C5BD59131195D2FF648F4D13DA5E25B2FE99F1604FAD38759DBFDEF52D8B5E93706C0BEBD16048A496C8A95609A4D370F131B3094C928F650311FFF864AC94F6A2AA18C7E203DEA188B9DBD20FA08EBDC4A2A59095CF7E64BD16F1BDCB44CEDF7409DFA209B1698E70F0EBE387DC40B45C47B621961A34BE1F53A7CD634A538740799A3CC17B69579B34168D1D7C601CCA733B4774F3BA611D38DC44D3A7FF829577304B76B3A2A3BB5A3AB0FCA3CEAE0C4E50B985C7A18CD37D517C4C53F91C8BAB32B90A4F157B09CF14A0536E01BC382C55DC83DC27289EA546326D7F7D91DF5F9145C4590D1A83494D2C3B29AF79844F0658B453A8C3E44EDA25198B108703584DFECC3686C0BABD1078E26FEA2292591054A5D9B555D4B056CA7536CB81F8F7D7B5A2B6028540E9CD21B2458F1B2A5572C373E31922408B26AB3D5184038A7CFD9B506AD4D3CDB5B6AC8DCBCF56332C042441C79B9CFB71D057303BFD6DC98AFA0B312B04EFB0ECC4479CC1A35D53C13ACE0D77C600D43BB79319ABEF7531FEEC9E42270DB58F8692A51E023614D8ABE7744E5B822DC883FFB7C11E2CF2B9CEF5A1E0EDD47688B653A0B2DCA55A7F46BC2355B0EF5981C1672D09A7A74B93E1A92C8D8797322E67492C2025D6EF89A2DAD153F261BD967D5D63A1285F134077FA25E1714108444F76F1212C11B4EE73E448256F93470A44D1E0F7D9941BA5689D3121A47546C6B40014397927720937C6FCB50D283BE16EF175BBA7E1759A1801CFAE26E2D00D0CCB9C155FA15D9D269A880A5B1A769FF4C74005407BD7CA73DD3DCD09F0E940B7D84A1876ECB65F0D712993B5F2EBB9BE0699F6C2F79DDFCCA8ABAC2C88B0A02BE72065AD98C017ACDB90FF3F90BBBCC7C8C34146272CFB36C2D04D073049AAB6BE66266046E975FCC31C6050BAB10243F774B75B12986F97BEB30E659B2EFCBD53001654BFFB603B6B9CFE03ECC41F1B46571688D33DF1932AD1B82DF9535D12FF964618A2F76C6FE4153D53264982466D1EA1101B3A4225387330289EF0ECE4F11A8F2CE5643DBA7089BC1482A754A000B53BA46DE6F55C13B4B4C858C0D494ED768DF9A366A2021157908D696FD95750AEF985D7A7A2C56766BFC1AF0DD3591A63068FA1C6E1BA9F13B0C08FCC71C6EE02C0A2AFAE2A9C7C35F0DCEDC5E9823F28D5C1BE4E1B656469C2551704DB934E9FE139C2E9897553424AD74D68AB31CDAD48ADAC6F0C89EAE8BFFC8C4CEFA2F0D09E2C96A134FC158CDCF62B1CDDBB072F62BA0930755C9759047553672FE03D21270CD5BFCFA6F30E9BB67CF9FA9D02F8A30C5B977BE4E52D71AAFE6D3D1223F73EC5481DA72491F7C906FF6642D9731B396C4F26BE506B23084421A527DCA74AFC6BE1F15084078DC1DF2D813AE5595F40A94C15A7FBBBF4EC05F0608B28F283E29F8E730268981DAF3AE4CFC111F57CAB46588F4E58EF2C1536B0629021D6A599648F8A5382EDE2A4452E9EF6F5A7A221D35E9C2BFA134D11D5C5DE65F5F0500A1DA11B0DC055D0C2C2789F14F8002A487478D1F989578AC6961E262A08B31D913042410A39C4F9F71D1E70C2B1951732346E79A0CBACB0D63FC4D78D45A0D17A2BFEA3B81A7F14E3C680B4B9B967447B95E0F4E06DEC7226BA245597D2A39FCE4D1CFAC9B204DF917CA3CB8F827AB9718EFA69DDE17458EF3B0C0FE1CC611955FBC64A436B77C33C28A690CDEA44E0EE82B346E2461C6A1A1DBA39A12FEC61A892CB27027C57C1F72CEF1F190ECCC686DDFC043CFB2FB0EA8CB280928139731D88DD257A7C5554EAB6279EA0D0B819595DFF68E1612B71304D007633EE49100823E90EB41211848ADC7A0821A4B3A9113383E8217F16C11B331867AEEA9CF4CBF8310F0EA0A477F5EE1B2CED3EEDC4D0B300BA19BB95E4455EBF195F5E12374D5B6FED2A0E5D6F98C2B187B03E6B4CBAC7C4B446BA02D057D20CB3FD80CE79CE0D74856834228FB07273F4FD4446B8350A8D7C8AA11C64B89329886FB1327253FA162E4757D9CE08968A5C31612328D24D881F8A9E81711C7778B26EBA4E93AB00F3AB996F3BFA79269BAF026F33F5D616A4B306A100BE5899609BEAFCDF981C9EFBDAB444AE7A5982BD925E6B82603B8F9388D7AF9474B8AD18348121AB3E5DF4E7A9151D91F7D724CB2D6AD60A2FEC17D29DF3DD2628D6022711E7D4EB486F90419E66EA2C1479BCD02D2543807ADB8D75226E8B7386CB4C4057590B466B4FF7A244759C5724910A7CD569DEA50E8520387BBFAC32DCED5575B6155BC66C82F6132A780AD670A8C91A6813C89DB6D900F17285DE4DDF110579FB1E28B323CFF7164961B014C82EC825B25AF70EDD5D0BF74331B8FAC3A69913D7030DC1A142FE2FDA1D4CC5C83A747024DE772BBFAEB89CDC880851020A9D4C5D03267CBF996691A7FC1399BF265E985BEDBC9BB5B79487B97E9BB2DA935579BC5AB555EF633F2FF85E51392FAEA07A664F329CD923D4460423BB6C74BD63A4AB0DB1E3BB7C0EFBDABDB95AF5727CD5DFF90878AF51EAA0648845AF99A2286479E7125F867B31B3166AF309102A05F60158A968484FE5F1C0275E67DA8A84AF33A1ECAC4D49DE5D925748FF1E7A5BB442DFA88E5A3797A10E4CB044EDECAD83324986DE44A5A3896FA6EC6C71C646C2B4431AF55A3C2F325C6A62460C7C9BE6235A503A2301333F0261D97AC6692BA5B9B8BA375149685F85A443FF8BCC240409B6A959C1045CAD6EDF0EE593F8C3FF535B46125E00EA4C4A96446BB3E261429BC6B656B401598BB83E365C438EF16C8CB2C25017"""), + TestUtils.hexDecode(""" +B5CD00AE06396DEB95C9BE213BEA279AF0D10F1423B5A71854413E99F7216D9EAE76C8AB884545496559B14AC9A69801EE3FD2EEECCC557D7988F34B82D244461388C7D4EB16DAC3C0FCE0783321A1488DC16C3C688126754BB4C26308054545D2E46C6BEE26C25A7C3B701341A0323BEBFC50C718162B7FF3B6FAAE7156FE300F2219655D8D44DE89845393011A2B466233B907355467EC49C9F832044BDFCFCF722D6DE7946FA503861C80037549ECE8FFF95026CDA33C9000FACC334765A60456084A0614455C83E0D5D991F7ED43952B7A69F1E326D7BD33822CF1F286D85FAE78F0B8DE186368EB334CA56070122DEBBEB920C5547C46C1291E78AE48B72C7A39020A1A2E54E59A2E46606C99E652FADB39AAB25399B0830AE733FDFD973294B93F47C30D0824686C735E05FF51A95C1C76467A4BE6BA80C5182353BD510E8D4B60BD43436F7021B3F5980D1A769B2E3BF04E0C257EF577828B327E2AD85E0581787B9B7FE44D6B826BF8405D3D0BF8974D2B1C569006C7FC3D2891DAF38DAC36F64A256E337B660CA59D2B45F1B4AA1C0C72B78495FBCC9EE9CFFA4B5A101F973E3211E728040904B0B2515DA4B1CB3774EBEA1324EB6907324E733C7F17BEF6FAD0F6BCEC1F08F785DC6FFE02FFED5C0B7A631907196835EFFD0730FC8FE020B0545C920DD7B2D705F22D8D205804397F6FCC60386F4A576204949EF60DEAB269905707396CCCD8DA9B895270CB39839BFD3EE64149B0085B96FEDAAF8C738E449E585ADBA037BD560EAAE978A6ED61DF432B6A9C2E50C2EA33A8702A23E6848401F85E2C18C7C767DB15920C9B3B030728FD9511F8903DFC8572A3679F986CA1B684B3AAF489DCD93C622C6C4D475DD60F10C390873B09B5A352B6F5A104C90782E053F8121317EB8D1D4C0145E04E3B68446B69A0EF81097CC6BD0B756AF78963724D9C83C61B7B79647F0844867B605E2B60988D2D7AD07CD6BE2D8F904F0D269187C141AC67C9DCF9961BBFFDDF3BF34D9CC5781D1BEA348F49EA8FF7750F7F3E0624C16FAEFAF1D8B6A818AF5FC5C04E2504A0CF4C2DB54930EFA759A292A2AECA1EC3A08918513D95C44BD133657FF043318A17BE4A5DCAC54B87FF38869D017A4B14DEB60480AF1C5F19A9F87B94B8EFE0DF3F931CFADFFD7AA50AC86D9CAF6D434CC81E6ED123711E34B8295A446B554F6DD5350B44C614324D8727F1CE501743043DE6EA085DB5154AD8E30E114A02CDFC96BEB4F2718033B227CB8638BCF617C73BA4473851E62C8A287CC4F9C659190E60AEC468DE7EA8841E3CEF893F3DC79DDDD56B63102EAA5B2793711A0451EE1655C6768393F59CA6085866FB41541D9997C94BB56F6ED5D731585E7B25B1DC853830DE5DD75F66298BDBD2E505DCB3850F96CCE0D7274633234EE2FA1E2782DA3D6CD8F5DA2C3063A923DCB6A2F82614527CA2A88C1AF21025B88A08C3104C679175DE2CF00602B13E58FAC9376BECAE56A60A6A8F144F1C98C8FBDCDE6FBCA4ED13228FA77CBA5CE631BCDB368AD9219568777FB4397BB40485A9AB63E9E3FB343154108D8117CE25BEA30BC854A241745FC6C26AF0D64124AF10BE4BE01B8A3D842FD9CC4D805B2BE26F8B7BA0631443F48C7F74207F640B215E0DDC42B1954A1EAB2C68E63601DE3AE3EA54E16282BDED00FC7665A9E8B098BF034F5E950ECDC46CDD22210244F102E41E0930FDCB24AD6C72507E5AB6FCCD4D6B2A2703C358EC1B51AC87302A5F507BD01CA6B5FE04EA2A5322EDFAE8161965524C61956CD201C4BF2F01B54F008F5F4B6770D0622099CDBF94D6C41DAB4A5362D630B9BF9CE240ED08D698D1AABF29E60BA533697C3C830521314F13EECD95C7D2600E2A756AF19AD94D9EA39FEEF0E3EAB3EB401225C2E55B2F2A8D7D1A3AA77A38BF9BA31399F6E6458F3F21DE354BBECC2E29740FFF91FBB23E0F61D7E0698CBF82D439AFB018DC5F5011B7BE98993E8B655D83C666FC0CF84A532C7655365746FDB97874D62329B1EFDB0B0C8A46056A85B60E38AF8979FA4910D2D9CACC3B5C1E42049D04C44273953350E0F756081D2DF6429193768802577C381897BFE540BC036293643360C848A1AE388CD17781296A99AF0CF75F81D568D0648C8A15436BDCB16FD83287C6A54F88F2F75E6B28E1C5A3AC03501D6D723AC5EBF90517D194A596F7F95947CC169CFF2A65D2BC9B54CA6AA45BA9E901D4AAC81FFE9E62A479EEC5B3F9BFF24C69FF56EC52F1183B5AC48A5BAA90BF595990B6EBA5B1CB6D88511C7D0D165FDF2615351B0343918B966ED1CA0CEBF6956BD2CA599E18619E1A5930E47CAEA92B8E9647A0262A2B24E955040750E6C7B935982CB742EE756DB65B462F677AE09A7521B0D3A42C2E97890C47148618FA6089975F5D491F4D3F69EBCD54C2B53130698A1F4A47505194F675D68F2DDF5983B008E498AB4A25956CF724F5C1250D5F9C75F3DF9BAA696E300AA86FB4B9378EE18E79D015CDA55D6ABBF5B0BE819F9EE58B49656D3B112AD8FA6651A8905061A8E37760C3F2EBE6DA611BADD44268975B5000051BDF7158EE3DC200B47FBF8568C9F22719FBEFE5906444DE9300689BFA1AD167"""), + TestUtils.hexDecode(""" +B2E661C2BE985A4DAA72B12734EE09DE1C78621F91D7E247553F39BFBEF28BEEE7F11654775416E4694086B0A640960D1DF784E8F62E16FB831097DD07A1121B00251D35E4275ED3312C22B41CCE76851A48D9BB0C46A64243110A4CB759675CA7D1B724CFD94255F11EEAD5AD01C88F70E2CC02001D6F44357BFDC159C4CE44E042FB429CC7D32968C5CA8BEED69C6C3769BF2A83AF75A7831B76232BE271B33A43A8B69A91D23E762280E2880559392B4752D29BA296BCE607AEBC0771AA0A92A30B72282611A693E828D068B04C34EC01634488AA8D1862239015BC437A23807FC2BB1B27CB9EC45DB5BAF866858F1D69A3005D4D5F210E0C25092D658CA9224B49FB147CF891C5127FAB6674FECD864A1C26E4881803BA3F8E6394BA98D70330F5D1221DA1D1E966EDB682FE3BC4F7CECBF7326AF5EB7C582B085B4B7F603212C3C8C6E59524A09227DFA93A44D532650F617470D9D250689538ABC832F38503392A96B0E7BFA01323A85696F3E80AC0A860C685AB4E248CB646A107562008358B53842123593E5FCF233951D43D33B110FFE33EFDA0D4A0CCA3F112F94C85F967F0C6A0F7E20B6836664B70522F962C395971692B29F659F0418FF753BD862966D10E44B406F4CA1DB909FE01B6F9F1B60715360D4617E7C0FC4B37692707ECB68B50D38DEB8F40B8C304080D81B84F60D49B7E4EC50B02E36E063FE28BE9A23E6BF17693B8B5C909B5B136BCBC6A3832D53E83A29ED9F933A8BDC8E318BDCEFBC10113888C1CBF39464AE16E2B30FD7F94AE1A0FE8B965CA8DB4667BD41B52E497D60C31277AB70C19350B2C410AB302754BBF7C126C1C9C8C298927AB39E9B4A024C0F47691880E11C0F8F7D5710D480FBADE860D72F43D1C676118E3F83A76FD6CBC7093B7BC18F851CD93D81B0564D4BE4BD39135BA2ADDC6A6DA8AB8F7B15284794E935A339E234E8452F766DDAAA0532DDE46FE6E4C727856CC29D7E78FFEE115147769543175546B8A838A0F831CBE16BE864C733C63F37E6FBC1CE2A36123BED296103FFDCF8F3BC36A7775A9C17F69193DEE0ED7C1423FAF6AE7CD99EF943BA174A6262916B78F9516B0464E8BFBCF512B80340C489B9857798EEB539062F40E39AC8EA3649E787C0A87FC548F0CCB801AF8C2B2156FE3FF69BBD30574D8C11D887A98231B7C6F24C662A48329DBD3DD410A019715DBB61F72D14883FE891731975DBDE9BAD0C2A85FFD773297E399B55D78C3A2C25C27E4FD0BDBBABAD85EA6BD6A3EC8931E0130EE4D068ECAD5BDAB22865A537B3ED2312D1462EA6E36E14D5E49F742F2A232E5216FBBBB1802B5ED89E361CDC0D2FBEA4555A895FDDA03597F2B8966D147FA586BB53316DAC62568CC823447B24052680CF67D8BC8D6399F928781A682A8BDDDCFF8785163A3615809D1D10E14ADF471CB1D93052434CF9D98F9D0D849283079FE431B8114EE9292E52F49C9868A013F0403A20BE45A2E157803CAB01F9C93701402595BBC90132E9FFF845165C799443F8B38E360F660AABB901485569D2B0081D00978B8A1B059BE9E4E98EBC19B027592E453FCA390F7C9DA085255D6A7436C8F1A857C547545FF0130A9F1E6A1B2DCD1EB03F7CDEBF39CAC153817CB450E501A62A1B93C450FD18CA956659D17A31310D517A81DC62640D8102DF1F79794CB7C096B5E37C2AE352E0BAF1A17DC8794D597A258BEFC66F26131298FAAB9EBD6AE3FBFB6DAE24AD74496BD1F077ED87BD1728D1809E96F70AB8254A9B8E3D30432700BC61FB747141609D4B9057BED02338233EE71B26364DFB9492A08933A2D3392C6453D34F33940C54B956BED2C11D9D1C68DD135AFF9165F3F2C801E0FD1480EF0BF99B95C68773CD2D765C1ECF04E1CCF68E659FAC8CDC03B44B5376EC888A485F7F71EF2E24195D75016CA6A9229C2D0FEAAFCAEFE07C46D3DA5942A15AD5EDFA8FCAD9A46ECFEF23A31F342071DA70A138BF5AA5003B70FEE1C00514EE0A3A2D5988F5EC5C279D7BEF153844DEDED0222DB3EF8A4579AF641444ADEFA07AC6CF37F58513771B8C7E406585296A7A2B6649B2FC1619BADF31951AA902EE48D5A9AE8DFD14A160538FF861FF64BC8E577C6E77F79672BC0273549D14AE1895479F8941AB0BF3093C5C439591F8A4FA453A9784A1F76FB792732405F05A8660740D329F2F68CCB6167D12958CC58AD567746667048C696FFBA426D40027820C4C740E66666E50DFD07C0ED76DD4C2080FF1C29794D6F17570A1B9D3D9AEB90AD34626B94A08202289A6409145D820C962183C58CB0345B287BE9EA15C5C443CE113270ACD15A075399DEE56E95E4DB23EB19E87C3E29BEF00D00A5442E67A7EBC5E12A096090C6AB5576DB5BECC84B8000D382540F98C41EDFEEB99D3DAA561FFA0C7FD6CC16FBEB6C514B45A70B2358EF4A53268612BF022FCFA354A80697225BC2AB988322DF31640FDBD05EE154F7C79A89463B2BF0C218749A454CA38DC8B5D1105183B7108E64EF8DB8FDDFA6BEF048C14CE5620A456DA5CB576F0BFFE4FFEB8333A9211707F5617628C2459A2104F8D5FB7B9581EDDDA27AD3BDCAAA7D037A3F996EB765237CF1C42B090F3B0453DABF26F9C92DBA120BFB577350705736EE295BE77CF70A7D3CC6AD388A526CAAFBDEAF67614224B6363E14B3DFCF2B6F4A0E8E2A8947D64437FF0E90DB68DA40D87AE431C02E9BBC647814C60F3CE5BE422C2BF3AA8529B8D706A5F6C3512979BA6E54401F405E6A8097CD0156A8B9D4C434014C2BCCD0DEC4559A87ECA3CC06200D77C02718330CA621F4F1B58ED3493B9126482BC941CD34A5BDC4BC3268C780479453CDD932C421229246D9BEDAD0B734F8B4D06A3780155FE9A88DB8C540FBB8677DF962FD0E0E4C39197479A68E42D9AAF4D1A1F56071F994B1C0FB4B9E6D150220DA7FDA2205E4729FC5517DBE0BFD9256EC717F0CCCE43C2862957E8630C10061D36AD371629912E9C1FA2A01B45AE331508D42630B39E5DAB3F141DEA254F1C6EE0A934B4CEBC4FEDB5B1BF6EDAD35810B836AC2A76EA9233D12E39553D77D1AFA964F8B104C48BE49A65CAC8EB3C352EE1ACD5EE14127340D6747886FE47DCABC13CCCB3410BAC0F96C718CE69DAD106C3D6F3565781EFF03812306F65C82613DC032F10ACABCA0E560D5A673F427FB231362D46BD40BD0B811903C259C2622E893DC4B91F21787BF0FDB976C4A6286D799EFE8269F9E8DA6870C9CF1A3A29897AA5C9D2C75D7C9FB29E467DAFE12A414398C6CE08917BB2A322057FF7BACE20782256624C1B7DDCBEC3AC680429497E06C022578A7D8CFEE14D20122C955005C0C4D3851C3D9D009334EC9B036AD7E1B08CED43DF8D148D5F6C72BB87F52A458910B0829B2848D082E3AAED3251818F7991136BF2E9433E025DB193C2581D1BD438F180CAFFE618CA88E677D0798DDEE55C4CC1776DBAEEB564770567432D34BCBAF6BFABC62E75C714BC76EFB785A37F91446E338546B5A1CFD83BE448405705D7F86B2E56F10FD54E6B3A047EC215DEC3F787EAA157D317C309B37BBA666810167EDC9079A4303D7402B8ABDB03383EC7A37964AF35C3C18D7713F22CA9D278A3F49FFE6C7D158DD97FB23AF1F23916E88539DBF6176F76A4DBFE11CBE3F914880AD2EE49FCA530E483859BF41DA5E42F01B0503A39D9C7A8F0A86B3A8184D87AD5F5CDCAD88BDBFF3C66907E7A448CE0C98260507CE656DA3316186A19B902DF6D1EBC77693BBFAA8121F2D679394772A7A1D127BCC51B140867EE4DABFF35E303BCDE2493D5CD02D302833AC464E34EBF202542AD81F38855BFC1C369F25C1AE2B3DAB609461BF7870D68D2E96D78176C2875F0C277D2493F5653CBA632CF655125D01CF48E2773C67EA58AADB857EF6CB50614AC3D1925C016E9112F36A28E142DCB5F2C1CFECEE0B974D254C764EF65C496D9489F65C976ADEAB8A21C2FB447FD7568C7E7D76617C67C812DDE31108200E5FD20182A393F2E2D6970195F7EE3C57DCF6392755991951F5471E402F88AC6200023E4B9E4EB49AE838F2289039664EC744C544994EF66DB2B86B970D20317C8A853AE532FEB55C5B3C09239435E1024565FB50B0C91A9896B2369F9CABC190C3131BBDA5C8673BA8C748A5FC49EA8E671C424F39E0162A9E479C3C611B5F5940C297050122978FCFF573100FA891CFD64D9825319EE01086D12A81F1D10FE77C8422DEE9E518F37A74FD8D1AA0070C99647B758D7EB8648618EEBB22A2049BC18A6FD41D3D9F712448AC3322B4F9BA2330E61AAD6FB3048AED745198ACA0598A97DC5B7A8BCE9803E0A62E19A2F54BB2C3EF80472AA5E27EE039B7B4E722358A242BBE7874EABFC76FB3ACF9D7F00C7AE2BC5B841DE02A8388DC800855340CD4B0A861B4E7C04FC5F50DA66FD845BCE7CC8269D81D7FB5D4968566A7EB7C984F71B9B5CB3B1D5AB3D6669472E92CDFA16B2C6B5E67BEA9FC54ED393121BC887BF0B099BA46082DF688126891D06808D2F2905B4F1607182745975A5752D890C4023BAD18A5FF8B4A4FA529B4EBC1244D715F186440EB3EFD5B6930C58DEDCD071384A1519B73F2EEADCFAEC130FA6DD6A6F0233BD1FE25AE7CB268405457EE6507DED9202544E0B5ACCCC830180D4DDBFC65DB3E32C16FEF0C1CB73949C2FB02ADB9A22C5727F911D308B3389A520441D5B5A7CFCCBF1656E6CF5B4B1D10B638E3D84440BFC32E45A74C0D428FB9517D765166973D25EB5BE2A5385AA6335975A4C8F3E94421E7DE1DDDA6E9BE97857C70F8C339485B5A85245180A317302A2E58404A1DA5D5583A806E8A7C8CF766F29A816C25BFE9EB6DBC2567C0D1D4D971FD95B7CECE133B6CF6B98CCC6C18DDB84B4B23FEE7BBA2FA00EF32110AE0B525F39DA0B0A7DD8C7DBF2A7F8B3CC90420B5EBCDC46A2367D236BB993ECE7FB1059453D08DF84ED0E1CB17C357BCD681765F8A6126C36ED49ADA5C82273143906B8FF421EC0B4DF20E9012B896DC3EF63FEF1DD1ADC09C93FA301C906FCB38F28A36EB13B4CD4FF9A6AC5D2E146595236047005814048A31226CB80E2ED09DAD75F95D5981AAC594B8C2EEE9D02D9C7383CB7EF4108EFE0FA7BED68F3E4B0972F2FC78373D7FBDFA91BA0A1982D47A7E6FFCD7DFE17CB23EFDF20B10460676EACDA5D46EB5EE83BD48B77C4F4559C460FB78CC3D7EF8D3016DA618D1866B69A99882812BCD6F2E72C679D894C97465EEB5EDE357FC34597F2490EE3CA813237AE80C55C86AFDB734627D188819E56C884286B51C5609C027D9E410B5B7ABDF45E539FC23B71F9068DD1E51C6A1DC922CB90716862B2F60532F34ED97627B43EA6D6D6A770DDA98E53C9358767B364386B549DB2B91219F17632BB02DD407969CA28CD8412B7FC8455A9C028A63930786FE41FAA360D240005F915EDA9E68B559113AD23F66541EE22632ED38187D4BBF77C15CC9F873105A749711382E202B5B66E9DABD165F3B296CD2A712C82BCDF9C3F0B9DA1C9BC0A34D6E9EC01397008492BEF118B3771BBD5756B42817BE46166C4CD13C8BD6D9B75D73A147AAD5F4863D664CF84A84BFE465855D7F373FCCF6EA3CFCC0E28BD76E5A5EFD85EEADFB15E7AF47ECE44DA1367C90C30092271964FF524909B97D2592742832933A0B04DC59CF62387AE581A2D7E13756C1D93855B8839F7965A46D830A083036FF30E42FC5F32F9E0021F79DA5C62E16BB2BF0AAE7769270704676A9257F62B0956EA742D8A3D176188029358F90BD91373ECFEE5B46AA23373CE75627B0C45C9A4F15D07425B5C1C1E1A3882499F030775A3CC6B5E2C91F48DA0BCC98CBD74691D7513E3817798AC0AFDF0C6B349829DCA9B9742ED77B4EC779366979829555FEF4BCF7270328773C850BC9348542113EF19012168BEA1BA4C1F607FC941A1B9BAB11F89D5033FE873D302CE0AAA51BAF328F74448E70907C302690385BC3C5E32AB5DFCDD887294377CEC6E1BA90EBF9204C28DE77CA85C7E870C3C74B91DCBC88CB30D07847912100B081578CAAEDD44CF9F79736E91EF4F0D8C3555D347ECB2AD272607AFAC189D3F8AD3C7594A66F2614133658D9FEA2DF536F6A11AE1B2DA795EC55FEA5435761F7A2E8F76563AA346F00CEEEB41B0E5D43A99BBBA029988D792FCF7B9E085C1052D319B5ECFEA85E84D354B832D84E370880D0552AB9DD31822D29E6476873E22E98EBE74A14B72437F5EF7E36987E905722B781B451053DD5A5D3CCDCF5ED40BFF1AB4D43921DD019C1F41B0A9E75CF740B6646380DA9A1372C4771E29C4772F67F0EDBA8FFA3D907ABDCC881F5D76E68EB8124A45478E9B66B061CE302D1605B708224A7DDFD25709F4F28E803F0E9FB3E90739CB3BC84CC84621A19F4050C4E93CBE089A2ADC1CAD12894C1E1000B6C9495ADB0B1BDC6DEE4F21B20689FF0F70317181A475F61626E717EC7DC48555E63A23C494C5D5E5FE0F60000000000000000000000000000060C101D2330353D""") + ), + new SigGenTestCase( + TestUtils.hexDecode(""" +8411ECF640CB9A3AA61EA95BB60D5A31B099D67046A1A1953EDA3CC207F8009EB1C0CA1A40A71137B98854F470CB52EF825FC9D08CCAB2A406388DD22421DBA0A99CCACA95CE95F9E32BEA8AB715A39A8271B7789699217B8452188F4AA078C4F481339C532A2C2DE5535CC7665237D357BF547A7A051B0E1F47270231F00029A1B204049189CCB20923322024468D5C086052461120334D4A06461BA9518C148922933190A460D9B4852107929220310B31061A284AC2122894A2300A048D1A9609E444319000269886681244841397006312056118219424602142868AB86489C2218C302EE3C2611A366DC1405093304221A24409B1901C20821A8624A12800913430C816860B49614A44090AB84DD2B25100948CCB040442040911407108812909886C442082C22401CC2209E194484C263040082660422A03C08D12B90D91220220172820474981806020B27000018518C90C0A95051B224053A040233830123246C0908D990201C4426900954594A070E218112409251AC5908C2602830225D0487124B90D9C024689B08461146C62404D1B45440C886DA2080A9826895AA46980004E8A308E19032DD8C88511394549948101B225D330690B440C52862D12979048206A0C041163C808D8A60189B0691A858118882511158E0337108B200D82B229E184718304300B298A00A4610A1522091748D13006DA262560342E133461A2182A12B885502810989408C3941118A10D0A102A91162849906924348AD9C441A004010CA521E10610110968DAB28D08A801C4A24421C37122B570D394710BA700A1962194886D0A1802A2240C10900910A57020A86D6130918A04290B474020C6288490204B4648518420CAC404D186440A257010460282A6101A0166534804E1A04CC2423208C54148C07080160093B220083382584440D490648234868C04309244628120620A154198122803340520084AE4122D189349149565A4C8015B184299800502A330600486DC026C8A488184085103298188928DA2480D624065213371C0088699822CA332920402821244649A4260100131A34040C3B8291B130142801022C2200CB131142885E390858C24664834451CA231CB1408232506D0982DCA166A1A982950C26D128065C2306824174414496400B36CC9022A0C1704531225E32808C114021B18049C340D44488904302D4A242E1036325B34104B401044A8881080290AB16C1C9871C44606CCC81042268062248058B08024476189A43020C67093042C94986523496689C481A1446EA3866C5B46325236509BC28C23248622B39120228D13040E98B28519B02D1440681A230E03C92D521829003170D410441CB760C132490385305412058336021394911815204A106A6218259A883143064C839028D9B06C42482E4C286CE4C88018148D4B06514B8280DBC67001A8280A394908B86DC106451C0866C892091024521408621A27901200691249658B4852C1140E24488ED4446CE096715A347241800964884D53A4708A36890CB964244391082305098325A0000652965010054DC93671C1B0444338824C42914C16901A314101014212232A09882C9826300189440293312484281B8525A3468448141081A065043169811872910402A4364C5B348821354982209083C02123942943282043A8092437881B454D48880840122521004A93367012840D14A0055A188A43168601828C11352C04312A00046409054D1816300A0849A2B67124128410B545DA228DDA380E44B44C61002452A46CD406122484604B148480428EE14400DCB288C200915C141011334151980158084ED1887058B02904810544C84449B6881005310C132DD2145114008959282D63404204042A84160D9C1245481091A4482D9A1032E1883101302E14120409B25109B084E486600B4429D4A88003932CD822001CA721DC8680921849D80242021844204601CB2090C43428C314500B18090B9061424426CB288DCCB845839431C010304124319C304ED4C82CE3440E24427201230D23C80524216C8CA48D528669C2060808140A0098201B13684218655C381004C31121B5715B242EA216698B1040530490030441A4164DCB483049286860200DC84412030324CA060D242202DC3082132511119411DA36905224468C286421C3505324859A462A13C72C403272DC9260508240D20624E833A3104705DC227A3AD315484B9EC824A82F500712D61D5693BEB0E024505429B4D136758D53F67E6A5C66C247B3D03D763B77C17CA1632E2B0FEA3CBAD528695E70753FB16A0727C6031DA837CE9D9F7AE12A7F091E8E246CFAE2955424255667155384E6BE2A03689BFCA5E1C58C7F16187AFADB4CE28E2F9432F2419173A4CCB0154D7F3443A15DA2687E608C02D6392EE3942159C2996700070C00A194D27BCB61945E04A94E95F60709E59DD49CE955044CADEDA9EE37FC28ED3F3EF89FB5F03B77C6EFE685706B85A1ED1E810195507A55023A2D1CF2A0A9E78801DE90E1C7B80133B0A7AA8E17C022B574B3D9503EC2E152A4C04564C9CD4F84B8B8342359EDC28A7578F5AA73F5A480DAF80F9831E3A1C102BFE8DCCDC4621AE89409FCF986B53DF21425C9CE4C9744B65F706AD99B975E9907F2C8B5228E072241CC1C25111F5455FDCDE4D72A28402C2DBE6D730F588387E7265DF3E8B3B6C78E0AC3A5A2839F1E2E021843BD0BFF9C71C47A0BB0DE3AEB0E99845821B10949EA2C72447C64BFAA143220156FB54C9A62F6EAD3D534CA9568457277AB8EBA9E8EE5F3F42849C8E661AF178461663FFBE17F78D41C830F3342EF799F97C6B0E848A96C4606F4B404C382F5CE9B36E3CE90361C4E8A7665736E0C5ABD625BC4E1D1F3FAF90A366E3D3D9606C8FDBFDEE49DF2CED8FA268E6CA4CE20E3F4C962CF85E37BCA06F6385072280E5F5533711B2E676946813083FEC5D6E2CDCE4F4DA6F58A6BAA13FB159C6D8F33B6FA8ECDC0E792F72F64766027DE385C3060F38466BD93C8ED981CD3F7EF7B81FB78D76E6BBFDD565DCE1B018372102D0BB8537C1E60B1BBB564D6D98E45108D45139C71A96AC788CA14F08837E200DC1F593A19337E518C18E40C4382ABCB486677804D44B31DAE664959D908C4611ECD2F657D46B72F009AFE3501AD50BC49AB94EA2CB36A07FBFE8E87D5337841BA123FD8AA72CC9A4AFF0235F4EC2B08796DB4878A9F3939834C324E4E0D37A9C5C59153811F21AB57B260E9E57441298EE7032C819DCC475236ADC4EBFC1C5B26778B7156C3D37667C8EBEA75477F3FAC495FFFE7651627C6C87EC7CDCB60A3692EF2AC72A8820225DA85A5161B4C7274DB3698F5F1A92E197F99689B8FF5970DAD8776550038EF55825E4E0C00CC148DAEFDE552BE9BE94C351069153A3148B30C1FD9E9FB6E962A9A8824A1FFF238395B61C422CF56013BEF428638F961BCA565E5F4BBED2831769EABDC0BB3F5729BA331CAF666DBCB7AA15463A4D0CBCB26132F598789C96314F5B51F34B9A0F48DE75DDA95E2D294589EF30D43E7C44CFA63865123DD3ED045038A8ED261007374D096A46758138B7E112A58482BC3F7B14A83B7CE7B5C219B8A16ABA3514E779DAD6BF06A3B530E6C2A2E5C81D1C6152A63AE3D1159F4BEEAF8D57F6670CB15091CA10200D7A76364D1A48582DF316B7C65FD0816096FE238360B291772F8EDDC6380465261108B53F3C7EEE33C5950C76A87ECC41E86432AC231966DAB8A0C1FF9FE593F98FE34625901CFDF163E113730232E98F00FBBFC068028CAA132F071A828BCFE78F52713DF0F7EF903D5EE10F272CA06EF94BB1AACEEE6A9B89D459B48A5D580B085E844AE3DD20B866796492B526FAC2028DECC362A7FF42CDF73A827E2EBC3712A15DDAE09EB26E57CE61211A7E108B8C588EDAAAA165C2AD916EE80162024A29B6546AC6CA73FA09EC898E93FC399ABFF13DE4E4DD22227105E207DB1C50855079FD96383B3BD50C32C3D1E37B8BDE972683453C3F9632749A84A93CB34CC130070E51FC0D00CF504D9FEB9A8F068D4A1D7AC648C8AE47DC54824A69506189861E6838A0B08E13A13FDEC95F9148F2610084E4BD56BAA4E30B39862F86CA9600B9A3A945A7499F391879390419782D2934D45636013AF6B23A7E072B393E6F4E62140146AB55C9766B872050E085C152C79DFFE2240CAAE43FECE88B4C44791ABAC91635CD3BF47981B65215F36AFC2ED63F6A9F56AF736C2A0651A6C9208C3720C8D5F48A0B42C7ADC7F6161DEE6EB2AF5270612932F7ED33E2EDDDC61C4F3B291D42FD90D2F28B64D26863B07E5A2C445167C7EA3CA8E9D07FF0D44795903416110051D4DD9C481124A99ED2DBEA7F59C714AF50A15F6FE518277A3C9B17D71B4265BFD2ABE06FEE2E27109BE2E53D1D5C9D287B383FE32500148C5158CBC6932F6684B07FA33E122D1406A1E313C0F5A9901E82CE5224E31CCD04D31058B4BF53D2E15322C0C8EC177C6D15A250FBD3474EB9D255F548253505C979E65E671A6B7D1A60876254314F1329BFAA0E5E8BC8882F6BAA9D5442C38E0A5C15C2A61F92D2063385827CF052553A352922F9CB6C035D1CC5E15E2625FAAA6FFA2E4954F31CA10B18A3ACE08C122F826CB33F9D6995C12CEA96766CAFAE5F32A381958EDED4904C12EF43D66BFC7B08CE8FD61D42FA3F6F91ED1453AFFF2819559A385B932C484530D33BCB406BB87BAC9EB3F338D77B506CE59C6CD59CEA376ADE92B9D2587D8987FAEA9F0C707900BD649C5B81E0D46C17D467928A2CB9C53AAF0C55CF27FA09673BC6A6A031402126A163C4EDA10AFA09477F8ABECC81A49334B14CCFDE2FE4759EE15FF7D7D0D60111269ACA4ED68FAB56DE7B6F10CFE2C7A0E6DC968C8F90444D535AA34C1DCEA03C84F1DDC7C392868EB07289C4DE14CD53D5C7A1B768B312F6E238E2FA6B93BBF14FF286DA3DCF9CF95583917AADC02DDAE785299907BBCB06D559A04FE1DBCC75FEDAB0E42231F6225C9C5761E4F7603F87DDCA8AF1CA9424D36324659E2D249D7A83FC187B41434CB7FDB08F7AAD100DD2D29E66CF8188EFD1B3ACDE47B281BE8974C255FDA49CBD06E55596CF3E387430FC67F8FCC4B82101CFC11184B3E16E62F18A4355AC5C6F84BEFF3AFC12075B3BA48ADDA38CD6FBC04346EEA24AC60F2B527AE8F3B61EC32EDF64D273322326C2BDFD441BA40ED87852A0E8FD197A7E7E05117AAA639692C35CA5AC4DF9B590DABB9806122B31047AA33B30BA68CB405E539CF9927B6F942465DADB9F4F70218FA95565E2290FFCE4D77D122C1148E0AFACF3C1CF89AAF85DB4F06C48566166AAD370EFA52A95FDB52BF5E55FCF577D43B0C2C5DFCEBEE16BD4A0A426E84AB1FB018B6D701EF4981DE257E2D1096E206435DB0E52DDEC81CA2F8E16DEF12D411329A1B0CC3C3E5474F452D20C2EBE9B219DA00CA07B8FE5A14E56E8DA3EFEB1539EA9F2ED9C7474DB12B93C744322746AE42D777F22E1435D5B9C867F29C2BE6316A0941BAA39BCCAB41C9A7B5FB4C918F6BFA1FA76FF242A2514AB5E4A7B8D65CF15BD4336D151BB374D7906DBD3A187D02C4BDC33BF26448085F7D66ACED1BD6E8E67F4B3DA551CC68A4C493AE35AF18F7DB09133EC0692AB08D6DF34F1FBE23491467B5457BD831BE4F76830774BCA5131CD539F47FBC5E6F041B01EFB6A7E586A02742D50AFE17986A3AD7B20524F9C1D2825BEECC5A2AA757A299C46F852D46834EC67AA048832BB46D76C7D752150854B8689A5D0A501D419E5269E34C13464F37FEF2613BA45EAEF5083F7F699213121456E5AAD50722E8965B78843280DBD07CE3267912BA2FC59AED7540CB9C6B464B1F983892C34C1E2149ED712F8A56B2C6AEF7996D45A4AA3A6EA833D5DC471BF3E9A47E83572EBDAFA3D3DA7D930A05501F0C9B6EEE0FBC9CDF86190C52851AC7961C36688F8BC11A39251ED1E2F1528F98FA360CAFF6C1F2DEEBD712DC1EE31A4B5BC819AE169338E4DE7BAA00224CE4F460E25D2586BE63AF29705D98705840930E64EA0A9D7FFFFABA09869D78A0E3866A137A412AF4FD5A5E671B735FF456C79E24BEE529DC0706C065E0C6D8BE32535DBA578F36630E6C3EBC3C69B6FAB135A530B4281D40CEFF4FAFA364CA274CCFFE3F8D16DCC2AA7835C7F7E7A376E16ADFB940A2725B64EC782FC5F0C36E5F990807DB90E6D1C6869D6406A07CFC0B84A2A3C1A4E1585D854BDC2B506EC8427940299A9B19B2FE3116FD4A0BDEDE83EF42741262E7A9CF4393C2DD8A7E60297CB76157C861ADE284D44E73447186AC00B064B5E02568716565648CA88623E16EBB81C00D4377FDDE04259AD5CDB9C8FF75C4C8AC2D4F96485FBD353130548637235D100A646FADD5341927CCD114CD6095E97C622F02AADF7FB634879DD0614EF0ED2BECDB5A15F2B05100D97BFB128407FD8D54A6FB35DAF2B206DCB2634C2B14B33A96F7DEBC9925052B075340F48A096BCEB99E4A0DD1F9A35E8CC14EC724AC3ED3EB512E1CCFBDE1D755B1B3A3F63A66573946052022A89838A61DDC0D4E2A34F3C2067BC51AC14DB95DA6EB7C31505C7872620DB5C1B623A92C91B895A65EAE4938D3F823DF37FEF1964A71DFA1F6EE034F7C07772835CBB43465AFB6EF5BCAC326FADF26F762DEBE12432EDC8E53390EA89334E9BE32E535C5077D6E77684A1F51B1BE2F28BA4DFC42FDD63E88296262CF0C66220DB4A88169CA24B4F8F1135A50F9696C0ACBF3C2D3B345010E43230DD4F3044B2C39B91A242505EE5B2F690972FEA4526A3F473839763021A620830384645B9BBA9947BA6BAB37A1727DD94BA14AA9EF039023BBB46DE81337011DCC78B8BA6F9BF3F92EDBDF55B0F9C7B0942E397EEE1EC85719C4"""), + TestUtils.hexDecode(""" +506462786389055DE2E4AA2A7C80388315711A7B5DCC73F2039DB99380D48D9A3DD8CC8B929B0AB224DAE74EA90808C302197EE9D847261DEFF4136D3B2A37CA32533384443B9D935AF2C384EA63E7160BF4BEB89EC0EE705D10C72F2F65A4E75ED2B1901F14B8C1D21DA9C6B8842DB62443D3DF12969CE4E45298FCFD6FB103B87B0817190C5ADED4D04E3BA4D2C3F60CC49FE0695D6366EACB9C79F28C9121584D997B7A3A7AC3243C3C75FC86AF81CC8B888E90095051F7825294CF7E1A11464BC153548F8195522FEAB9AF5AE93C5F6CF80D9ED76C19A0ED0BFBCFCDF30FF6EBD0E5C20EEEC4992765FD23F13F027E2261C38D11FD1631846142541ABCB82C0EABEE5D675EC130861F9BEE9D9E02305F168C85201DA1DA2E4D21CF1E4BB8C2539BC1F3706194AEE7E3ABB2D7447EA531619FD27F0CC7D09E5FBFFB0DA81432D173321C433391FEE90B92E8EE3F39ED492E78327D8A3586B7052602607EBA79CC9AF21132C7D3A9931D5DB4937FD5C5611F79C722E0CDC48564E416DD251C46C02567C4059A0DC2F59A124A4EBAEB9B1B04277CC47A9F345FF8AC3F8AC844A668AC6F7E1BF1C9889C3E42C1142CBC31A46EDE21CC84F230A483B5CE23A901375B27770BEC8F0AFA25F301B7AB43B714C6D0E98B009FCDDFB75C0E26EBEF7C9DF5ED04CB4183028DFADFC09963AA8CB3A9A1BDA047F62460F2B88FEE1C05D9E68D646137F660B68470308225FFC097474B2B2BC5D50A025724FB2CF70873BE7D04C05AFBF1D7DED56693AA4A4E495B1FAF9762DB83DDA6E75F530ED5351D171B7BD06E5ADF46DEAD06AEA37CF262AA33D062141F8E394E731B3942D084E583090F9CADF87C2B81C4B7F114D150C221A12393BAB92727B828C9EB86600B969E1B80F33E1304CEC68A1B3B474762175EA19A4D67220004FD4EB0B2C643B69C00FF3876E9AF63BBEF8AB6BBBE247668DA8F2E3CFD0B95D6926AA3A2CFF4587C45DA60BDB03DA78DDD9758FCF9926FA1F080A61FC0FC7660BDE9B4913C40534887B04E2DC666E981AEEE38746C52BF46FCE0E2233CE02C9307262499BE567C150CC54FB9D96B81D3A3E200EC8F7E87E28272E7B956600DD7692799473A8C63AEDBC8F3F43542B9E399398349B896BBA16E5F26210558DDFFB984FC924E1B0D272CB8834B1FF641A894EC113460C65C66BAE86248B48F675F1313EA76EB4DD0AB6EE41014FD7589D1A7DAB16CB8F113A3FBE7E01EC67B0B3CCD81C0A8C7E9824658C926736A574E9A0729C3BFCC34E0D4BCB1606E93287494577A6C4B1090FA6B997DA098C6CF555B5574473B1063B739CCD139C2541CC3F962EC42BFB3A40F4E64D322836EADA5F574B48B5722D7809A3A20EF1FDF5F3EBC000E466BC4CA10E0CC6A1390FDF159BCF0182293D9C408A8570789C485DBB977642074C869960E9648641C2A80D8A1C4E474FB98D7A3DD75D7AF01D2605945E89493699EB53E30EBB0F936B63ADF5859D9EA1DCAC44D0BCDBF2A069982BE907F1B560AD8327BAE013FBFE6E2709C9FDD498491F1D8603F9F6C9B1A643F6FAB97DCA752D9BDA1DD6BDBF52B03ED7768D98E46092D556C266E30C77A10E68AF76AC3D359D8752E2453B2E75DFECE6F66E6AB00EF37DA6E6A367FC808E1F4905339F4FA73545D13DA7E7DE49CC0A2A63639A96EA039C4EB643627B7EC4FACA1374EA800A505A80F554B3AB3233FA492ED6C17B5832BDEFB3A99FF1C64B35F1531A023415290124EEE2C9A7E34FE8563528B6A4B64DE425A8FFA91B753973CF0C96FB2A8A3F71D58B77C93C5866DF5CB5152B3A0A32884E349C63870E9CACA82F121EC2ACAD7B6052B0D74E9C28B20C76A7A821D192E11B59A7C8059FC49662C655551A7356046D46FCCCEB4DE1F5FC91F35B950F630D743C8218A10AB25D2FAC25308225540FC24CA794EF171DAD7258C2B7FCF43297F6E77A6E83184114DBDBE408EB644ECF49E04FD79769E4FE9B0530F21F8E3913A51094D0E49DF012144EFEC415B8B2A34AE2462607E7B89BB86F0C733A5553CAAFF9B19E0799A1901657BF4FF5AD6DA7886B477358E90D56BEAC6A963E0669C38EF47173503B0E9255AF1F153E673813053A899418E2BF217D01D9162C073F256CEDB73DC062D201FF6056180A8A6887B286AD6D3BD6B1462231D6223D0DF2BBB7299FA6FEFAA9A297C56ACA28E163533406141EB2E65F0C94A6286A0579C76A3A8EF96DDDAC9DC6A550538AD345FC4AABEBAC04682D4AB0977D439CB14F02FB504E10252C1F3ED01A7C4BFDA6E689D842D9B9086517A84AA4257D1C8CB842E15DFA615D2E3F2464E4012C0067EEE60489C044F43050E5B1AB3E54507422E1368CB3EC8CFB03A887DDF9695AD95378F875F14F7DEECFA54A775C60C6B7025E5D6C0563E0E76C05C93E33C3E5AB6D1E1C051B52D2805D3BE0A4D3E8F0DCE6BBA1DF04C7F76F7E13D8C3CFCB2AB04A1E605D4DAD72A43D5223FCC36EFB34D999095E742FB9DD7B69A28E070FD28138B403DF1DCA75E00A160ECE9562C92091DFD3A24C53645DED8E17B39D8CCA4C20C96F9C9F9D14AD3B45A1E87DA75B831D400AC14BF34A9840936C3277A135BC0E8C65E0F5E670AC912FA586FBB4E149B09F64D338C8C886BA65730039B5DCD0DCAD9D6EF11C228213438A1489F4FDC39395E8447212599BEB570D186883E02B442F8BF97884EF98D3D6E59254B3DDB77DEB8429D110F0689715F3E0A4F65908E5EEC867AC7BBF27CFB965727AF0A1EF37B21EC18CD60A1C87287527BCBF5249596083069315699CAD10FFEB2D87810C4DA090074FB26978E56B7D06186C48BFA4830A0BFCEF8FC7B95E73F64EFF78043E8D93F57EF6DC636C8FF612ED22FB21174EDAA59BCF89D1A60F0E1C15C5F8EB8E6A39139D500E8F28A5DB86C125C6C76A99BC47DAF66E679121557D85F5093806B748B3EA65CAC386B59C0A372AF2FB7C84111F0E0FA2C71E137958239534C4A012B1B421435B7BB8CA577DCD8C8B0A798902BAC9B95AB87B6A0735D1839DEE336996C2357C748F4EDAD858C81E2115595ADBC173782E36D4E720A5D29A5681231F9BEE91D455554A8632F7F02FAFAC0FD9D03804B10DDF4828A69AC1CF0581D2C88877BA30EF2982E0827147766F8B71E264E82C3949BB87562F810DE835CCF78A7E5FAB219E64B1FC615E7C952577B9B482F78C0D0C512833994895A125F43EFF066CEE293004E9E0E5288A61EF209EC52233EC64BC0DE76C78EB2678559724FBC05BB5B43CDBE86F6C481AF3BDA11EBFC0FB384AE00F4ABC212B0518644638F01C38030DD05FB06A7EDC6406CA18878DF38ACE8E974123D3699613ED46673BD04ED51C352F124A8F89DF8C13D2B44245084B7FA02677D5287D22102AEF4A4A0AE046BB1C6D9FC9733AE5066C69A10589B0F33780622C1709F179D4E8857564804BF5C4D83E03484FDBD1CC4D71C6A2421AA59043DA85F0B51EF91FA5DF9555072278331BF3102F5147021662D135F3011FA48DDA7C97087F01B7F86D549F41E244AD7374C7C1F698801CEAD305026D17666435217799A4A5FD0ADDF9B8BF6E31E51B654E4D697554D5F574213CF579EFB1B11CB2C136FDB9EBC0DE4D16DC9DF43E17D88EE22EC88326F65875439066CB47E4C656A3AC59BD9A576D05ECAC5B3E7AB7B1A3C0C1C48807C06F1AE4881158D6BAE9620B08BBFFCB9940B6A6D04396014CFD54E93D863156D16F6F9C1556DB1E13E630326C8B681CAAD146F32B6977200B204B632F6CBCFB2BCE9670D89A9CE043E2004773913188608455FA715D1577E03826A2471EF0143DB3C39E03D890F0CBC85040D1675821D282822F80EAAEFF5CAA49699B68B89422D1BEDBC3041AE2A3D6D5205C72123991B21AFFB312F5EC8F96922EBB44D7A0F8ACC2E390F9E3FD82353276D73E85FEC904AE6319B140E5C54FD5B6F19D17E65DAC5EE270DB3E402534B0F408BB3C554D93BBD32B255D478F33BEDF4A192233294B320393D38284D7D9987708C019742F2FC023C041219FBFE2B603501629BDABB9C4223F5B751DB78C144CC50D3A35370EE563D6DDECFD6D715F08E14A00FC265D8433055083048396F1BD4E9F010EFB974D6102401B2FECD972C26008A4B94952EBC61C35DC846FF7B3E20DD9C6E033BF1185F35A5F02139068E1D4F30C4778FF87057F34CE1D2D40BB61423EC055BB57B56C502DB8D0685B0ADA42F9C52B590610CE2F8237F92B71B3AC2AB75D2E6ABBDBAA1E554D99CDB687B72DE98ED0FCD618AF5D2B0196F1D3C19DB77686F01228C3D1DAB1F171A56DF9311939CCED0F7B22A1B77F473E8DB65C0FD6E307B6F7A0F0FAD69E5C1F87D01EA4699F4D5DE39880CF2D8E910313AA6026C17941C41252C06687A085903A502048726AE8EDDD2D8918B71A19B807889B6C2E866FB818810F427D2A7B6CB137D94746A88BBF068EAD31216A5511A54D81031D36C8139776E0FE29EF7C8A5EAA730C3BBF05988BB892F699F72F098F2931F9B4DA17243404F64C311767A98547284063D44AE74735DD246B0C189DB322058198F1D176EAE6E076965CDE68DD0DF2B284D23B94BADAFB8650F21B148B9C990F7044A777F9BD229F7905B242CC2E267610A42A5C3185C64079DB340D86598C589F9A96F3741356BF3E6D2A811B6551850F917E07E5289A07382B8B506C510C9396DDA81DB336179EAC1F84DB9D0E7BF52B906E82FD132647A84A299BA202DEB338B79F976A8D257E246B2B1B60425161C72D534B04355B2665129AD8A44C09D73AF51DEE7043228EDB62B858399B5A4312DDD7ABDA09A846A60FDA8D0C00E0ECC364A6CA95643FAED93D44BC8BF1264FAFA6D98528CD3BD1BFA352BFE1FBCC202F44496FDAF9F9EC53007915EB67F9F8BFBC88D82100210CD471C48F5092AF4253302475F9E60C287F0A8549DA00538432A342814E1F6043BA4355D72268F6E84A43264EEC3CAC024DD6E79143EB502A58E6F8478AE985797F00A295E84A0F669BD9252A3AAC6B2AFACD7AD398DF546"""), + TestUtils.hexDecode(""" +C1023740D113A2AA12CAC8BC94DFF2FDD05E5A70F45818FE3113DA3D727C8F99F9268FB99F75F98D3F9487A4084175064A4C06548D37E8FB76ECAE0B8613BB804C9C04ABC54570FDDFA0C938A339F5134C5C37D7FAA2037118ABB9D1FBC522A334AFE43E529EF3DA76AEE24B27EDCF98430CBEDB46EFF55E9F53FA479F60C95ED0FCDC31666CF15AF8EB6D4B870BF0FBED290860ABF033C9743CC8544B02C8F85BEEA3817909B39D3D68049E6383EFF3677D2B94830073AAA44EF9B056FC1C316A2B9B94D347EC2A551F65F540068D6F787786BFE45EE254663D6B99DC1A8E32620451A839C9C7B6D637B993F2906287EC8A0F270EB23E99263510BBD7364561D56FA3E73D87F0C5632983B63C9915CA85A6C38970CD6EE1041E7307A797094EDEC1F84D947EE2E4542B3865237C60AC5125F7515C805730F07D2562D76EEB5DEED5E3AA000E38D00A64E754163A42CD2508E496E02F7FB7C1078AEB7D673680EF47EC7D8F1130E4D61F631D6B6D43244345322F3766F1E246DA51438C265F66BFAD6C20A4FA0A462395BF7408B14A0791C21BA5C307FD38414B2B8DE07D4B134342A9C12CF170D3DDBA18BE378D52963514ADE5F9EBE135D86F0AEEEDCCED7729E2AA25456CA85ACBD18BCB8B79E97DB56AD29D94BC295F1F89EB9D8E71FA14B1BCAA46B8035C4AA25D14DE7C35BB5A02CABEA4EDF9F090873906906F68A13396CD2124410EECADCF085D5925BF6308DDAC2242CE240893CA7054C4B4C19332F4ACA897BE8F998D83E82944DAB9D65125085176CF5CDBF60EEF8954428EA0ACCC6A7FBBBAA9DB34AE72B93BF5D3A709CE3CA346644D5FAFAF3FDBF9D9D7C504E86371E0DEC5B3E2EE120E064CBF4FCD455E99207549D27E233D06FCAE3699BD34D5D7F195509601154044EB3EAA0527DAB3F9BEDBB316023AD53FEB71249F0BCD3A08F0CDB9878403C1812D36883DC444089999FAF16A40B75679E2F053E6EA2B835DB463C1202050FAE236134BCC8703397E1CC344CA7901295D3AF28B39853758D086561AB9A6A9904BAEB37C2AF4D973B702850BF0FCB08CDC48D582238A0FA0AAADF832AE76420439BF29A9B32FDE6D67D3D6B25EEB521218B013AD3408AF36C466F67FC5722D4EB2E57D0E58D045D46592BB1FE907D56E0B378FF59DF68B2819D21BFC686364DFE074764DB8613DF0BD35A919048A2CFAFDED34CD3331124E8C5F8811D730803845C7CE568E66F9E50A1EE2DF92450321BA09AD2C4D75D1D92CACA21A2737672559B1B1894130472F40C177F1CEB1C348EE8AAD47B5D1ABFE148877C39A0A46B8F9E4D3FBEF95B774AB5D768FE130711A9DD9EA2B8F4DB4E7F938352772ECB46E9A00A9479C409A4F9E4526DC307BAF5C3A0493EC9E1816D11CE212E0054501D2CD9865F6E942856D32B971E83C81D94DA4F584B230491D2013E84C898386F55C8F224BB09FFE58CBD0D9E9D7E21BDC2AC4335E2FF94EC95CE2D509CFA5EE33BA848D75D046D8F576237417701A7B11B3E67BB9740B7BA3D7A37784E6CE081D3F41E8AF21CB46D46B083796A08721B7E80F0A157E86BE0F08D3125A12F4733F8C27236AA898E6E950BE190A931D07A08597633F5187767D3CFC095D1886769E1CBDF6C20FFE471E9396476660DCD21877D799A124A2F0251128F08F9D45AD45F0DF38FC9A42CBF4EC4BE10ED87FD86B63DFFC5246239517690696EE839A501EE221C16A153C0800E7D6B4385F6ACFBCDA62981CD22F06A12497B97D13C6EC1F39879B2432BFE6FC7CB3CFA78DEC8B3B800916CE777BE327641DEA9E7F156EF6E943161F78466C0300A29B1B5EE8CB68F532176DF4FCCF606738A95B3224573D5DC26F90DA69146BC8FA37D1917E3CF3336FE8D444B606979D9650B2649B1F016F6B9543E31C6E9F48594F538CBECE25C4EB8F78955BDC88EB9540BF7AA4AAF1E51DA958EA818A8DC9008FFAD91529B4D8AD5576EE1CB21216136A0C85BA87C01B8A0E8B9B31F7826537A0F920F335CE24053500CCC4EFDFE3742B9403ED950D61BB27FABD1E397BCD6CDF885DA0E3559B21197BE6FC71B25DAE1C4B51DB765C154E4F313A6EA4BD79144CDDEAA94AAA9AD40D0167C5779F022116E56154F74F42D67540D8D0988A5869FB30ED2EAEBC4B0D80E1A547551BFA5D77A695094162557B76D52472A1601884331C9A0EBE0405FA61E5F5B38278EE11A315B20633F534115C02114B24D07A343003E2730BC17BE1F4432B617D0BC160BC2249E7B87A4A4C0B8DA3C6F082C8D515DA2E90FEB30852FB35D2A19A0A39C4C44561703C97C0B660A05FDC553DBFB21271011BBA5D4ABD2C8B757BF022C6225D401A56A33C901961DC765626B1607443368D2BC37886EA65B35A9378923B9F6D2962B1DA2A4DB3250928E2DE09DDB7C2B6D27EFA33A21FBD7C3C38B6B193A1AEFCEEF9AF68FAB8F87D20E1FA1DE0AF8E40BD00AB5C88573F2FB1FAE76028EF40793EFB36D92091A353F6B044603711514C4E5288BDA0DFE9BB6E10BE6FF42705FAC7C05DF1E49C7C93B464C4F3571821378B3AB9BF020999B2421F6BDD98DCAE5F976EF507B9E0A02E1F7C7BCCEE1849403F2FA5851D8000AB7933AD568313771A436CDF40909360A33D83D42ED1D2D5DD1D1BF4AF704646DF4178D83B3031D9DEF090CC6271DF522FC4013E049D031DD504856D217E9E79F5359421EC1D3F77138F3E2CA07FC83FCF72066AD407C27A80D48A484285ADCB8114BB6D98CE6863428D3D378E5C1132E0139CF6DD841230AC0D5F0240C589FA66D6EF1380C9C2F5D9482C0E387DFDCF966EC364FC614CE707EDF8E16C783E22F8FF29A31791861F70B3DD487B4C72D5658D436FA5B3426CE337214E705489798753666B47CF8591B608A28871239BECF722BD726C0029DD7B8C72BB2F7D60CA8D2A8091749686B62BD642F55AEC9777AFA52BE3ABEE6FE5ED2258D6FA3A9A1B55B7A263287A8A52EFDAA0A817F410FE325B16A1BE3B70CCBC50EEC72A70C27CFEA321005FD982EC093D87286FE7A46822D640893334BFA932BB62AD41B4BC88D87EF1890C24907BCA4136C5BCCE546B5470038E5D70D177E7F33B0571FAEB48165F94AFF353CFD315C303CDE5098093BA39052FB1ADF904F1C117503C58A7A991F9FA1422190E0A4952374D624C7D9ADCEB0F124111000047CB5662EB71B6325528C72C1D82F0459A2BED71982CCF84DE2434A4A7DEF2C1210308DC1FAE705360DE9BBE42E9F9204044C99EFE50361BB84DB15657E3B85C7E7E4D298A34933FFB5754CE06B2CA1F6F7599790962B0E77641567AD3DFF95DAD0315DC6CBB3D29EBC8F3B68089140BA87063B21E45C3B1AD5DC6972A7A65C711301C05AB5E48F31F031EE939740EAB8CB8DE627445EC5219116D3A43FDDDD91A967A400F149399B9A82FC54C0D629A349C84085A3D30EFE9AC4381B7C8B24501BCE8F827F27CD507BE20018DFDC9343DC5282F61D74E4B4CBFEDFBE33A3CC67A210BE8E012C8277FB202608E96C355BFFD3B4FBBCECB65B7D4A61C1B9463A7F6F732B5F73A51B01596CC650EBAEC8DD40C7C3ECA3F95AC010DD275D6CB419BE78CC107B6D0DC2C060F57A8D7E4BCD53289CC57F5FE0B0831F93024148D60CB87201335F4DDEC3EAA0D749C04D08C345C0ED169DD4AF598169990CC2C8CA3986660712D615C084331030FEAA5078C0C28D3432E9B1DC5B4F48F508417D588A5CAB2DEF9DB601E0FB6975FA0E9D681C84AED7B5364E192F4847D1090924E6463E527B1185DEBFC376E0EF221D55D0DD556C6468E56D09609484391981DFAA3558CA8B35806E4CBF48489EBE0D23A9A035C52BCB4839DA20BCC6939463E4B03FBB7382E435B97C7A53A48183AAE0A8095D9E04D750535292E6F5293B5E75E6065510537DA2E919E2172D232586865070551EC02ACE7DB95E75D3B321CBC233D5D48B5EEED7E93D9FCFAA378DA92B704F9FF3C992DE34713BAFCC3C38D672194D314A3CCE47DF297C739CF7DB273EFA474D436CFE109BE692E1EA8786F703D81ED2928CA69F38F45D819B08FB8BF9213DDCB2AA24B9E50CE9421ADFF3FDA75A95E3948803FEA3AF80E59C7AECC594B2E11F35A37B9B9C684B5977E5A4A0F9DB7C89772DC17B2D2902DC6B409937934CAF22C27FC38EA4E35F2AA64D6193AB2B340B63201C82F91C20E4BB631D684321C0EED29925FFE916CCE3F403C6364F827497350274F12B405D8BDD2E9FA56F088117B1F682D98AF2A8BFAE4F4B3B1A0626632F55E747A40B1CDD8DF9665834BAA353413DF698C5AFA6AD56EB8AFA9EA22E6B042F6016F803201E974E8E1A19FB5DC9B6210C192196C97B2B4FC0FB24441A6CFF898691E948D0082DD19F72BE037BD4F48D553280708F41A7DF37C6C6130C9C02D540DB3F6CF1AF3E1878E57F267D08F4E761B5DDD7D0276726FA942328A4393A2AA9FC25F6F4B531CD5C32E92D1436DF8E1491283318445D4F0BC81830B3A1B016E02A885751C65044610D24771A9E5F72BB3B62AF913B923DD1FF09DDC7E5077F6B91B19B9E7D552372E81C05B34799814E839C4C62FD8F7A010073DFE851F273E1AD4516B4D8F8389951E47B10BE213B553C76F6BAD8F19EC88A8D6D098F7CACA69DE23B9BA40AE8862981F3DE150207A55FC474ED195A596D96C64FB3A6CE439A89F350FA24B93EC74D4AB8793AA28C3C7701B0E6A301B00C4B384B49CE713F439F853CF204CE46A330695D640F1243165AE0721E2499483E879636CD5C6126EFAF822A21A4BD77FC6B067345715D879F29B41D53B3CCE27C21B68B2A46D14D99B34AF1A6317439E52C8BC1F3A6A83B108381BB2EB80991A1EA80687D61ABAEC2895BFD9DCFBD45E3B34FCBD031446AEBDEA38179533EA7E3D15C579D3B485EDD7778105717DCB70A727A572A978DEA742C0BD05836497AD40A39BD5AA945C942512654884015B32B920EFCCE1EB74BE65B50FFB9FEE543C953A8D586B718746C4214F0544E66D60E6E78F8C3EF6FA35344E5147CF861AD2A928C451D00B35FB6FAC2CB3910F214FAEEFE59CFC099B8E020CEC68ED87957512BAB2CECFA9AE8D5244A6637CE8B2ECC60417D674C10665DE5DC64392E3E0E525CE8CE3877E9C0C9A34B2768AD41206C3E172671E9D89556013CC22BC06B74BE25C6856E89EED22D7D9BF8E3F6AD3B43D9BF966EC521BC6424A9F45E5D459B5D6370CE73312EB766BC89B2C283FB59FAD9F857FDD67F599D71E78827834AFE8CF5A002659CE0B4CC03609321C8398B651C6D1EEA2224A0E54B819C9C867116D5C7E00C588C38AFECBBF35CBF5894130F9FEA689D6389CE65D77B16DB62AE9B8E2E68AC9299AA3AF4DD65FB70F2DC3F01B1EDE3D75D61FF92F8FC3E0FCB6C2F3D06A401AA67C445CB80F045B9A7B79DE15BB997A5ADE3BCFFD8F70738E61415A252E91FEAD291303EDA176D9B9004A6107F8C0C4CC29AD478099BBDE92A5C95B35559065AFFE7B5A2D65E7A85E95FD79302B229EA40A516CA45D320DF15E7F835B0A1F05813A5706B6B73E50121758259DAA790DC21EBFC25C45934717792B46215088AC8CF99857FDB20D985C3DC1BF052F4183D895A55237C34B2F0893F091BBED221B68902A469CD505E6F3EC768823135666DBFAC1CCAD86C149D68BF8D86CF9EFD6007EBEEF7973F6DE09C298637C7FA4ADF1A2159B07425B1636DC4CCA613278CAAAC7B6071C8ADC69DE93DDEC276443C8B284B7A0BB8B38B648171A9066CB6A7F868B6204AEEFB10C26D3774DC290C39CF87E7E9B9FC164E4D52CF5E3F48381C0E9E606FD0B2EBEFF0888F94B3EDCF2414F9D922AC26C75894E61721C18B6C381CCFDB847419CDAB84F3FD033ADA263777F36E07C38EAB79C28ECD65C3623E25479E3E3CCC109F7AB3F1FC3FB2D3529D722AF9A14B3A1D553F009364EFC462B3629E077E918674DABB948CB879430010E829AB6072C25CE6FA44439173026D0487D6F89337C40CFA28D4131D4D107CD8A44D677CD5256CE7A18DB338DD8FDF2159B5F1AD1E980E76DC0FADF27A970449A5059F4BDD6BF1D16A22F11062974AD2F8B267AAC4A3F2F1607CBCD91D0B55895825016E6D721B51DAA94E49BA45C1EDA32610ACAA0E5DDCB146C72FE55964F7CF76ED809749741D6DD1894C083BFD787FAC25149C0D9F095A9383B0256A4680A81B4BC4E86997EA0051C8805456D572ECFAA60E868A58F05B6BE4DD28BA59E64143CBD7FDF75C33D545F2845DA1496DF3BDB3D76268648245C00D8B6272F1C4A986649DD66574BEC036588508519F4ED9FA08874AC1561F7A54BBE7E29DCABC1499FE71467CF0F278E792CA6942F145011BDCDB73C63541B0C9CB7B005EF6243349471EE711C2D086C3984FE00887A408015787522D0037FB7AA0774F946526DF6FC0D1925325B5E67AFDCFB113D42A1ADB854717283C9FB020306262F3C718B98BAC1CCEB0F535FA5B5C4D4FC03151D46556E7293ACD2161B336FA2AA0000000000000000000000050F151B28303A40""") + ), + new SigGenTestCase( + TestUtils.hexDecode(""" +823FFC401BBCE83F04D9EC178826A5BB4894DBCEE86C43B44F2D9F93DEDF2A58F1FF2BD5F907D42D6C18DCFE32F644C301C36F572570E985327F49254E9F4138562EAB80024CD250525C4C7FAAB88132E1BF3141E5CE354AA95574F75C48FEB3B742B08859BB4462738E5EA9ADE997A97129059FB937F7C5CD57884AE12AD95DA11289A00206CB068663C804501851D834812226451B4912C126048C281192464850900C18B54024B08823C02552904101B8280139664840882410015C9620D98001D40252E44811089601E33410C2A60108120212108A9012919038655B2431422065229468E4306A9A988C543450C8284160C28109251191064DA3440DA0B0499C182550A891A1A24D1133681B16280343504A2248CB28106498098212322423604300299B0869D8B80414890C0417721B18920A05859B14884B0071C3126184048000190C8B244D001349C13688DC046D2139068432305832905C828D94466EC93446C9282D48A00C4248119B806CA1244D100861C9B640C4127124337201260C02A241C2029113962C1CC16C60284E0C382C23190D01A22520836552B291E022800B3442DA2066043152E12846442024C1404558204A0B974119132A0BC3294C38000B21525B140A2319221A428E40124444362248A27084A048934891E1088E41020842C45063146020C12104A1455C228909108221012E42C0250B0569E1C68193B84089B605C0B6081016810199101B28204B386D04874C14C14912419000A58419900CD410110499250992005484010447015B3248244771A046214914640B024D084140D10022A0404604C4002037441825059908641C310DA2C02D23436221A76419B3455B261103C64CD1824818C420618051A024485022064AC09108338E1A92454C986C88407011403120410541089019B38C5A3284C92045132452998468C3422211B6914CA2450BA95064380862168A54040E4984100CB78923444104364A04A9110207211A202922034D888830604049C3486150984518801092960C18B22D24828562188453443088C62DD2B041C1202204312A02270D0821095390440A475088988121A04051426109C18983122CE3C49108496808172D81A6282235040220294C928818940911A9881A210AA3A44D0110890B4544523480D04085C8189011B2905A84058A92895CC051D9C42C94304EE126719242860B312DD3100821804120196EA4460D4B12101C002C92308A219961D1440AE3A00C9B206DD3B688DB4045634621D3C04084986102942D60420E242609CC424608C04C61900511308160386C438070A34209A3366D01850CD3144102C205D1C080A4202CD8A65142484D9C106E42C4091C304684C42D621260C33044C8A6640B043094448823B6711893655B30095A028E84A02D82204481066A1805301C082A20B1685C22298B46221C9204DBA285132622DB460510415180B60D249171E3202C04140A13382C9A8410A2140699B2318B207002B35002B080E20632901025513631641089982885DA4430113048E0024CD3008623916952C24D981824222185A33690D4948D9A028DD91888E0882482086DE2486502972C1C962519428519130A03A82493088613458808306C0B030EC1B828E0104AD1C680613826081588620805234588093781622028D2B610C3204283086D1116702481250C324124258411266124028A09158E4B34108A949092C40D24997084B48092B600C100641B292890003289426CE3A0299332701C910544028414097293900D1A424522434A04978512C22021156164226A00B9212439508B1492D9C625232449039201818690D208460016681A364209B3905C06268880701B166E1420281A03601B45618282908810091C258512820C83144ECA146022A080A41226884652C04849D13226C9186C9A2481124021C31881981048A1022188164D54962553222118C548E49610239509D03050221681A134284AA824D81022C114494A2681E2184E1A444401A64D2048848980410B820063A66D4B46251A96299932464C464003110852244519292A1010068808411B114824228404B30C53A08884967002342120A929183049603446D4846049829010954510B22853C01002020E00A00491286E1319258C822C19330E0C874D130610C0164A91160593C609E44072CB18709A02620A170994A291666064069F3922967BF867A52B7F48CCA1475730371BAE7D3CA391B017ACE1FE2B9E67D4F8EA687910569EF4CE84372DDC13FDB1DA2EB9E2634F9AA71E87CFFC9E28F1BFC862E08671CB976A54EA31AAE67F4EF5E7391CCF4F6614920057B8617E6B7743F7795E3D8FF767D908614D9FB5FA029AD4B9289CFB78D4A8084DB261F67F281523C1E191004FB18D7605A5E1B61B2ECB0543C153173C981B86EE4B47602D5478FA02DEF589E0B4CBE9A95ED74E25253A882E50C64C8BDD131487E02AA035B47E2B11CF723971CC44DDFEB02C6A112E2A5BC929E53D6A4C8A197C14C2995550E9CDDDEC38E9E09A5C4F8AA97DEEAF1BE0A5DF604230916128ED49ACBD9F59A4E0F4144391A8D718D3F7C0CEA8AB31B04CB0E6E5415AA6E0F2111601EE1C98E6A6B670B265EBF325208036407D3E768B7D68C0D9FA7DB1830A95BC2E41D60273CD0E0E9C8DB63BC1A3ADC3F126475596DDC43FC64C9FFD82B92E2D7BE1E095DFC89B18BD5DB3E601A1F1033888730CDABCBF13C2C7309E4B14E687236B11CAD4853D367B146DAA251CDF595858F4190C01A95292A94F43FF7BB3FB0D7E6747029BED764134CCBCA8C517DD44A0DBF59D135C9E7562A64FAED25AB711AA7578DB087BF8DD5EC7DBB7FBE54B6F7EE9E0C4D0625DDB0379D1949FCDF2F93B49D7949E81A1DA000461FC3F5DB8152E63F37D3DDD885DA6CDABFDEE4DC620159DA78CAD3C9E407BAA84226824C142A893D7A44B73172BE3D0DE12CAB4C247DEB9575EB2040A180E7C8155933396AB69E5C1F6995A3C85D1FE0FFC3F09522ECEC1CE40B033424CD27E22C8DDCC9BEB01796524CF433D9DAA4895D0EF1FDE770446EC32C2DD87D3B42CE75F4146F7528EB68ED027B9D789405C41E4B35B3557967480909696E00B6BF1AD7903D97A58422EE4A4DD9F2EE8AE163C930530CE93DCD6DBF475A245932F0C7EDA1DE3D7BDD6CBE66F93C0BC79250606AD329554F94CEFBC7C1DA08C4B1FBBCE1C4C68F36787F730262CFFBCA4CE3794178F08402890FE3948E0C9CD5DFED68C83D40AEB2C05BDAB5EEDD980F9783F6E29DB2058D3ED5E6D1952FAB5BB9DB63BDCD1BC2F02B81A7AC09FEAC6716FE18120D48DBFADE9A919AAAC8757488B2CB53CE83AC2F9A3DA3549649200F2402F574B1A636A40AAC099E8F25E22CA2949380F53D2A8AA9DBAA36088C6CCFE95B453F3CB39D147E25836B789A33031A850E16CD99C11CB8856D0ED82CA8078417D73C1C716672030257EC839D379E9095FCB0E83406DA139C9F93C0546B476899303B333609DFD11AB6788C650EE06BCA3948651C315F12EB518D843E8A718C04C53C968B2A951085E0E5A28037427C72C851467C8E737E72AC2156E4FDDF491097062126BAF36CDF7ED41C8BA4081937567618BFA869C2A21B0046269731BEE0BB1686B2966E3658651E259151A6A98B1958C5F37DD8C5CADE9504D1211A77773A78DA9E9A60070250443773B7943E0FF672C77219D5F76ADE6625802C9A7221B10A5DBF9F3BF5019983280ED3AF23BE20721564CCD7868DE7DB9A83A80AAAEDF357B215DCF9095F79F0DA5D4C3BB98740E6BE09070829C33767A52CDB97E3EEEDFE6E43199EB09881C2F3A18B43EDB5BC835AC7C3DCAA7D3E638C07E0CBF68DE1E6D14A2C3DEC77F26D890127EF9C42FBBEFD04E9C74D4B9C80A4E4B3FCDC8C8D9AB2CD4875DEA9D5AEA72BDE1E5C558B4753E480ED410FDBF2946104DCEF40525BB445EBA4FA77C4C65B0507FD0C9542919B3B367EF4F4ADC5A1DEFBD3092188758B4437B7F7B27D8D2285C24E4DACAF513391A8CB6733DAD32EE0E00710E278072DB19A2330ECA56D923DAB749A671214E812B324161DBAFBB2ADCC33C96ED14CF04A300255DF22ADFC618C405B718988E5DFA30255B75F8F0357A57761642811E3180C18D7D167E5DDA6D05B1FE2392240B62ABF2705DE27360061F10F6F98A0ED9CA604A3F1494AE66E4A8D637472EC8674BCD95B4915511BA70F5DE8A26EA034388AAC5BD8990A99FC3BCCB61612F99708A307C0BB966D198F603A777109A6416565C9AF7D06F620F48B44A9B2F32E034D2E5EF6B6CC9012BEC98CD1F89ECE7B3E5B3A1D61DEC92FBFAAAB32D668892BB315498DD208016E7AB0EB95B6FFD2059DB926E89053D78293E1F17E07D8404FDC24B4E2B4C3B3BFFAED8539FF095CF7B7BC97A4FB06B245E0D2C0823BC869F935CBF844AC346F0E3D5976D815FB6A484D7F5E72A1C1A6E8FB0F0BC209196B0F016E672D17771E04EA919EFFEBD317604A0FB5D4327D74DF07CC1AD6165733ECBB32623D0FB6A3B1EABAEE89100FE1B7F2185CE041E030A4271DF421D5FFDDC55F846F670498B59B4397BDCBEF252EFEA81BB4B3E4EFF3756E8B2A46CE51A84AE69B774374B1995DD2D9E5E656B0573D16676397BBD9955EFE959539080E11268B071F33E125BF2F6F90FD8BD166567ED9AEEAAE0D47F5CB9BB2262EA1C07943B4413E39470B97A2B5E8C92C083AFFD1BE622C1A00B436CACCD75C81ECE9262A737E3BE3558058A330C7C570F85CCDFDAAD6962503B91D16AFC1DBCA076F8023127FF0BDCBE1C343588B60653C6BD695E954EC4ECE6D034B4DF63A92F2D7FC212FA36C88E8137B3892DBA87C2396A9FCF539098F73B043C09AE38D0730356A0E90516DDF0300FEDE1FDD0B4C84E61616F9BDA41F50388BE8D5BAC92DC42759023679B05D02A536777947E3D1F24A91D935E2AE76B9AB5A865F83E2340DDF3AB0B9A56A5B08FD648B7900A48D2D65954F51D43CA39925A75E16F32DC1ADBD22301B0EC93DA01F06ECAA8EDA6F770D4DED24D512BB1764CC515D69D87966F0BDA86769149D38DDA1BDB3EDB7EED89C603235CA16890189F560A0542455E8E4A09BCB02DE7D5FB06DF64DDCDE70F0381C98466BA48A69436DA9BF3DD713EF802B214872A397CBE53D5C573890F9E9D2212FBEB99231D1DFB98241A9B10F10704C91E313115BCA7F3663F7203482CF6696E04567DB6AEA8E8D7B29492A0EBDBD4A97A7E6F0965A84B37D55E9F88777A968BEBFCD4A3C5C94A732F5C74BA11C7B4A57648909610C89D27A3A273A0D5DA2B3331E7036161807F1162B602EA5D7B83984C0EF08868571046673112D4CFA652EB927109DAF76A728DAE6437A6DE15027514983FC1C1CB08DECD7B31C609B0F7AFAF8D183F2588D4F60A1C7E80BED6D0FB64F05AD8C7AF5B6B5E861666761D53A6109310C11AAC7CCFCAD51CC54222B88FB7644C2625397D5745E4B282F8500AD496CDAC91078124E5416C3CE66FA8C82385A3DFD549ADFCA317A3DAB331D203EAFCC3DFCB7536FE8981FDD6C00912DFDB2B0D708C162440C5CACD1EE593F4FA891DCBDDD18EA0BCB1987152B3FE0CFDDF75DD31751E8F74AE01231BF3164D4917A9EA2372D5AD19523F657FC24C4A6D0C2BBCE794D2CC270B6585A4F7E2153E6E41CA9BE747D0348E68D7269084BFE188E4324E4FFC55AFC7D8DBDC2A47B6923556C9BE84CF29B1C6A3AF1B82B723D79F65810C767C140430DFAC14968F2581259CBE74475BF427A5012F93DAD6846B976846EC308903C489DD1733BE7193431EC09F70CAF0C14D539584F58E23A0B93CAE93128D1B52A68059D4D3FA6C4F7568C991B3FEBAB081498EC59EF340F91C2640596C7C8A69230354346C1BDD89DD99CFAB4EEDC3C2B0FB8A70C5391BE2D533D26F6A3BEAD450C05C93A43D07162068DCAD467FF6EDCCE1E1C594B01717E8345EAC25887EDB71A221BAD69E5F3E9B62A7C0303DC62CFA8CCD93659FF50F2A446A797026C0DFDD5D1D50B0D0297AF09402B570196DED70CFB7088E2ECC5D474D7D382E4C073130F12D4C23A7071D93BD7E66E2D6DC1FA98307C44D013F6C1335D321620591377FB5622AD625AE9AF030BCF3F6F32608AB45E2C15E78ED195488E5995D933FD54ADC6C73A02F105CC03D19EED13F3733389CD42F07F7D900FFEC6179CFED21C5AC4CE31691578805D2E6BEDD06953D0EA004CF9B630CA71FED339FBC6D465E69397919B3FC508A3CAE49A9B3276D1B0A75C78D8686DB7184BFE2878C0944256F98AB6C25DCC67C90F1DA7720ABE159C8743C15B3BD3469708879FE4C915A63AAEF01E5407DE35B1772513CD33D2678A9A34F430ADD7B41623DA000578A24E5737DA976DBA5C69569296FAD87A5E6E8DF5C7C2C1EDBB7085C046106C50FF4B4A3500A00E7E730D8E9B0627E10ADDCE06C296A6F5BEF4E99C411BB8218F6304311FAC1218ABB847D8FBDF5CDB74CBDDEE983FAD3A9447BB80C60C58AB0CA05FFA8875275C6E973EF9F80917F11B4C76EAFD58AAA34650A438B18246A4D87ACDFA57DCAB2209F65AACAB4730D6DF6CFF2E87FBA14B720B16ABE927590EB015D288DDED8DFF500FFA2E0ED288CA86CC76DD7FC7F84F5F926CBBF026C7E6D5D85D3DDD25EA103B7FA98946E4CD8D450D457E85ACA4311F8B52F27B4EB8AB2F993CE5C81583021CD385C2589073F997A21BAE447D3B4D3BEA154F188F7FA7A19C7B4E9315BA358F5FFF6D9FE9023C8EEEF0A240F10E698102A19FE48900C304E049C5A5C3C476D224815AE298520CD4CD889B44E5DE0C052F76AFC2F7A9F068D5A81E38CA8FD5D4D9ADB47D9D385E5B5C4BA54B8DFB42DE493D5080B326AAD8D41104D7EE98F51A147A9DD8130ECFD817A7A"""), + TestUtils.hexDecode(""" +701B8AE25CD8187095349A4D41A067D4FD48732E62547E491D38845B3507A7A6AD8F8AFC53D139E47FC5AF2723B1BB057FC797519AC93CFB18DEB496BD9735455CBDFFFCA5E69C95990EF89F509728D1CE41F36A4C0364AC8C30E3EF67D3F3776400BF4C838A477231E455FF76C92CFCCE1B69B00F99451B0A8287ED59CD79EF0D6E697C93F7ED38F20204921E6E2F141D3DBDE1C201E5CE7C524370C339753676746DA5DE4A398CFC2CB1F568C16D4DF34A27CF04F0637B1447C6CC83E965A3F86C538CBC235E440CC2D1257CF916421EC75928DD6DA3CA002AC93C8F464ECD522EEF7E048C154D73053DA7BB63A5DD845512D2B6B7D1E7EB5818D170D14A4A698C8922D69A98319A10E0AF558E2318FC390ED990B75ADB50C6199DBEAF5D53B49235DE7CA116932EA38A109322AD05F5D681CE25FFDC9F6A05C4ED2EC6D4242173D2039318EF7D0733D86D57C4E114B3476392D47FC68796C9F66B1F1EC70610E1D57436614D5969564DEB8673686170E40BF5CDE506F7E70964E07258D4551F5EE0BF2651F8BF3D3177DA76AE90FAAA69C4F373E664F0A1FCC62F208A8BE130C499166D13CB34D77FDB32D5A7F3AD38856BFD3A0419B8744DD2F186D03E18634D826A5BC87F1566FEF88D9ED93E74ED4C005EA3EE2EB22FF5DEED283132D00C7A0B131BE1FA38E30EEC68B748AD533BFB23B9A14A936F609D4C560163235367B0D64C2C796F1106A1A9365E8F507B4BE0514C849A81E2C7388C8AF300D98D444BF808C4F9338C47A853222D5AA8ED283F57DBF0689E5FB89A456005B6B95AC3D791077C79BAA2BB42B423F93A7D0D999241AC5B9D64D65274817F9BEFCEFBCB4D5CAA67427F69ECB279553EF0D33A19E14FD4B284A72081F949FBE2A7543497F314CD7496EEE866F33102BEE5CF9C706426EF2365EFDF1AD141552BE65D1DB4373B0E8D449F3FD1733AA164C1F2C24F74E240C5096CD201A11113D6BF5CA19595C4B0A81E1153A4EBF88F38F1812BE517158787F2B378E8E32C9F97432BC9027292E5EDD7DA64FC6A32788154B62E40A85701895E13287BB18883820DBDD7647AE4EE1FC1D43C199EE69B1A2E2A7067AFAC541A8F44E660B2A7C114F402E2054DA7ACC41DDDEDFD7291CD4573DA22739C7785EFC2240B27A90BFCAFD1AFAB6C2B0EF5509D0DDF349C173E9A6C906BAF5692C39F6E0D1442F84AD2FC118A14B12C3AD5DF8A79056017F4FDD76603717B080E3AE560D7A601EE7FCAA36DF7289AEEA59EDD0B73BE91782377150F03C2C2ED40F33A250356CA17E153480A7E848F090DDA29C65FBBFB495FE9B7A2BEE342C7D422F28631A8C9CF643DC76F07F162DA1AD3F24589971032796BCDCD262F55A8C34FFCE05FA9DC001FB35D6FEE75B42DB6DDD2138C0517D003512F0EA8E982C2ADB5E5BC1F19B8ECE67E4AA1681383A97976B6A8F2025EA80B1BFA1796C27F6A54C583711E2EA46D85C515EAAD22ECFD68C5D02853D688302704EAC4863DB1FC69F8C35411EC6F4A9F0A7E7B3385ACF6DF805447BFE863181A945E8E7944770340496F5A19CB7DBD0D9010B7EEA3C585926408FD40F245D852DD208EA97CDAB0C16C1EF80B3E5BE77D953A04C1B6F53A23080B54F439705E417B9874B3FB524794D26DE3DDE88E9DB9FC36B1508754EB51D389FCC46F822F50FCE199DC14E4B4468B8B15A2460EAD05D0C47668C05A2315748897AF99D320E70F2AEB96936D7D739F72ABAA6960DA6A3996988F6A3F7AE7772D49915753B936367E022179E69B6853E1A83B429B42BE19EE03520A5666124B657D2FD6D15447AEEE45AB1FF4593DE9A2E6D152C64DF45C1F62AB9B67257B2A2115D224850A3AB2FA028F8F9FDE7C9A9FBA2FD291346037A1B4E00B0642B07ED54BFD70F3DCA3D1B8628627859611006DB2DD17A351751F85C60028DCF21481291526B1DEEA4C7CD2D3230653E6FEA1DDBDFE1BC3DA93FBFCDC5A405975A5DC68DA0D8338EFBD6CCDA1F2374D72FBE007599E81CF7D5C37985EA09C561A1EC40A70784FC606FB7C3FCD981F112C599C78B15B7739AF4DE129D489336BFD3966C10363A60E749162D1D8311C5E850B22910B999080DFC86D1787C35768CD5470E9F7A51D4EEBA71241DB57021D6569ED2BF201C06E235D6621B292B686D23E29DA4E81C873371593CB07B3DE46E91FAA3D4A2AA6F62FBF6BBF1954647E731AF4B99EEB3C0FA6385699F8EF2D8E1D7F75161129A1C7F8C7C68B906EAB8DAE8BBB3541FBC65F36BB67ECF19EBEF54BFC2EC4E1130A2E4F36B5644A73CB0E244738B6E5788A4B4457291B57F1FDAD2C11FE5C7DCFD4E742A0AECC460BB660D7BFDDEE4CEA074958AB94B6FA4CCEFE02FC7001D3A2CD013684A1ECC2E2F6D90D246726EFFFA99C12D1FE4AD10A6BE38D70AE3DE5C4843FE6CCEEF587191B56F666C1662F5C6FB03955C557E1B4CE247A2806DE39EC40CF8B97835EB0E3F2D829E0FEA02FE60C934FE72A25930FD6692B9ED979F14536F406F04C3CF0BE98647A5967B81DFAC353A2F8236FE147BFD7D3731C49476C3191981C9AF239AE8C72570C6C53E7AADD48E721E623D6CF11A1E386EA7C30F070E7AC4F63FB42AB74881BFA3FF3E8A35EBEF04D39B853DDE0FB17DD9DAE37A76C96FF55F64669CD9521DA3900B7CB297E813521239D87703CA395CDC8D8CC4EC21CB10A1C672493E013EAC0298F8076C8E0B56AFDF9C31EA01CBC1BDA4AE17FE103C9812E940A34EB321BE7BB288CF8BE7017AA58AD528C9DE09E269B10C6FBFBA5E8B6883FE7E08A0D184F8561FE3F43582CA045DC25CABA52C0157495410382A048BA67D051EA115D867D780CDE5EF512BCDD14489C43604F86D929F83D118B905C63BFF451FF3540E9E220851A402BEA0DB1A7CD94DE0407AEB9CF862BFA3FA703924D0A4803C463AAA827A04B0F09556054F27DB98E22A96D07F81662E0E910836B9423968C3F002E605BB688720FA7CF3167140BC21398B5E4968804F3C3065FAF125BB6D887C869FE3FCC27D88E048FFD0925E748C096C74BFB1E54A8FF6E2C838F16769FA4D8564E5CCC58DAE3B102EA300361EF89EEC689FB5BB0DE16C5CA98A60B8990EEC0006A147036871FC2A6ACFC6A6EC907D28E18A76560A5436BBF9353789C8A5DFE559FCD68C117066EEE5B00F349D6591E104295E78F445FCDD3D6883DF50D1DA6A04541C7E8171523FF36A9C072164147D14985BA30FD449667B580D73B06A5971B720A8B1D2A6896FDC5E4D4DAC78353ADC3449AA53919AAD15EF250AE12E9E40B8487F66AEF0B15E42BF34AA816F559062EEA24EBB01BA369747B29404DC1F1108DEAD021898298E72F4BC1DD821E4C88329D6F03F971F554A87FEC87F34430ECD1CCC6627D8CA49EEE1D5DA6704CE960021C847DAEC2DD544D4EAD2E2086058CF131296B7F4FA4B71A1DC6D6C642A256AE0C0EF9D1211EFA3845B12243BFBCB4F423E913A2976C1015569ECCBC159AFE70F1EDDC3AFAAFDA45CC02EB60BA0DB9EA83EC604113479BE848F381FC63C63B3111DC5179A637E0832A26EA32555908D79B308351CB104C43668371DB32056BB63540B9C3E5551A063D2B525F8A016BBACEB402CE7D7072CB9F37CEC13E1EAF7D867534C013D78B9DFE01C13DDCEC7A3444AFF9E182F12B6901CD9A70F21908FE692E4C0536B069C89685BFA9D973983AA8C1DA461D18ABD27A6A717D9F2122BEAA9BB1742622F51FF616FA2EC3A6D4724A3A9215D7B29A1BA372282CCF60DE90B3834FADE6E3743AD6B2F9B7344F45A29740DD7DB2D642F94998579A5DCCD2EFCD2F7D08486BB327B844EB19ACE3B4FB0D85F8A24FACBF318C98199A0B2C7FC2CCA59AE84A522890E22C2A7207CE91623362C7DD8E9F946817C75B71FB9654E2B7F2E83E46E75ED5638741E414D7F8E70914315F0E37B5B4E3E1CFA8288B1724113E4A00B59B7764C2D61443537849E77083FD13BA652001F39DD9BD4B20AB77CB945C5EBE686A0627ECC52F38A852BC9E1AC8D303E3B96D9D086920A19E5088054DECA635E802385600F673D3BD0A5CBE7A5B9BA8B1C4B73B9246C1A1C1071E5F98ED42041037FAB67184C89BF4FFE3CA0AE2A9BCB020F390F0B76DE2B8AADBC99268D3A1D467A024184CC9A455A8F2FF287A4C9DD1B0C86C8E176BB15B12023B291D44E7FF0C44577F7A6D788D82A75C68C9F5BBE504E7D64FD2AD18BE209E85C45627FC045BC81E3531A2B886173F3C3029D1FA98C792501A4942C72A7A892232F390CCBFD7863AC38D837755011F919AD8934742D0795523E6D48A958BACB9A9F7B9A5A9D914C37114CB111CB536EED3D753D6333219EC993AA5D39BF74E8E9FA02D8BEFF369EDAEC67A5CBD128FC9BA6F82E31A4C59D783A99912C7C389EC708824AC7FF05D56BA6D228C0A9D96324C6D9725E3BE17C44CAC7C4D49235BD15384F95345DC36519466A13110A58300F7E3362295DD7069DC6A88B542F2BC5C9F33328D9D8D1683902C025427F32FD562BE3F0680FA05851296E15C5FC67E96BAC924407AE6BE37E9B61D9A6383FFBDC6E77CC0887726C474AD735BC50039AEC665D827B0F6BCDF7EC87EA6BF793386F2A65C997545FB93F0D53737C53D00685DDC13960AF2632380F105840A1699ABE53999C568978ADAFBE21913193DD0844D89BD582418BF8B6BC430FF1FF7750AE8507495C14DF21A3437AFCA7DCEE7B1F1247C802081FC5ACE5B125AB2BF11ABAC97E201EEC2A8C90ADED920728EE77E1FE2BF31A222A1CA5263586A16FCF80E582258654D0793B1551EA3C24C4EBD27C52956ABCE6ACD05FC2F088273FEE8ADA0256F30B5ADA8768D8E9B70279DF95AE5CC68FFA99934C7520E12F57D213FF18ECA6046A9A3F32E280044023220140E2485A3B3EF7778006B18D4A9DCD177D190CD903CAC1EE0897F58762299A0E026B8EEC6F4F3D0BE1F070C648A2D73869F22DDA21246CCFDEB7A9784AE967F0DD0A2011C637099AF33E0D608AA0A5B2103060CA1A6718328D451368EA3049FF60FB66FE54E778DABC48413966EA14E22083A884E8C8EC33F885093F01B5E34477745A9F82C645C8C5498306AB00B78684252ECD74C163BB8AF9B49AA03E244F4EFC4A2E7099074F512D465C84773DBD1FA96D26053230C192DB289A1596E60B96178DD8CDD72FF14B340FB5830696B393CA319649BA56DCD517F5A08A528350E2D9531B3AC187414FA6E06C0F05D9987BB2FC98F7C8D4F922B8AA45287FA83B900ECB6C9F02669063296F1EA389858F6D2E10228E136FAE35F21DA151EA7AAEC593E5948536B68BE58ABC57771AEB406A0C3F931E7DCF85A350A3558E5C1B1F70E6299EC9FF8B9CC13E905D9902FED957ABFD7D09FB84FF22BF8410D387BA85D8555A75F432EC5789498EA36CF235276176ED48D1E374DB5C2DD1A64714D64FD20D4FDE2A605034E4DF607EC6E11D0465DB25B9D79C83182384D64477C126E9B8558489F69AF29730B4D5650B9860326249777DFE9EA5669736692D0780E9BA346C1727138F5DDD4914487CF32A4E9CB1DDD5617B6B45CF8C981944684BBB7921C88F5A25120047BAF2D9346E220EA08AD168B30A1B82B3B63C4913C708C02258B6AEF1CAC96E2A90EF7D0E1EFC0BC5BBE05D286E143FC0CA4A23833CA12727F0F83079F7BA80D809D6C739EC4D0DD9CF75C4FE30B12A892096BC4B9167F16819694B2CD5DB4B80DE8DE988AD50677695C4FB3E0940913C250645333B6F55E36F649A43C3A39ECAA3DE3EC1FD4F9F65D9F7AAF75B60DCA3BD1EC06495FF5F1D4FD6D83CC6316E40BC469EE5F44E5AE56ADB229A7CA5CA37A1508531E44B0142B4330048350A40FC82279D25A87E043240B4BFA7321340502F0D37073DF068596C4753F8709BAA2A7264ADBCF5F934E857B3225CA47D8A182B80D3DF24C3612FE4931EED565BE563115414CC2B6BD102DC6BCA9F104CEC8B24BA5465FEBB7E9730C928D6FC1144224232A990F8BED27FE6D28AA35A91F90D6A0AFE9A7E37A5BAE51D8AFDEBB7D5670F2521095A56862354D2AD946663B4BBC7049ED1884347734BF3E78ED227428476F1070F4DB011F8DC86EDC5BAE1BEDC9C5D253E4C5C6816347EC96C5F62AA3298588625304118EC32DB2DE0597BF2056046E17C69EAECFD26475066AC54D40A673741BCE72F138DD98F1939598E5D94D565C1337D1179DA057D4453DEE27B5C04777EA710D77B317A6E8DD3B4F26A6A9B3F4917A0E881E5EE528462508DEC6762DE2BC3F8F8C42E8D721BFEF7583C99DFA4D1CB49DE2A303B67AFD505F8A3865D853BF19C4A0F7CFA92F5CB18CD5D8E378A5B041449EC9ECFB80E0865CEC1734D34BC44E664243AA8F605366CE9F849700593C76BE0CB19CA1255B074A8630FC962B50106CD93DB41C6E4DF53B6B1257872B0D8CE9AD5F245C3027A3F75F19DC568ED1E0F60CC20DE625241D300DCDC8C953676363868B680B471C2EE623DA408C7E030833DBAAEE8E701374156A6B785E0EC7D1A0A55A599605BCA0FB517EF99939889C862CD790240709BEE0226DC7E8177F641C747A151A89340A6CCFF6982EF39683325390DE72E4451BBA74E3CB102870F1E9ACED30BDBBEF160A49746A23C432C3ED7EEF580969110AA438D00AA03F54E039195D61B7840222AC994784EEEA538B7E830A6508AA0B460DA4B4C0DD9CB052CE6254774FB147F7E4F80214AF1FAE59F8ADA6509123438E90AC13FF7CE71AAEAEF7A39C434C3824D49B894C389CF320A430A7F84A5F4972FF98C388D61C936E453BB1A340528A9FA5F0B0DA9543275435E91B0F5560E95F9AE4EFCDECDE1584761F8F60F0280ABF40FC5834BFE456EF66AF66ECA1098DD49BA2CC4B12CA9CFE256FBEEC328D049BD6BD19E2358502672F029888DC3AF3350BC2EDF5C4E07D59DF8DB9C14B86F1FE384227953E98978997902C8F237C8BDF300A72248B3DDEFD52577BCC0F99F75B92BC056719243F7EE67932A2DECFB15B59C95B43E183BA3DAA41B97E177D03CA320A5FD5D7E5A88C4D54A8467B883E0CD5924912642A65F191DD4DC2B08DD28EC0AD2B1CDB86EEA3DBBF6D47754B1BF7036A0BE90CC3775D263A5BC688844BBB9B1D9296804176E17C55D6DB888C2BEDA3D546FC496EAC5243AB5D51686AF9B29BF6D4A138BECD49665458B816BB09848CC4318136E6B170BECA544E8ADC35D40DED979111B8B1D4577DE2FADE6A1D97F9E82E9D3F069F3287E559E99224C6494F36233453036DBA617088D619395518B4E6725125850B3121EA957E721244DF53FB343483D27E6C3A53224B38C11C1D64CBFCD7041A44836AA606D170A80E84BBC0973556B9E4B1BD776C6A0876D727BB0526809700A0EB318BED67843CE4A6BE2BC10FE9D8228A4C94D7A506760E580E8A0E544ECCB07DD0810D79443046951C72E017CEE5B2C959754D477D706C3E043298CAD200189F4390F59BA27B0099DC551673B5138AA654E054676BF30DC61CAFF444CA22EB32E5952A598C07AAAEDDB83B8B3789EEF97663ECBD33FE356DE981A24C29DD5217E14DFCA30C0109419D8765A061F747BFFC1E221D3ACC7FE239375A9548483543599C837F48EA189880278AB2E06EA44417EB945F20ACB464CC458E249A8969273A460F063C5FAA907E42C9EE304B27C85BF41FB170708969A2BFDEF37B97DB4A16BBFE07370039369D04D0A9155623AA390ABB75D47FE2394E4606759648954FECDF4554F660D3176AF33153A9D7B0A935753B11E6C7295B0FF5680A18A42ACE577981C500581F741CA23DFDDBF22EB6511E19C016EDC96DA545AD16D5EFB9A8F10C45D78E01C74E3552FFAF35CFA1BC0C3DF9D14C1BDA9D510FC7C7A755C71B5273CD7CAF3AF44AF066DCF18B1B7D6C0D546C9C0B0B1BBE88F512824CB8B512438ACBB23CAE1178DA05DD67DA6392649213805D680AA61D26092BC1B2CE50CECEB7541D7F10808DB2D4A6B12841C8B4B6C5519C8683C998A74AC3BC3CC44D81B606A9A3174929E4AF06E032A24E67E9C66885004F07D4775A6C66A8F42F94920749FF902A8F1C3BC5A1A35BFA24040EF3B7ECD05654CAB696D3323485EF855361DB57A65C5AA0B238DC551ABD6B4A8DA0EB987A82F56E5EF05CEBCB4155181BBC61C645B2A4FA8B316FC6C5B3BA12829E74899D0A42B42821094B57E6D221FFA108D5D0EDE9012A88A2BC361D90673BB3D19D6355B9239131B42FB3CE832DEEA6E4551BF6C6533CD8DE572ED3E5DC51BC1ADA13C0C7E4F723CB964125DA08E0D08F1CFAE124568DE55E2B39B1475DC8F6558ED763FD7EC2DE373F4C54399A0317087630AED2A64BF13D113E8AC32E6318EB7BC0DE20E846C0CACD876F47CBF79DB6FCDFAB75B371156CF74B443E8DACBEAF94203037BA14E821A66244BBB7E989567D176FED12AD0BACF79834D067662C11422631554D1ACD6BCCBE23BF1D0C042C1CACA4B9BD01D6C5757E52877FB5DFC92161C8BB15A60222D12CEEE973812B4920B38547304E720AE246FB503C9F97BBA79640485624DFA2F4D508300BB80C70CF8E271770876062AA1EE0F548F6F7D95CFAA17FF1FAD847CBF6CF90B01D29C33B43473379F4B5491532432F6CAB98C365B84D357B48B416C2A00B25D07594ED4E4CA0E1BA5C92AA2F1DC7A6109AE8D71B9F06440A770FDC2501900B9EE466DDD853CA5482B4636BFD58AD8B24D91852ABAA0A37536D4118A122951DC78F02DDA8EC8029ED938125D759B24C90B0FEBA1F589AA1C10FC9597CB7E703D93AC4AFA43D3C239337AA454BCC471CC6BECF89266F588C3EA71AE50F146097D9CCF21E75790A5F3A252977E4D848DCF5D96DDD4FC1D0CB583A28AF9D7648BDAF8F1E94A83CF5349B1F4AF63AB1C66757B75C58D10F27F8619A5A6BADA67E841B6429AB40A09451313EED76B93166B3A5D5561CFB6421D83A5E343C8D277389950328A1646C3DAED357BCF2E8615695D7E8922030148844058D177D4E68A8EE31D5D810C73D9B38F6863083A8266652DB82A43615A45E6D14EFDF00A4333404DB65194EB432187C1EA7C48F819C34E48EBCB0836C84534A238C42E0B9BADFBB15B220DD0BF40F8C0511BA69EF82FA57D099BA84EE4AB6FC422442C3BE1E8DD910B4117BF4047D49419FCD2380966F665001FE4793F06F272E14E1893D502BD3343AFF5EE94A58CEE04E745E72E51124AE8013EAF2C2141012FAC54CD25E97B6FD3F0891BA1DE663EBF009A7008222F461B4E7D50628133DCCBA7CD0AE44BFE9F675E094D972D896551A1205FFE0CA8FCB739192488D2BDDD4E10493B43C7EFEF60888CB11ED68F34630623206E81ED04D300C2C43B6F27E41F18241651FC6B84C19EE1EB018BFD7A0D4483B0B6DCF57236AB27BF4CA17E52739E4D1C508C78F6B6E9FD53F423AFFAB01F75A9B1AB725C247492DAE3227ECEE2D60EB186BD8972FE455C393919E6D9760AD1BB706138824FC3C9EA0F673C1323366DEAFD260591DAE60AEA2DC22FFE5EA2421F35920550C0FBD78C4F6469092F89FB6908457BC81A175D75B1F97E2750194E68705B9D1E9F762068EE2FA9286BCCD3ABE98007AD1AB27AD2A094C6E164C5BBF88CD4C5F325E4E91FE2867A94E9FE1A78DAE2ED1C11CB4D365EC2F3888612FF58B493268645BE9ED69C196857F8C995A42D5CF4542E609BB35B0BB1B4BB85295ADE635E8FA237C5DF471B8CAD7E98420077BF1DBF6DCDCC1322C8BE1B8DD5E228B6E6E04ADA1D533B0C6221FA83BE7C19273F9AADADE041CEAE389D0572D2317906005BFAA17940026CCBAFAF8C7A4BBFCE30EDBF4EF82902E181B41A1FC006AC01BE64CF6E4A4A14FED995D6F323405242BCC5797E43276ADFBA44EB8E3EEC029292D2DCDC8E6C93AA6C02766308CD367D3"""), + TestUtils.hexDecode(""" +367CAC590EE6829B0FE910294F23515114CBA0A04D39CBBAE3BF908DC1A13ABBCD5CE2A9DDD0FDD2A011068C48EEF6BE5B4524ADCBB6F51E9A5B0F57068385D42704B0B48B3CB8D1AB011B8F13AE83726E0EDEA0A5880590AB8FBD689E6495AD68379993C44AB4308D0FB19D3F0E6D98E61BD2EAE1B49EF4229AB10D18CAC1750A60F1CFA9430649A7DE0BE1330A180106BFCC165CF60ED91711E5033E7B8FF29812CAE5A8900CD31A4B254CDF41ED4C5B4506F6FEEE43B389218191246A661CBB86F6C8F790D3D87343A37108E1D79C2DBD9A1533542A5766D56C9D013D74E2D7CB1EE7AABF50221ED657D8C2AABDB26DC3F7662CFBDF5F6484BB9B04060280AB53F0D22093967A19E754EC5180024F3AA2A615A45A0A43AF44D6204BB8BF512CF9F5DFBB8C9E6CA594FA9875E9801B1A3BE7983DC4865F649E3AF8AC28B0780C65314006024569774E8C7909A92539F9A647BE2CA6874B4438E0FDAA7691105C3D6CBE3F355FA37676C65C3508047A521454FC3A5F13F028465FDC9074BDD506365AECE7120980AA4622A7353C366202046CC2EFDC87459641CD56FC9AA723174DF368EF63517CA839813E16072951F53F4A2AC0B54F0E7A5A21683B81ED562358DA14794A798C1C14AA2B51B2F87637446F235316F0B047E757F84D8EA86B35A9F24115387DEC18FA8FDD6F0DF4A918EFFAD381EC87727578185A214B334C77FC5545923463D2601A302BDB21067FBBA672B7E33F3974FE1C2206A0EC233DCC44412A9440D7A09EC3A8ACFC99EC24F9BF021BF3298831AF56F272FC1C7A06DA01B1B38E8C421865EB8092CEDBE376E836B9D8181D853BCD48E97740E8AC046FFD2013691587461DA91FEAD7C840D923B0ED227F5389536FF871859F459FE2FBF24C84A8D290189BDAB6EA31BC1BBD98D64958106FAEED0E8B9BA1C10B66AEB7836063030E641A8E00422E2827D8DF1BD982773E0F13D17BAC5CE3DB813F712C95CEEB0E7CFCA45FD27289EBF6C7269EF58A5E4135A6F651B2139AAE3E1068E19C4EF3191DF10F37872DA952E95B2A831333742864D6FCEA8C0E37BD1CDC2EC902D210E7693D30E36595892CA5724853510B6C01E91763F376F20D650BD1C3A647FD2C29FB3ED1B8A8D15624E60837F55F65E0D0D8B0CEBA1A903293BDDA52B354196A1B138677235E41CC894DB5B1FB474463B168E25E7F55EA5AC0572428768DB4CE75255C47422B2D92C99F8AC8F296F1F823E59591DDEC09DD4440BFB9007B8BC04EBA7A7A959BAA624E2165D6C5C3873DF0589A377C6157A4EC57773F98763745627A51FB36CB82279EB9514E452F381AA65B3EE860D0EA2DFBFC838C98821907C1A99C0C18AC49BCBB6FF01127C46C439BEFE217AB080337B66F6FFBF934FB5A6D16118DDA48CC987A13D52416F7FB4D10C7F22D8F97A9E380C8A3902C2014F3C6B2F36702EBCAD5182E33641FE6D65A2BDC1729FD8230D5814545EE15D6D02907D2615E9DE534EB49D638FE0CCF5497D351C421C7F25FE57A507749640328EDDE3DFD807DACDB335971FC46AA37177C78D179DF12F187B531CD5B02A08A12A0C5B7CDAFEB636A1EFB6CDAFF16F4D128A0C1EC96FB97083C622C94F3F65105F865B1FDC81F69A56427B900EC13EDFA938C0E8FB31DFA821F04CFBADD892B1EEA6F596A6D02947F50B3B66A3F0323B9A1FF95C33F68EC2B833D2CE958552A8205B5BF0E554FDC441EAB46DB0E8FC319C7FFDE01BB3F118413C8FF941C37CFB39A60606780EDB9F5818CA4A26E1240EE6AD117745F173DA5B2936F1B25FF1AB49E10913E9144F6A1C0C547A93408C5C5E1155F02D5C90DC5E750F06BA51746536E351814F1639AE3C845BA88EC3FA60111C7F8285284AD1CBA5997BED7FDD71205032180050C4010FE353CE4695AC49DB104CCAF5309949E2D6B4485C10E92656FA130C7D0A2C424F98683A8A2F4ACCD31EDDE5B11DFE71057983A79DEF73DF46427A00952A69C0403C73707F151EF1C1B3C39121181FBDFEE8EEEFFC74BDCA8DE6078ED56A7968E2B13426CC387776CCE40411220FF01E2ADE27EA9F9445A635EB8C0D073232FEF7F580143EDACE3954AEDF5FD01756102F639FA9643173146FAFD50CA4FE2338584632D433640FCF619D141541B0C15D39C89CE07A47F24F59B3DA68A42E7FF5394A02B77A35DA7A61C2B7C430678FC9956211038CC2EFFC9D7C8E04EB0CD6277210F49940B39395022A226553DB46292774276CE5CC184B29CB598CD85672BDDABE25B8F20486C775DA97B9C3B97B4EB9B729854120555C25F130FE3807BC886A43BF605FDA29898BB7160DE95B927AA7EC5D5A5249E82D4D50ADBE591FBE49C927EDD94E557FB64F73643464E7AF168201C57A16C6A6FF6ABF1FF392F8561A66AFE569E51F820591C0A7A43D841CD13AEE08FC15A8BD8C0EA63C69EC331881697EBEF2C1646660E34B775BF497C9432394393A7E3200E63E477169D9C3FD737BB79C1155ECBCAA73B0C54A5C0A2B8ED6DB93504C5ACD7FBB15181696C9B6EF1A93C002FEFA46007D8DB5DF3A7F659AC032BC3780D8A7C7FF485761E632573E96D052183B287174E96B230025543288C37DEE87D6EB3C44FF58544C598EDD123CABA17B0C17C1D129BD90D72382FA5644FC94CEE6BAA9C152A04F6A1B5F6D167E8B27E2665D861D5E439F2425B562DB155DAF1573B3F69649BFFCCC73DC72F3E3A40900D56A810BB99DBC75A6594840006909E78299F4C56E451147C3FF9F069A65399B296C2B906E5B493FE4DDE19B4831F43BC2F0221A833EE99938E60BB2A71CE0E4E47140D73D5BBA00952E01883D9CD3FDDC0430B9C413455F732FB0AC226BB59DC0A65C73C915023C035C6C62CD6D1F3D5C27F473A0AB4C2D946D726A0B8742E8FCAB04D2CC23DDE5B0BD952D5223501DA188822F481B8F8CC377903EE38A740AE1125F4789777D94176042C70317528ADF14DCE224FF871105257DF7F1385D1508C04F46ECD2C2E1F3E49783181ABB0E2E503FD5DECF38461C9D6E093CC55850DC0239B7F550D7C054097CBB554CB53C3F43FE1E7EDBED3B55491AB564EE3AD7A9CF330BC4D42F2837E56F15E9676A838489F0908E1DC59DCE7AD7E72F57017BF6F610F486FAD183C714F99226889020534972BF58D414E6DB20F22FD60EF8359438FFE56C20F28D966B41717D3B63250DD0B5A961E73E06793AAD1836F8341C5504C15990B1DA9F37DDF87EA2046AB57D894998725CBE7CDBCC1B5F4EF0B48B05E545AB5125CD4A9C883BFB58BD3136F03E3CFE3F225284E17798A1F4B38A91747DC5A2D64AE13E2C72CBC24D25F809AE19100FF0C9B9E9063BBDB08DD776F7CF2900C56201F56269F3BD8C3EF15BAB0821E1330DA0C441CF3A5D0EFDDD4B2B48C0F567C00346B97F8EF9D377A7A590FFE77A6BB2D6FB6AFEFDB7C8260CC1EC3A3EACEFF8AD086CDEA49C39C961DCAC0BC22FE446FD1F7099425D559CBFBFD68EEF03525B01DECB52D5ECB1DE9FF4427C8C607428CD43E33F5DE8DF9D995D033DF6A41F69BF623F36451E53E422BE18F5F9667F5AC1FAE21B4106CDFF91333749AD32978EF6FE73D7AF88D4DE4D9E2BFEACE96D8DB08DA9ADF8BB51A16D326378B3394AE7307587F98FAD697BA01C1B78387DABB5D6E8A1F2CAB663A3ED1B8A833E4F76D11E0AA38CCF4476847741AC8ADEC7A5C4DD802604F690CEF94B014A1CC2FBE8F2F71247F426AA5CFE3745706E744DF24BB7BDB8BBE8BC8EEA92E46F8BFD515D52B3CFFAF81F127C5CB65B1AE5D4925161610CF562B660CCECABB35EB7F8BE085761EFB4A8F29EBECEF2726938606D2562B4ED69044AC08769EC112DCD7D7D54331549C41D7A9A9D9F5B004E4490ED183DF65D917DD1AA8A2B50E86F59576A304606FD527079F60A3D0EC2E36A12D354B6187D1A5301FB1977EA5E5011F3CC02B84BD6A5F21D411B4BB276129A81AE6471EFF6432427A191134542EF23CBFA2E32D2007C2637A189D7AF0A7D3990BAE139BCD2E225A671740F83856825ABC24F6CE908C4AC1FC3A61AAD816281985AB215AFFD2AB0060B66885168260028090FCFF612A034C68E0B2BC83F33585C3FE403A094DA453ECB21CBEFC03B69AFA16942691759701F101BE11478DD5A4DA021781642D9646040D6539A8A8B15868852E8E233178BF9DF56D048D17A88CC5C5FF875B2AEF274D18164B16CBACF4D2C12C2DE37EDF89A76E4273C7F888820B5C56699AFA1D2322D399010926DD5363B6755F75EF1AA5C0DB58D92FFDC0D666E2F466490B7FBDD01D2282B014F08581682A8070F48E69670446E0E8A22D388F2C36FE6B4A0958BC20EBD7D6471D89CC45C01CBCF09F3EB54ECFE1C1211F5A5C27D7C12FE983CB1CB02ECA7E7400F700B78346B9A4B669FE0D7B6DD805BA558DB32952C90EFA3E1DAFD68D8A00F5406A9B127B8BABDBE01FD099549A8F006DD30D20E7773027A3A402D8972FF70A02E33F6285D55990F0D378A56F5CB27F22904A37241C23B2284DFF79EC41895ED8D37EAA794D45C1AD60F6730F423F874AC4F2DCD82539E0EEBA01FA3B1EA2042E31999291E470606C96C23CFF97270972D0CA855DCF5BAA7CAE8205932D42012B0DE47201218528A76C21E5C0685FF03306656A6E5BB15494AA2BE9F01CB9FD740B8B0FF27C852665087EEE29806EF19265EE458275AF2BBEB9848D2E1825E617AE07D14A8B3C1C270F0FB607EA823EED616B90065F2BD545A0F6782E4491994A57D785D40CC92742AE7CCCCF12459461415449C8E59F44A8799CBADB6EB8AC5E0DE34DE602FD536BECA0C2A5DCACB9AA8A46843921A382DFFAF4381776C2EC6A588437D908F0639FA2F23C997FEF001262C996B7E28E074B7A1D2B217FC28E9C72333C89577CE807333F1255095E624530DF50FFF3E3FCF5CC25505E294A022E439611827C869E5D13540348EC4BAEEDF3DCCDD78D771AFB3978D82DA1799A930EEF91CFB315521CD70B194E413FDD1635DBCD193916C3C659F61DAC973A879F189D696D3F175FBBBF0FFAE496A5668A6E20458C9920794B0DDE8D06627AD4E224E112AEFD59BD32AE37BA750624D5AB84611D8031A3C3A377B10E2BCBA5E12AA23D3DFFE6BAF03FFC5BE4EE39E6612F917DA9215CE479AD49F59A34353EF65E82DBE07FC3E9C8D92EE011A5879DC5C9AB26EAC415D520DD2B72DA37E948C56AA177CDDD4B7DA86D1F6E739FEBD5EF78EBDCABEDF4E159D15DC81F2C9EB46079E1DF3010B133CE46CAD6350FB83833D4C33AE8FE4653B4A441800AFE90D4F0CF74C4716FDAC1FA292DA454791CA823136EE844CDC153FF4AB5B2FBBD2924B822A2EA96254CA33C2837041B70B20A3B15830EF876008BE6A8E412CFA7207B35EA6185A7A1AC2B81B4A6EF72A1C2B105836D49B7F96CC9E219D3511FBECCB704DB704961E669EB3FA517A7686DD118AEF575BD351AEC67477283344ED69C0F5308F8B1F82E3DC7A5029542E2F991242B179E92201AB8AE951C0198410A5A5C7C4CAD7CA714D9D706D2F7E0F9E4E2F04CFCDB4A3316F7984AF20F4D2A5BFD44D1B1D043954DA9D6DAD6A53E6B9F3574FD8D98B3DD7C207ACC73118C6C76EDFDE760E87AC11AC8B45F5B654C256FE61CC7F19DBF91E17CAC7261A9D3FED328E2DEAEB1EC2E8AC6865D339922892C680C84C66FAE7CA866468A67BD7AC99E532BDB02A687F3E7DC1DF7B6321598C0CDB20C994F2C1D84B601D8C497264396040670710A7FACB3F245E32044F988F6534766081480EB66208A03BC1B39DAA90200A98A0CB3965FD17031252F9D8E1BA3E5A555195BBFF408C899B138E5EF0F5F83B80AF8B9EE51C7264B2EA53A429CDD28C67020FA23E5D84165409B5EB01D091918648BD630DFF02CB082DF2FFF46E7674EC85F8630D38F5814879EA3B4634B2B60E73AD8540904A4D1AA123F2B21C3607EBD8BC49C4CFB36059E0AB14A528152552611A3B542A31A11FC238BD954A38D671DEB393D8953F0232A5FC11FC99E169B0B47928FE5342C3759CF052DA0C40CC39CBDA11D9C7FC05ACE2AB35454B2BB3F44C647499CC55174085BAC97FC4051E18E48D93F35FCD6DE8CA0FB468B7A5429C3A5845EFD379686F59B5FEBD931CD9AE932336AACC05E2840A8C599A560C25570C1F4B0D4638FF832628A7D9BD88FAB4E94A185C05FD8919C91B9D44FA4B52DCF678DD0182B9F2D3628E751DDB91F3B60C29D5A0B29E745EA2A99C84471E1B0957F1B2C591032BECD263038ACF0AE3BFEF0F28CCA64453CA4A02CB58752AE9C1E3AB98363FCBDA22A23C4B070AE3B92B9145B3C5BBF3B08BE93C42632A54ED8D728F84C5522B313C007B74605BC965A5B2B2C556A12B4D8CBAD54F370E86052C63CF26BB83EB430AD5482C8EC7DAAF302063A455878DAF56D8C93A4C6D34F82ADB4CBFD4A8BB8E3E6E7FC1F2627416ED0021E43516C81B4B6CCF5F822455860779D032033719DC80000000000000000000000000000000000000000070D131A202B3137""") + ), + new SigGenTestCase( + TestUtils.hexDecode(""" +435FA0487592C90055BDC2DA68F33959F690A4F2724A4363262E2DF99A6073EF6EA41B044DA7B536B18FB802026B7A0DBFE4A80D41CAC87FD98B09A9AE370EF97FA99BD302424B43DA240CF31FD918246429B393D5EA9E01963E7B03547A6E19282B86CBB267B1038DFBBC3AD915C4997F7547CA709F68F4E8534A0E54FDBCC650B690D12005CC14444CC088E2120E43C0511BC391D844721BC6900A0744D930215C082E83066590462164245003A720422209044308129740424888C226615CB831800432983464C844051A3268D148501B326020970008C10101810D0BA41054300299204D0045662245494832104A844D09B9500438701BB889C80248844202191701C0B805422048DAA245A202060A4021DC006A110085A238092496494000411C968181808024B7696086480288701C9811900209A012814AA084CB122481300008314C49124940A62098286D99326E0906299C3804E082294AB09140A84508019011237019171023A45018B491C01601CCC609012601A1884991A06CE4268561120E1CA840CC120D0CA920491048A0A261E3047089460519B6248B446C5C306D5B8608C388444A428123144243C669DC44080CA660DC826D99C885A31092E0446D1BA605C9C870D9A085633269921866DC34508B305158C4211A496049384DA438294192045AA24CC31090DC366180C420D930041C0511C3B085098080D9C25121014C63186E4A16262129510A9185C1886D5B48921AA94121C14998162C98844841B444CB1062CC18324400460315440B252E80348092960422B74458004A12010E4106628B486481389012952109377002B008000651883672C1382ECC24201912700234461C2182092421241150A4B28553165101B2710A8770CC983149224E8C1630993046DCA6704A240944324D521224D2907111436923164A24394C18203223970491B0014AA87140A01011394002302812A365199065114521D882640B30061BA220D3082449402599366D22C06101B34199225223B460D8226818100944282218468AC11406DC46864AC005540260A1C02080304E21417050342001342A0A382590186018154522284418C94898A43092323012004C0192619A102CC816004C906524064A44028954144E21B55084B451E2366C12018D42826C233260DC240EA1A8081A896812359224854818352C9B1492532430203192123390A48228D3B281581849D3A6895C086A90A28C610806D0486CA3242A00076911B831030932211026828288022286D2A87193142C64047200B7088C80114398840C058E803265243631049889DA4881E0825000A765C94401A01648909885588628C8142E1A8380102185A3964903B8480A996C4C92319AA269CC864CD088095400260A80510824250083894B02481B108E12304D908449644490CB289012158A1AA724CC384A59360A42422858128E13804CE1124A51B691D0A46CC4328C1B8861080849239584CB9260200661401840E438204A2070C838888C3852214761A308604B04465194914C82010AB4442385612225024186809C2271D2B689D012691CA2458C420A8BB0885A040E9A926509A22881A220DB42695C42224A325050382D9C362A12262C241446212212CA922D9A166224108AD20825CA9844DC0825919045DB402D09A86504201188A629E014310836491489401B4520492449E2203122B46DD3184D600242981400449610C0880481A65188B0804CA4110A2650133802D0960D1B17264A48410807309396218A086610B29101B32459962094968411818118A090A29210D4806158903103018C893850A4B44140C004C0184200210E13012D0249649C14084A2646CA046C0C316DA1882904C02C4B9621082208A404325B264E9CB20D1AA549198484CC10626106291A1481039964C3124481186640326A220402999611A3902C1B097011206C5A342DE1128A88A4801A49401342849B82911A4391082525A3346DD0B2051A852C4800720800840C376510930050A22D5C04711B426D91804C82C241142632C8C86D8B824800B69090C088509060E3420DC41066640640A18401C202210CB32DA0A824919051A1906189202A12806590182149244683B645E19208C212095B96050942682122905AA020CB98091B302D09C410CB368CE3420623226122B070D4A290440841541208D3326694860C0CCA61EB683B44A65D855C8A8CD65BB1DD44C7E676ED115E302FAE539B8D26405CDB80C936C02CA3ADCB2D45237F170BF28E29C52598FD7B1C389A1A03C415B2B5CB096E345354FB26AC5DE65678CFA22BC9EADE8B1AB9863CA97848EC9D5E343F1C6936186D3C9DE36342175D26A5611E46F424D3319F65787FA40EC6E0C29162F572DAD37CCA44005DA35F5C85920C0463C266C502D2BBD9A697C0E69336290C5818A692CA61F1D60487043756B9F8FB16B807E918C4DA8B0F3360FAC63809682839FA7B52296BCD67F98B5FC0691184670D463143AD983A1ADB5F1AFC845A6FFF947DE0A98CBA74D06387F0BA27FB7F45BF49E89BA49EE6BE6D8F712F976C0C0971B766AD7AACC39C0ECCC4D2F2046E3390076989789C4E8C9FEE60567BB71DEE7CAB410CC1A9AB8D0751E5204D2AE85E38786FE3F436E8818FF7DA12949B52E9D4A3ACFE5E738163BFDDA76965FBD9FE49FE834A0B8C27AD5A00522D0B515E019E4CE8808A828597F25F2973DCAEA91F99F4EAAA101C41B9D9E303C22349FB39E7DFFB916443FBF9F9F231D6A615ABB5DAC5C63636B36D0E493A66930CD8C18B8E30B51E2F35B19B7D0C6118C9CA787F65148A3953DBA871A2B2105052DAF29C09DED9D838448E7459948501A6612013C599F51EA8BFAFDAEE41C94AECA8643623F46CC19A33A20191A9EB4FF98F484A86F7FB60864D5B4DB538A0FE14D6D12FDA1629B2D6BE674A242FF199F3567623C7BB649E229281C2BC355CD19C577A38614267471EAF4A46DE3FED534E150EA30D14E4CCB2C10B5F8CA2B8086B5B6748CC76065CEE5E96B4BB75649247164DCB67750B9597CF7F0C4A883B8D255375B048FB156F4B1E587B7387BA3B5452204F76CDA6DDBA7668284EEEEDFF0A504E19B737D733CAD1503DB662ACF2BBC9B64542EB1EE2D3A589A2DB224188FAF5BB8369245839449AE58C84D907E0F34FA83FABB302ED92BEDF217903C5769581AE4D783D545A8F3DC924119BD7998CE47919824AB5590A74C5AFD2D0A484232408710EED75ACD8E2671CAD9FC7A65788D6E988A621AB764E2B8B7C35D77ADAA684DDAB63B72316861F593609768AC761782E40B4C81D84169E04EF527B631269EC3F787143623311C7181B383FA6ECE49E11722A6C5A5900193E2427B56E961449874240E4E23523BA8B321BE7A0D984E1E84BC51D3844593CC56E61A6EB08F9107A097CDB8CE39FAB34DDD12DCC3475171FE0145152F44B4AE66E4D0226ED9BE6DA532C04DEE1162AE6692F8F94DBFF4A8141CA11936F1D2FD56CD9244036C73CE0B6EE0203CD328A5E1A04E0F6DEBB5FA6D648598EF1F0EFB0D05A16EFF32D527BBABD964425135105E67D0418BB17C3C5E4C53597C5CC9B6CC27B0139B61EF053DE290F511D7C39393A6B8C5D8FA46119C93E79AD18657B199A35A01CC48AD090CD6A68F84CD512A44514F997353A43F1807221B29BFEA62B5FEECC1F9388CB72FEBD181C49BA1DD96FCF24A6116A62563F8088148D5CF697CDF140EB000FBBE2B54FFCC36CD5B90E92AB4BC8B5D6D4C47C74C5329E70D87D8361A3484DCECB0C018C1A9EB6DB8094B8C7E0F8E5B1682948F76BBCFAA1D80C5CDAA1650428E2E1409DECFA7A1AD4AD428469B6A750C74297C46C7F216827197F775CD8D12280193E0471BC7449D8EB97A4B6EE40C5D73DE0C14293DA0B4C40C9543C284F251C2D4ACD332289D10442B72C3FBC564C092F3D0FC86F71E4E4228D7E746EF2153CF2A2FDCFE50E8699A7F5374B872EE9494D5A00BC50D7D9B356F9DBCB7DF82475AC89A88C6515ECF1F2989745EE765D4B347CF8A2BB358579B7C09C797A339CD744E8A69646B122F7C5386634B5F69C2CFE791DDE0EA8540DBD30187C9AA5737B728011160DA202D96D56E21BD38DD33EEA68CF5BF69FC64985FDAD57F329CDEDACE0C8103AACEAFE3AA1CC3F0A79934F6E57B8B5EA73F2DCBD0B4FBA7A7FE06C6707DC5549E0567FA09D1FF4829D127A5B427F2ED0C071A3FB317088B689DE3585240E74CF8920AFAC2E82F16541863DBBFB7FFCDCEF75F43C186DD87C91D917F4B9A25E8AD13FD4D771A427BC43A27054CCA599AFD0F5864B3C92EF3D0F29A5B43079C09BC6BD9A7F8C6757BBC2C99A944AF3A0C34D56C91637B6CD7331FFCDEE817DB1F91F30B5685361DC8C58007FC2A95DE3BE0EE011859652F72A0892DE1FF0B21E81F6155613D0A6A58A5F91272EC3FA864EE9BBCF875405D9CC9F103D0BE1F4CFEE618EB7C9F872FC1DB88DE967CE96B9C6ED273D1916D25A07702CD27D61162FEE2646F7B147EED996F817B0CF5EF4939FE7D13D653D3A8FF35427B50C0FA54E1788CBBFF7EFE8CFD7B7FC17963CFBC817FA2D75E9FE199AD0A92CA95A0AE769D40E71B7D61D4EC90A69FE28003844A0117538FC5CBE6F1B4C65B41D9161477C23D9F601B7B40A8AD23D79699A8A28271C000F160998FFFCEA6B0242ED8449C692AE85B64D3FB0C0DD3F0EEC1FDE20143504043D63EB4DB27DB8C3FB1A9605D1C13EDAB1025784FAA92BE63714F8A013AF297BC0C56AA291A0236E444B197704A03577AE59246F46EE4AC61A0FD9781F13DBFA5BA07E956DC9F7018EF0814B9C5F6F5EE95654D6D222BF1CD75843FC1482A8445C73AA2A82345904FEDEFF0EAABDF4F1936765A2FEE895F8A933A88C485FB39F1D36C9C6C3194B46E9DDF80B5F0C3F63A10C4E2C064D6D81FB4C9243A2C8449272C1B2066BC8E8662DC7130F940EA2B5BE2E7A5E31E1C7919F09FE277B7C0425C4477AC534E083789AD5FD06976D13DD229E93DF2EA8FCD22B501EA1D6A31BDCC34C225C858E6C307368F09071963A431F5DAA9C9CA5C5195AD9545DF69989E23871DB3D6BC793E5CCFEF6D9FF60912CD554416052E3D72865BD9AED12F48FFC38F6E9F0349566692D0E1711005C5925D3F679D6B118EFFA63CFE7C0892BC58A98FC64E1D0853F515CEB10693BC9D25960038A3F0F12D108D0094F0D4AB855847DB4F8B9D334D76589CE2A0F9C17A297FF5429F239DF27899C38C6BB426E459572A4620802BB55210E74D0B23334AB8686F2F0A078BA7668235E60E487F494165BE8BAA98565D7312357E7123443D9E161E663EA4E1F6F46BF36FE77D06A220D6CC7741C96C20925A99D7919588A21AE79F6F279E23D54CFC3BBB14A189974AA6E74853A494E780492F466AB4B49678F66A4C619C3E9BE8B904E9E6B3A0BAA7539C975E23FABE9BC401A4EC308239C73E9419C686A12741D5E75D940F6C59425C20137FC8F7A36E12241CCB1C3C97CC2C6D593C3FA81BF431C976C3369BEC74785BAEC41F8A671B983775416978AB2A779B907D76BEC0B25202ACCFAC15C9EC0CE171C330A1D2079892A4F5AE3F203A941F643C3C50CFF426BEF5833996312D8E34F4C606A9183A9B959136B7CB151E4EEB84361DA76A518285790BA43ECDED59377AB75B2E221D23C8CE880528A24C0E237A7A64FCC4D90BC0508C092D25F3F429A49F8FBE908497122BD8D2DE287FFA11273B61534448061426D37F960CD06A94E374AB6D7F3C69125F2FAA9B76F8A82E32AD4905BA7925415F0BB497F546191F4C6F5283E73D826733F1B6EA5B73A9C3874887E46D7F5BAA12BBAE84474CA1EABD2A5E83DBA51145D723B670187A2D54467ECB82C83F08636586D962147AF49C5AF9971B2F0F391F79FB96E2714C3D559D196511627487DAC91F0C011C8E3D73A6274DE801BE34762FFE9D030AD0282CE0DB79F1FF2543BD92E9EBC0317189C7883450EAF7DC8CAA45554D5E1359BAB98EF23E75A832B1477AFC4BE66C5160FF49E6F50B88EEF8DFC5F4C97BCCEB5BE1A1E9D0866DC8477C6C6F937D7D458CD7356A8770B4513767B2B4D9A8D29D763EF80698CE2605D0716DB6793FC46F46DD361AAB79DDC2EF6E41A1EA9D0A912BBCDA555DF3DE04C09F6AE1154306BCF9BD366FA43A1FC73CBDF41C0D46978C4BE84E999A94F9B36FDF1ECD0F6DD24A974E7719C3D63D6637BC317589EAC60BDEDE1208E05EC87FE382D0EA7179B713EF9C5DE38631081181C8D2E86A6957E5D75B2DB09CA1C1A6A6F6797F059760866B7585F0E2C6754237980B0973486C63DCD260E5846A23A7C9C45053078E0A1CCB4535F3CEADB65CACF20E74755179AA370F4214D81E9425261CBD181D25F192454B1E3BD890518C56D43CF46B2E57662E1BF523D864A6A705EC23F3B57578283807349261BC38FBB0D856BDEEBB18B545C96530722039F129D79F9784B99A960D32598C54FDD6D3F62248EB61DE26BFD73C584FAB4ED339AD7ED4062596E7908C2111E367352338AA3FDCA8248A6958CD153C395546C258DAD42C0FFAE0E5145F14F9883706EA9DA06AEBF193F02B03F27E261DA3A46E13DBE6F20A319230BE1A6E480C159B85261C74A0A4956799D03C70396F9B0F7605A54E4F2A928C7F68A2D4EBC5F930BC381EC7E347706F27C44CDA560A75623324B6C0415B4E78CEB6467BC987845917F63849F2DC6467154E65C8F14BD7D5FDD23547EA2E10DE39EC26C13AA36AC27728826CFB29723EEF5F3CB62809BF3FCBB0DBE718704CAD9AACE7EEAF4E56FF90DBB3E0F383B3F71166C25923580BF42364DD5050DDEF64B48337E0AECE1384DAFD79A00D7903E7B16885AE76134750B9E9E4654C819979E94296EAAA6EA011BC6D6"""), + TestUtils.hexDecode(""" +14A8B812B4C9129CED02A09C8AB19443D34DBCEE85AA12528B61F84A2AA9D9DA49011C8E2C3C3856FCF761EA9C9882FB18666F3EC2C8543037E54FEC1F0F944FED3D350CACADA9428B7FB7D9DA4937DA4D1859BEF8C6177F0EC93BD67FC3D5B3D13C34D472D01372246704DA4763FA73BBCEB0F4C3658B2111A7DDC01FCEAA9059FE3DD5BDF2A9FE0D1C2384E82926EB895AA529532FB20E12F1C61BCE208E48ECED036E4F84CD60F8042475749E13D8C3ABE0AE17967D5C6D8C598A53A10231929822FB01EA976A08BCC0D18B1F9B6C7C1ABDD15121E00EE80459E6EFD61CB8D5AF950F0A8FF2807C32CFF7A56661C67348617059D7E128A72C8AF36B149DD8B46537EDE60EB5DE8A16A93349883B73F7C4FB8CAFD01E0C9D7B1EBF6D7C9725651980E0DA598A6ED5114178E47EA4C6ECF870033A03F134461146717C8AEFCB8E8DB1ED4E286C68C7358FA105641EE3ED9B4A5D4826B31706CF0946C152A365B246DC036191613655B829ED1AF8044F5707C320EFA1126B90137EB05FC220F122AA990AB476EBB0BB3AFF5B92442A857F6808E144C60F4B5190794C411C705513BC32447D83B760E907E6FEED63FC0A60C0CCD01734AD55EE178E6BD6D4B8A238ECBE8E4F8A464C381F16F11BFE62DFFC5021FABEA941D24B81CFC3D0F07F00F902FC5042F95A81BB8B795907F8D6BEDB5E5C56D4B2A4353D0188A90C01D7B2781EEAF2BC3D3D58A6F6AD63DF7FD4D32ADBC5A7A2F81EE3F5B98E8052017868EE59D8DCCC0199A006FE4FF39699EECC82DBAA846AC60B51FAB6F456DE4357F5EA43FDCE4B57AED55F2F6EAE49199AE90F6CC4AAF662ACEC2724337AD7F9CF74AC990D3083FE384685A1E616B233752E31CC4FAEB8048EF77480CC849D3376464621E2BF48CBB55E1A7CAE855A216DF4A8D1AE4E4016958F5855FC395C53C23327403720271EFFDF1A90C44E93E74D71BA29D860679E877E410ADE48ABD0EFDECA426DA792271D813116ECC894D799369EA8094C328D7694E8CA47459F31F5065858252C1EEB1AC4750AEDDD327048894F7D79A1D64737EF6E8B93ADEB938C1EF31E38DD60E8B4174AE093697DE4207C7733D82B4FE92590358515D30264A408746AC252ECC0BC28A9C98BFCD76C75845E9611909B0089B571259D1D115EE0D5DC6BD6F3697E1289C4742CD99F97B5D3A22631E33A81734A5D2BD1FF4A819CD6A22A938D3F18AA90794C120F4BE7E14324E89EAD34820070F8160B140E8CD5D68378C081DADABB41D365663AF26C606940E08B20581F4E63AC6E68FB5A7EF5DF86047BAC502223AF08F6CD82E6ACDE60116593046B5CDBFE2411A3FE89C438A1E84CE6D1CD72CFD3E5F67C331E72754F6CF2BF921FDE2C6DD5481F20F509A6852AEBF55BFB4B52D1F8B3E397C9B147433198073049638DDEA7E21C2043C786C88E45E566B6A7E8742209F5ADBCD34FF26962E87CD235CA1052AC02E4BF75DAEE60A06B19A4B0A61A15D9651473DF8AAAC6DB951EB6E669FA5F89175DC1FD4D881D688C477D16CEFE809E623B2F2A996909C3E10CFEF756ECE8E93072AF27B87715953E0C48946DA8E893160CD351E48FFCC6847975621E5C75D5DBEBBFB79297AB368D13BA95308E3D576F1C54CCC1C4D5EF2A41BE63AEA2A9F9A27822ABFF58B06AD99515B97F260843DD2304C855184EFE96BF10420184CBA2CD3ABC38D11B7A74E4A9E40FC26CAF3A84BFE8794477335EB1F4C67ACC9513BDA5D8252E608D03C69D493F8876FFF25D39DCD71442707AF2681CC6D5E117BD24315B0FB5C9E8175CD42AEABF699B7B77C9A8918AB94518B48DEE1777EAD8F18709A824F277BC06CB67915A5A2508E18094B0ADD29FC7CD554D8671CFB47EED2F850FC84B1C0F27767B3052869B653BFFBECBF6D8077697D1F440019E3381FCB917F5C06008A04C8A88B4493698C1964E25A551B03805244570D0EB6999AF2BC467EA4732B460A40F7C2EDD2CBB07A2DFA99B4E5F4663A45F2774C1ACB0C8B965E1053E3AA140E973049714DD644CB9317D9B3252150CC9A525E8729ED4A9A7900B417875391F7BDCEE646B1009CA479A1295555759C5A7597A775A1D1CD8D870A71DA7ACE7CCC7D2F38B18BD66441D80068F76AC194FADB3ED5F4201F26F670621D254264A4D2A88426FA6077895B9BD794C8C84DEF942FC43F2FA115509429A939052200196CC921454A65C4BF1A6E871970A3409FB9773F356BC17E03EDDE8CBF2F91E7D2B548380967F756D36520009DA5032F20D8C8CAFCF4B561A4C2894CA13929DF2AFC2C1C9FC41968746433FACD66309D2A7FB5D90EBCE40ED1E80C12D07BCB075FED76DE423D9EE6B1C787E1039749A0E559B86C4079CCA1CA7E4A3EAACB300C453782071725F6E2DC0652DB5EBE7D1C16B6EE0078004ED1F49DF439107AED04A2E69F70A35057C36A307C8F5BC13FCEA76AA997DFD2E2E4B835677EE961234895BE9C9E7D1486C04ECDE36AF4F7075C0CED9A33C372C33F751C953A2096815D9B6186632D3CAC31AE6D0A931258014D6F88157ABEBEBA1C11B9CB2956253D4950F5B2F64476E4125848F27D9ED4F93035FB5F5DEFE2435E67DADA015F048A90EAA9780B983748CED6056D021D21F6FBCB1A2DE0C627F2D9015B3D9D35CA17C54B0FAF85D0C45A53DC2575E2CB54B9A5681FDB66C9D5A09A3F48DFF29B24E45BE82856C6C76F0B9680F7B666B22221E14DD8B22A15FFFDA1D666F4EC6ADB5B929C2804ED36077E1A39F166C777770124253ADDE6B77083ED159CCE35894597E7BF3DEDB346571C2BBF69AAA9ED133E94AC7E31F2C30AD079EB4B4452232D83E49B43DAB60BBD92673D90F187FA6F3859EEE1630D3A232B99F3F960E8BE49CCA0F1A519156D2D861F8B6C15FEA4C4635C23F2ABEFDE8589A45947D391CD1DC3439F965C6DBB5C5C9AD14192B3D784D1C78B3DF6719D5C474E02D471B9B857611E2FED83869BFE8A2A74493C25D39C78DB019BE93E3BE331131CE85C4586C0D40D676640405FE363646C2264DE6F64365F19F87A8C54C884703DD369FF52F65CD9179B8A09EB92C38C284E06B0537EE686D7BF3BD399FBA8E1703BE3236F8BA262E2C84D55EB1E1E55DC14780DBA04BC1106D98B05593F9164F1651809E8AFA0A04BB0B51F9FFD5062B495133B509A569845CBC3003BFE23A7D7ED433B70C2EAFF5FD898009CF1ECD9E9B6F37CD7794234A098CCC39EF078E3C152017CC73A19B811FAB4A2CEF721029F6200A4D1E4F9E95A0A758A7AFCFA047B6707CE048C3BEA6BC561D152AC4F161347C098F4F44AD92006090324757D73DC074F1E1D445A500AF5A92CBE19EF631D99FFF870C60BCA8515125EEC36D004F22FFB420F5CB01330315F00CECFEE3254E54A047A7FA3C7495E6ACD579A9159F667FCAC4C4448579E7A68148D5518EFE269E97D90D67CEEDC378657A45E9DA855EC55E7BFD0AC3E52DADAF76E800ECFA61F2BF532E7365C4FBC8CE882AB327961C6A48C24CF0F0E6F2C54D732BC9B592008F2E6C80F7EFA788AA6BEEF0B6AB7B21DA3F9D92ED8A8F5F3F4B1D1BED6F66B6BF3ED52E49715C07DBAFD67F4F253DE368619A306C513E645CB5F154F7823781EB3E15F38EE482757009E42CEEEC1530A0159D25F052F4D4326412CBE6CD11C0DCC56B6556DDF806868B83602671C96F81D8210842144757A36CD187EA0900F36A0A9DB85B9609C11DE03A38A9984003EBFDD4E7C07CCA7A7DC7FB5F9F16E6C0C32CF86774B46C56BFE2840D8EC51E9FCB719DD1CAC4206372126DC8EDC9A4A2EDC8FDC8370C7589CE9FABE0DF3C8CEA90E82944B8D489C0F52F73EA3E3BF56BC3644A1BB0AF88F4B556A554851593E5FCAB03E235670638E4AD77BF012AE074F331F67222899694CB5EABBF0D6E6E6CEF75151FAFE89DB9D66DA4464353526116B3C2F382825B11CAB3CBD221DDA588F4BA13548CF627B52478F47D9B61479730CD9CB3F6622702C9A115D69EC232CBEB3FA88AEB832EB266B855A98424B2E08A699453A891C89C45FED7BBA98D6E7A2179A24D41D201C4214444BFFE6D01A15CBE640C3C54458E8DEA5DED484FF7AA78541686C60F9FEE76D1A7ED1F5686A2EC1F0AA037E6CE38FF695DE0C17895C9326415840FEDC1675E9CF30B8C45F8EACA1E65DD18290E8ED826738876FE8B69DC3432174151C051FD23CA4675A75E73F1D3DE4CE172FD657B57D5D03FBF8B29E268B3EBB8E9BEA96A4750168E8AE5AEF6B34701276DD18F1FEB01FFFA2A984D3A59D05A56552639D506BAB3021D507D56D0FBD80DC582B3C20940DF2393AF24FA5233DF073C7FF28B54C7A921949960CB2593AA4F93A06D38D896D547B28E9CAFDB479B7D1BA2EA7B4A6BAD33BA8B59DF8792B22F5FFF41EDB1FAA926FA3CF602FA63ACED78E85DD7C3094ED48D1F3381BCD084A9909613873513657879AD8599403A52ED0D16AF0B3B43C672867700167323D37FD6373C4D51B90327F4981A897CD54C8E35A6A5904F5AE0CDE36440393A59119437016E8CC88894B2A6FF661C10AAD7C7B03B7085B70A8145C305D5E66CAA265AB42B34539CFCC9A62B5D9BD09FA4D3B94BACE361B4C6BF6B550B89922EC01041CF05C0E4632274949D244B7776D6504C9803A67CECF65F750F9876109167CA77D412A7EFF06CBCF129D057143BCF03CB1C1AFAF937E55477F5B15020149D64F53887467AA16C6692FDDE61406D552660B88AADF65C03FE1B8D485C57FEBACF8B11C569622FBC56CA1056FD3600E1BF51084FDAE32876BAA1E97637F73677E8FA1462222DA72FB0936ED66C16A5E892C44093CFE7B4E3EE33F21091E04FC4A07C6CA21E93A500E5D7378EC716A9ACB27A5687BCD7F4559C32F6C82E8C06E82135ED16C35762E94BFD6BC33D5116E4FB209C98C871FA8E9230FA807CF1FD509A75DFDDFBA5CD4F131FF8B666878697B372B92CDDA15D0113E8BB91A7750843B3D14AC4E8C956B44C7A3A26720E774EC1A1F68435B122E539C8A7515A1AC94D456BC4DDD54839AAF6EEDDFF8797C9BA3A15AC70C34DAF78AF1F0C21734DA32A79C1BD3CC8B2636E12B9D2E42AD10446EA1A9FFD45430E03A78D8F38B64B64C9D308D18CDDB4D5DA13F1B4D15157063E58C36DD71677334B4D9BF09D8C765FC68B233B31105D0957F1B675798E5B9E982B1BAF1611EFED0E39E1E9E70BC790886A422DEFEF325A07D97FC603866C2C3682FC651CFFCA09B8122B636A65E2D6B8B9FBE6BB9220959038AEE11AA7003A9C4C4EC9E27F4A8350FEBF1084C292B6BA9A6E03C00979854CDFE566831B077823B025FD1B9C7127BDBBEF34186C74759E32FC222023EAC24A6A6653A7073F4033D77CF83831E8B6BC8F26AACBC3EFB2328C6EC35C3A509FA85E2E04532DB6E466BBF8071FA6020CF5585C70C29320786EBA815EECA6FB2BDF9C9F3A3DDD0F1800E93DEC3C5E6DB4EA5A695865303C48986CE26346B6CEA4A734668D5BED675EB0C2A1FFDBB9E5511EC715BB4BA3604629FA28A53CC0DBA1E819A521AF8B7BFF16B4FBC6766543C0111E232157B7BE4D561618D6ED7D13AC8817641E7AF77042E96C7209F1B65C42D115234F6C63B84D381F1820CD656C88BDEC7CD2A814D6346E90841005F66D6E36E63C5906D19904EA0D33502BDED36E7D77FF5E2592290D6F29200668A25A6B6F44FEA1D3EA00BD4BA165D122455E8F97EDB36061DCB335870F44068EE4A64FDE5695896D6A5B30D7613BD8C8B11DB330AEEB0EF239C105CE6C0B2E1BD81E867A2D823FF88E3E82FCA69923E281A2933D5FDFAC6B217D60958D18ACED57D670851D5A6A445A120F5B563070995793E618F885F149A3A3D498C69A0B9D99D92C16327B7568BA8CC35128500FF515273099B645C683EDA30092C225D01E6337AC652586C0872C9C5EBF09DFECA43697BD97B86FD5463F529CF303A105194BCC3014F4458CD3BEE8088B8B05D58A960334C73E1CEA934CA0ABB2597F703428EAC5DF6983A76A5EFBB4A20221E6EA04F67273D52D0311AB99979CB0EBCE738B0BAD72F0DA80097609F4422D962DE43D5B9E27F2FB3FD55DB5B9E98C1E74533DE23930052446A31E656E150261C6658324BB243E0C55C43BB397367D9E6EE51FF7A3F4FBB008F87FDC3448C07B88F4EC3788FB04944AE1D734E00E1CC58052AD2F908B55B39C0B1FBFB889EE2CF91CC1B3FCFEF11C14B083F8A898BB28B838662274B9974AA8E83579181944CEDA7FCD9C36D5FEE67522E828D6FD9CD28537D9FD57C8ACC7B8F888FAE4673FFDD859F6446B41609135BEEB20804F4331E31AE057171D27D1C338DD976634A460436977192E7FED668FF01B7F996F00958FEF2F89C78367507225C458A7EF81513D849081E4D22013A4A8DA7E6E9AF687918486E785E2E5D4EA5CEC4F92910E6A6F89198FF7911A16D7B46BAC5752AD5F7457E9B65AF0DB57148812FFE9F7C70F5531D11CF96ADF7A3AE1D86039FA5CFD5BD5465AA1649C40A513FAD60B54F7AF15A5A6B34F0935BAB28A1AF631816A0F5F1E53E1A7DDB5FCE521252E25910555D70AE1A309BB1BAFB7ED3856618161CB41206810AACFB9F748B06F6BB8ECA8EAE07B77934CAB2FC72FFDB061D5FEAC548CDD1BCE7CE5D04E9D2E4F38834AAD674F0D540DD6EEA85CEEE4F67B1D572597E9F2B66554F7F835894E81F4081EAB2578CEB8FA95964742436FC6741A5A9D1F2257572E7026360708EAA41D31ECCCB55811D5BB7648EF4021268C8AFF001F2D6BB3E1D4D304374E892E4384D66869CFFAC575398808D2042B2A33A874BF364B6E7A859BBCC67ACD4B5DC3494C1A6B55CE004A354C8EA8F14E9D9A4ED282AC4D78909F42BD38D044FBC1C730F921A1C678062A200CAEDB0EBD42D48C0B758F138EBD6BEEE1E45BF92157E3279C6534232AA6C361953A0AE37E81261832F29CDEE864962D44CC6C3C68C05B16915A8FE35B067EA754777725EAB0BB4E20C3BA7D6E75812C498F29A94D18D90D60F49339CF46DCEC6F0A546A90E0BD6E75B95441CEBC0B25945F2A38F3EEB1A9E20805A81E3008750588397A9A168C73C81C97FEC1BC16659DB16AD7BCE275A884EF801D53868B0DB816FDE421A9D7FE37E61B699736986325592EA93DC18B036D5B237115C35AE3862E355A1F3CBECC5BA89947E6E304A86196E0AD6A113BED701D21E07532A6D02D014C9BDEF9F9060799BB79AFFB218F3B98A4BC9488E5D2CA13531842C6651621484207723F41055274364FE30601C33663A6DA49C8187008BFDB1FFF4B7B3DE89F7FB0BF57F2E273EE84ACF8EE91A5335364BD034DB6A1F8025E6522B4F3D6212F3E75AB34179B21AA28FF6911736724FDD4F3229C6C26142BE5D6F2148C9BEDEEBE6C56B6A20746875A6F74CACCDED95179AF50E1C5E09B942B4E3C5E227C1A9DCA36F04CB89EAC24D5E87D07BB407922341590A739B825AFB80F544F2B1B70D877300B46000E660A568999EB8F54A3809D6879935492CDD67DF15A1FA902AE6ED30D5C5EC1178AAEA8E539068EA2A0132EFE51DA8A43E5D48ECD5D8BBD0FEF8F90288E3068D17EEF4204D639665BA3DB7C172E99913E97613DC4304006CCB37F1E9F62327E1C2B5D97E31822A52298BE0D6457708E0E2EF25A0C4C932F16D25A277C5BFE1AB13FD488BDA7BF30F26E89585F56D827DAFC799D7DE3BEF0B41A3EA3491514ABF11E633D7F4B8A88CB6F3ECA3D48495475A33C9107EF39157D53D447308BA03139C7A1A9AB4ECB178D818DB6F83B4489626E2EE9464D7392C80F8B4B6317095926370681D1ABC3A48D82DE7A810124099E375F39E5C6683F4972556FF258996BFB0FB81C44E3C0C1A814AFAE8CBC041D7E7EA4FD830568DE534B65926D6CB83D306A36861FA2874234E33F4EA5BB8AAE05C3DBAB96CAD63295D7BECC26F5A4E862546A166A09E059293AC85937FEB612178B8812541A929B81A090FFFBB17DFC3C774C5BCEA1398DD530C5286658D326D7BA7DA3F2E15FAEB038B8A397B68AEF622EB10B248DCC942E7BF4B4C942D33A4427B685A0DF2BEE8271E89A366708C9E48F6A3992174E8D401D821DCFE12099D3EF0BA0806E7ECD674422731B0DB2B198C495E9DBA6294FC736F41EAD9232A5E404A8E918A18D7A7846E0BB6716C4343C2FB00286049D7BD823410EE8F71347008A89DF42EFE049C61CEE782102730944DD15C0DA322F6DE4EAD8F9EA549767BF02BEDB1F091252F08B34B6728165B11D2C62805ED24ABE65A8E95441D1D5FBD361FA87B39135A75D749325F09416CD3E1ACBC04F6AC8B989716C55B06FC784B0254A884EA4CCE8ECB2EA278CD32FD1FD99C3085585201EE9492B7F7A2259479B1FF820661466022321457088B202B5F1E67709B763A3A945B19CB5A6EF0A322272D98F8921B775A37B6CF92F66CF86FFD26F84547BBA75AE82411E890A7D8F1B74D657380287606ACC8572D8522B87CF26C0247F25A7F8CA12911081224128ED444C5AED9EADBFF6EEA9FB7485884093C340CB326BD467CFC4F6E6C17D4F13C7F9F76192BF4A10F2F28F538C76BDC1F8528ED1360922E5A6DF1A38AF9FB28542357231478192219477D554507A47E9FCA585730292493A2B3EE225E0DF87C747E0CED460BA677EC691637F444D248805FA183666FA65110AD3ECAEFF59B2F8F619A275034CE415DCEC6E68A3530D17EDE27E93D87EE1EA55D22045CF436A34F907D35264116A848DF0B448E4BBE32A18BBF16A8DAC00CA6B07876ED0720591345223877E26D2DF4C0C3FD8484DF1DC40F1B7D4D49E871D8F527837F1B790CDC9FD95D698231CD090C60915C98F1CE43F7825613FCF8EC929BBAB9BF663A555210868653131556553F7A36368B0D83AED6F9A970CB2D63163C607ED896FC7342A71C6A1C90A53DA0F32141600F28F31A9340ABE97D0C6E8AA3270850B6598670DA455F8E2816EF82D3267D39A8163D34B135221D7D5D98069A8233802810C7605AF9764C6DB44FB55E29470503090CE6A720617DC9D17A5091CD3267DC4DBC1A2B7032B50CE46522A2FBFEE7BE29C3DCFA1FCDD43AE2E09DAE7330D2E6F2B15D10F53EC6D607066504AC50AA7F18D3C290296A8D9ACD1F5A3708BC035979CF03966E0081FC53F654AD68A15A3D17A65A768A4CA5F647BB21872B1ACC5BA3DDB5F69DC215735A5CDCCF50D555FE968551D507A7272FB591587383DC5930C5A572BE9FE0C2797B622DA16C6B87A03EA563845B8201168C45E7603B80E5780E493AE87584A40A09AD6718CDA3759CF1940479545789F08DE83333FACC26D28AEB54E2088934332EB7DBD5829F0ECF89D22C62636063532B4361B9C7C2B1D582E9A7DC72FF7F2DF667D9B7BAA543FFA20AF6BCA1A9CC22B7D7D177B73AAB087F868AC68EA0CA808EDE0C2F931B3B0CCB28E472CB316C0DB0367D4D7FFE0C02977CD2E5B20F28867DB1EE0DA77C5935155175B33D3275426C3CC5B73748426CEBB3ABFC50405E30EC21A53073C83A85EDB485B26AE7B633692326003004A822F261D5E20246F99B03D0AAE36"""), + TestUtils.hexDecode(""" +82A8419E4D978417C3C821D056A9393685833E38237A688EBAE52F9D22F6204C7AA8F8BD5898702532B6A56388041730123C978F23EC29A03340C162C9486044FE5263C5BBCB894F856153000923BD19369563F96DBB4E44D2EE7FF2ACFACD81CE7057D8F82DA68C4C06718732002C3441CB07FD7F01F72E28BC170DC10054F8C8F75F0BC4757E2F97B0C8721B8B8462A0452D3E8A9D55EB9342B9D747019A05EA83C6548905F72B2C9D62ECF92103DF350C926D46C4994F35E54D436B51E1B165B5FFA4AB85D5276270CB94973BB49A5589F2CC9919546E51DC629D81573D9A0FFA2D52D31A1CC81A7FDB76FA7A84FD312804BA266A5882E82E71DBDB8C816ABD9A631F8619BB85E91BE69C88ADFF9DB36794D7F97617E7C118BEF10AD3178BAACC2104E11BBDF22642A79F05B56B5827D1790EBE998BBE2821CA1D0D69D5091FCB2677565BB6E50AC4F7F3D1B4DBE411692F289FC0E8DD072C3D93A2D617EFB8E3C914941792E39480391A8033DFCBECBA8710439D83A821D3224965CD0B95EF31A160334458F22C9FE4DAD9126399D2E02D6D539DB4865A780F0A5CC125537B00B581778BF1FC8125C09B319DB6DF5F9AB2DB766589DC7DDADD62CB3E67215B37C34B3D019D85E4E94E4557EB934519679947F09FC5A80AC5EDF04549B4089F14AE3768914D05E22F6FE2AD7D098C90F13E6763E8B230570A13B15F0779525EDCC704F43D8E15EED9E1FD7EE39BE339A3FBB7FE91EC51855BA72859BCE0F78983FD0CE5ED5AEB6FD5F1380507DC37F893FADEB653A5693E16397D1566AACCBD9853FEFDB2FCF300452330D3353344C51ECDFEC3D055B7B113A337A94B43F0CAD1C74FB3317EB9E08D5CF252584D7B3DFBC9577D7E440D5B70D6C2DAB679B9ACDA3545A9AE523EECB01F403F3AB123A3A6A79E89E5D4DAA2D1DE6652C09E4A62EFCD924CEBD48B854A2F17BDDCB2E332F035EAA85810CE6DAC97297129EB4827228F360D4A30F83FE0E5F05A69F115A4315E83A9355D3F02819FAED553EB1AC05C67E89B095D1B09689F1F30F6E5B1E3281C52919866F0E297A6E70A507AA3643C5A7B1217BCE36851BE4A45C2E690FEFFA210A93C8EACD644BBACA1B3668B61612CC299ECAF8413AC3DF9493FB99F1FCF7CD4F261907B6A7E823F5D7DF62856EA94351AC0B1BD24532E8A58B7E9F49BE2C0C8C6D102327CA90FB2A20AA533BBA2CD56AC0222F697914AB7DB037E53975821F4A4D12FA24D5C8E0981B02475ECEE9DEDFD7EBD71A3D8FBD9940717A70681D3A5766082D2012D534949D5EE31E9CDE629B12523C4CE1BBF0EAF468A871C06E4CE30C05D5D5CBC7B75604F0288ED84C49FA80897281F4C1BD56D3ADBEA4532F6DACCA40CAC34575BEA447DA7EB2D7BAA676971D5D6C1B6EAE7F4704E46F9EB0F90A38BA3D4E308A685E0EBC44DD79EAC9E93CD94EBF8E6557C877F5A06F11C9AE05882D653E9214C6BFE82BD52B2E74B6BDB1FC72150720DC9F92B8BBCD96B0FC6AE0C8C51CB35A167FB93E755C7BBF39914D5BF1AD32AF8E2A53C4AD96B73F6BF5987389C4A089FAFC2527779FA3DDFD9C23AF408EB7637B0FC9FE1937B153F63FF3502C70DCBFC15E1E2817F3AF7DA6552F46696EB0E71D992B391B3A550E0C2078FD17994F8F9913ABEC08E8AC2812D2DB1BC7C1A3E718F665158BE3D92199EA226E5C1E2CD56A8B0D7A780A50E2E519A81E13909016A920CC7D557CC10AE56274FD6137C292CF4527172093E8268E1E4ACE29F9635E34EB83799F9E3901D5DB653807BCB6AA5217923A7FFC77D941A878383CFE455E5D84823A5642155097F60768F494C6C4D8737423FC66575940AAA46E62DA5F0EC6F20F517CC5D7F3FF12F7E127E0EAF8CFCACA2A198FA9EE5A0329926B3AD63F2D8EAD33877D8346965E93FA5E985E5171498A4DC3E6FB5CD914595D8FDF971EE1F63B5ED27B4D74D302ED11D518004D4B68A3666658FB3636952387055D0187FFBD7C18B29AC28C8A06B284EB0E9543CEE183BB5E98E4BB4CBE2291964689C98F21FBC4505F309B1EAD2FD6431CE913EC4415C01E3FE2B75586041092E77E2F2D1BEEE3084BF9F5D9E7D035F4E789924396B52EE47C502FE881520895C0026297F7336A50CD0FB46E966D32E5098C665AEF52AB2EFC89FF5D7378B2E6972291A57D4A82629F3F14D98B707B60704B18B48F0093AA2477C297E5798D34E1EAA25E8F440D8B2E2A4C556B8DFFB7D08FC690E15291FA768C960A8C7B962C03632452AC7888F20170CABC04B091D5A173592EFFFCC7860A870691AC48D44AC35F29CB7D57971E5051349D699DD8B511DEA73816A592B7D4E1C66B8406608ACFFC09F872AE6C2B13B0C8DBAA51186CF9BC3EA3AAD2DE618E13F0079984B11CB092CD1C938D3774AD4708ABA354880F98F0B3AE28E6BB4C8E5964FA69ADB78A68B075C30E08DCC8E8849C0631B8C9236E986D2E6FC6C3982F5F1C4683D7C61B8B469B617EC0976876A69C22180C37D9DAABC654A91E991122EC08BE674E9A02CEF4D0EFAB94EF5590D5E797490810BBA7894DF86219E813108BEE6541AB9E43F68AD43477AAF5FC5670FA2FAE1B3A559AC418E674994CF8E57BDD99D2CB349E09C1C68E5568282DF501B34BEA35D00613FE208334573A9E88710BB32E68363EB76F6B9F29297DF743609622345E4395BB52B9E36EBFB5A5A5F7F8EBDDB081C36AF9C26C9078DC7833FA7ECD78A4DD3CDBAE9C56ACCC711E29CDD03B740ECBA5D0A53E3F0F9379B96B9561F80186C4F0C8EE7BE11FE864B6F2E21379698820C32C12B8D8D4AF2E5781830E84F03A9E84B66335A3A454C269976BE5CAECC27894BC71AAD3AD6A6F0774D4DFCE48D6882E2BA9259AC6460801256101A35CC1C56955D8589C91542B9CF947EC7504FAC304C57C8D862A292DB0351DBF5B5B100D037479A401AA81320680C4EBE9E3A954CBE168B24F930E9928E1DA3714BFCA4C2D55DD971EDA243A92122F3648B9E1DAFB6FA303E4C48D4085260984AA0334713C4CED4116BDB3BD10C004451071AEBC2635ED8D401AC9801C694041B8A25398C50D0C1A7A14EC42A403ED3572AEC00CEC00F51C170E3E3738F7DEA1D64CB61270E38172760A71B7A9B52ABC0571541FAC7B96A9C0B3F8682E8BDBAC16E049BD38396787004F4BF722B6ABED9C5B3B058D06D92311EA9D2C67496551F2BEB1D353B52AE714723B1693C7CA78B1D0E5F212D2DD95C34DA583C95ABE1BB4ED435C5CC4105390825F0548D2D960B31AAE5558071DA276F28AF4F96B1FDD20A51499858839C80BDB845F3F799855AEF0069D20F3C9D455F34FF718B953B6B3AD111CC5ED7AF7F0B37969A0E474B21B1908F54806ABB8F6CE24F147C7767D10D1C42EE17FEC645253BD993E85DD82C77483667748E9AD17E463925EF4756A90EEEA62E0B9984CDA389D9B784ADDEFAE9CDE3279BC9DA177D842B9C1964FADF4694D9E1519D40D49D194089D1561FF729B41C6A111B749A14B2F84718892EEE595CCC97CD64048379024D76F04D31AB78348887B53DF69AD1F376C69D7FD86D919C98CF8B6D974C425D6C0F9DCC70DF596C8025E1D60C1D0C240B02DCABF093A7CB2287A5596FA1C0170645D4646584B4A27D65452AB91F79A9AC938B0058C7BD069DF24F5982E923CE56B070C84109C11ABF5BBA299DDC0E9E78E0D34488A564D4313562530828D732D98EA08E73DF307184470E3A010B8A0662BDEDE5CBBD15AA4438552D809164BB6C3D2B2F0A8AE13C3D78305A7D3140925D0A5D7E5F14CC168673E682C5779C9A325D3AF591B88BE881C47A313395FA88B2680DA2625AFE996BCD98748C2E82EDC20A3EBED94CD3FCF8FDBBA910D6EFDF22B66B955FA84D5476686EBF6F8A29D90F679773FC237211A4958FADACAA5C24ECC9A95A3E6D077966577159A32D44DA9FCE2689326C56F748774551E9F121E43D336AA2A2766E0A1E8745B4348BD36169D11A7046A98A22C866B2FB05EFD40BF95543FFC25993F2B516937DFAF8C9211D6CD6E10EE1FC1C4A6CF29999E7A63222433A4C54B98F00941DBB2A8B0AC62FA5C32E9436F9B2A88E1E683E04E36ECACA272B9515DE52A1B5ACBBB0C5946DC21665DC7DC6CDF9FDF40C9A0273BAF5D5F052F955528441311D12A7B92F306BCB08687CBAA3C094BEC781D3A05A3AECB65F22F086382CCD76827F03F1FC251428776FB4BE1AA65FB12A07F288FC4522E3BDA80C0195A2AA683F18BABB2DEA6B8A030A4FBE833300D1F19CD52FA250C178E214484B528BF01CB674607F5D5C36A7F7FC8EB52A25645AB38610104DB09DA179748AD16E35CF972BA3014B683029DE092F966F730124EDDF09F91D145024C74DD7D48A28F5111B73D3566C1F1FEEEFE06AC83D805CA81346C85B07D80559747A94C7AC24DEB3E54CC75A73235453DE3DCE3EB31382E83E398EE877375CFAF27199B51BABB70DAA700B8D0137B46AD7AB1AD0DBCF1686481C770305B2FAB0AF378C9BD4FBF9C11FC744970B5E2716FDD7E79E2FC57749120AD92292750011360A51987CF58998911AC914EE82C56CF3ADD2B8DF00EECEE9FA4C5D1905CC1A97A7223CB86EC5F1ED278141A681D772CE3D5063754C549BEECDDCC422A9C5C7832155D0EAA42D455D7F7D916AAEDB7DE3575345C9B22F6584E169167D818A8BC670B9E2303332B91D52CEA5F26674B819927B6374429FC5AF1BF08E8D9848E92BE742A93118606601D8BD2E42E1783224962DFFB826770D960FC9E0E5F3D68B635AB2C277FE0145CC03523FD06F52597A3D4AAFBB191B9C2BB59CB4E89557D801E77D491BA4A1FF81FADAFB2AA137A1AD099F839F60F74986A4E69E73595F10B7CC6A2FF94DF6D6887FFC45E3F1A39B2B0AE850862022CA4A3495FC0944964E0C5B517130DF7C7ECFFC8327AE8C3AFB665C751471863D3E59D79D8BA048E5C07772705024396930188C65CA8C2A3B9888B9D651483F7C2E96EFFE962CD5C3C26B781C506977D761A3C0E3752F1E45889AF1A74BC14643D44E79120323D0C649AAD09FA903478C7F8A4DB3F96514F78B6D8D46195EE66443B11569170CDC7898B3514B7AD9E7165CA58110EB58801E5E10466DF42E347CC690F6C9B95196F143AF84E3A81BC412F7BFDFDF222F8EA0D6F742C37BD4DBB77EA9BB0A942B10442285BC11F631A19A25C34B01C11552544981A3A6D0BB4DE21FBAAA2FCEAB1D65B961FE7D546C7942FABABD25F3E605100AAB09A0B389F7AB58668D31FC54EEB0433DF42D64869FD5662233DD5D48F7A9495E30068F9C80D4A66FD9BF1C7CBECB9944C6B79DBBA18981F7D0ED9F2945BD2646464D7DA473B2B64A9CC1388A0A7B588328577B644EB7EFF0E62A413B56B422D9FE36AA6B2D0B7F609E11085C4EE889CEA76E41B4B0DCF8CC0E19C656A17EC184FBAA22AA3D6E5DE5EFF0C212FC82BE6BA92653BBD044726D4E87AB68A1CF0A80D0F8B8860EFEEA3A257605578EFFBC43E50A8E86C9663DCAFA6793BA37B116272F8DCC803B5E9A819827B84EE975CAF6367E421B9970175D9593402B7394EA56703B1BB241592830EF0D168A4FCB54C0F3D88A90D5A1C2F977789C2DA3ED638C08F5932E91AE20341FF9CB9F65E0C07656D9F79420EE20AFE7F5C9F49DF3C87B8D23E709D1FD3ABF9375E095ED34BD768F8C07EC0FFE9A9C93453197738E16B76D7E02163B489C6F6426AE9BB86AA9A653F527A1D93FF780411ED5E59C478FEBA710D2C475FE2B2649E1FD940BC1223CDDFB566D94C9D2B4D0C91D3DC2BCC6F73B4C586A5C0BE72DA7B1B5FC1164B3E3091C58BB89529B83C3578A82B11542FD27B33D2ABD1E3D4A45EF0340D912BF8EC24C2D315F6C9F58F68AD0DA46920F896241EFD7F98DA1D10ED22BCBEB6A273CD7B29BF273F8B6895C05A622687B2BE13B3CEBDF6175CE25607CB83E46924C5CB00BFDD6F73F2C5DE790A87DC10FD1C77CCD9C9630C57A1973AF48EE1D283964891859D64D3FFFF8EE500DC4744D8871F7C2A735AC4366DDE9F03690AB740566F611C78D3E238365A017020C3959AFD4E152588F5825F5D8DB0A840FF6C7BB1F7BB87BB7BD1BFACCC806975190166EACB26FD8C388D940591A68C489D32BBE4E607541D05A6381157D53AA2120216C971B94E2FCF834E8D37EFE65EC5F086F30C316C889DB23FFF9B152718897AE049E4A191A043ABE2BBAFA94CE73F1CE17DC47EADAF8C8882D40000E2AA0C703C04D5332F54A0BABB7641A1F4C3376345B5800D737EFF9D99BEB908EE59069F504B6B8625A2343F070E6DAF42BA24FB48B9795332CD5A9EB317FB7DFE4B2663A17F6270BF75F888BCEFB51844E711A1ADBB9A935543ED5BCF134C1F52E8CE1404F789D0BBAB14CD229F8267CD5F631B9BA284F6D633576B6BFEDF1394A5673CBEFF90F172B3256799FBC0239567DB1BDEBFE05ADB6C71E5B7E9DB4B9E0E1015E7CA4CBF706073341750000000000000000000000000000000000000000000000060D151D21292F34""") + ), + new SigGenTestCase( + TestUtils.hexDecode(""" +7377D2CE98A125D2293896EA97285838DF426EF6D3E06D3EDBBA7C6BF034FE0C3DA0A5CCB79ED5176DC24ABCE7EE76E7C1CD259CC05A4A784C8E7DE70FE1F4C1CDB96CBC97A40CAE2D0F29CBC084E65111808FC3BF9FAF728738346768C481B8DD506B9845F3A22B533A384D394FA268F6B8C863112AEB94D469DA66C7AEC36703035149C02D0B124CC89825A2A644D4A089010549DBA0885B82898B042094064D209988DA0432D2A80D8CA08922955013A79064222401202D9C144422B16892820D0B821180B66C62284EA2B40C08A35122C760DC20510CB77104446194006523B68058820449064199920D18170C02106E12146D40024D5BC40113056AA310284AC0302180292226455A384E8C040A08980812436ED838491318295A90651B094909B7248CB04909B28C18C34D044989420645A2922191A42019409198246C1B877103B40102048201B14801212D14130C1A204D0B176CCB046A03485112316E0B4572E2325013192C8AA640D98064022001C9320209100E134849429030A114120392445CC84CE24212C00844E0B62918A00514200241080E04456858B0101C1930113320111280028689D84684121168A3A0211009718BA42C0BA1450C279214972D01354E0B230C88C0418320492047660A908889064EC2B8449B206911B20413C32C40322E53162011096611072CE2420CE0106D1947720285254B264E58A4815848861B068E12126453865013338D8298500892285120111019708024214234080C1306CBB46CD808000CB3659042124C82612219296102411A94410980490A2580431450DAA684403249C18008A1067101C38514102EE1B60C99244459006863201104134A0B4104242352929845941872892249D038494C8490200164DCC864D43440A428060BC009E482104C82411BA088192649C4B64822208911986CC9C240A03442D340710492708200651A032C0CC4118CB42CC032051938280AA30D63A04D24C03012864DA4088559380659B868013852C8C4044C900C4A026582283101A7091402449AB8691C85701C414113148E0B4084A012120BC88559C82C22876912A10122950D64B06150120A23344DA1A64151C28408C20DC3825120A96420B325E0829118C94423924C03256EA28444A0000C0A4712A226621B43311C17464BA6458A340E228830C3368518106E09038E01322C01866010C4100AC4204C2282C8C07120B848D1200200426C081200E4A8040C444063A4718A304CC8B421E406521C92509B4889842082CC406108155020B171C2184A4A246C218421A3B004D2B608A1880D63B02C02B4455AC881143606C8C410DA86615B3466203131D9240D20B530021206E0264151040EDA048E4B2822A444319B008ADA822023086D1090888AB411CAC44C980282A016002128928C44325C262159182D101571CB406840C22DCB10669B30024AC00023B84C138724A4B030241764E1120604961161068084000104840D204461C8A610A00469A20285CC14880886481002620895240840401B421120A328D30401E4381051901091948459C8299B40895498681C3712C4A0905A180D04312003B5800BA6699B28244486509B3242930680E04251E2320A99420DD4A248CC929004B9310C366C09185200238600B14C24B7014A887108A1511B850023A328C846529C40848A8045D4C6715344290AC8650B22304C28268B462922008D8844691B230110C0480B492064148024223104466E21448A09430A22056601896989228C24866D23337062288E5082708CC031130341C1022D23007188247141102E09A684133266024661C9B491C0B08403B90CD0821012312249B00C11356A83A6444BB64562A84199444C63A645DAB42DC38601609680441206DAB840233170C338925B1271C8A660A04402A026068A305283A0458A14825B268C43445222272510332E8CC6414BB025521025A0142940486522982811194E14267102336420A80043124C6128241B3952E2C8459C086C90B6050B3452C1C06024210921A06053C68013360202802C80486808A54160488E1B2784518420834244C8C88C443690CB04860A42269CA62D9132101AA9515A320800A5845A8831A2B8641434605A146414152C00C90C02B510D3A229021728E40826E482014B280690B6851B428D10C225D38409C8B029E110882024200C280512454DA807B179BE146E96EC60914E74B78099DC2BB667ED709C1DC39DAE07760FAE0FBB086016F3BE0FD574560A68A9DCAC7A44629362330AE6293A88276F4B82BEAA2A42482D9C708EC75E60DC52DE3B70EF0F8EBAA0F591197273AF0DEAD7CA2BE5F6B7F67C99AAE59A016938F035DAF644ED94B5E9B64E153EB0DC49EFEC8F61BDFCE44B28532FAE0FAA09F430F4DCBDF34CAB952FD7E7C61C8FF1C36D9CB8330B556BAC79C4286331D7BC0023B643325C4E23B6E544D62F8D1E3B8B5F1241BE69A9AAC2F124DEBBDA3127093F4EA42E9DF7C7BA388E44197FB95FA17DCD6E6562D22C933C32A73F0D3FB9081DE04E513C9047F4DBB0F1A085CCBDF80BC0B6BCB652C302400F2D4C0C67B3698C23FC888D4BF06CCACFC202830D84ECD416189D0107B2F27B173D7541335004AAE5DFFC0DC60854298B1FD961D96BB8672A679E0D360150BA1E510B7151A440AD4BCE9A997B5D330DF5EEB6449264BDD4AEE6A86B8B00E0173838F2A645C9D8C4673908F6DBFD634034D840B378B185B21C92BBDCCCA0804ED6286FBC375473C46AEC46415B468CAEB97797FD03C374E422461F0807AA53D4C6CAE6FB5AF4C5EA616D295C5DC7D6886E5816FE47313A90BE1A7B8D528B96B351F1F0379F7F4301D7C669C0D27813EFA58827C26F04A09B4D9FF4B6007FF8BCCD3CB91E7CED0CBC1D0CDAC5F9205E6C9F3A1CD17FDF88CBD0C2554D162BD6BAC9AF0390A80745C6221B1CCAC44C6FD5F68DE32A9613AC4D4F77640A04141CA967061228F4E2D7C514C9FFA349004C0251E631C10B45BE25F148D37B05E14C3DF976B20EA5C26925818058584DF8428A8ADBA8377F74658834B3A72B938DC6C9FF8F923B22E99990730CA9723F531A5BAE5D619725CDEBA78FEF75ACB0C9D3BCD9C5BAAD600282F4145BF3E3BEB2A1BA7AE035659CB10F70D11D7F0A5DF5671466CF6554766C024AF1B9914F87BD74719DEB89014A9FD6247D089063D1578471B5BEDA5907825CD0A024716C21B186F3147F3C1309968782D8AF9CF40024BFC067111A68E27FF2E93D640657F422FC45537D9EFD2383B770E3702E2DCE1BE4530D17E4FC4C3755D47963B6E0184D277ADAB8037117DED146924DB13A05ACA3D7694CEDF95A0603F7B833ABAF05EEFBFC2585FD1E332070F63B486D93FA9D5457A09D9D27F84E80D49DB6548326D5F82A56B259271AD9EA4E90875D38718B2EC45E97F556FBB48FFDEAE2FA95A2A8FE1979DD2F48047685A3362C5F08B4C119305364293A498B4871CB7F5DB4E6B62E909960FC7495AA997EE6B885D5DD0BDAFC89BE1B4FFFE06789F6AA25497BF225B9AEB737F3C21BE2C7FDAF84F495E8EDABECCCDE3B0D60AB7E5958AAF5D0C5C062ED8775DBFC07E7A54EF47C8CEB59004FA347F1799481607497CB029C0A3981E564D4290C61BDE180CFC82F5ED40F6C89AB93635AAD175D488C1BF1C9A787DD3586EE49C028D65BFF792842D76F20E643E4E14312B1A52958DCCA1D9F7E0AEECAAA07B8BE1612AB2D5076A7F079F3872D8CDB5B128835436D14323732FA806B82014022F68E04862315FE6F16EE9254789DB98420BBA3F0DCC51159CFB7EA79E248CA2D21879E262DDBDE7F9C10757164A7096F5343AFA7ED777B8E2F0D13DD0A03ECA6F064EBB01E2FF84DA3542E1DCF62E7F911CE8CF632DEC6E376690C5D05CDDB42F7B0ABB6101D164D2A7CE931A12BCAF8E6BFB3D80E6E4CFD5ACAB85D4807054C406B7A93FA29F3589D5693CA4294834542884BB92BC1C88BC27AEEDD69E3D836130DD467F5CDD6CB82C2529B1E82837864188F6BEA25ECD031A55CF035A9F8523C30D30F93D2AB7BBC53E3E632B8F432BCA0D45F85FCD007CDAD638749DD09F7EC85C8C6B6FC7A4A3D87347515C73F64900C9B788B9E27C73469823C9FB6DAA6760D95626E74F18EDE6CF3E5888AFBE5D4CE686DF584AE67B5C300E8352288BFD55E5B8337A4CCB872BB999E86AAC9EFBC559437B10DC290D9A745692795D178B9134592232A696C5F0FDD653CD10EDABDEDDB746082AE54A800B43235DFD791BF7AA582155794D67204F87D9CCC52E51DF8ABFD24A4769C423C70B256C2E150844659F68E974B277840E98A6879333966F79B7A41ACEB1110E7E8B9DEB3D09C18285BE31A833AF62923E81B2499AC91F6273916B8E067892FC407074D2A99F287E78212194CB3862AC1F48D4B520B592D3BAB72D0101FE8FAF11564C88DDE8856FDA56AEBEFEA67B7F0BC4836190A8E6433F3698C0837F049F04AFFA2313FCCA95D22744C2C6FE08FD296E884E4D8BF1C05C0A7792F077900647B7D496CE3E2FC2690F2EB4402E853DE1BC21BBED13BC4930F1F3672702D9E676EFCFC6DBE120C398D6B335CB7F0C2483E1334FF4D526D59E5DB66E2B6BD865CAFD3A7EAE254536B07B67F7D883B92E0A0F59FB17F1B116626479117418F09F2C158EFE88F082A89957F1A4A625474C970B0C7BDB0AE0552BECE8485640C4BBDBE3E57D23F8D2419D8D5FE63CEFA90B239F611A13D2768212AD616025F3989FECB6834F3644ED914D75F08B3DFBFE497731FAEC81F84136A312BD91EC337E82524FC5E00EDDC07F59823320FF38DB34224BCC5502FD7BD572ADCB0EF53E4C16A35F37AB8B90E908016A649588AD1917FD5FB489C105CD2E59470EED23C90C7D9370F6406BF7EBDE494A658CFA1B93515C9894085DEAD882195E381BDE00DE045D1E1D4378D0DD80076C647C12DFE6441768CA16424331A8E8694C8442280BBD5CB6C1B6D504AE2DA853D089F56100E2ACC709A43FADF2FF110DDE85D2AD3F9F74854931CFD1A45CC769A444CEE253817D66AC7D8D2E0088A63D86608DBE29D1147AE85BB7F8EC87564D70FB2BFE0EB6D130EAECE850E9E030E1714D9E9A5BBA7EEC0FDF5BC660813B7893342B3959D137253F43EFDC6214D20B3C3C905A4813522091FD9D35D41193ED8E8478AAB5CC2650C19E4278EE10FC1F0EF3872C4CEC40DB39DB6384193E67E7E105A781BFAFCDFA8E88E1C85C5B893B8A442B4BEC0ED103F2F01C756B92A8ED8BC184632F9344C16EA3062457171CEC635DF6B1994CD1737C23CB37C32529B8A810DB30AF3376378F3F230BF58FDC564654ACF8AEB082E3C4DF005516D1522A7683F7A7092874861D46C44F605DA94DE8B004141B30152AFADFBE54744B0C1DEAF8F13221C050A9F4C967C1E5BA7BF78F579133C47767DDA12CFA827E76FE8E4CF31483E883ADD009639ED4EED93F4956D93449659C83EC23A7BD30AF8A55C8E6921A3B16959B3F1386A517A8C9416C838362E9AE08827F45BB10C1D222694AEF09B15D79140F8C0AEBCFD88394FB764371B67EF88E64C4140F34012179A394DCACD9E1CACE336BF723BE8FEA3D5E52E455E4F49F3900BED703ACBA38F27BFA3319445C4EC2EDDBF9DE7F9A1168CDC603C2C642764DDD0ACCD7809E98E4D36C838C2A57CDAA9444CAE82CE4DE5CED4377CEEE1922D10C96392262B4A57875A95FC4418A5953BE192580854EE92AF29E0949D4FDDD15AC811279E8E8EFC95183679117FE9C43A26AD455960A07FBA34FAB01386EA50072A0C5C026D1FBDA924525F3DFABAC3BCB69A7D2F800CA81872707D4EE0AF663768506C54A9A036D4D9C3FC3C20F8CC2203CA5F8DE285F70F4919A8044D39FCA06F484084F4F29471C2DFD3DF9E6D1E1AB2DE12287DCEA64E91EAA7C9C4CAA063710F4637983E66269D4C55CF24A1CCD1F02A08FD00EF4154DDDD104040CD15F588C93D030AFB06B35D7B06C3150E00FE3421DD24BCC0BEAEDB8185BB36D4E2F7A4493B98FE5613AB335475DE06B3E75766E9C662973A3BA91C0071606E4FD56EF9CF9E174BE2A42D8158207DCB81EEBDE31DACCC1EBC3BEFCEDF6316F929740C1F54C9C95E1E890D0A12CA2EDD0F265B5C3381DC8B1C2E719A4382862481E9D990F70ACAB53DC63BD502D9C99473CA00C452A604C137921E7BC050A776F03EDEDF95634FAD43D1DF4A239F047595EF220882097B282BBDEBD72AE26AB6DB46930E9ED585943A7CFD3597B134EBD74EA45BED2E3E06601DF441D7C2C9032E182B15E6B82276D4A450146B533BDCC662C9EB3D78EF75CE870272C0271C949DDE533FFA6CB4B9C70224FD877054B500D2D6192126F4659D11DFF75F624CF2304C92CFDCC1FBF02D57BEF75C69AD9502E387AB0F3C8A225D8486BDDF480C5B10F9442BD52A0DA149E1AD34185767A663A721218C7D06AF3E6AE29F5DA9BDB16E70856C3341DC58B8AB7CC133CFCACE0798123CE6C4735477CCD8E10499A0BC2D992E084A5E438605FE967DA5A24D0F66F769F78E2B321282717FFFECE8347B3AA78FCDD633E53B6709C2025C89A6DA9538AA643B833718A85477817AD8AF7B5986034CDAE1A4816C7449C11A628577AF65AD999EB00D08AC57053ADF533B2563001D08B001A65D46970E00DF0F83B692FB8683FBD62211B706E53C4AA30DB159D14235D0AC88FE1FC4FC994277A3838CDD84A0A08061F85CC1575831E7B56B87FFEB5E404E64B72C36966323F98E8A19202FA7F3C187E925DA291FE4C3E34A06C0C5CEB76BB7F8CCC0436A0001DB12B261BD47675C2490C914401694FDC04118372678AD2AE171F40B51C6CB4D40C849320F58B877CB72B222F2E4562AFC4C2FF91267F81BCF6D31DB8BF838F6EC3A3C45"""), + TestUtils.hexDecode(""" +4F4C7E0134BE5200C4512299D134770A64A76B73A82463FD8C86594939DCFD9DC55B895B32A2E96B8AFDB8CA83AB857679C372CD88754CD8A7B0A31D2ADDFD7D1BA64556AAF1CDD674F3E8F5FC0BAD2FA38326365918430AB2344CFF785D5F73F2B5D631DB29FAA0F9CCE5CB7FFE0CF4AF1C7A8950EF32F1D72080A492C7A25ABF67F409FF5D4B1E0D77268C0A1B2A32D9DEC61BB71EDAE6BFD58F274707182058F0E6AA31E6D3763732A82BD6F2C76647C7ACAAE7FB4AA51125F0D2D48351B6A3FC7FD18172FA8689AE1602C4EC0CAFA863AA98BDBB1CD8C2681C2B6C5C254E346C18E2A270CAF2606A6504D30C0E2E505C2FF9D18523BBDF21424C645AF0EFB2EA0FD21B5D0CD85C7C1EE176FCF904B481855C4CD739443F3340AE48276E7F4BDC00CD11C2B0D6B97BD00AC962EE1FCF8A73D3DA3CCBB3B72095CB33C5542D86E843641CC98E27545F99188AF064D5FE74739C54F5678F411D96A0EA043652935BFB2E37EC934327C7C841CB0CD04EC17FD06A18E88882177B51B00DB6EF1DA164245A3F2554CEDE8C84DD777F0B92CDA456D922D8B7B8B63B548CBB72CFACA540C0D69F9EF21759F243CFA03EBD6B080D23DD62945E623BC4F8323DAEC1215B251C35EA13A0F081B86E803BF37DAE6D913B7D942BD1C276ABEA3F8F74D0C8727EC21EED2AFD438BB7"""), + TestUtils.hexDecode(""" +EC857FE47C6764CF4EBC33AFB24BCB47BD927916A484087D8C0770EB6B0E09427AFC3C3D41F83FAC1FDD609BFEB217C6DA6F54792F0B7C7BD05251CB34001A4B77F1DA65BEBF1C8CC8778C0DD44E8EE655279A96860E333F8EAFA468F3B2C3CDABB00E4444EB8F6E11F4284B17979010335493869C1DAD4D88293C629900A5AF6EFCEE9D0A685D712139FB5CEEDFDF5212C4DD6436376DA5890165B11F47B45251FF9F83F5218B966C0A6CB2C3FBC25D50950D9552DF6AFDDDFB6FFF40CAAFDA74A3A6E697142CFB3F3327293B45528B3D46CE998A24DF46D9BAC9450E64D73FDA9A14307E7CEDCFF2874E65E8CCDCFE66E93A6D07BE6E27494EA75170C4028173C638D7CF1125D3F2FC66025A3B0FB83F80EFD11B483B7CFAF05B86AFA62C2E85C4DEF6049A11C4B76E9CB0E9A959669B8376359D21C26DE603C0CCA5F99BE34872B9279E50A1504C20FA0DEE99BF757F68C0759E1287618F86F157DDF2F8D532D19F77C42914FB6C3E88EED0E52A939BDF22D548937C19185516B9358B4EB34E03D150B0B4AFB629E754BC5E4067284AE7133D0D5EFB3BE5DA06F567A2A4B1E91E8D1E7AF50B463E1ED8967131D6D1C33FEB94011E8ED1074D4EB2E4D30952FB76145541E5CB643750223F6952C196D51393B3184AB35F7E7B4929647721139F7D115A9F02745B46C22BC5C5ED151C7F764064C453179B221935EC48128026525EAF5287311AB4FB87824B772C093CC21DE77E660186B8D5A4493DCF0B4EA7A751187C9AC73953F22785371312FC4D12421A17EAE731FEFAE466BD923E08BF2196A820E94E1D0334B2B86994CACACE28256CFE1B1CC5E56102D16CDF512D5135668803AC9BC931B20162D17B1861C8D5A7584056E462815E9726AE29CE5BE9547FE2A698E366865949169F30430B8CA0D73037223B6D2D97F6552ED21A2FC0A9804A5B12F07AF98D44FBE3CF12927AD586AB80953B25D308E3863D5AC23A54AEA7A0EA0786198F6DDB4CACBC2EEF4987913FA6CFCC6AB0354EE7A226CA9F46FE5C8EFEF7B9D1B3718D27FA1227A47F213794116ACBF4F120175A189DFB83D786C2F89A7CACF23825DE573274F7A964B3A070D66D049C7245D7739611FDBDFFAC21373A1B52D9DD3068A814EC08599EECD46ED0C775AEF19513622DEE75DF2792D7F123A45025378912A35B303708D0B3426C65C69B24358ADDA1708989E2D1217EC7F7BE32C37449BE2D1B843C77555EADC7B29878B71D95C420A9A744CA247E3382DDA1996A4E749F7315942E47EB1383339A1C20A7943543531A9EF0309EA7114AB0B3DC4ED9EDA988D6E978092EB9938815A355087C63149ABF9FE4D1F1B2A37FE3404F7587246F42758BBC7F8B111136092C28400D45D28E50F685240019A30574ABDC1906CDEA07B29155A71700731904CB3B49A3DE0626003E6D903C22FE058F47D8CABF213BECE4C4371A0DBF0EE89C6C018EBD8C6D0C74B548931514AA46B6AFCEDFDC5BEC48A5333476CF48704DD3F8E031F62937214FCE74DB483740CEB6898426635C38C740939EEF69B4E009F8C3D208769AC3017C827BC2073911C3B1AF2BBCDF14334BC9265A38A494B033FB887E7FF7D1C3931C483CD8AB4E5B1374D03C325D7E266F6E9D9ACD06E341AE9E4C4F18E9CF15FFE0DAC5FBBF65F6ECACB4798BEA3AE6C4123B7BDFF4A9B34DBDAC333E3ECF74F892BB91BAADF533161764824970683AD1D513C98063779BBE2F1C80B90B29F9A333CF5FB391354F1838AD2650F3B8C3519A0CDF69E359D73379FC11022EB256FD1DB270EEBED9A0FC2E25F59DA828F8B0D0A756ADCF7F1BD3ACE22811062219CB9DD16FF101BC879B7B057D8C3A53E028469CE476B136B0CC929EFCAE217CC49C941F22953084C50C31F75B9F7E309CCA6AC26A33A66EE8F4FF4B3363D8748C89115D38CB895C653D07BB99677DC919BD6DB824A31FD90BB56BA5C62546E45360AB276729F070456CDF89B5F48B50AA534C8EE341CAE2CBE2A79689464C2CF7D65318C6AB8ACAB5FDA822F132F2B5637963174A628156E1D166654A11C77B3A428B41CC7C618E03C97EA13E8489E3BDEF8AF3EC98B74EB68474191E15019EC80649A04DE49136384EF7C0831E9B3F4582402D5F07F0D75C12B57220C7E762243996065366F5F6663A8621DDE3819A0BD52AB1E64A07FB0006B9FB458761C3255E88BF794141647E7A42A422328C87F6BCCA09B8CA3D435B5815491ECC58B874A264E61EA49BAF9D0F8C75CDF72A68B1DE29BFBC0EC715E2C4B9EAD89B30315D8C5D554ABF4D862CE78EC051D635D6771388B00E50AB1C1FD412FC592ECB7A7C0F36EDB8E9C3EBA02B3FB4784199D7C3984DC56B5B19847CFBF6A889BBD98F3105CE8A4039DAEAB3CE4784DE71E3AE19C2355C09982653A5A85C554F7B86A3839B7928B2E3433BE19C4C4C2B2A23D0BB99FF2297AFF64CA4983CA89F450D5E173F930733F63E83914D771022353D8DB88A28401F785ACB7D6BC3FD5293F600299E22871422C5DC47DEFD4D818AA741E64E8DAB7354CC927FA2A93397218823340CC695998B073DF31808C41A0DA96540B64C10C929FE54C62C99319F628CBF8004977BD13DBDDF029D2902C2DA2C0A0658D85D336CBED91B1A5813C63A5149BA4771E2EBEDFEAE4FBBEE78FADE02E8F1E03BCDDC1C07C6F9C402CEAC52A98FC6CB51D3EFF91F909DADCBC8E469E2E5585DA9914A93CF36838D737CEC90718BFD30CA4E0AD7EF7BB2C6C0A6E26D0C54E2A3C038177057B079B241CC886EA58E145496C932EEF5461D2D68FAA6FEF92BB8A0EB10544E81DE7C3C1FE3BDC25FD0F60DF0B21D55F005AC9F2D0C4E9D39FBF213359AC59FE2C6489149661688918CE6521BA46491296EABA965F6109D3E521B74556CE80ACE4F8A34B57D0FD6913BA3F1C68D56E41735F8D0EDF9E2C293659A73455829F1ACDA870E9F36051DC977C828946B3B89C640340051447B2F67CD5DC2A5AD3B298E655D49019B8A8AD0CE4BB3A3BA7DC10E8A619B12A394027E27060C9CB9C890206114A3F688C154703D468461A9D4A3FCDA140101035923B27498BAF3EE7F0D38A870E85839899052C48809C54D266830EDE8B5BA0F85C7BA5CC857DDC41D6013D51CB64B7F7F1258C9B70C9A2109DEE3416880253E05B4AB7191A4E4411154E84F623138D755CBD55F9CE28CB6560A4B9D8B2D391CB52FF989A147F48BB17587E1C382ACE220619E5DDE43EA51F711CDAAED45F9CC10EC1713DB50FB7DE410CD39F97A6779AFFC4A0B2C889A15C606382F431BDDA0186889DDD99FFC7EF6A871DE751BD0D3825F1290C0853C488675B4F29DB3EE7B6D14BBE454D8BCB005815725CE413F03DE990AD6F2AFAB259E70074CE4B7F9800FF680715F3FD20A605366B32CC7632C2E703F0084A1D821B7F760A324B3AD5E65D9098DACB039C75F9DB9F9A85820CDC9A779D3722E3C35480D8A7286E2D36FEE7E8A14D32F3C192C39E67ECD7693B3280266CA07A06A3BF118DC9EAE1A23F4034CD976B32D334365058AB3C8DF0BF69879C8FDF90FE33F61205ABB6A89369DF4C96476D77B6C79C370F853E4FA49C186C221411F7C504D5CECD66114649119C26FF8000433F4F7392CDC073D51B3D15210ED8BEB5A2EB60645F8A4FA228B971F347D94B9ACD102605968AB2F7ED6635B0A90A7AE75F3E526F86F6A062C77BE9B0391BFA87C219D258E5C3FD64D3CB360F96DEB05311DCAB0B5A0BD9AB1BD36E4F9C4AA62BDAADA7404B08FF4328FF5AA0D9651B676B23855845DF4712980E04262C6D7B6CA5B4F4941EC0F8DC4835355559FEC78D06E41EC597B47B74C1E5AD7C61A987B5A88D1ED4362B3C132967EC09182E4BE876BD86F1D5C3B1632A8F56E13125C0387454E66C6BA34412E509F1736FA4FC9694AC550979AB064389577038662628922316BD7F042B6A69B516F46A56C28C2139A3506AB7B4283BC8A383748C9BC24504993C2B2B42A83C362CFC1798B342A9510BF37654FFC41A2DD3B14AE1F23F349CF7F920A07923AAF8E106A83929A85200E2CCF4BF4D78418A37DE65A5B4F9D270DD3213910E765F8C8FC567B2BA1062153F9DFA639779418EB343924567B0E42D85015BF2F3379027973C080107285650AF8CAEF9B892E607DD3321914EEE134B3DF7282ED9EC79FCAB130A15357A2B858FA77108D9B086263A08B482DCC375F0C4CFC5084D3F1181FD4F64C04B3B8088E9E4D18FB75B376890798DE7BB1E85132A7D92E2E0EACDC92EA04B847FD07B9DB141F0CD1C823C39EB20C0C8F53724DD314305A2849044EFC32F0F0535DB38219C98FD8BBE0A8CD897FE00DC500D9F44288468B03C8E0301E2555E863128FF3F9649F03275EF56204EDAD48B20E05558EA52A2813E998E9BCDBA3426E53D2A3B3C047F42FEE803C5561392887C3FA2449444D6CDFE4A89A9396F7F6BE56747961C021CDED77CDA3230D30CFF132A8A6FF524FF7E1E6335D6C97D5769FD62B1BE97675770286712A4B72D8FD3B3674EB8E71491D70508F9B9A1624C8A4F9EDE2EE27CD3205E6890FF8314D840CD3C270DAB6A4CCF896A7C3195E766F96E67381AF09D303A22C62CB1D6C66DD51028508971E2916DBA5DADF4DDF6AED606B16A34DFFFD8BD79072281351AE4C55A9136683A9B78A240254CF3AE877A9061CD17B33487944BEB504D03DC2F0FA8CDD563E45E4FBBE5DA3AD9B9D5E27A8962915B40997FD64F1A10EAB864DE75F67E948B116384DCC14CC27D8964AE7E8D70BB9B8928883E435E34B923BE01F35140CF7EC5D1CBCD0B8FADF0399453F4C048B9D4009A82B8864359B9A5BB53B98934656DD05CC8B677B87740A84D3DE64C49D802E81F5AE95321DC249A466D87CC6F64C2DCB666B4437A75C42D68E1DB5CCCEB1CCE9C68A6E1F47F920CC7299DE922A18D95CC894823B38A900CFC2AE9F23AFAE8675F89D590B0E9BB69C8BE83B9F9EBEF273D0A7EA30690F66CAA88DAF29CDA9BFD3C88A11B02763602F978500BC2DFA0898D83898C09D4FDBFF5928D2DFE9CF6E058BCC1DD30508E58ED1ED170090E523C9413734AD74CE5CAC2732E012FFA6ABF04C6B689CF70F10C04938CAEF9946973F36B3AC4EAF643FA5922BBBCF32C6B648488207D7E7E236351BA4085EDCCC8C6F3BAF37C2B532A5DFE4AF3F65F65E321AB14E3F7F75B6F2930F47BC93FA683842F45B7AE9B432E9D160F67B45413DC31C319ADCB4E075954C7E5C353AB7DB1E422F123C97B83EE25F8A8A66A8F1880819365A8E53BD398D8C73A5EDC546B84780E0BB633C082AE93B0B03ED6C8CC900FDBCF386062516103F618CD8EDDE18F8885ADC860405234121CAF7AA1F9C31AE56B8BE807D8A51C67DA0370FF637D085CE08BE04834FDD95525164A1741117A6F15795D70585BC8355636448504A5DF0576D94FD542F8103D418E99413873D52D11EBD6E46B23CAACBA7898FDA32B33D0CF8B7A4A25611834F309B1AF06DE37B3993CC77EA755466AC4535C5970DAC912D0F8DF0DB18FFC17F8B9882F1DD7E01583B85662C8003E0F694AD2FC72732490A090D25F5933AE71185ACA1260F4719880BB46F1E22F56661BB341AD226814C73FAAAEA6E054D01A5E0A66B525DA998C8CEB1D90125B54D5599BF4714F5D6CAB9D7D205D90D1D0A1CEF7D241CC987F6F9767E73DBE3D734393DA178C72B1F24DC9C2F1E5ADCF10EB893AF6ABF157477A88DA0853E01B7F7D34DD77F429E76814C4974B8D8C2BA4CD8977FDD1156C5CAD5C75FA438876AC8C4BDD8E44843BED62F649E7C993096D26A77B067B4505B9FF6336E30D2B36D1B0C7FA8202F1FB584E47F8C02D5663AAE87575287C5896E3E6EFD143F7E0DEFEE4389EC579EBC9C8D75BDE56B2F7AC703AC85E97EBC6C08B55A29BA3A06C8165FB2D03889E300E39364BC4CD856D67291524C81E884B5153A45D7B53C66751E863594D40CC00A9B23B9B22E40AEAC1D9F12F4D4EC0A73A1456506AEFC318F8AEBBAFA5F8467209F03AFAEF0571863F7735C858776CA4016370AC39794B42509668791F614ABED4F3B31FD92E52E5790E0EBB47344D62E4254935EC21FD3443B62C6CF46FA9E82CDC3A2B58958FEB91AF1E26537BF98734112E2F8C70A4CDB3AF63F60F746339915AAA60CA846C4E2DA28B43018BA24D9A34D348335A4261CBA82A7C390F86B51FA5478E1053A5D7EDC07F2322AC52E0BCAF24FC665928979A9E51079F71A61144A8F13B7F979303271397998B349F1AD62B53EC90D0DED31B429A9448ACE6672AC28A74FF45CD596CE60D64AC247467AEB4E54C6C9A46719DD4D98D37642BF87AF933EE2D0492115392AA79373948D7D4E3BBF67C46E52B1CAB534FCD662F40C0B1F8EE5465FA0C40D6D49DC0DE315BD972B3EB87CF6BB182D507C8F97FA061BA7AE4FC2E5484C5D769AB5BFED418B95AFC1D2D5EC1B243D40586974A1CBE403092438565E8E90AFC4F0F30C474C507BC9CCFE000000000000000000000000000000070B0E161E28343C""") + ) + }; + + // Only three are expected to pass, so I repeat to get 10. + static SigVerTestCase[] SigVerTestCases87 = new SigVerTestCase[] { + new SigVerTestCase( + TestUtils.hexDecode(""" +59B2371FE7BACC207FE1FEE88A8B3805A7052865691789BB90542FA47F7EF2B75FCA13DBA5888BEC320514DCB05FD26EB5541F6E572ECEA6C4F1D38AA70259094AA945F19FED0D980E65DBF65DB80F564FE29D836C5479288B55CF07F4E00159B6955DABDECC8C4D66AE688728BA6D5C0442F3C1232C782C465B9B7C5014B1464065CCD8A56D6B1C16510869E014E6933998EF725520B400913D93B0EC75E2FB725DC1AEC0C0CC7343B9E544BAA4D679860E347B2E947D8D2436F09298A7BB8336B9DE9CFD5CDBCD91C7249268CA03EFAC273AF52968D501406CD9C96159D7C15AA2900330C1189CFC2CD8B912C480E458297EF14DB694A3F1E72C1DFA3A3D2A8A69E011602B93020BACD1C2F3AD06C95A7F36EBF5261F6EC106816BB3303CC00BF4E8688D2E8548F10490D9EB23C56793B34B8406CBE443D8356BCD0F4F61D0D017D54831B9BA329F8948F25C3122F9DEDE8CECBA51569EDFFF895FA020862C5DF79F864078486B5FB228FD789C35FDE1C54BFFBF4A025A7FE7D8C3490A5D4E62D04F79F4183CA68379F4648BD5B2416DBE5B845C9F4B7A7E2339C0506D58539EAEA9451C9B2FE2A18C849DCA7EED9DACC058D005FB7375C4EF45B001543FC68E47DDB6D14FF937D1AA0D4D7489DFFA6210679CCCECF9B8551DCF682D2AF1E5BD869F3E8D400D5C861AE51FE7EBBB5457F2EAAFD093A9598EC721C69327C51930F4B9FFB2AA7F1A28436B6D808D75392BC43C1B5B859C66C54FA515C7A615A69E60921434AA9CF9F9E03C3CA35B5EBC6A409E822FE76E0924C6C062F1724C382FF3C8ACB5C1666C2EC26B7628E3D7C13DA8D758890E6CC017B7892582E95EDD04BA9345DF70FAD56EA68BF8875B932C28B32807C86371E17DCC04725CB597B524467963E1D4A61B5FBF9EC504D5DDB61793DD4E34AE082A5990EFCE801E938CCAE738E02E90599D971C2D7C64E5B6F8639F758ED621C1F21073C03EDB782C7A0F5D7C66F5CE161DED55B3E92DC27183AB083DBC1F3930AE56EDB8C53E9A7E020FFF0C4042F518B26F390C96C8183B79B53C7C7BC515187B3DE8CAB08769C5DD6FF5492112E8B0F28D09F4067ADB04194F60250E75ADE331A5C25593BCD92A6D1350439585860BB6FEEDBD2F839F317A01358876C88E898AC0C85378F572F23CDE931D47DE71D3353DAB1F810A61B18D24CD83DDAB8D53BA9C7B8274B0FE82AFF30C57072F643787CA1DF03B99EB57DBDA8C8EE8EB201F2847CBC9D34FD80CE6BC5E1E328EB6EFC83C4BD9D52F324E30EE4B5E86351E5C8C4C5456836D5A452203B3C372C787AE3332C8A5E9DC2197D9C341B9756BB1E63C75BBD5CF3E5CD4BF47BD1FEBC3E3710912D63032F6B97DC19C4DE196ACD9157715E2C14E054A9317BF96A684BB96CEFB7D8FDCA8AA477A2AF6F726D2CAC1A603CF1360EC11CA897E5BC735AB69B8647F30CED4947BA9F635D9CB2D82A662FF17A0E12D4D06D641EE76EB8B45C71EDE38C905C52BE76C6109F2612FEE6C3194465C19BA5D3EBCF1F0B5E534E0F0F1D31CB1E7A36C4303F283DBA8591CC609311A809E444E33A893880CDBAE29119146A368E4D2EDD91FE471647FFE821AA6D31C9FA49695EB9941B08F7BE3F06CDDF2739B8CAD2AB0DA4F5A3C0A26DF6A17B137CAAB3B919AB636D6C89BEDA3058898628721F2770315FEEE881595E24CF48B441660D0B2E9D5B90928C381F2B0FA26342E4C9B88C0887A4687124C012D969E1AFD8532754BA12125E9433DCF6D7BC1A36A83E6A10BA1CB7652A81350899C2DFC6E4FED38D009E6D0F1D44CCCB95E551B3AD54B3AC81E8BA4665EA428B3C861E8677890CF5F625C19A7C5943A9401CB78E7026BAE92B60A8B6807C17745415CD8E030C64C56E822139A35DA423F264336E0AFDF167430DD36E0064B2F6E8D8BB6BE99C5A9FB551CC63E508DB636667DDA53F611F02FCD1F99410F1A7A82882F9623ADDC50EB01E1F39978BF68506C71DBBEE42E4A80069B0E4C7FC4CC1471F4F1028DB25C4687B60DF4255DEC9148197A74796EC760A66AFC7884038651920973A69C203516222632EC5875EA6D838096E7FE9B5B4FB69C5E9407E70D27FA34B0CDBD6E119D87CE38581DF1D3E0DF3AE029042A3B20E923EBCE19A4958755EE2F98FD234C4413E2DBC93559A428DC37F2D1235BD4419B099E0F0DE542C46935991BE0692A6D80B8FD9886E0FA1769B49E8AE6307CB0BC1B49732D26E25CA1CD9D407E0D8864040941611F9333B6367E8300FD646AC5A71AD913EEFD808D5CAFBF1521A3062EC184E52165501E005556DE4DEE46F9E53D7DEF9909F3D5D98CA80D87707F7BC0FF8D879D65D4D783D196F2460693811CDF33358E082D81F4DB8F6C20486183A36D4FBCC8A1C6DA21AA4DD136E19FEF2EA993972BB9989AC1C38A79F31852178004123C46277D38A88FC1589F257332284CD8A873C25A1A6D40265B285DF09370E88F72FF70E434E8F66084CCFEBDBBC4B99EDFBC750CC5DEA63617F647F5F021D57D64D5EFF048634DB2209D7C8B82FB63B8823E4CA057168BAE88D9715291240B3758D7684501F861867B7A241C063B05D5E8CA6B4C79CB2435D7F994CB76915B4A548708B11B29449685941D43E60A8976F9A96072F91041F4C3DF7C73969012AE1B30E4B9C4E133558DABC46C103C0CB1DFB99B585374A54F9BA56B7248B8C3F66F1D55760D6ABB430375774DFBA2059C5DDDB659FD2E1DA9C3F0B80868C92BCAC10403DCD140D6A3D3F35F8EF1A2DD98DE1A4334238599EDAD920DC0AA698E9FE6106A0780C9C245F2C65A0C3E5CD5366110B1760FCD414D450DB9D76A22A9EAEA0C9FB72ED543CE9FA3314BAB17687E9DE5ADAD7561F1A5BEC16339269A87E09ACB29E4C439605E9572AA9B7D0E8371A30E41A0A7BDC02DA3A6121BF261EAA016A2074E4432CF63AF96BE81CEB6E0C2676A8545C66D2F30C98B5424F0FEF04B3C6C7064E2D2E11CBE60F85723FFC0B770D6866FFA589E3F9B2ABF75104019AA69CB58895B474A0ADE2B60A4AB077C3A6DF615334EBBE732E95220213994D3BDC443C8EF94AD515F45418355183314485857AC12BA1D62CF4FD4F4DE2A7FFF1ECF0D290C4CDFFA88D8F48C5B837D3A94CD17B3D169966EB038FE5A6E85DFC60A00233F10731973DC475D53BC7B9E60320BA7905D88519FA325DF5AB02B40F2ABBDB37D2261CB8148277B87AE3297976C80C35134E5F786904564C1469947F620FE09FDF3862C4057A3BCEF70750CB727F031283A1826F1381B3348E3EA4688609ECB193AFAAEE1CD97E4DDAA02C0C30E49F137D08285941528101759A7422AA499C900A379DD73B307284CCDDAF1FA1B0C4B280E3F9F1DB6D38ECF8A841F9D4E40ECA86247D6CD9B31EACD6A46F0E333B9E83D690D7E13467619B46AF9AFCFDC4AA9A049B180260D70D9EEDB8A533051AB83517AADC2CD900B3EA51260F464AFC5D2DC411029779B21CE2CBD160218DF41F661DA1AD95AD40B8C353C7F10FC23F830D117BCAEF8CECEBCBFA49D79D8D9391E8D08281F000A55E92DB331BDECD73183E058FF3FE5839AF50D8C55F22F6AFF5A33DA774BA1B3E643F5877CF549C4F908EA64A37DF3BFA4CD5F70F8CD154476D34BC853C9E8F7979E5F4EBB888AF761"""), + TestUtils.hexDecode(""" +4AC4675C96D9117D1EDEB80D7CD284A3E1E1FE038E301205B4C408EB965235AD1C85F8BE3F77CA486FD207F7C75F4121CD3CA2B23D6BCE4382A6D36121815025D5806CBEF452E083933C6E5C7394AC88262A6DE7770B2D8843EC101FFB5E84DE2F7A8B74E7674B3B2319BD6BF4112F92C5CFC0A55F7FA061F45325408D039D51"""), + TestUtils.hexDecode(""" +4B3F52F081B3D914BC7C6C073B182B268ADF5189E298A869BFB991B199993C1042DEF5B59270B6CD3FF8F907A1CB0D3B6FEDCA143838F8F81E0C370FFEEE6B25CD07035641A051944EAB516CFBB801536B4F262B16198E7DDB1D61C35A64D90D3948CEAAC8EE580DCEF540ED99D912BBA2BC4F5145BB949C73CCBD582613B10EAAE863ACA34683EB922B3DADFC74F76F47E4978602592402D9154394EB09FBC2EBCCC594732F2D8BC38350E5535A4412A77ADD7916604576FD6A3631E515BAF26A6F9CA4061EBBDD3BEC7179AD58552A5B508F31348A56AD1ADA7A05352C72C004B94C47E7049A10B3A59BF238A8DFC6C7019A17F05D5BFCB9D93D9D1CCBCB47F8C438098FDBDFE23F9F78BC28069908C6B9898B434CBF37787E1AF6A6B827E830E9F7629CD8F51070C4C8A8DEB260D07C3E41D8490484877491B39AA6D9E10D91748B64E33160629D8AE43EFD5F85781E69F76B6895C141EBCDDFEEB485A00BDBA4F7C991F53F2F84933926AF39E6964ABF2DFEBBC19A7E31C50797B8DA2931E10F3DAC493F198DFD785D21ADB2C062B097E889A20737F186008F2928F6B84D6E09E975A8F2AAADC785234234FDA03703A7C21F812D650BD2510B30F0550081047A155C848586A96F100D774F3E39E029B0777CD33E68318A11C1980293FAD3E787D20DFE7EEE7053C05EEB6A159BAAD4020B9EC3F537DA4DADAFB3B1BB1DBEB2D5B8F9D05A019798EAE0ED099DB066D73EE8E9A56DE368E878A7FF39140D8021D50085E6252941AB315309CB53AAA49E86347FBAD54A1F873E0CB4B86A8D5B1B2A95D485F37A9FB6105DF8440FDB8578F2624C079329569A75F36F2C55D8D030FBFEAA8889AD746C323B1AC4EC8C403E775A6FBE596E7E6A5A2863576625149940976F7CC93617B43FB13489074ECAC5BEB1A4DFE58B9AD2E0C6A15B76A7C2D208725A3123CA4E6F2C5847EE5FA8384919EF89011D219B257B3E4DC4F2095160844CAEEAFCF857260F1C63D3B05A67D3D0F2B0EC9DCC2723F13755750BAE62FCC361CFB584F774C09ADF9A0431B23E488C359C0AEF5B1C9787BD8F52B083BC9DBCC9B3039F777C7E8EABC80078050CE6D49C3BB70168FA2177298FB0A8F72C1CD28D662A07DAE6C7ACB7FB8E7FDD01DFB27C62EE683F4E5F88C7C1DDDD5EECC1C3AF853F1FF6B1D9DE672F1BF6473AF0021D8A3D4DD04A2FCA2325C721CF1C821676D0A0D574186625DE831C8411F64179F9167F78BCB22FB41C2CDB63C4DB5E138766D3803589598F114F41BA42CDB1341020449BA99656113990B4E022D8DA20D744491C6EEAB67B918E80FFF343CC5B4C8E58C3484B0125A60C36AEF763894D35148B578F417C3A98A143EDFE9F8C95BCC346C6F5EAF97AAD11DAE01C477C227A88D10ECFDCF450B37F881968027849D9B43E2BFF90C6A34AE41B8BBD743083D3C58786B036671CD6EED94DAE51F7613247EF8607ACF74A3CCE932F1C3869BDB35CA17FC6BA9F9C956FF1D4D88094325CABCE41233FB1D808EF41010396DEB0ECF50734D818DDAB70015A0ABDD1926DFA491F711AA85DA2A8EC60E3255CCF975C23CC4E8DAFDDED9FEC60A6467C45B03CA476499AA331B0E3999576CEC3191A9A62BC1BEAC1EAF20E18CFC3216127DE4AAE2E75201F9E427E39BF921150EAB949559C022D876FA242C2A845BCA7235F721B0056788A44ECC3EB98F0F502B89F8E7410EA5679AE7C0434F13AD816421D2FEE30CBCB2DAA6B851CD1B6E996DA7A757E4C4D8572C8B600DE85DDB65320D1CB71D9378349C0C401AD4F9E91272139228A8DA2F4FD2F48891A4DCB066D501D447483B611BB3C80550A90EA0B732D639D8B3926B6E7C35453ED3CC110BAF556CF46D8FC2177E76FB2663B8BDD171E94C0ACAF25B9153B22BCA749916756FB3ED3018E0944B6C3B9B6BFA15B9BE803AC79333CD2C3A27A26BC17CDA257798AE16B28B463B6DF3FA87C2D742D0F6885BEE0BEC6E20D01E5DADC86823E92D60FEC79B0D240248753E42048384C804289604821A57F4F9F50AE0C38527FE5A34938DDBCDCD9A1D020839BEBB62F9F41FBA08052ABB82FADA884CBE563791103AA585546EBFEB11272CC2E87A3B75B3C6BB1853AE7F9CF5585B2653CF5EEA244D204EB269C56A20985160659CB0725EE13CE35D55EB095A53414F232DF8108B18024EB0DBF345EB5CDAD0BCE7263509A341D54A7D534E553EAEFFE4E242EA23BCFE59A58A60425882CB7E3B0C9E4AFE8698E3DF56AFD6D611E9168747D8735CF9246D94F2126BE727FB42B2241A83B34F0B9EB47938D726502C54E4572766331628FA5CDA893C35376AB4538FF8717C2795B0F51F08E1137612B89B0C1E2CD1F099E88556923AE57A1DAD2AFB1230B5094A1B21BAD7DBBC333A97F179304718F3289B6DE31315B74C1A73AC7756FAA4D7EB568BBC6F7E788CD089B395564D2176B0056DFFE952C7748B048306720F602B67E8F6ADCC91F8E3AA4B8C4D7FAC233AAF93653AD2209E2FF92DA30C2D53FDEF6F4C90EAA0DE60D594ADA3915DB24279D867476EAD757B4C0264A1DB8A1F57A1B5D7173BB1A960CE02FDEFEF160D512667D655268FCC3A153A4314782A0EBFF84F65F14A0E3E12A13250C07D08C225B11A6831BC25C40467B768004DDE0E874A51144C18920BDF286090B59F51564EA4070FBBF61E3696435F28F63332B64496DF3EC8B65D54E1CF4789DDAB122DA6B264D312A711C129E3B07F4C6DA25A56173AF58B90A71B7ACFA3161A81F59D17914C99BBAC4F9A314977A89CEF7696943609BB4827964FB2976403BD4996F1E842BF5AAAE1ECCA11255B9E6001C20F72F1FD5E32CDA32D8A7AC5F62B09A0E615847CA746F489515CF8F183162859F53B97E9E5CA800EE624F729843A0009164A4A9FF76EB34E4704184848A139AD97D909F7A7ED114F087A4B2E1B4A3032391160B6F3A3649FF15AEA2B7107AF8A3B5FCAD61D43D602E6286A900870CC8CE24E39E78F0397A0D7E27E8E2D4776A44CBA218EBCD88B3C28C182A7C9F4DBB2DBB5E981563D66CEEB77E7F9034BD429D27637CF797DE82E01FEBBCE2171EFD016E402A42D78EA1ACE2CB370E75C90ADFA1A793B2169CC26522DB2F546AC1DE34C9087120C42A9F10C00D493C25730166F9D219FBDAD222C8B28115543313210848FB2F04BFDCE15D320C3634A8E4D63755515900C75BFD090AD78DD588659FBF97C96E0D0ACC8E815E608F9E861D79AF3051B942B52570B6292BF48C2BFAA9077DC76FE902683217B8BF809ED7A0050ADDBB65FDDFBD24019C9181B5AC81566113D6694EA6291D7F4A7F56A41EB91F76368DF82B164B4859259D7189240F1D8803F8107296D378BAB4D24FE6D10EF788367BCE16C5AB77FBC168B857F7BA5CDCBE5067C864F879809FE5217DEF0294BFAFDF809ABCE9532DD9DAB3448F4DA68ECA51609476278EB8C4F69EA29673F69418041D26857EBC24A487BB4B0BA63AF848545EE9BE89F139D502099B9D35DB3807B925CBA576E27170EAEC48CC2CC15B043677825D0EE81EB2CEE3A8ED14A798B879530220E50CE8C003A305382A24D23C277B99D1F4C54F9A8D33FA3D1E337E18D7CBBA5E5A47F2D5E096CF4551B23B1B86436E81B4A09D1E3D38492EC8B2A00967016AB76B9A9B1864671421DA56F57D008D5CE1B892A7E9C1F69F6C722CF109DB500E53F6BC07837AD1CD4CF4A64DA763B4A9C4929B0DCDDF7C7E1186BE3FF0C321158437820C81E74FF316AE3254E972FC197A7F0E620242AC05A4E43E987C2A8355B0357745CA79E6AE48AB29ED4FA63D3A1F19B999DE251FDE0640DD87876D55762878AD1DB12D65BAFD14B6A9A7081BF23F9F06D90CE273C5A26E012CA94DD481D32E10938C165163E89BE8A93A63034D345B74E2A94EF643D06AF9E1F5C9F104930DA00E61E061EE8C3BB17C11E05D45C1682E4D593C9198238D2BA289779E7D0F227BCB0B09972B19770FF011BF6C60D9D193CFAB32747A0095E1A4AD32514C782EF3DE7A26EA771F5530D9DE9736D0F6AE1AFB78EC7CE4884A1BB436CFCE459CD99358260906AAC99716A536CC7687A0375FDA11007618E553534E54D5B214F7AA6FC7DBE37C2BD2B64850AE469A9858987F3FA4B1FD26D954BFEC365DBE06DDCD615E1FED58A88676402D1D6B581485498B5ADFFFC42D47D61DF99384E22C5157F0178A6FDAF8F4A9491DAF298B2C3EC88085022C0A7CF245ED0FB5A38CD16F30D37DA5C4959A55501DAD50F1B48BBBDD86AB8BB522A936DDF0003B81BE16231A04E7A589C56FFFB51B07927B4AFA1DB7D48BC6FBC3F3675637184B7ADB9BADF4DE7C085BCA1D428DC9FC8277CBD85884A5921B52BB05B710615508261BB4546BD6E1FC730D16B049EA12798CE2E6DF43F5B8F3EF9AC8FBAE31B011E10C4FC62FFD7F39D16EC32CA8210ED16E041DA43D9274229514054A0F82D462FE080C6FFD7BBDBFBF0BFFC6D5ECC432A3256C0BE0DDFD5D9080C676C7955D66E44D1CE51FCC2382F868D732E85851721B48A01D08C639626EE0509CB581EFF5628FA6CCD1089AC0E12DEBE0851782E64C5049CBD6501013965CC0CA25ACAB176EF7CAB92940985DDB49021DF6C60D6C4A489116311E86BA19EDF00D74797358207CDE50506D007FE03C8804C66451F02A0182D387B759894096F65232952D183DBAAABB6BC0E191DC2C3F75FC72BD61BAB2EF19B6532B231C4AFB1A9C2CB2F3D6C451E8440D6A923CF72A63E2ED8554773887910CA5C671AD4FD5923CB95EC73FFDFBDA4B6655F55DBFD1317D024422301ED66A6E4C672085CED1F4C7B05030A100C4788FEF4CD3E494A853BDE63E9D449AE3BB6BA1083238DA3F4090515D143C67DBE53D8D507A5229FFEB2072D0BD092FC9AE52DEAAACD1F0F14B5AC84752BFD0025E5F55B869350F4B2719C5C05AC1669BB0FD3C614ACE02A270613FD3309706DDCD5B1A6AD26F359ADA80B30E50A7E50BBD3AA45D0654DD7D058B0BBF4D0D92135142214EE70511F3676AE643B5F245063B9419CF6B49FD647F27D7C41C866E6CAD9D5E2E3E331BF6B9F72ACA329BB64259C3E79783A26674B7D38EBDE8318411F4764EBDC4C7E41ACFF85BBB30318D59C42C9203ABD6636BA3F772B6725121C052DE99910D55158C6F3EF8BB7FEDE2F81E58A7AEB25E2E46FD7232302FAFA8FC37FC8B55D594B76EC4A53EB11EB3FD634428AAA5D86F839D089ABE2FEFE2AE5262FEFC7348D836692EDB215D6F8F548B885290C2403C51C3E269D493FBD339B5DFB0A38EEDA7754DAFFA16E5BCA5A9BBDE04B014B7AEA8988F3749D52D2FC1C9F7C7B2C2D692E7896E4C34F57C558CFE8317A8374409D566879A08628F644FB45B818455BCA6042B4E6187C1DD177E9E5146319904B1505F3EE00CD7FEAF0E83C3024956F77659ACC56D8D917A37E8FF7EB88713CCA334EA04B8E258C9345DA9DE26A0A366519451E1012DE6AABF4697C9DE821D70021C3250A106CF4C23A1B1785F549D3C8CD71B05FEA753E0046A3AE0A9B1F40277CF453A2BA14CBA923CC6269706DFFFD517C1E5930079912E05A5571897A06865516C86699F707E00CB38CE193490AEE30BA47DDDF3A5B4FBCEBA73DC13D0A160EA642D30D63A02964EDFDB2F29DCD32CA9974F89C32D1FA9A83C94A2770FCFCF86E64646882BD550DDD65B4E2D287AF6C196F42DBD39B020D7CDFBB6E6E75FFAAB26099EC1D25E3234F70DD972286AEA0C3436595FE49FCA898BFA421604C82D3E94856D186905076D186C684174BF4290DF31769EDC97A1DF2DFED03CF45CE678C8A1429EB978D02A79D4F8CF0168DAAB482C6C612F04B1C93637FE77B302CEFA788C11356C52C54F37A9DCFDA55927A8EF0A0CEA7CC4ADCEE459EB64DF08ED0FC29FDC3C7B762B399332063340D473966219BFC87B4A3C91C80F0E4BA86AA1879C76625C8680A227AB22780659D4B5D30E0E9A0DCE094DAF537679273A9B277ED2A2E250EEA0938204C9E963D338522A3D1A4440E2A12397A5B97D35657307BEC94CC0C72C5C6B09DAF2BAF0020B7D8CA560BF6596929AC8D4E5460F7837B41B4AE6FF12339DB8EBD7028AACFE0B42E02CDE906783ABFF694E7CBE0897ED6ED438ACDB00A4709CFEF7150EBEB08C8FF6C1543815F4B8951C3CACE499586458A73C8572389AFC9703A7FEAF673445FB4B0CCAA511D4A2CF463F57E3A6D72DA04B256699A30212E7C5768EFC151B71744156575A2E9443319232D159C6CC006FDB57C58173AD8D2C866C8887437C223888E21EF67E1A332C1FDFCC15EF17476FE0FB57D4229894725E1474C1BA1216562817F16C53ECE01C7F9E3664EEDBBA94952987431AA2A57D330EB11B28E6BF770E349ECE350C83E90DA6FE0D0A4AB9715DB28BDD397FAFA1428302151E1F222B4469879EB5D0F018606A7594BFC82C394E91B9264495C9063D505262799B9FCBE6316BBCC8D8093053636A74D4FA000000000000000000000000000000000000000000020F161B1F292E36""") + ), + new SigVerTestCase( + TestUtils.hexDecode(""" +59B2371FE7BACC207FE1FEE88A8B3805A7052865691789BB90542FA47F7EF2B75FCA13DBA5888BEC320514DCB05FD26EB5541F6E572ECEA6C4F1D38AA70259094AA945F19FED0D980E65DBF65DB80F564FE29D836C5479288B55CF07F4E00159B6955DABDECC8C4D66AE688728BA6D5C0442F3C1232C782C465B9B7C5014B1464065CCD8A56D6B1C16510869E014E6933998EF725520B400913D93B0EC75E2FB725DC1AEC0C0CC7343B9E544BAA4D679860E347B2E947D8D2436F09298A7BB8336B9DE9CFD5CDBCD91C7249268CA03EFAC273AF52968D501406CD9C96159D7C15AA2900330C1189CFC2CD8B912C480E458297EF14DB694A3F1E72C1DFA3A3D2A8A69E011602B93020BACD1C2F3AD06C95A7F36EBF5261F6EC106816BB3303CC00BF4E8688D2E8548F10490D9EB23C56793B34B8406CBE443D8356BCD0F4F61D0D017D54831B9BA329F8948F25C3122F9DEDE8CECBA51569EDFFF895FA020862C5DF79F864078486B5FB228FD789C35FDE1C54BFFBF4A025A7FE7D8C3490A5D4E62D04F79F4183CA68379F4648BD5B2416DBE5B845C9F4B7A7E2339C0506D58539EAEA9451C9B2FE2A18C849DCA7EED9DACC058D005FB7375C4EF45B001543FC68E47DDB6D14FF937D1AA0D4D7489DFFA6210679CCCECF9B8551DCF682D2AF1E5BD869F3E8D400D5C861AE51FE7EBBB5457F2EAAFD093A9598EC721C69327C51930F4B9FFB2AA7F1A28436B6D808D75392BC43C1B5B859C66C54FA515C7A615A69E60921434AA9CF9F9E03C3CA35B5EBC6A409E822FE76E0924C6C062F1724C382FF3C8ACB5C1666C2EC26B7628E3D7C13DA8D758890E6CC017B7892582E95EDD04BA9345DF70FAD56EA68BF8875B932C28B32807C86371E17DCC04725CB597B524467963E1D4A61B5FBF9EC504D5DDB61793DD4E34AE082A5990EFCE801E938CCAE738E02E90599D971C2D7C64E5B6F8639F758ED621C1F21073C03EDB782C7A0F5D7C66F5CE161DED55B3E92DC27183AB083DBC1F3930AE56EDB8C53E9A7E020FFF0C4042F518B26F390C96C8183B79B53C7C7BC515187B3DE8CAB08769C5DD6FF5492112E8B0F28D09F4067ADB04194F60250E75ADE331A5C25593BCD92A6D1350439585860BB6FEEDBD2F839F317A01358876C88E898AC0C85378F572F23CDE931D47DE71D3353DAB1F810A61B18D24CD83DDAB8D53BA9C7B8274B0FE82AFF30C57072F643787CA1DF03B99EB57DBDA8C8EE8EB201F2847CBC9D34FD80CE6BC5E1E328EB6EFC83C4BD9D52F324E30EE4B5E86351E5C8C4C5456836D5A452203B3C372C787AE3332C8A5E9DC2197D9C341B9756BB1E63C75BBD5CF3E5CD4BF47BD1FEBC3E3710912D63032F6B97DC19C4DE196ACD9157715E2C14E054A9317BF96A684BB96CEFB7D8FDCA8AA477A2AF6F726D2CAC1A603CF1360EC11CA897E5BC735AB69B8647F30CED4947BA9F635D9CB2D82A662FF17A0E12D4D06D641EE76EB8B45C71EDE38C905C52BE76C6109F2612FEE6C3194465C19BA5D3EBCF1F0B5E534E0F0F1D31CB1E7A36C4303F283DBA8591CC609311A809E444E33A893880CDBAE29119146A368E4D2EDD91FE471647FFE821AA6D31C9FA49695EB9941B08F7BE3F06CDDF2739B8CAD2AB0DA4F5A3C0A26DF6A17B137CAAB3B919AB636D6C89BEDA3058898628721F2770315FEEE881595E24CF48B441660D0B2E9D5B90928C381F2B0FA26342E4C9B88C0887A4687124C012D969E1AFD8532754BA12125E9433DCF6D7BC1A36A83E6A10BA1CB7652A81350899C2DFC6E4FED38D009E6D0F1D44CCCB95E551B3AD54B3AC81E8BA4665EA428B3C861E8677890CF5F625C19A7C5943A9401CB78E7026BAE92B60A8B6807C17745415CD8E030C64C56E822139A35DA423F264336E0AFDF167430DD36E0064B2F6E8D8BB6BE99C5A9FB551CC63E508DB636667DDA53F611F02FCD1F99410F1A7A82882F9623ADDC50EB01E1F39978BF68506C71DBBEE42E4A80069B0E4C7FC4CC1471F4F1028DB25C4687B60DF4255DEC9148197A74796EC760A66AFC7884038651920973A69C203516222632EC5875EA6D838096E7FE9B5B4FB69C5E9407E70D27FA34B0CDBD6E119D87CE38581DF1D3E0DF3AE029042A3B20E923EBCE19A4958755EE2F98FD234C4413E2DBC93559A428DC37F2D1235BD4419B099E0F0DE542C46935991BE0692A6D80B8FD9886E0FA1769B49E8AE6307CB0BC1B49732D26E25CA1CD9D407E0D8864040941611F9333B6367E8300FD646AC5A71AD913EEFD808D5CAFBF1521A3062EC184E52165501E005556DE4DEE46F9E53D7DEF9909F3D5D98CA80D87707F7BC0FF8D879D65D4D783D196F2460693811CDF33358E082D81F4DB8F6C20486183A36D4FBCC8A1C6DA21AA4DD136E19FEF2EA993972BB9989AC1C38A79F31852178004123C46277D38A88FC1589F257332284CD8A873C25A1A6D40265B285DF09370E88F72FF70E434E8F66084CCFEBDBBC4B99EDFBC750CC5DEA63617F647F5F021D57D64D5EFF048634DB2209D7C8B82FB63B8823E4CA057168BAE88D9715291240B3758D7684501F861867B7A241C063B05D5E8CA6B4C79CB2435D7F994CB76915B4A548708B11B29449685941D43E60A8976F9A96072F91041F4C3DF7C73969012AE1B30E4B9C4E133558DABC46C103C0CB1DFB99B585374A54F9BA56B7248B8C3F66F1D55760D6ABB430375774DFBA2059C5DDDB659FD2E1DA9C3F0B80868C92BCAC10403DCD140D6A3D3F35F8EF1A2DD98DE1A4334238599EDAD920DC0AA698E9FE6106A0780C9C245F2C65A0C3E5CD5366110B1760FCD414D450DB9D76A22A9EAEA0C9FB72ED543CE9FA3314BAB17687E9DE5ADAD7561F1A5BEC16339269A87E09ACB29E4C439605E9572AA9B7D0E8371A30E41A0A7BDC02DA3A6121BF261EAA016A2074E4432CF63AF96BE81CEB6E0C2676A8545C66D2F30C98B5424F0FEF04B3C6C7064E2D2E11CBE60F85723FFC0B770D6866FFA589E3F9B2ABF75104019AA69CB58895B474A0ADE2B60A4AB077C3A6DF615334EBBE732E95220213994D3BDC443C8EF94AD515F45418355183314485857AC12BA1D62CF4FD4F4DE2A7FFF1ECF0D290C4CDFFA88D8F48C5B837D3A94CD17B3D169966EB038FE5A6E85DFC60A00233F10731973DC475D53BC7B9E60320BA7905D88519FA325DF5AB02B40F2ABBDB37D2261CB8148277B87AE3297976C80C35134E5F786904564C1469947F620FE09FDF3862C4057A3BCEF70750CB727F031283A1826F1381B3348E3EA4688609ECB193AFAAEE1CD97E4DDAA02C0C30E49F137D08285941528101759A7422AA499C900A379DD73B307284CCDDAF1FA1B0C4B280E3F9F1DB6D38ECF8A841F9D4E40ECA86247D6CD9B31EACD6A46F0E333B9E83D690D7E13467619B46AF9AFCFDC4AA9A049B180260D70D9EEDB8A533051AB83517AADC2CD900B3EA51260F464AFC5D2DC411029779B21CE2CBD160218DF41F661DA1AD95AD40B8C353C7F10FC23F830D117BCAEF8CECEBCBFA49D79D8D9391E8D08281F000A55E92DB331BDECD73183E058FF3FE5839AF50D8C55F22F6AFF5A33DA774BA1B3E643F5877CF549C4F908EA64A37DF3BFA4CD5F70F8CD154476D34BC853C9E8F7979E5F4EBB888AF761"""), + TestUtils.hexDecode(""" +EA707F27A8896AA860FDF5D5897B58538D1CB6096CDF2AD5F583C5D4FCC2C91839C1AD44920216F8D027AAEE2E563D779E86FAC4B2502497B41229BE823ACF0BEB232CC6F3F7DA88E0685A9176DFE71E42470FCCCDB43C6688A03B6D8AF6612AB821CD16757FBEAE52C779EFB6AC38EF7FB4B5E365882CB83AA246B2A52D5059"""), + TestUtils.hexDecode(""" +372BF9FD2061BD26939A23C3DB128746EA3346F0C0E75C4C358405C12CAC9636D241A5E555ADF1B8C448152326F9248EBE31E8C171B3CE7C0079610C6C715BF8DA26F4344C0F043EAE26E749E56BAA190E502BCBE70740A8CDED41CF2FAB99AF00A6D788FF05C30CB8B9ACC125FEAC8C7CDFC1DD7226C819BE3A237BEE81FDA6B1DEBB83207B53BBD1E3FE07D3919AA9B3505F3DA78B7AF7A61979B9C8290563B7ADFB676D06C7AAF545452D3D7C9262AD40456D0333B362A68207D0273F488AA60F87543B4E4F4B0BFA36AAB42D523AC1D6691B680C673832888480CFF337B1590A8544A3663515198481B17D0839944754E14D565A8C32CA1D2BD4863EAEE16AC0BF8D52EFAA731CDB0A3A25D2583424F0F57E08E2018247B610F843B1ACBC54B3AE0E880B994254B4DADD9652EF5E36D3F1CCAE76DB8FF110CB3AEF24EA7B00E32278A05267C3A3319EB58E92172DC5C7EE748739C5E19AE54F7A8D714CA642958B820CF8C71F20E03730641CBCAD74E1956A1C50562E27F21FB03F44A3F032519E2E20577D4611764159405D7BB138F34126A4E5C8B3AC1A8F19817061BFE1C50A8A6767053677F1B507D70B56BAECB8BBE2F54DAACC13AD373020C13B103D2079B140ACD18D3824C03205C6198AC1603CE63602EE853B08395BC749B0DA7ACCA6DE54D1D742442C81ADA46C3A21F8F8B4A1E3C212315E6D19D290D139E70C037D4E64D3630996606E443414A371A96B19433B1DB4B5EE677113DE2005ABB42CC8DF12C33DC7791FC7AEE807E7946B023FE451ED32FF21ECA246AF26B535A11B4C6F380EF56DBFFF984ED15818EEB08578D045F2FCF39C3CB456C73EFB76C66AA09E6F9458AF39BC5A9E1E9D6E8826AD3ED681DE22E9AEE77FAACE34385376EFFA306098EDDF4F122106EEBDF32AC04884554BE6945753E6B831FAF701B4AEA4F48A8D490BDCF33B0E1630C94F756A1C565D2554F5081EE3B4EA5C33EAE04F06BD44CA0D0671708E9392EEB6C4EB80AE8A17911B27CAC8980A87A3ADD2F5E2FEC71FF711D89A6F96EA423411E81B292668F60AF44F0CC83BCF835E78F2F6BC503F54C2C6CE827D97023B98F23A85D269238013F29E9AE8BE2FB54C9AA69BB6FCCD96916918B8E534D3CDFE506A2AE474B59589CCC730A0A857BEE1F4CFAD0433BA4D34E8888FE2785A7B6331C1CE3F66E0DCC2F801C112DEE85EB869567C387305922B252073023259E1C042D3A245D141DFB0F2A1A5CE0FB772B12A0AD875DE56A8A0151891D4D4D2E2DD4E025D8BA25E63E44AD8798D495CD099B57CF73623A2FBEDBCAF1ECEE43AA0882E553F5058C50AD9C4FFCC59D93F51DA653DDDA17B14EF03D86EE7234A3808B54A1BAB7FE12154816735D62BF3ED4CA9C180D6BC050EA3937EBA6F8AEB4A7811A7307FC7A0BDB24360AA517A2333FE86CFD05E5924923AD390E6F0DC4E757AC78A754BC6B3C15954674F4AD41D05007BB984C89C198C4E4109683BFD1A1E59FD8CA36040090764B81A747ED14CED83ABE341473BCBA6B5629044DB6CCD65CF6DE91C91AC20875565440194FDB3D21CA637E019636B44F69D578C1E1CB12312FB109242C228B02A70FF001095801CC2D308A5E802C34B102F174C6C0A44D14A76B9D82D8B97C01205BDB22AEA9B2F0DE6507C0FADD1321BA71157C203DFF28207B5CD7AE18923DAB57AE263BD26A97210DAC238427857AFF7639195EC13CB74D511B40A5C5855E1EC1223B6B44C5B630AD94050B573FDF919FEA24AEAE8095AA8136D15294D876D1ACA1F862B038F35265BE879A0F1FCCE07FB76884DDE073E73785B46DC0EC95B7859594119D272CBDCEC3FFF7A1AF8B5076C977B76C7FD640B834B92066257EEF27ECA1699A7BE3ADD1746624C27256BFF5F9177C01147585D1D5CBF576F381DD6DF2320F24293F32BAD164E474CE9C741EF87302331AA9B67D64E95527C4BCFB601699D68F1F712222BF00262BF4AE8C49E098A8EADD108288EC0995D068315CE39C6429CCCB00E1D94477B76D866AD7B7968B5AA98A590782354EA512344FE58290DB10717E5C6102BC7EDC1CF85D634439D5D82C1B5A2A9928FE389BDBE4FE9AA859DCCDE68392AD6B35F516AEA70220B0D6DD2A91239EBC0D15B5930937207E0CC5AFD925A4B8BF5A0A4DB25BF87294CCD7E148684F331508A752386A0811B606B91283D865B58B347084CC01C874C046861ED3FD8DF8C5B07E8A2F27176685A39A9BCD955645F1EA58B4811DFBA16C98BA52BC0EA443D592756B00CC4CA428511A7F8051E94C5C273CC6E8652F3E9132E0ABB003C31DC61A8802D2CA650EC0B5AF5BC3E983C2746F4747AEB1F6624F010C5104F7A577E58D5D527CA58BC838C60049C99270A66C846258D32A5A5E4245088E7C6F824671AC80571DEFB07A21B64A688100F0BCC7F28B985DD9B0A1F6780B561BAA8616909555E6BF656F1E02691EF83E475E90FCE338195A88FC1DF0864B5375496B5D8FCEED265163ED2EDA2CE6CAEF6583800F225084662591706E1F8AACE331689219268A591379219CEAEF219A02CA85AFED70C96CDC7B50905EB6C2BD0E1B09DB19CC8728EB108123228628212EC1A591148DEDCEB7F4938F0A99B727B79F230BFB96B82E03AD90B6EF858CB899AA2549E0FB1E8919AADE94580A530479C140641D6620676927DFCE0DC4374AF05B379AEDAF0BFAFB0A4EF6FE04E2CD93DC6F0F4B8B680804F296FF8703219988FFD69110830F3C66555A33026EB524E75F9D4AAAFD385BEAF64BB448B2CAF9546ED326E0690948EC06BC7FC9204315D68161EAC551F228373C86BE56208DAFF85C71053355C6FBC677C87E1BEEB1D0F03B8B77F86315F98CBB8FE07B17762D9FA93E484A6E991D616E95476FCF1EF1659DAE67FA92A30CE609127DFA818CB109B5C33615BFDC647B7CB8F74581BC90EA05071E7F4E542EC1940D0E8B0BA4772DC4AB89A3F0989BD4EECC4D026BACDB44AAC9524828EE59DA8F9AEA5323F54FA60633F676B4A6537BAEDAD0B8492695D7333AFFD413DB2134328568B5B7B892585ECE9E5618F7573F014EACD05289DE2404E2A2B7CAE0E79E7AC7AFFA74CAE66B956A7F6BD9FEC4D4E10F3ED7CDD8433A35D785CA2217C5D963A29E9389928FBC1BF380E37CF1242C47342B58AF18CF83F209CD1932378C02538A5C07D369120B3B493B28AC4202971A0D2C7ED6B65E3098107ED5B20BBFF10ADBB33710DC13064C1ED6A289559FF7CC3CE77FD7A7C8701D4F9606FBC7E554E0047883EC6CD106616BF8CB821E0D17792622310BD3FDA8C5C7088C395C6272D8BF06F8F33DB65333F097211A05E2DA3E07FD05331241DD2A1DB878124F57237F5DFFC021263197B10B9352B6BA8061C58BC1BEF2DF186C376E3059862CD9AE36DEEFE6F8DC72D43BD043DAFBD54FBBB93EE72D0E792BCA927E785C9330E79C39581F408A4DA9CB0B4FEEDEB5DD9D8DBF08A736C0418284C41E9195EC680D5A9B56843E87DD76A7519CF03C5A447E407386FA81A38FDCAB479F7F239202DA95D64EA059C05DBE730A5AC672FD3D7C854FE0DDED4340F4FF0E7536F640ABBF7FB1E12DDC7CEEA34FD46BC24918A52EA55FA6FB1B91456932BA95897C92CF3B805994EA5B4C7FA069135F19CBA85E3BB73F55336A9B6113B798BCD3758E1CBBE09E7207345B6DAC55E358C60B6C9768AE2E6DDC15CBBE058B6EC06F1E99D4797E66AB0935B340D392A4C4726D8265B9C5D58B0C7FC77B367495D81518492650D37EB852E8B4672453330E30727F200646E6BDD6D70CE290739A06081F433E27D87C09ADD00E217CAEC0CAA9493AA681C777307E70EEF7184FD658F4B77B88FFDFF539E9284047787AB974CAD538FED6AFB978A38959D02217774C1B3BBCF36C805C17AC104EB27AD4E40A3F46BA2B08ADC30B713F224C18D13F83CC60B59CFBCBFE0E7864BC7A7CAD976D3BDB8CF71DD5888169E85639304D759BBF6FE7C3C6CBEBEEDA02E819A4DCBA188407295AB2D885B34EE22572518BFC0E9749192A839CC08D4A160794AE52113AA94A09258DF03A7A4DCA3EDEF6CCDC720A780DDB561B319B574F2A22A15341746B4DD6281328B3667786AF8B729C135BA418DEC122D3E119F3950FD6ADB0B0C773B90ADBC4B9E8B27043BC5D287BA5B92727FF4759F4F64B620BB226646F08414A0513F72FAA4401E371465EC7E6F4A867A47183ACD434159BBE352FE1C2D8E30BB3D7E08E25D15F1C3D996C811B9AD35A8D5B4B6D0A9A606895E4044E9ADB7A6427DF47C48614C6431F72897E5052B878996C520E9D33AF693BC69F879B8BE87BAE0564701438A51CCFAA342663927F9B2D2271ADA3CF44D8C4016020368C25FD56CECC6EE192734753D66A97E13C2327AC71E5726560D4800B26C604F1A9629F451454C86B6F5AF4CC3419AAA120BCF19671D577927E1A88185D0457DBAEE168A9A45F9BDF0DEE2A35D5E66C2DDA27D6B4EA492BB88D4EEC6CB68B23FA2338530009D9C9CD1041BB0592E83EBA03D39C7FDCEAB5C1654470399E6B85E63616CA705FDA4EAAECA06AB3F87857F15D2EBA75A3A2EEC060177F74009F5943244913E1959820D0D92A0C2AF7844881BD408F4A0CAD81AD6EC9243C8CBA108C8F58A23D5971807233173F1B98AB5C3C73B72706131C9AE644F46FDA74839D497236F152D15B97B93BCC9ACF405C1A1CEDDB9C2F03CE111977426D3438F929219E859CFF3EAFB5D2BBE48E00DF7A4B627E181A8982A3D0E640677B6F3B419B5E2AEC12B8E306253236B5D3B0C7252C2D2F7637610F07094570431E129FC23B631DAA0B6A2A6CB3C75FF8D2ED1CB906EA9CBB20956306E4EA261E10DF1FB7B3FE1D63CA8EA742104DC678AB572D0792DE89CEBFAC8E541E91CF2F7E8CF7A767365FB99A57D2C259DECB1957EF6AFAEDAAD93AB7DBBDD7341C73AC40D25161A103888C8CA74CA0EB52E195848A006E872D0BE5F5A6B5E972444E925B5DA4A3F8F81AA168B836F17F38977ECC7AF48839978A1EAD106E0C3A8A715C86448E9CF4D23703273F4CF00FCA36DAF8834DCD97655B95E6ACF495D4CFC9A7F7D5499260794107B331BFBBD211021B9B7E4C9F947BB9D338C6385B9BF73F0FF6C97C7BD8EA33228EE939BB17E11B3C9D182F818055F753C5356C5BF371E21EAF1CF14B0CE8E3EBFEEB28010DA0B7EA9E0A4285E435FC06B70F4E6DE1DA12D871C3BC8D0C884A7A99DCF2A2C8561CD445B852ADE1A11217A9658D210050AEED89DC18D71D7906389D4056E7DF99DAA462D4C77E7F93874883F33BD13BBBB5E1AA8CB86A981B5491DFCFE2B474F63EB68D923F2D43FDC21E9A56A535347C021B65E54D7935B8EBC249903C7BDC69419E683F3E1BA7450DBEB2F175E2A5593A202543E0655B909D6614290DF1792FCD7B17CDBDFF0E9121D185A082EDBB630369AECBA8C6D4C642ED0AA644832A234DBD48B4C6D8037BF97AFB75626FF28EE1206DA462ED05FF43B23D98D1790106D88C3103232B82DFEDD8B62C8006E2717C921C1695E49B742281AF1CC870CDACA295F867BD72BDAC03CFF02D406A1DD6C3A3E59E8DCF93A5BD54ABB022F9952EF1906FA66ADD7124AC3CB35209BA7958C246AE6AAEF91C5C85F844AFA38335AB67C0735F634203AACA2272994B719B655629E54537A1E75B316E22FCAE758EC85D4D968CB3242510CCBAEAE4AAEC63303EA8E1DB841893CA1BEA38EF797C756A2A75D8C7A823C2DA46FB9996C3C2BA27E19BC5D23005D97BE4D2B899CBD0748811D6E920D535BA9BBA33C4D08868E70AAB6731982181C784EA4D4CFF1D20137645CAEACB27D295F14334D102A5508DD586CDFCE93CFE4D6B5B948D16AC6363B4DF5D7DA3E61D9E0966BD23D46B2263277363524437F18FDCC302540A58823990DF6A6214CBE9FD47F336534E89BC307FB0B030FF063748DEE749FC7907F78588DE4E099CE3D9DBC4ED4F254E7B4B297F5A11999450E485B462C83E9D6519FA1BA4FA39B25D195ADC14C1B862DB6A2222FEC7A4DD09A5472410758B85AA8AC57BDFC80BB4786B2A5C3091B7D24B6854EBACFAA87FA6895E81554AE08D5EF4B3144F872CA9644FD8E7A0C613CFEA146275A72CA3F68AA2F67FF49ECA257FD912F48C6637473EEBADAFBEECB7019B99FD5FA050811ACC255F02307835771417C782D43497C7D2B39B00220396E3C5B02696A16AE562E2E57D227E71502A3DE95D88BF98492035DAE2D468795DA1C32DE795717D43B1BB0DED8C450C34CEEC27AB138D303A083980F535D9F63EEF8D8200A52EE84802B5C6D4CB14D75CC8A719202363F97878B3E719FB607897C49752875A4C9CA7CAAD5511DB6523AFDF0CEF8BCFD96AB239044FB53EEBF3A70001C62E9B86E1A604709082330081EE7538C474D94B0C5FB2664787C85CCED00080E1349869EA6AACDF321546FE415268A8D9195B6C8DDEB337887A9BCE20C2C4178B2C2CAD9386F7C000000000000000000000000000000000000000000050C171B252B3336""") + ), + new SigVerTestCase( + TestUtils.hexDecode(""" +59B2371FE7BACC207FE1FEE88A8B3805A7052865691789BB90542FA47F7EF2B75FCA13DBA5888BEC320514DCB05FD26EB5541F6E572ECEA6C4F1D38AA70259094AA945F19FED0D980E65DBF65DB80F564FE29D836C5479288B55CF07F4E00159B6955DABDECC8C4D66AE688728BA6D5C0442F3C1232C782C465B9B7C5014B1464065CCD8A56D6B1C16510869E014E6933998EF725520B400913D93B0EC75E2FB725DC1AEC0C0CC7343B9E544BAA4D679860E347B2E947D8D2436F09298A7BB8336B9DE9CFD5CDBCD91C7249268CA03EFAC273AF52968D501406CD9C96159D7C15AA2900330C1189CFC2CD8B912C480E458297EF14DB694A3F1E72C1DFA3A3D2A8A69E011602B93020BACD1C2F3AD06C95A7F36EBF5261F6EC106816BB3303CC00BF4E8688D2E8548F10490D9EB23C56793B34B8406CBE443D8356BCD0F4F61D0D017D54831B9BA329F8948F25C3122F9DEDE8CECBA51569EDFFF895FA020862C5DF79F864078486B5FB228FD789C35FDE1C54BFFBF4A025A7FE7D8C3490A5D4E62D04F79F4183CA68379F4648BD5B2416DBE5B845C9F4B7A7E2339C0506D58539EAEA9451C9B2FE2A18C849DCA7EED9DACC058D005FB7375C4EF45B001543FC68E47DDB6D14FF937D1AA0D4D7489DFFA6210679CCCECF9B8551DCF682D2AF1E5BD869F3E8D400D5C861AE51FE7EBBB5457F2EAAFD093A9598EC721C69327C51930F4B9FFB2AA7F1A28436B6D808D75392BC43C1B5B859C66C54FA515C7A615A69E60921434AA9CF9F9E03C3CA35B5EBC6A409E822FE76E0924C6C062F1724C382FF3C8ACB5C1666C2EC26B7628E3D7C13DA8D758890E6CC017B7892582E95EDD04BA9345DF70FAD56EA68BF8875B932C28B32807C86371E17DCC04725CB597B524467963E1D4A61B5FBF9EC504D5DDB61793DD4E34AE082A5990EFCE801E938CCAE738E02E90599D971C2D7C64E5B6F8639F758ED621C1F21073C03EDB782C7A0F5D7C66F5CE161DED55B3E92DC27183AB083DBC1F3930AE56EDB8C53E9A7E020FFF0C4042F518B26F390C96C8183B79B53C7C7BC515187B3DE8CAB08769C5DD6FF5492112E8B0F28D09F4067ADB04194F60250E75ADE331A5C25593BCD92A6D1350439585860BB6FEEDBD2F839F317A01358876C88E898AC0C85378F572F23CDE931D47DE71D3353DAB1F810A61B18D24CD83DDAB8D53BA9C7B8274B0FE82AFF30C57072F643787CA1DF03B99EB57DBDA8C8EE8EB201F2847CBC9D34FD80CE6BC5E1E328EB6EFC83C4BD9D52F324E30EE4B5E86351E5C8C4C5456836D5A452203B3C372C787AE3332C8A5E9DC2197D9C341B9756BB1E63C75BBD5CF3E5CD4BF47BD1FEBC3E3710912D63032F6B97DC19C4DE196ACD9157715E2C14E054A9317BF96A684BB96CEFB7D8FDCA8AA477A2AF6F726D2CAC1A603CF1360EC11CA897E5BC735AB69B8647F30CED4947BA9F635D9CB2D82A662FF17A0E12D4D06D641EE76EB8B45C71EDE38C905C52BE76C6109F2612FEE6C3194465C19BA5D3EBCF1F0B5E534E0F0F1D31CB1E7A36C4303F283DBA8591CC609311A809E444E33A893880CDBAE29119146A368E4D2EDD91FE471647FFE821AA6D31C9FA49695EB9941B08F7BE3F06CDDF2739B8CAD2AB0DA4F5A3C0A26DF6A17B137CAAB3B919AB636D6C89BEDA3058898628721F2770315FEEE881595E24CF48B441660D0B2E9D5B90928C381F2B0FA26342E4C9B88C0887A4687124C012D969E1AFD8532754BA12125E9433DCF6D7BC1A36A83E6A10BA1CB7652A81350899C2DFC6E4FED38D009E6D0F1D44CCCB95E551B3AD54B3AC81E8BA4665EA428B3C861E8677890CF5F625C19A7C5943A9401CB78E7026BAE92B60A8B6807C17745415CD8E030C64C56E822139A35DA423F264336E0AFDF167430DD36E0064B2F6E8D8BB6BE99C5A9FB551CC63E508DB636667DDA53F611F02FCD1F99410F1A7A82882F9623ADDC50EB01E1F39978BF68506C71DBBEE42E4A80069B0E4C7FC4CC1471F4F1028DB25C4687B60DF4255DEC9148197A74796EC760A66AFC7884038651920973A69C203516222632EC5875EA6D838096E7FE9B5B4FB69C5E9407E70D27FA34B0CDBD6E119D87CE38581DF1D3E0DF3AE029042A3B20E923EBCE19A4958755EE2F98FD234C4413E2DBC93559A428DC37F2D1235BD4419B099E0F0DE542C46935991BE0692A6D80B8FD9886E0FA1769B49E8AE6307CB0BC1B49732D26E25CA1CD9D407E0D8864040941611F9333B6367E8300FD646AC5A71AD913EEFD808D5CAFBF1521A3062EC184E52165501E005556DE4DEE46F9E53D7DEF9909F3D5D98CA80D87707F7BC0FF8D879D65D4D783D196F2460693811CDF33358E082D81F4DB8F6C20486183A36D4FBCC8A1C6DA21AA4DD136E19FEF2EA993972BB9989AC1C38A79F31852178004123C46277D38A88FC1589F257332284CD8A873C25A1A6D40265B285DF09370E88F72FF70E434E8F66084CCFEBDBBC4B99EDFBC750CC5DEA63617F647F5F021D57D64D5EFF048634DB2209D7C8B82FB63B8823E4CA057168BAE88D9715291240B3758D7684501F861867B7A241C063B05D5E8CA6B4C79CB2435D7F994CB76915B4A548708B11B29449685941D43E60A8976F9A96072F91041F4C3DF7C73969012AE1B30E4B9C4E133558DABC46C103C0CB1DFB99B585374A54F9BA56B7248B8C3F66F1D55760D6ABB430375774DFBA2059C5DDDB659FD2E1DA9C3F0B80868C92BCAC10403DCD140D6A3D3F35F8EF1A2DD98DE1A4334238599EDAD920DC0AA698E9FE6106A0780C9C245F2C65A0C3E5CD5366110B1760FCD414D450DB9D76A22A9EAEA0C9FB72ED543CE9FA3314BAB17687E9DE5ADAD7561F1A5BEC16339269A87E09ACB29E4C439605E9572AA9B7D0E8371A30E41A0A7BDC02DA3A6121BF261EAA016A2074E4432CF63AF96BE81CEB6E0C2676A8545C66D2F30C98B5424F0FEF04B3C6C7064E2D2E11CBE60F85723FFC0B770D6866FFA589E3F9B2ABF75104019AA69CB58895B474A0ADE2B60A4AB077C3A6DF615334EBBE732E95220213994D3BDC443C8EF94AD515F45418355183314485857AC12BA1D62CF4FD4F4DE2A7FFF1ECF0D290C4CDFFA88D8F48C5B837D3A94CD17B3D169966EB038FE5A6E85DFC60A00233F10731973DC475D53BC7B9E60320BA7905D88519FA325DF5AB02B40F2ABBDB37D2261CB8148277B87AE3297976C80C35134E5F786904564C1469947F620FE09FDF3862C4057A3BCEF70750CB727F031283A1826F1381B3348E3EA4688609ECB193AFAAEE1CD97E4DDAA02C0C30E49F137D08285941528101759A7422AA499C900A379DD73B307284CCDDAF1FA1B0C4B280E3F9F1DB6D38ECF8A841F9D4E40ECA86247D6CD9B31EACD6A46F0E333B9E83D690D7E13467619B46AF9AFCFDC4AA9A049B180260D70D9EEDB8A533051AB83517AADC2CD900B3EA51260F464AFC5D2DC411029779B21CE2CBD160218DF41F661DA1AD95AD40B8C353C7F10FC23F830D117BCAEF8CECEBCBFA49D79D8D9391E8D08281F000A55E92DB331BDECD73183E058FF3FE5839AF50D8C55F22F6AFF5A33DA774BA1B3E643F5877CF549C4F908EA64A37DF3BFA4CD5F70F8CD154476D34BC853C9E8F7979E5F4EBB888AF761"""), + TestUtils.hexDecode(""" +EBDA4B4198C041F515BA16E227F1491F54109B04C5836855038149B60978EA146DF46299A38794D61DA89DCB74A46E3EFED16C832884194E74EEC82C965E9DB2858B87962F48F0C094C389DFD1DD44CBAEDF14A62A709FF48A92E193472899A6876EA8B9701C1D137896F3C779A4E056820F55300524202E44F8B24D5B685787"""), + TestUtils.hexDecode(""" +A2E6DFCDB93DAEF3A2B0A3A548EA48D51157F45034134ACCA15A29E5417475AFE72F571B34545F92DE26B06F141B1A18545CB06D547A1E3D19F9006D7C0E9640273AE424EE20CDC0AB8CCD680AD1CA98047108ED0FFADBD8B568753E4FA7C74CE79F7980297426BEF9ED2C88ED43B45B92E77D47480DEB54993BB03A956F617FBC9E40EE1F726A1E095BF25AA2B8BAD9578506A624E018287DE7A844D4ED1AFFD8B013131272948ADBFB1B40477CE56FA0C94E1DA951049268F26B7544FC1CB0F24F14C2D7A51EE5AA9BCB8A0237231F7ED5F7D2DF14184DFB66CE0336233A506193D6CDDACCD1E2D32A449459DB55DB87080603330CD1A865B719C0C389B19C18ECBB240EFD582A0AA372C47CD00DA92CD0549AA7F7C41FEA9A348D6B7BB78F46DD2998767ECC6CF9F7E2545CA2CB1A18503167A85EA96523C537EE2FCFBE870E40E00E25E7C092A2AD5D5936AAC869D167D9D76BF2AB47185A6F3F64D0557D78D553379ED2542EF2A3CE45E5D97EB7046219E9A9F4A0021EBF5B87A95056F3D14F8A67130B8BDDDB7F5F6C41E189E070A914BF69154F06E45109E2725C5516D1FDCD93A610D3328E2758D5BF0FE58B51E05075D7DFF949E9285924CB3773C8A16CC09F86A0F14925ECADC6FE687C5F864B93868E17D5D3CF218B8E49B991A8CD7879194C425DB3ABAF41B9FCD5E0DDFABD24369EEAA68E50932F6C1C81A72D12DB8EF868B4CAD837EAF5FA0B5915C9BC48FD089F365485A92A6153D1A48B4B28682921C432DFF4B09D63EF3C9A692DCB8FF2D48A5EF0FA63FBC24C9CA2E26AC2ABBA339D2DED6EECC6784C1ECF9F0D39BA10AC8688408AF5B85D4FBC09B73D9DEEA0101146ADBC08004DAF9BC68E66515BA9E103EC4B062A45E733485FAFD9262CC7737999C76305E1106553E495B26F0B22EA7F093B4A543AE8CEB0DB3607F4CC023E45EF9F957563DEDF945CD88FDDDDE42826ADF24D95C314BA718A1C81462C2A4D1BBC2E9418A11954D972D386899B65A2D7D8FBB170A91EE0EA02D18DF1541D95BB64CC54AE8DB48E7B66A633051C04767D708C98BE328EF865431B29348D7306D389287BE9F41BB23BBD3D7A7A3C5D4C3A5F171D574B0640EE6927C1E96F2E9CD0A1BD90430D42A330C93CE66DFDC65B067D8F173EFC0EED00EF24F108B143F589AD94D0A6FC98798C1B63510734A7853D2EDF70A1918D2780C23B12CF5B1EF279604304160364651965646E0E223562381B36CD81FAB31D436F53A9D65EFB3A7EA2092CE202C1ED7FB9EA64AAB6FE7FE107424014E5AB946A3EFBAFDA9619CB7A603F11E9AE507098AFF80331075B06AC4936A711BDAAE97057E31521D5479E046EAD7E8F024E3B9C49A8A253C81A283FBFFCB0C1D896D99E881314C04FA7E0C9DF25B6166F57D97065E9166B37EF612F702E6FF1C9E81F0189E22ADD54B9F2880B23F1D3F88E120B89BEC9C699BFF18DCF870362F9B4D0F66D7416198864484393156D16A7069C0D385910DB49DC9FE8015851DC43E8B03132444BEB19B60DB6052379E5F41109354C0350A2078D397389228726C33DC492DEAD0D55DB917C6E212ACEEAE78A8530DB6A53C7A566E91E1AB62D3AA16F2736CDCD965D38D945E8A15EB68CC2B50A9C5E88F5C40B8F67AF4C36F241F3DE9EC66911937739F8F5C56C28CEC16FB453818178A3698D639A7E9A215D2F7400F5FA0772485BD75A58CA574CAC9BEF89F8F3B554A92687EEA5C6AE9651D9CEC267E13F84FB98D43FC7D24895296D78FEC1B2012F732092511930FF78664E926A57F23D3CF17BF19EEE27D833B88B6E30BF5AE5498FA55EC0D14FB127D5E6EE80560F540FBE26FD81AA62B006A139A065C11B7B48B2AB038B522168748A57DDB6C0A6CA0D7B4B79527673E58617F22F3C1B32FEFC787B41DDE9399549B0608478487126611634E5166BE7AFAEAB42F348B2691A1978CE61C753A049767A02E7055DBBFE771ECD8613B3AA29622F2FBC06F9BDCD9C94D0FB8C75310E2D4100C5248FFCDA8A898AD331BB4ECA6939FF31094F418BB8BAEC58AEF7B6FA33ED8588A21B437F4AD5EA5F2D86C4DCF1C4A559BE9B0C384AD2AA778EE93CA70989BD2ED681666CA8B082B7B83272F8A10E2D245628C8E1B5FF3BF8C5FA9C6E09C238482679888827D0E3D0B9A8CC36027649B0798E14390AD84D3D766DCEBEEB670E3560C6378F90A411196365F4FA6D332244EEF1016085C9B51614D8BF3BB44A67C906E7241213318B714824C03D9E8927AB2ADFFF50494D3F398F37E6BFAB3F8E0B89643FD220DA424BF2D751D07B5F335944462B374F297726DBBBF8C3A2D7B26BBACF192C05FF89F0878E26ACF8275644CB85C7D81022D1E85FDE63E7055E1202B85E0118687994931DE1617BA91CE9054327D3DC9DA0135DB676E9A4388DBDC3727DFCE71FCA2CEE2B2331DD836086D86C3F36767BD2F210B7B8CB1458CE8252DE845F507D78C93F7ECA7FD8CADA3DDDFEA34D2FA9AD31F10F02430C884F65346840E4CA5CC54572D6533A4E2417CF859185CA5B905BF83135BCBD88C0D86CB7C3344674F8A9A09BFD460CA828BACBE12B661459123201A5CACEBB6EF6E449B049552AEB5EA305B870055201B4686CB255E12BB1CA67DB46AED1890716672A898F71B5109A5C253276C42A22ACAEAD6E4F0798067FE983494752574A612969F1C923AD5718362E2AA1C4E5255A777DC6CBD53F553B0953BB464EBC29AA36E3F72B5C6614FAB08CC65F540D662599D45269754C0D6BE109BD7E0DF04D5EFF30000D8D6AF25B5AAD51057C31C4C134C59C3356B34638692222273144CE9D768196749FCE54DC7A7A1E2E36192FD7E756994E37D0078850E81D2D9C40670B77A02C9F708DA28CF2CCF478309B4279A6C45B9FF854A5F5B553CB291FEF5D1970883A064200D2C99597829F15DB4D9506C82154EACC4FEB0800D268902B462FE9D3284D89D83A7009AF5BDEFBCB310608151430B779A6FA4CBF6DF1E13C4A9DEE96D6BBC0CF989C48888BA58316FFA0114020B5C326D723960FC20DCFB01DC50982FD824F9512AE73E3676ED8040481CB536F851274087BFCB77A0EC7DA2BE274288D2212471DC7949EEF77A8333AABAFB57581CB43774E07F192B825F14AD564658792A0E235F4DB5EA6E3A84403492E209484542C2C2881042F54CD56CC00F2C31810EEC70D8386D0C8B7E4756A77B11563A42BC3A5D2A495D0C8278810D55EE7CB38D80C34E4DC58F0A8B1EC6E2193E6184E5F0793AB882051EBBDB3303D86F4A0E22090C7A957BE5F7BDF4652FC8F38DAC71257B2570D5B1DFA95BFEEB7E377DD581A8975D72398B4D258B1B9E7DA60217FF77BAD7008FBCCDAF7479573F9ED6BA8D13F83C233166D8D7A400F00840887BE510EAF1CF2E30B244C9EB6E166C98156C27A5FF0DB563A204B830C8FFC64D6685C9E3BF8968F3A2D2B329AA6AAB0D49EDEC26C2B5D7462AB465381D5431C85268EFB89F4E04DC660EBF4A0962F9C9F4EBB7F2A1EC5B3262DE971219FB56CF42CD720811EAF66DC2C428F94E1DE4ECE5F2116533B25E65D732A4BBD5221D28EFA946DAF52437AD6657703A9B454422C7DADEBF063E5FC433536CBA84E07F7086FE031A0A2B4DACDC99E5D3486E77D41D949EBE69E14BDF21090646CD9FF8E9F0FBF5E737DD38C0EED3D73D22A7C23AC781341109997594B3D1D4153AA1A35FF7AAD5636BFA9BE09E3329FB61950CB6DA58600E05DC2782B2EF58466AC9A4BBF6264D0D616968C6BAFC496F859EE9512072180172E91E3B581FF5CE9B8AC0624F221D111BBAAD988A530C0CADE0C4CC399EFAE9ECD624F55D93F9D0F0FC915292419ED119E177095880FBCE058783D85380F1F6673B7ED6702446098693F3FEBB9C9D7906391608453158C695D073B259518AA7DC5125B51E58A5170D1A68CF6CFC1A705B344911A63875080B4FACD9835AE85294D03EFF6D3B02888BC1D094B9E7374CAABBD1D0C32F1786B8CC12D0E4C76BC99694A1862A73ADB58A20908A601ABC4015ACC17E5B0AC28F3D8896F8BF0AA344B814D63CF558E0CED39D1F7B16D411E014BCB594F37CF18BCF46EBDEEDF1AECBD13ED97AD65A0674275868F34148D6E03E7D802258987937DBAA69215216F1CDF8BA2BCDA245D42A5D9891CF0ABC804595B320A774F1DE69F8ED595007A59F1FB570D6D024ADC97B121C28542E3043C3F99EA5EA4BE47E3DC0B66E297477537041CF880B5FAF2828E3DA2D2F9414297C59F17ED60E2DBA0502E8FE6B8E5B13FE2E945B2E78277C568082F678E4F4FF2E323D1E0AF996364E2AF2FC95C53F83953028D38BB168A1FE68C02E4477CF567DF6C2A72AF3F56EFFC99C0F5223E4CF32CA3B97C700A40803E3C91DA686DDF45A47208FC904B2384730F050A9E3440CF9A010044F7E8B6B0FEDA288F810E27AAC5DAF358046D8AE85AFB6020C22986C4788E07EFB41B2C18C482C72027673E9695CAB29FA04ABC0D7C790D3F32565A859696B6C036ACB5A6D1E444CC7D9D23B3A8FBE6E2E851914711EF790E8CBB097ACAE791825EEBA70C3AF28E6E8EFCCA38CF6B6F466D568100ECA07BF3B4B8E18EB791A2431A7FC2A795B4CDE07A38E1662044E81E85667BE36058095C7F0573D930CACEFE4C97B3393F8400451AAC6B55C5399826D8C7746BDE6484D4377BDFAD25CC5CC17C774B4623BE25184DD627CE8E6547788BD7CA2FABC9B7D4A602C457FE9EFD82B79E9322F99962FC7DAD35BFAF85A03D67DC7E83FD3C627160DC96640683AAD733B3D1EB59646A2533B99EAEA4E5CFDB2C94A8724B03FC4B72BB5BC5D90B0D4A136E44D64F3985A7EF7C6D7C55B61486CE529475F21630DD824F8AD4D3FBF0CB2C48CCC0DC27516733FF5BDC1F459B00B88883006AEDE6602DC51A316959DEBEDC0F36BBE8D017207225C1C2BD94CFC1CC60933CEA2ADE45BB4425578F4D28E0AA36DA346E2BA4B34B65BD7E71B9FCC3B52F8C425AD44B5CCD006E26857FC5BAD79D8345C5FACEAA4DC3A7C613D085826F82F10961AB2BB7C087FDB490B5A082B2F5DA5D9E6210D6E8B37ADB10DF510990F3ACD81CF93965CAAB334F1B2A76D9B17D758F273860B074B2FFFB88D9B5E6991EDBFC5FFB54325BFFC0C66092E7729C9971101D7CBF74491CC4F54D535936CBC5455E3215215E836500F411382CB8658BBB60636BAC343A645741FCD6C5E23433EFEF4F14967C5B742BDA45B2FAE1946FD0042229A1E462E172102124540CB203D58DF1EB8ADEBC4DCB37F8450DBD0FEC87CB4A56696141C9513F7D6E61BB117B0E35E1DD314837965004C6C86388C2D3EA57EA4C0CE9C563C68F5B3CA20043742BB5060935C23FC7FD5368EABE5C1A1B715B99B96E1B434229D3ADE0129AAD85710596DF9AA2D86C7EC88B9552F876861DBAD135B4EB318FC6FFBC3AF0C98EC57468A0F4BC3A29CF1625B03E33360D152B0B5F5706C169B68C7470379BA15D9188F13DFCF789C18A9DA14EAB56DB261F978D9BD894C84C1BD203A777DF785C82B87FF975BAE11437F9A243627A1715CBFFEED727B405C545542A7BED9395ADE1A671807954EAC7C9BFB8785F18D5D5C31A01320E7D863743BFC7852E251631A03EB671912F6138C21E1D62D88E1941095A8DFDF3B052A0104E72C186BFEA9CAF32B2FCA121FCF6A3D85FCBB9D7978EF2E227F321C1BD932A4DB007CB2DFE3BFD9578BD7AA6844611E4F3ED7E5370205A07B6CBBFCA7AA204D76CC8DCB9A1CB6FE6C4AFC5E5A79E59C6934D473BF834F69B89073DEC0D9ABD347B12BA21E308D42D1576F03CE4BE6EF8F07EA08CF1846C27ECEE7F8415C0FA756A540E42738892C7E6D0F90520FEAC6160911BB18BDEA2A1D925CDFBA7C585DAA3A3D27B12E4880A9B8C87B0EB5EFD7C07507D8C3B274738C90EB4A745C1AB3749ED000075E99277B927B1CAF2E19E8D588AFD3CF9BC0302724E71F129E3E3BE9D114542B16C4DB65AC8529CF95CAF7A2EED53548D1769F809F1780E5102D80B7E52B99203F5CA6F2A2A7608171190EF391A4EF5384D15C101895B5402E8D4FEA052872FBAF6DC9FFDCD3FF9EA884ABA4D90E202206E861B9785AC572A0013765C24B5E3AB9C4E31A6B7F958A4D3DE78CA4D4C097AB9AD50E588BDEC45528EC7B248BAA3BD3DF31F8FEB29F823123421388A2A021F37426188CF830BDD10C75BFFFDA15623B33F89567EBD2EC66EC7DF533CE8F33C32EBD6D074606380F37F3E9D186E4A93EB098B6EC0455843E7784A9CCC67E0326920223993CEEF7E4AE399E21993CCD078084804EAB9881B6C40CE2B20BEC97DF60381E930CBCC038A4A9153B2AF6AC6F743FE6E2FDA9A0FBD4C00D93C972333C8A8D99041D8C93718CA0CB864B5E50059D73978FA3FF33115880D43D93B8512246D82CF104A4B525F6F8B95AAB9C8DF02649497A9AAF01EB4C7EB1E232738557175E6090C2F657E9DBAD6F90860BBDEE0F701236C8489A7C200000000000000000000000000000000000511181C242D333A""") + ), + new SigVerTestCase( + TestUtils.hexDecode(""" +59B2371FE7BACC207FE1FEE88A8B3805A7052865691789BB90542FA47F7EF2B75FCA13DBA5888BEC320514DCB05FD26EB5541F6E572ECEA6C4F1D38AA70259094AA945F19FED0D980E65DBF65DB80F564FE29D836C5479288B55CF07F4E00159B6955DABDECC8C4D66AE688728BA6D5C0442F3C1232C782C465B9B7C5014B1464065CCD8A56D6B1C16510869E014E6933998EF725520B400913D93B0EC75E2FB725DC1AEC0C0CC7343B9E544BAA4D679860E347B2E947D8D2436F09298A7BB8336B9DE9CFD5CDBCD91C7249268CA03EFAC273AF52968D501406CD9C96159D7C15AA2900330C1189CFC2CD8B912C480E458297EF14DB694A3F1E72C1DFA3A3D2A8A69E011602B93020BACD1C2F3AD06C95A7F36EBF5261F6EC106816BB3303CC00BF4E8688D2E8548F10490D9EB23C56793B34B8406CBE443D8356BCD0F4F61D0D017D54831B9BA329F8948F25C3122F9DEDE8CECBA51569EDFFF895FA020862C5DF79F864078486B5FB228FD789C35FDE1C54BFFBF4A025A7FE7D8C3490A5D4E62D04F79F4183CA68379F4648BD5B2416DBE5B845C9F4B7A7E2339C0506D58539EAEA9451C9B2FE2A18C849DCA7EED9DACC058D005FB7375C4EF45B001543FC68E47DDB6D14FF937D1AA0D4D7489DFFA6210679CCCECF9B8551DCF682D2AF1E5BD869F3E8D400D5C861AE51FE7EBBB5457F2EAAFD093A9598EC721C69327C51930F4B9FFB2AA7F1A28436B6D808D75392BC43C1B5B859C66C54FA515C7A615A69E60921434AA9CF9F9E03C3CA35B5EBC6A409E822FE76E0924C6C062F1724C382FF3C8ACB5C1666C2EC26B7628E3D7C13DA8D758890E6CC017B7892582E95EDD04BA9345DF70FAD56EA68BF8875B932C28B32807C86371E17DCC04725CB597B524467963E1D4A61B5FBF9EC504D5DDB61793DD4E34AE082A5990EFCE801E938CCAE738E02E90599D971C2D7C64E5B6F8639F758ED621C1F21073C03EDB782C7A0F5D7C66F5CE161DED55B3E92DC27183AB083DBC1F3930AE56EDB8C53E9A7E020FFF0C4042F518B26F390C96C8183B79B53C7C7BC515187B3DE8CAB08769C5DD6FF5492112E8B0F28D09F4067ADB04194F60250E75ADE331A5C25593BCD92A6D1350439585860BB6FEEDBD2F839F317A01358876C88E898AC0C85378F572F23CDE931D47DE71D3353DAB1F810A61B18D24CD83DDAB8D53BA9C7B8274B0FE82AFF30C57072F643787CA1DF03B99EB57DBDA8C8EE8EB201F2847CBC9D34FD80CE6BC5E1E328EB6EFC83C4BD9D52F324E30EE4B5E86351E5C8C4C5456836D5A452203B3C372C787AE3332C8A5E9DC2197D9C341B9756BB1E63C75BBD5CF3E5CD4BF47BD1FEBC3E3710912D63032F6B97DC19C4DE196ACD9157715E2C14E054A9317BF96A684BB96CEFB7D8FDCA8AA477A2AF6F726D2CAC1A603CF1360EC11CA897E5BC735AB69B8647F30CED4947BA9F635D9CB2D82A662FF17A0E12D4D06D641EE76EB8B45C71EDE38C905C52BE76C6109F2612FEE6C3194465C19BA5D3EBCF1F0B5E534E0F0F1D31CB1E7A36C4303F283DBA8591CC609311A809E444E33A893880CDBAE29119146A368E4D2EDD91FE471647FFE821AA6D31C9FA49695EB9941B08F7BE3F06CDDF2739B8CAD2AB0DA4F5A3C0A26DF6A17B137CAAB3B919AB636D6C89BEDA3058898628721F2770315FEEE881595E24CF48B441660D0B2E9D5B90928C381F2B0FA26342E4C9B88C0887A4687124C012D969E1AFD8532754BA12125E9433DCF6D7BC1A36A83E6A10BA1CB7652A81350899C2DFC6E4FED38D009E6D0F1D44CCCB95E551B3AD54B3AC81E8BA4665EA428B3C861E8677890CF5F625C19A7C5943A9401CB78E7026BAE92B60A8B6807C17745415CD8E030C64C56E822139A35DA423F264336E0AFDF167430DD36E0064B2F6E8D8BB6BE99C5A9FB551CC63E508DB636667DDA53F611F02FCD1F99410F1A7A82882F9623ADDC50EB01E1F39978BF68506C71DBBEE42E4A80069B0E4C7FC4CC1471F4F1028DB25C4687B60DF4255DEC9148197A74796EC760A66AFC7884038651920973A69C203516222632EC5875EA6D838096E7FE9B5B4FB69C5E9407E70D27FA34B0CDBD6E119D87CE38581DF1D3E0DF3AE029042A3B20E923EBCE19A4958755EE2F98FD234C4413E2DBC93559A428DC37F2D1235BD4419B099E0F0DE542C46935991BE0692A6D80B8FD9886E0FA1769B49E8AE6307CB0BC1B49732D26E25CA1CD9D407E0D8864040941611F9333B6367E8300FD646AC5A71AD913EEFD808D5CAFBF1521A3062EC184E52165501E005556DE4DEE46F9E53D7DEF9909F3D5D98CA80D87707F7BC0FF8D879D65D4D783D196F2460693811CDF33358E082D81F4DB8F6C20486183A36D4FBCC8A1C6DA21AA4DD136E19FEF2EA993972BB9989AC1C38A79F31852178004123C46277D38A88FC1589F257332284CD8A873C25A1A6D40265B285DF09370E88F72FF70E434E8F66084CCFEBDBBC4B99EDFBC750CC5DEA63617F647F5F021D57D64D5EFF048634DB2209D7C8B82FB63B8823E4CA057168BAE88D9715291240B3758D7684501F861867B7A241C063B05D5E8CA6B4C79CB2435D7F994CB76915B4A548708B11B29449685941D43E60A8976F9A96072F91041F4C3DF7C73969012AE1B30E4B9C4E133558DABC46C103C0CB1DFB99B585374A54F9BA56B7248B8C3F66F1D55760D6ABB430375774DFBA2059C5DDDB659FD2E1DA9C3F0B80868C92BCAC10403DCD140D6A3D3F35F8EF1A2DD98DE1A4334238599EDAD920DC0AA698E9FE6106A0780C9C245F2C65A0C3E5CD5366110B1760FCD414D450DB9D76A22A9EAEA0C9FB72ED543CE9FA3314BAB17687E9DE5ADAD7561F1A5BEC16339269A87E09ACB29E4C439605E9572AA9B7D0E8371A30E41A0A7BDC02DA3A6121BF261EAA016A2074E4432CF63AF96BE81CEB6E0C2676A8545C66D2F30C98B5424F0FEF04B3C6C7064E2D2E11CBE60F85723FFC0B770D6866FFA589E3F9B2ABF75104019AA69CB58895B474A0ADE2B60A4AB077C3A6DF615334EBBE732E95220213994D3BDC443C8EF94AD515F45418355183314485857AC12BA1D62CF4FD4F4DE2A7FFF1ECF0D290C4CDFFA88D8F48C5B837D3A94CD17B3D169966EB038FE5A6E85DFC60A00233F10731973DC475D53BC7B9E60320BA7905D88519FA325DF5AB02B40F2ABBDB37D2261CB8148277B87AE3297976C80C35134E5F786904564C1469947F620FE09FDF3862C4057A3BCEF70750CB727F031283A1826F1381B3348E3EA4688609ECB193AFAAEE1CD97E4DDAA02C0C30E49F137D08285941528101759A7422AA499C900A379DD73B307284CCDDAF1FA1B0C4B280E3F9F1DB6D38ECF8A841F9D4E40ECA86247D6CD9B31EACD6A46F0E333B9E83D690D7E13467619B46AF9AFCFDC4AA9A049B180260D70D9EEDB8A533051AB83517AADC2CD900B3EA51260F464AFC5D2DC411029779B21CE2CBD160218DF41F661DA1AD95AD40B8C353C7F10FC23F830D117BCAEF8CECEBCBFA49D79D8D9391E8D08281F000A55E92DB331BDECD73183E058FF3FE5839AF50D8C55F22F6AFF5A33DA774BA1B3E643F5877CF549C4F908EA64A37DF3BFA4CD5F70F8CD154476D34BC853C9E8F7979E5F4EBB888AF761"""), + TestUtils.hexDecode(""" +4AC4675C96D9117D1EDEB80D7CD284A3E1E1FE038E301205B4C408EB965235AD1C85F8BE3F77CA486FD207F7C75F4121CD3CA2B23D6BCE4382A6D36121815025D5806CBEF452E083933C6E5C7394AC88262A6DE7770B2D8843EC101FFB5E84DE2F7A8B74E7674B3B2319BD6BF4112F92C5CFC0A55F7FA061F45325408D039D51"""), + TestUtils.hexDecode(""" +4B3F52F081B3D914BC7C6C073B182B268ADF5189E298A869BFB991B199993C1042DEF5B59270B6CD3FF8F907A1CB0D3B6FEDCA143838F8F81E0C370FFEEE6B25CD07035641A051944EAB516CFBB801536B4F262B16198E7DDB1D61C35A64D90D3948CEAAC8EE580DCEF540ED99D912BBA2BC4F5145BB949C73CCBD582613B10EAAE863ACA34683EB922B3DADFC74F76F47E4978602592402D9154394EB09FBC2EBCCC594732F2D8BC38350E5535A4412A77ADD7916604576FD6A3631E515BAF26A6F9CA4061EBBDD3BEC7179AD58552A5B508F31348A56AD1ADA7A05352C72C004B94C47E7049A10B3A59BF238A8DFC6C7019A17F05D5BFCB9D93D9D1CCBCB47F8C438098FDBDFE23F9F78BC28069908C6B9898B434CBF37787E1AF6A6B827E830E9F7629CD8F51070C4C8A8DEB260D07C3E41D8490484877491B39AA6D9E10D91748B64E33160629D8AE43EFD5F85781E69F76B6895C141EBCDDFEEB485A00BDBA4F7C991F53F2F84933926AF39E6964ABF2DFEBBC19A7E31C50797B8DA2931E10F3DAC493F198DFD785D21ADB2C062B097E889A20737F186008F2928F6B84D6E09E975A8F2AAADC785234234FDA03703A7C21F812D650BD2510B30F0550081047A155C848586A96F100D774F3E39E029B0777CD33E68318A11C1980293FAD3E787D20DFE7EEE7053C05EEB6A159BAAD4020B9EC3F537DA4DADAFB3B1BB1DBEB2D5B8F9D05A019798EAE0ED099DB066D73EE8E9A56DE368E878A7FF39140D8021D50085E6252941AB315309CB53AAA49E86347FBAD54A1F873E0CB4B86A8D5B1B2A95D485F37A9FB6105DF8440FDB8578F2624C079329569A75F36F2C55D8D030FBFEAA8889AD746C323B1AC4EC8C403E775A6FBE596E7E6A5A2863576625149940976F7CC93617B43FB13489074ECAC5BEB1A4DFE58B9AD2E0C6A15B76A7C2D208725A3123CA4E6F2C5847EE5FA8384919EF89011D219B257B3E4DC4F2095160844CAEEAFCF857260F1C63D3B05A67D3D0F2B0EC9DCC2723F13755750BAE62FCC361CFB584F774C09ADF9A0431B23E488C359C0AEF5B1C9787BD8F52B083BC9DBCC9B3039F777C7E8EABC80078050CE6D49C3BB70168FA2177298FB0A8F72C1CD28D662A07DAE6C7ACB7FB8E7FDD01DFB27C62EE683F4E5F88C7C1DDDD5EECC1C3AF853F1FF6B1D9DE672F1BF6473AF0021D8A3D4DD04A2FCA2325C721CF1C821676D0A0D574186625DE831C8411F64179F9167F78BCB22FB41C2CDB63C4DB5E138766D3803589598F114F41BA42CDB1341020449BA99656113990B4E022D8DA20D744491C6EEAB67B918E80FFF343CC5B4C8E58C3484B0125A60C36AEF763894D35148B578F417C3A98A143EDFE9F8C95BCC346C6F5EAF97AAD11DAE01C477C227A88D10ECFDCF450B37F881968027849D9B43E2BFF90C6A34AE41B8BBD743083D3C58786B036671CD6EED94DAE51F7613247EF8607ACF74A3CCE932F1C3869BDB35CA17FC6BA9F9C956FF1D4D88094325CABCE41233FB1D808EF41010396DEB0ECF50734D818DDAB70015A0ABDD1926DFA491F711AA85DA2A8EC60E3255CCF975C23CC4E8DAFDDED9FEC60A6467C45B03CA476499AA331B0E3999576CEC3191A9A62BC1BEAC1EAF20E18CFC3216127DE4AAE2E75201F9E427E39BF921150EAB949559C022D876FA242C2A845BCA7235F721B0056788A44ECC3EB98F0F502B89F8E7410EA5679AE7C0434F13AD816421D2FEE30CBCB2DAA6B851CD1B6E996DA7A757E4C4D8572C8B600DE85DDB65320D1CB71D9378349C0C401AD4F9E91272139228A8DA2F4FD2F48891A4DCB066D501D447483B611BB3C80550A90EA0B732D639D8B3926B6E7C35453ED3CC110BAF556CF46D8FC2177E76FB2663B8BDD171E94C0ACAF25B9153B22BCA749916756FB3ED3018E0944B6C3B9B6BFA15B9BE803AC79333CD2C3A27A26BC17CDA257798AE16B28B463B6DF3FA87C2D742D0F6885BEE0BEC6E20D01E5DADC86823E92D60FEC79B0D240248753E42048384C804289604821A57F4F9F50AE0C38527FE5A34938DDBCDCD9A1D020839BEBB62F9F41FBA08052ABB82FADA884CBE563791103AA585546EBFEB11272CC2E87A3B75B3C6BB1853AE7F9CF5585B2653CF5EEA244D204EB269C56A20985160659CB0725EE13CE35D55EB095A53414F232DF8108B18024EB0DBF345EB5CDAD0BCE7263509A341D54A7D534E553EAEFFE4E242EA23BCFE59A58A60425882CB7E3B0C9E4AFE8698E3DF56AFD6D611E9168747D8735CF9246D94F2126BE727FB42B2241A83B34F0B9EB47938D726502C54E4572766331628FA5CDA893C35376AB4538FF8717C2795B0F51F08E1137612B89B0C1E2CD1F099E88556923AE57A1DAD2AFB1230B5094A1B21BAD7DBBC333A97F179304718F3289B6DE31315B74C1A73AC7756FAA4D7EB568BBC6F7E788CD089B395564D2176B0056DFFE952C7748B048306720F602B67E8F6ADCC91F8E3AA4B8C4D7FAC233AAF93653AD2209E2FF92DA30C2D53FDEF6F4C90EAA0DE60D594ADA3915DB24279D867476EAD757B4C0264A1DB8A1F57A1B5D7173BB1A960CE02FDEFEF160D512667D655268FCC3A153A4314782A0EBFF84F65F14A0E3E12A13250C07D08C225B11A6831BC25C40467B768004DDE0E874A51144C18920BDF286090B59F51564EA4070FBBF61E3696435F28F63332B64496DF3EC8B65D54E1CF4789DDAB122DA6B264D312A711C129E3B07F4C6DA25A56173AF58B90A71B7ACFA3161A81F59D17914C99BBAC4F9A314977A89CEF7696943609BB4827964FB2976403BD4996F1E842BF5AAAE1ECCA11255B9E6001C20F72F1FD5E32CDA32D8A7AC5F62B09A0E615847CA746F489515CF8F183162859F53B97E9E5CA800EE624F729843A0009164A4A9FF76EB34E4704184848A139AD97D909F7A7ED114F087A4B2E1B4A3032391160B6F3A3649FF15AEA2B7107AF8A3B5FCAD61D43D602E6286A900870CC8CE24E39E78F0397A0D7E27E8E2D4776A44CBA218EBCD88B3C28C182A7C9F4DBB2DBB5E981563D66CEEB77E7F9034BD429D27637CF797DE82E01FEBBCE2171EFD016E402A42D78EA1ACE2CB370E75C90ADFA1A793B2169CC26522DB2F546AC1DE34C9087120C42A9F10C00D493C25730166F9D219FBDAD222C8B28115543313210848FB2F04BFDCE15D320C3634A8E4D63755515900C75BFD090AD78DD588659FBF97C96E0D0ACC8E815E608F9E861D79AF3051B942B52570B6292BF48C2BFAA9077DC76FE902683217B8BF809ED7A0050ADDBB65FDDFBD24019C9181B5AC81566113D6694EA6291D7F4A7F56A41EB91F76368DF82B164B4859259D7189240F1D8803F8107296D378BAB4D24FE6D10EF788367BCE16C5AB77FBC168B857F7BA5CDCBE5067C864F879809FE5217DEF0294BFAFDF809ABCE9532DD9DAB3448F4DA68ECA51609476278EB8C4F69EA29673F69418041D26857EBC24A487BB4B0BA63AF848545EE9BE89F139D502099B9D35DB3807B925CBA576E27170EAEC48CC2CC15B043677825D0EE81EB2CEE3A8ED14A798B879530220E50CE8C003A305382A24D23C277B99D1F4C54F9A8D33FA3D1E337E18D7CBBA5E5A47F2D5E096CF4551B23B1B86436E81B4A09D1E3D38492EC8B2A00967016AB76B9A9B1864671421DA56F57D008D5CE1B892A7E9C1F69F6C722CF109DB500E53F6BC07837AD1CD4CF4A64DA763B4A9C4929B0DCDDF7C7E1186BE3FF0C321158437820C81E74FF316AE3254E972FC197A7F0E620242AC05A4E43E987C2A8355B0357745CA79E6AE48AB29ED4FA63D3A1F19B999DE251FDE0640DD87876D55762878AD1DB12D65BAFD14B6A9A7081BF23F9F06D90CE273C5A26E012CA94DD481D32E10938C165163E89BE8A93A63034D345B74E2A94EF643D06AF9E1F5C9F104930DA00E61E061EE8C3BB17C11E05D45C1682E4D593C9198238D2BA289779E7D0F227BCB0B09972B19770FF011BF6C60D9D193CFAB32747A0095E1A4AD32514C782EF3DE7A26EA771F5530D9DE9736D0F6AE1AFB78EC7CE4884A1BB436CFCE459CD99358260906AAC99716A536CC7687A0375FDA11007618E553534E54D5B214F7AA6FC7DBE37C2BD2B64850AE469A9858987F3FA4B1FD26D954BFEC365DBE06DDCD615E1FED58A88676402D1D6B581485498B5ADFFFC42D47D61DF99384E22C5157F0178A6FDAF8F4A9491DAF298B2C3EC88085022C0A7CF245ED0FB5A38CD16F30D37DA5C4959A55501DAD50F1B48BBBDD86AB8BB522A936DDF0003B81BE16231A04E7A589C56FFFB51B07927B4AFA1DB7D48BC6FBC3F3675637184B7ADB9BADF4DE7C085BCA1D428DC9FC8277CBD85884A5921B52BB05B710615508261BB4546BD6E1FC730D16B049EA12798CE2E6DF43F5B8F3EF9AC8FBAE31B011E10C4FC62FFD7F39D16EC32CA8210ED16E041DA43D9274229514054A0F82D462FE080C6FFD7BBDBFBF0BFFC6D5ECC432A3256C0BE0DDFD5D9080C676C7955D66E44D1CE51FCC2382F868D732E85851721B48A01D08C639626EE0509CB581EFF5628FA6CCD1089AC0E12DEBE0851782E64C5049CBD6501013965CC0CA25ACAB176EF7CAB92940985DDB49021DF6C60D6C4A489116311E86BA19EDF00D74797358207CDE50506D007FE03C8804C66451F02A0182D387B759894096F65232952D183DBAAABB6BC0E191DC2C3F75FC72BD61BAB2EF19B6532B231C4AFB1A9C2CB2F3D6C451E8440D6A923CF72A63E2ED8554773887910CA5C671AD4FD5923CB95EC73FFDFBDA4B6655F55DBFD1317D024422301ED66A6E4C672085CED1F4C7B05030A100C4788FEF4CD3E494A853BDE63E9D449AE3BB6BA1083238DA3F4090515D143C67DBE53D8D507A5229FFEB2072D0BD092FC9AE52DEAAACD1F0F14B5AC84752BFD0025E5F55B869350F4B2719C5C05AC1669BB0FD3C614ACE02A270613FD3309706DDCD5B1A6AD26F359ADA80B30E50A7E50BBD3AA45D0654DD7D058B0BBF4D0D92135142214EE70511F3676AE643B5F245063B9419CF6B49FD647F27D7C41C866E6CAD9D5E2E3E331BF6B9F72ACA329BB64259C3E79783A26674B7D38EBDE8318411F4764EBDC4C7E41ACFF85BBB30318D59C42C9203ABD6636BA3F772B6725121C052DE99910D55158C6F3EF8BB7FEDE2F81E58A7AEB25E2E46FD7232302FAFA8FC37FC8B55D594B76EC4A53EB11EB3FD634428AAA5D86F839D089ABE2FEFE2AE5262FEFC7348D836692EDB215D6F8F548B885290C2403C51C3E269D493FBD339B5DFB0A38EEDA7754DAFFA16E5BCA5A9BBDE04B014B7AEA8988F3749D52D2FC1C9F7C7B2C2D692E7896E4C34F57C558CFE8317A8374409D566879A08628F644FB45B818455BCA6042B4E6187C1DD177E9E5146319904B1505F3EE00CD7FEAF0E83C3024956F77659ACC56D8D917A37E8FF7EB88713CCA334EA04B8E258C9345DA9DE26A0A366519451E1012DE6AABF4697C9DE821D70021C3250A106CF4C23A1B1785F549D3C8CD71B05FEA753E0046A3AE0A9B1F40277CF453A2BA14CBA923CC6269706DFFFD517C1E5930079912E05A5571897A06865516C86699F707E00CB38CE193490AEE30BA47DDDF3A5B4FBCEBA73DC13D0A160EA642D30D63A02964EDFDB2F29DCD32CA9974F89C32D1FA9A83C94A2770FCFCF86E64646882BD550DDD65B4E2D287AF6C196F42DBD39B020D7CDFBB6E6E75FFAAB26099EC1D25E3234F70DD972286AEA0C3436595FE49FCA898BFA421604C82D3E94856D186905076D186C684174BF4290DF31769EDC97A1DF2DFED03CF45CE678C8A1429EB978D02A79D4F8CF0168DAAB482C6C612F04B1C93637FE77B302CEFA788C11356C52C54F37A9DCFDA55927A8EF0A0CEA7CC4ADCEE459EB64DF08ED0FC29FDC3C7B762B399332063340D473966219BFC87B4A3C91C80F0E4BA86AA1879C76625C8680A227AB22780659D4B5D30E0E9A0DCE094DAF537679273A9B277ED2A2E250EEA0938204C9E963D338522A3D1A4440E2A12397A5B97D35657307BEC94CC0C72C5C6B09DAF2BAF0020B7D8CA560BF6596929AC8D4E5460F7837B41B4AE6FF12339DB8EBD7028AACFE0B42E02CDE906783ABFF694E7CBE0897ED6ED438ACDB00A4709CFEF7150EBEB08C8FF6C1543815F4B8951C3CACE499586458A73C8572389AFC9703A7FEAF673445FB4B0CCAA511D4A2CF463F57E3A6D72DA04B256699A30212E7C5768EFC151B71744156575A2E9443319232D159C6CC006FDB57C58173AD8D2C866C8887437C223888E21EF67E1A332C1FDFCC15EF17476FE0FB57D4229894725E1474C1BA1216562817F16C53ECE01C7F9E3664EEDBBA94952987431AA2A57D330EB11B28E6BF770E349ECE350C83E90DA6FE0D0A4AB9715DB28BDD397FAFA1428302151E1F222B4469879EB5D0F018606A7594BFC82C394E91B9264495C9063D505262799B9FCBE6316BBCC8D8093053636A74D4FA000000000000000000000000000000000000000000020F161B1F292E36""") + ), + new SigVerTestCase( + TestUtils.hexDecode(""" +59B2371FE7BACC207FE1FEE88A8B3805A7052865691789BB90542FA47F7EF2B75FCA13DBA5888BEC320514DCB05FD26EB5541F6E572ECEA6C4F1D38AA70259094AA945F19FED0D980E65DBF65DB80F564FE29D836C5479288B55CF07F4E00159B6955DABDECC8C4D66AE688728BA6D5C0442F3C1232C782C465B9B7C5014B1464065CCD8A56D6B1C16510869E014E6933998EF725520B400913D93B0EC75E2FB725DC1AEC0C0CC7343B9E544BAA4D679860E347B2E947D8D2436F09298A7BB8336B9DE9CFD5CDBCD91C7249268CA03EFAC273AF52968D501406CD9C96159D7C15AA2900330C1189CFC2CD8B912C480E458297EF14DB694A3F1E72C1DFA3A3D2A8A69E011602B93020BACD1C2F3AD06C95A7F36EBF5261F6EC106816BB3303CC00BF4E8688D2E8548F10490D9EB23C56793B34B8406CBE443D8356BCD0F4F61D0D017D54831B9BA329F8948F25C3122F9DEDE8CECBA51569EDFFF895FA020862C5DF79F864078486B5FB228FD789C35FDE1C54BFFBF4A025A7FE7D8C3490A5D4E62D04F79F4183CA68379F4648BD5B2416DBE5B845C9F4B7A7E2339C0506D58539EAEA9451C9B2FE2A18C849DCA7EED9DACC058D005FB7375C4EF45B001543FC68E47DDB6D14FF937D1AA0D4D7489DFFA6210679CCCECF9B8551DCF682D2AF1E5BD869F3E8D400D5C861AE51FE7EBBB5457F2EAAFD093A9598EC721C69327C51930F4B9FFB2AA7F1A28436B6D808D75392BC43C1B5B859C66C54FA515C7A615A69E60921434AA9CF9F9E03C3CA35B5EBC6A409E822FE76E0924C6C062F1724C382FF3C8ACB5C1666C2EC26B7628E3D7C13DA8D758890E6CC017B7892582E95EDD04BA9345DF70FAD56EA68BF8875B932C28B32807C86371E17DCC04725CB597B524467963E1D4A61B5FBF9EC504D5DDB61793DD4E34AE082A5990EFCE801E938CCAE738E02E90599D971C2D7C64E5B6F8639F758ED621C1F21073C03EDB782C7A0F5D7C66F5CE161DED55B3E92DC27183AB083DBC1F3930AE56EDB8C53E9A7E020FFF0C4042F518B26F390C96C8183B79B53C7C7BC515187B3DE8CAB08769C5DD6FF5492112E8B0F28D09F4067ADB04194F60250E75ADE331A5C25593BCD92A6D1350439585860BB6FEEDBD2F839F317A01358876C88E898AC0C85378F572F23CDE931D47DE71D3353DAB1F810A61B18D24CD83DDAB8D53BA9C7B8274B0FE82AFF30C57072F643787CA1DF03B99EB57DBDA8C8EE8EB201F2847CBC9D34FD80CE6BC5E1E328EB6EFC83C4BD9D52F324E30EE4B5E86351E5C8C4C5456836D5A452203B3C372C787AE3332C8A5E9DC2197D9C341B9756BB1E63C75BBD5CF3E5CD4BF47BD1FEBC3E3710912D63032F6B97DC19C4DE196ACD9157715E2C14E054A9317BF96A684BB96CEFB7D8FDCA8AA477A2AF6F726D2CAC1A603CF1360EC11CA897E5BC735AB69B8647F30CED4947BA9F635D9CB2D82A662FF17A0E12D4D06D641EE76EB8B45C71EDE38C905C52BE76C6109F2612FEE6C3194465C19BA5D3EBCF1F0B5E534E0F0F1D31CB1E7A36C4303F283DBA8591CC609311A809E444E33A893880CDBAE29119146A368E4D2EDD91FE471647FFE821AA6D31C9FA49695EB9941B08F7BE3F06CDDF2739B8CAD2AB0DA4F5A3C0A26DF6A17B137CAAB3B919AB636D6C89BEDA3058898628721F2770315FEEE881595E24CF48B441660D0B2E9D5B90928C381F2B0FA26342E4C9B88C0887A4687124C012D969E1AFD8532754BA12125E9433DCF6D7BC1A36A83E6A10BA1CB7652A81350899C2DFC6E4FED38D009E6D0F1D44CCCB95E551B3AD54B3AC81E8BA4665EA428B3C861E8677890CF5F625C19A7C5943A9401CB78E7026BAE92B60A8B6807C17745415CD8E030C64C56E822139A35DA423F264336E0AFDF167430DD36E0064B2F6E8D8BB6BE99C5A9FB551CC63E508DB636667DDA53F611F02FCD1F99410F1A7A82882F9623ADDC50EB01E1F39978BF68506C71DBBEE42E4A80069B0E4C7FC4CC1471F4F1028DB25C4687B60DF4255DEC9148197A74796EC760A66AFC7884038651920973A69C203516222632EC5875EA6D838096E7FE9B5B4FB69C5E9407E70D27FA34B0CDBD6E119D87CE38581DF1D3E0DF3AE029042A3B20E923EBCE19A4958755EE2F98FD234C4413E2DBC93559A428DC37F2D1235BD4419B099E0F0DE542C46935991BE0692A6D80B8FD9886E0FA1769B49E8AE6307CB0BC1B49732D26E25CA1CD9D407E0D8864040941611F9333B6367E8300FD646AC5A71AD913EEFD808D5CAFBF1521A3062EC184E52165501E005556DE4DEE46F9E53D7DEF9909F3D5D98CA80D87707F7BC0FF8D879D65D4D783D196F2460693811CDF33358E082D81F4DB8F6C20486183A36D4FBCC8A1C6DA21AA4DD136E19FEF2EA993972BB9989AC1C38A79F31852178004123C46277D38A88FC1589F257332284CD8A873C25A1A6D40265B285DF09370E88F72FF70E434E8F66084CCFEBDBBC4B99EDFBC750CC5DEA63617F647F5F021D57D64D5EFF048634DB2209D7C8B82FB63B8823E4CA057168BAE88D9715291240B3758D7684501F861867B7A241C063B05D5E8CA6B4C79CB2435D7F994CB76915B4A548708B11B29449685941D43E60A8976F9A96072F91041F4C3DF7C73969012AE1B30E4B9C4E133558DABC46C103C0CB1DFB99B585374A54F9BA56B7248B8C3F66F1D55760D6ABB430375774DFBA2059C5DDDB659FD2E1DA9C3F0B80868C92BCAC10403DCD140D6A3D3F35F8EF1A2DD98DE1A4334238599EDAD920DC0AA698E9FE6106A0780C9C245F2C65A0C3E5CD5366110B1760FCD414D450DB9D76A22A9EAEA0C9FB72ED543CE9FA3314BAB17687E9DE5ADAD7561F1A5BEC16339269A87E09ACB29E4C439605E9572AA9B7D0E8371A30E41A0A7BDC02DA3A6121BF261EAA016A2074E4432CF63AF96BE81CEB6E0C2676A8545C66D2F30C98B5424F0FEF04B3C6C7064E2D2E11CBE60F85723FFC0B770D6866FFA589E3F9B2ABF75104019AA69CB58895B474A0ADE2B60A4AB077C3A6DF615334EBBE732E95220213994D3BDC443C8EF94AD515F45418355183314485857AC12BA1D62CF4FD4F4DE2A7FFF1ECF0D290C4CDFFA88D8F48C5B837D3A94CD17B3D169966EB038FE5A6E85DFC60A00233F10731973DC475D53BC7B9E60320BA7905D88519FA325DF5AB02B40F2ABBDB37D2261CB8148277B87AE3297976C80C35134E5F786904564C1469947F620FE09FDF3862C4057A3BCEF70750CB727F031283A1826F1381B3348E3EA4688609ECB193AFAAEE1CD97E4DDAA02C0C30E49F137D08285941528101759A7422AA499C900A379DD73B307284CCDDAF1FA1B0C4B280E3F9F1DB6D38ECF8A841F9D4E40ECA86247D6CD9B31EACD6A46F0E333B9E83D690D7E13467619B46AF9AFCFDC4AA9A049B180260D70D9EEDB8A533051AB83517AADC2CD900B3EA51260F464AFC5D2DC411029779B21CE2CBD160218DF41F661DA1AD95AD40B8C353C7F10FC23F830D117BCAEF8CECEBCBFA49D79D8D9391E8D08281F000A55E92DB331BDECD73183E058FF3FE5839AF50D8C55F22F6AFF5A33DA774BA1B3E643F5877CF549C4F908EA64A37DF3BFA4CD5F70F8CD154476D34BC853C9E8F7979E5F4EBB888AF761"""), + TestUtils.hexDecode(""" +EA707F27A8896AA860FDF5D5897B58538D1CB6096CDF2AD5F583C5D4FCC2C91839C1AD44920216F8D027AAEE2E563D779E86FAC4B2502497B41229BE823ACF0BEB232CC6F3F7DA88E0685A9176DFE71E42470FCCCDB43C6688A03B6D8AF6612AB821CD16757FBEAE52C779EFB6AC38EF7FB4B5E365882CB83AA246B2A52D5059"""), + TestUtils.hexDecode(""" +372BF9FD2061BD26939A23C3DB128746EA3346F0C0E75C4C358405C12CAC9636D241A5E555ADF1B8C448152326F9248EBE31E8C171B3CE7C0079610C6C715BF8DA26F4344C0F043EAE26E749E56BAA190E502BCBE70740A8CDED41CF2FAB99AF00A6D788FF05C30CB8B9ACC125FEAC8C7CDFC1DD7226C819BE3A237BEE81FDA6B1DEBB83207B53BBD1E3FE07D3919AA9B3505F3DA78B7AF7A61979B9C8290563B7ADFB676D06C7AAF545452D3D7C9262AD40456D0333B362A68207D0273F488AA60F87543B4E4F4B0BFA36AAB42D523AC1D6691B680C673832888480CFF337B1590A8544A3663515198481B17D0839944754E14D565A8C32CA1D2BD4863EAEE16AC0BF8D52EFAA731CDB0A3A25D2583424F0F57E08E2018247B610F843B1ACBC54B3AE0E880B994254B4DADD9652EF5E36D3F1CCAE76DB8FF110CB3AEF24EA7B00E32278A05267C3A3319EB58E92172DC5C7EE748739C5E19AE54F7A8D714CA642958B820CF8C71F20E03730641CBCAD74E1956A1C50562E27F21FB03F44A3F032519E2E20577D4611764159405D7BB138F34126A4E5C8B3AC1A8F19817061BFE1C50A8A6767053677F1B507D70B56BAECB8BBE2F54DAACC13AD373020C13B103D2079B140ACD18D3824C03205C6198AC1603CE63602EE853B08395BC749B0DA7ACCA6DE54D1D742442C81ADA46C3A21F8F8B4A1E3C212315E6D19D290D139E70C037D4E64D3630996606E443414A371A96B19433B1DB4B5EE677113DE2005ABB42CC8DF12C33DC7791FC7AEE807E7946B023FE451ED32FF21ECA246AF26B535A11B4C6F380EF56DBFFF984ED15818EEB08578D045F2FCF39C3CB456C73EFB76C66AA09E6F9458AF39BC5A9E1E9D6E8826AD3ED681DE22E9AEE77FAACE34385376EFFA306098EDDF4F122106EEBDF32AC04884554BE6945753E6B831FAF701B4AEA4F48A8D490BDCF33B0E1630C94F756A1C565D2554F5081EE3B4EA5C33EAE04F06BD44CA0D0671708E9392EEB6C4EB80AE8A17911B27CAC8980A87A3ADD2F5E2FEC71FF711D89A6F96EA423411E81B292668F60AF44F0CC83BCF835E78F2F6BC503F54C2C6CE827D97023B98F23A85D269238013F29E9AE8BE2FB54C9AA69BB6FCCD96916918B8E534D3CDFE506A2AE474B59589CCC730A0A857BEE1F4CFAD0433BA4D34E8888FE2785A7B6331C1CE3F66E0DCC2F801C112DEE85EB869567C387305922B252073023259E1C042D3A245D141DFB0F2A1A5CE0FB772B12A0AD875DE56A8A0151891D4D4D2E2DD4E025D8BA25E63E44AD8798D495CD099B57CF73623A2FBEDBCAF1ECEE43AA0882E553F5058C50AD9C4FFCC59D93F51DA653DDDA17B14EF03D86EE7234A3808B54A1BAB7FE12154816735D62BF3ED4CA9C180D6BC050EA3937EBA6F8AEB4A7811A7307FC7A0BDB24360AA517A2333FE86CFD05E5924923AD390E6F0DC4E757AC78A754BC6B3C15954674F4AD41D05007BB984C89C198C4E4109683BFD1A1E59FD8CA36040090764B81A747ED14CED83ABE341473BCBA6B5629044DB6CCD65CF6DE91C91AC20875565440194FDB3D21CA637E019636B44F69D578C1E1CB12312FB109242C228B02A70FF001095801CC2D308A5E802C34B102F174C6C0A44D14A76B9D82D8B97C01205BDB22AEA9B2F0DE6507C0FADD1321BA71157C203DFF28207B5CD7AE18923DAB57AE263BD26A97210DAC238427857AFF7639195EC13CB74D511B40A5C5855E1EC1223B6B44C5B630AD94050B573FDF919FEA24AEAE8095AA8136D15294D876D1ACA1F862B038F35265BE879A0F1FCCE07FB76884DDE073E73785B46DC0EC95B7859594119D272CBDCEC3FFF7A1AF8B5076C977B76C7FD640B834B92066257EEF27ECA1699A7BE3ADD1746624C27256BFF5F9177C01147585D1D5CBF576F381DD6DF2320F24293F32BAD164E474CE9C741EF87302331AA9B67D64E95527C4BCFB601699D68F1F712222BF00262BF4AE8C49E098A8EADD108288EC0995D068315CE39C6429CCCB00E1D94477B76D866AD7B7968B5AA98A590782354EA512344FE58290DB10717E5C6102BC7EDC1CF85D634439D5D82C1B5A2A9928FE389BDBE4FE9AA859DCCDE68392AD6B35F516AEA70220B0D6DD2A91239EBC0D15B5930937207E0CC5AFD925A4B8BF5A0A4DB25BF87294CCD7E148684F331508A752386A0811B606B91283D865B58B347084CC01C874C046861ED3FD8DF8C5B07E8A2F27176685A39A9BCD955645F1EA58B4811DFBA16C98BA52BC0EA443D592756B00CC4CA428511A7F8051E94C5C273CC6E8652F3E9132E0ABB003C31DC61A8802D2CA650EC0B5AF5BC3E983C2746F4747AEB1F6624F010C5104F7A577E58D5D527CA58BC838C60049C99270A66C846258D32A5A5E4245088E7C6F824671AC80571DEFB07A21B64A688100F0BCC7F28B985DD9B0A1F6780B561BAA8616909555E6BF656F1E02691EF83E475E90FCE338195A88FC1DF0864B5375496B5D8FCEED265163ED2EDA2CE6CAEF6583800F225084662591706E1F8AACE331689219268A591379219CEAEF219A02CA85AFED70C96CDC7B50905EB6C2BD0E1B09DB19CC8728EB108123228628212EC1A591148DEDCEB7F4938F0A99B727B79F230BFB96B82E03AD90B6EF858CB899AA2549E0FB1E8919AADE94580A530479C140641D6620676927DFCE0DC4374AF05B379AEDAF0BFAFB0A4EF6FE04E2CD93DC6F0F4B8B680804F296FF8703219988FFD69110830F3C66555A33026EB524E75F9D4AAAFD385BEAF64BB448B2CAF9546ED326E0690948EC06BC7FC9204315D68161EAC551F228373C86BE56208DAFF85C71053355C6FBC677C87E1BEEB1D0F03B8B77F86315F98CBB8FE07B17762D9FA93E484A6E991D616E95476FCF1EF1659DAE67FA92A30CE609127DFA818CB109B5C33615BFDC647B7CB8F74581BC90EA05071E7F4E542EC1940D0E8B0BA4772DC4AB89A3F0989BD4EECC4D026BACDB44AAC9524828EE59DA8F9AEA5323F54FA60633F676B4A6537BAEDAD0B8492695D7333AFFD413DB2134328568B5B7B892585ECE9E5618F7573F014EACD05289DE2404E2A2B7CAE0E79E7AC7AFFA74CAE66B956A7F6BD9FEC4D4E10F3ED7CDD8433A35D785CA2217C5D963A29E9389928FBC1BF380E37CF1242C47342B58AF18CF83F209CD1932378C02538A5C07D369120B3B493B28AC4202971A0D2C7ED6B65E3098107ED5B20BBFF10ADBB33710DC13064C1ED6A289559FF7CC3CE77FD7A7C8701D4F9606FBC7E554E0047883EC6CD106616BF8CB821E0D17792622310BD3FDA8C5C7088C395C6272D8BF06F8F33DB65333F097211A05E2DA3E07FD05331241DD2A1DB878124F57237F5DFFC021263197B10B9352B6BA8061C58BC1BEF2DF186C376E3059862CD9AE36DEEFE6F8DC72D43BD043DAFBD54FBBB93EE72D0E792BCA927E785C9330E79C39581F408A4DA9CB0B4FEEDEB5DD9D8DBF08A736C0418284C41E9195EC680D5A9B56843E87DD76A7519CF03C5A447E407386FA81A38FDCAB479F7F239202DA95D64EA059C05DBE730A5AC672FD3D7C854FE0DDED4340F4FF0E7536F640ABBF7FB1E12DDC7CEEA34FD46BC24918A52EA55FA6FB1B91456932BA95897C92CF3B805994EA5B4C7FA069135F19CBA85E3BB73F55336A9B6113B798BCD3758E1CBBE09E7207345B6DAC55E358C60B6C9768AE2E6DDC15CBBE058B6EC06F1E99D4797E66AB0935B340D392A4C4726D8265B9C5D58B0C7FC77B367495D81518492650D37EB852E8B4672453330E30727F200646E6BDD6D70CE290739A06081F433E27D87C09ADD00E217CAEC0CAA9493AA681C777307E70EEF7184FD658F4B77B88FFDFF539E9284047787AB974CAD538FED6AFB978A38959D02217774C1B3BBCF36C805C17AC104EB27AD4E40A3F46BA2B08ADC30B713F224C18D13F83CC60B59CFBCBFE0E7864BC7A7CAD976D3BDB8CF71DD5888169E85639304D759BBF6FE7C3C6CBEBEEDA02E819A4DCBA188407295AB2D885B34EE22572518BFC0E9749192A839CC08D4A160794AE52113AA94A09258DF03A7A4DCA3EDEF6CCDC720A780DDB561B319B574F2A22A15341746B4DD6281328B3667786AF8B729C135BA418DEC122D3E119F3950FD6ADB0B0C773B90ADBC4B9E8B27043BC5D287BA5B92727FF4759F4F64B620BB226646F08414A0513F72FAA4401E371465EC7E6F4A867A47183ACD434159BBE352FE1C2D8E30BB3D7E08E25D15F1C3D996C811B9AD35A8D5B4B6D0A9A606895E4044E9ADB7A6427DF47C48614C6431F72897E5052B878996C520E9D33AF693BC69F879B8BE87BAE0564701438A51CCFAA342663927F9B2D2271ADA3CF44D8C4016020368C25FD56CECC6EE192734753D66A97E13C2327AC71E5726560D4800B26C604F1A9629F451454C86B6F5AF4CC3419AAA120BCF19671D577927E1A88185D0457DBAEE168A9A45F9BDF0DEE2A35D5E66C2DDA27D6B4EA492BB88D4EEC6CB68B23FA2338530009D9C9CD1041BB0592E83EBA03D39C7FDCEAB5C1654470399E6B85E63616CA705FDA4EAAECA06AB3F87857F15D2EBA75A3A2EEC060177F74009F5943244913E1959820D0D92A0C2AF7844881BD408F4A0CAD81AD6EC9243C8CBA108C8F58A23D5971807233173F1B98AB5C3C73B72706131C9AE644F46FDA74839D497236F152D15B97B93BCC9ACF405C1A1CEDDB9C2F03CE111977426D3438F929219E859CFF3EAFB5D2BBE48E00DF7A4B627E181A8982A3D0E640677B6F3B419B5E2AEC12B8E306253236B5D3B0C7252C2D2F7637610F07094570431E129FC23B631DAA0B6A2A6CB3C75FF8D2ED1CB906EA9CBB20956306E4EA261E10DF1FB7B3FE1D63CA8EA742104DC678AB572D0792DE89CEBFAC8E541E91CF2F7E8CF7A767365FB99A57D2C259DECB1957EF6AFAEDAAD93AB7DBBDD7341C73AC40D25161A103888C8CA74CA0EB52E195848A006E872D0BE5F5A6B5E972444E925B5DA4A3F8F81AA168B836F17F38977ECC7AF48839978A1EAD106E0C3A8A715C86448E9CF4D23703273F4CF00FCA36DAF8834DCD97655B95E6ACF495D4CFC9A7F7D5499260794107B331BFBBD211021B9B7E4C9F947BB9D338C6385B9BF73F0FF6C97C7BD8EA33228EE939BB17E11B3C9D182F818055F753C5356C5BF371E21EAF1CF14B0CE8E3EBFEEB28010DA0B7EA9E0A4285E435FC06B70F4E6DE1DA12D871C3BC8D0C884A7A99DCF2A2C8561CD445B852ADE1A11217A9658D210050AEED89DC18D71D7906389D4056E7DF99DAA462D4C77E7F93874883F33BD13BBBB5E1AA8CB86A981B5491DFCFE2B474F63EB68D923F2D43FDC21E9A56A535347C021B65E54D7935B8EBC249903C7BDC69419E683F3E1BA7450DBEB2F175E2A5593A202543E0655B909D6614290DF1792FCD7B17CDBDFF0E9121D185A082EDBB630369AECBA8C6D4C642ED0AA644832A234DBD48B4C6D8037BF97AFB75626FF28EE1206DA462ED05FF43B23D98D1790106D88C3103232B82DFEDD8B62C8006E2717C921C1695E49B742281AF1CC870CDACA295F867BD72BDAC03CFF02D406A1DD6C3A3E59E8DCF93A5BD54ABB022F9952EF1906FA66ADD7124AC3CB35209BA7958C246AE6AAEF91C5C85F844AFA38335AB67C0735F634203AACA2272994B719B655629E54537A1E75B316E22FCAE758EC85D4D968CB3242510CCBAEAE4AAEC63303EA8E1DB841893CA1BEA38EF797C756A2A75D8C7A823C2DA46FB9996C3C2BA27E19BC5D23005D97BE4D2B899CBD0748811D6E920D535BA9BBA33C4D08868E70AAB6731982181C784EA4D4CFF1D20137645CAEACB27D295F14334D102A5508DD586CDFCE93CFE4D6B5B948D16AC6363B4DF5D7DA3E61D9E0966BD23D46B2263277363524437F18FDCC302540A58823990DF6A6214CBE9FD47F336534E89BC307FB0B030FF063748DEE749FC7907F78588DE4E099CE3D9DBC4ED4F254E7B4B297F5A11999450E485B462C83E9D6519FA1BA4FA39B25D195ADC14C1B862DB6A2222FEC7A4DD09A5472410758B85AA8AC57BDFC80BB4786B2A5C3091B7D24B6854EBACFAA87FA6895E81554AE08D5EF4B3144F872CA9644FD8E7A0C613CFEA146275A72CA3F68AA2F67FF49ECA257FD912F48C6637473EEBADAFBEECB7019B99FD5FA050811ACC255F02307835771417C782D43497C7D2B39B00220396E3C5B02696A16AE562E2E57D227E71502A3DE95D88BF98492035DAE2D468795DA1C32DE795717D43B1BB0DED8C450C34CEEC27AB138D303A083980F535D9F63EEF8D8200A52EE84802B5C6D4CB14D75CC8A719202363F97878B3E719FB607897C49752875A4C9CA7CAAD5511DB6523AFDF0CEF8BCFD96AB239044FB53EEBF3A70001C62E9B86E1A604709082330081EE7538C474D94B0C5FB2664787C85CCED00080E1349869EA6AACDF321546FE415268A8D9195B6C8DDEB337887A9BCE20C2C4178B2C2CAD9386F7C000000000000000000000000000000000000000000050C171B252B3336""") + ), + new SigVerTestCase( + TestUtils.hexDecode(""" +59B2371FE7BACC207FE1FEE88A8B3805A7052865691789BB90542FA47F7EF2B75FCA13DBA5888BEC320514DCB05FD26EB5541F6E572ECEA6C4F1D38AA70259094AA945F19FED0D980E65DBF65DB80F564FE29D836C5479288B55CF07F4E00159B6955DABDECC8C4D66AE688728BA6D5C0442F3C1232C782C465B9B7C5014B1464065CCD8A56D6B1C16510869E014E6933998EF725520B400913D93B0EC75E2FB725DC1AEC0C0CC7343B9E544BAA4D679860E347B2E947D8D2436F09298A7BB8336B9DE9CFD5CDBCD91C7249268CA03EFAC273AF52968D501406CD9C96159D7C15AA2900330C1189CFC2CD8B912C480E458297EF14DB694A3F1E72C1DFA3A3D2A8A69E011602B93020BACD1C2F3AD06C95A7F36EBF5261F6EC106816BB3303CC00BF4E8688D2E8548F10490D9EB23C56793B34B8406CBE443D8356BCD0F4F61D0D017D54831B9BA329F8948F25C3122F9DEDE8CECBA51569EDFFF895FA020862C5DF79F864078486B5FB228FD789C35FDE1C54BFFBF4A025A7FE7D8C3490A5D4E62D04F79F4183CA68379F4648BD5B2416DBE5B845C9F4B7A7E2339C0506D58539EAEA9451C9B2FE2A18C849DCA7EED9DACC058D005FB7375C4EF45B001543FC68E47DDB6D14FF937D1AA0D4D7489DFFA6210679CCCECF9B8551DCF682D2AF1E5BD869F3E8D400D5C861AE51FE7EBBB5457F2EAAFD093A9598EC721C69327C51930F4B9FFB2AA7F1A28436B6D808D75392BC43C1B5B859C66C54FA515C7A615A69E60921434AA9CF9F9E03C3CA35B5EBC6A409E822FE76E0924C6C062F1724C382FF3C8ACB5C1666C2EC26B7628E3D7C13DA8D758890E6CC017B7892582E95EDD04BA9345DF70FAD56EA68BF8875B932C28B32807C86371E17DCC04725CB597B524467963E1D4A61B5FBF9EC504D5DDB61793DD4E34AE082A5990EFCE801E938CCAE738E02E90599D971C2D7C64E5B6F8639F758ED621C1F21073C03EDB782C7A0F5D7C66F5CE161DED55B3E92DC27183AB083DBC1F3930AE56EDB8C53E9A7E020FFF0C4042F518B26F390C96C8183B79B53C7C7BC515187B3DE8CAB08769C5DD6FF5492112E8B0F28D09F4067ADB04194F60250E75ADE331A5C25593BCD92A6D1350439585860BB6FEEDBD2F839F317A01358876C88E898AC0C85378F572F23CDE931D47DE71D3353DAB1F810A61B18D24CD83DDAB8D53BA9C7B8274B0FE82AFF30C57072F643787CA1DF03B99EB57DBDA8C8EE8EB201F2847CBC9D34FD80CE6BC5E1E328EB6EFC83C4BD9D52F324E30EE4B5E86351E5C8C4C5456836D5A452203B3C372C787AE3332C8A5E9DC2197D9C341B9756BB1E63C75BBD5CF3E5CD4BF47BD1FEBC3E3710912D63032F6B97DC19C4DE196ACD9157715E2C14E054A9317BF96A684BB96CEFB7D8FDCA8AA477A2AF6F726D2CAC1A603CF1360EC11CA897E5BC735AB69B8647F30CED4947BA9F635D9CB2D82A662FF17A0E12D4D06D641EE76EB8B45C71EDE38C905C52BE76C6109F2612FEE6C3194465C19BA5D3EBCF1F0B5E534E0F0F1D31CB1E7A36C4303F283DBA8591CC609311A809E444E33A893880CDBAE29119146A368E4D2EDD91FE471647FFE821AA6D31C9FA49695EB9941B08F7BE3F06CDDF2739B8CAD2AB0DA4F5A3C0A26DF6A17B137CAAB3B919AB636D6C89BEDA3058898628721F2770315FEEE881595E24CF48B441660D0B2E9D5B90928C381F2B0FA26342E4C9B88C0887A4687124C012D969E1AFD8532754BA12125E9433DCF6D7BC1A36A83E6A10BA1CB7652A81350899C2DFC6E4FED38D009E6D0F1D44CCCB95E551B3AD54B3AC81E8BA4665EA428B3C861E8677890CF5F625C19A7C5943A9401CB78E7026BAE92B60A8B6807C17745415CD8E030C64C56E822139A35DA423F264336E0AFDF167430DD36E0064B2F6E8D8BB6BE99C5A9FB551CC63E508DB636667DDA53F611F02FCD1F99410F1A7A82882F9623ADDC50EB01E1F39978BF68506C71DBBEE42E4A80069B0E4C7FC4CC1471F4F1028DB25C4687B60DF4255DEC9148197A74796EC760A66AFC7884038651920973A69C203516222632EC5875EA6D838096E7FE9B5B4FB69C5E9407E70D27FA34B0CDBD6E119D87CE38581DF1D3E0DF3AE029042A3B20E923EBCE19A4958755EE2F98FD234C4413E2DBC93559A428DC37F2D1235BD4419B099E0F0DE542C46935991BE0692A6D80B8FD9886E0FA1769B49E8AE6307CB0BC1B49732D26E25CA1CD9D407E0D8864040941611F9333B6367E8300FD646AC5A71AD913EEFD808D5CAFBF1521A3062EC184E52165501E005556DE4DEE46F9E53D7DEF9909F3D5D98CA80D87707F7BC0FF8D879D65D4D783D196F2460693811CDF33358E082D81F4DB8F6C20486183A36D4FBCC8A1C6DA21AA4DD136E19FEF2EA993972BB9989AC1C38A79F31852178004123C46277D38A88FC1589F257332284CD8A873C25A1A6D40265B285DF09370E88F72FF70E434E8F66084CCFEBDBBC4B99EDFBC750CC5DEA63617F647F5F021D57D64D5EFF048634DB2209D7C8B82FB63B8823E4CA057168BAE88D9715291240B3758D7684501F861867B7A241C063B05D5E8CA6B4C79CB2435D7F994CB76915B4A548708B11B29449685941D43E60A8976F9A96072F91041F4C3DF7C73969012AE1B30E4B9C4E133558DABC46C103C0CB1DFB99B585374A54F9BA56B7248B8C3F66F1D55760D6ABB430375774DFBA2059C5DDDB659FD2E1DA9C3F0B80868C92BCAC10403DCD140D6A3D3F35F8EF1A2DD98DE1A4334238599EDAD920DC0AA698E9FE6106A0780C9C245F2C65A0C3E5CD5366110B1760FCD414D450DB9D76A22A9EAEA0C9FB72ED543CE9FA3314BAB17687E9DE5ADAD7561F1A5BEC16339269A87E09ACB29E4C439605E9572AA9B7D0E8371A30E41A0A7BDC02DA3A6121BF261EAA016A2074E4432CF63AF96BE81CEB6E0C2676A8545C66D2F30C98B5424F0FEF04B3C6C7064E2D2E11CBE60F85723FFC0B770D6866FFA589E3F9B2ABF75104019AA69CB58895B474A0ADE2B60A4AB077C3A6DF615334EBBE732E95220213994D3BDC443C8EF94AD515F45418355183314485857AC12BA1D62CF4FD4F4DE2A7FFF1ECF0D290C4CDFFA88D8F48C5B837D3A94CD17B3D169966EB038FE5A6E85DFC60A00233F10731973DC475D53BC7B9E60320BA7905D88519FA325DF5AB02B40F2ABBDB37D2261CB8148277B87AE3297976C80C35134E5F786904564C1469947F620FE09FDF3862C4057A3BCEF70750CB727F031283A1826F1381B3348E3EA4688609ECB193AFAAEE1CD97E4DDAA02C0C30E49F137D08285941528101759A7422AA499C900A379DD73B307284CCDDAF1FA1B0C4B280E3F9F1DB6D38ECF8A841F9D4E40ECA86247D6CD9B31EACD6A46F0E333B9E83D690D7E13467619B46AF9AFCFDC4AA9A049B180260D70D9EEDB8A533051AB83517AADC2CD900B3EA51260F464AFC5D2DC411029779B21CE2CBD160218DF41F661DA1AD95AD40B8C353C7F10FC23F830D117BCAEF8CECEBCBFA49D79D8D9391E8D08281F000A55E92DB331BDECD73183E058FF3FE5839AF50D8C55F22F6AFF5A33DA774BA1B3E643F5877CF549C4F908EA64A37DF3BFA4CD5F70F8CD154476D34BC853C9E8F7979E5F4EBB888AF761"""), + TestUtils.hexDecode(""" +EBDA4B4198C041F515BA16E227F1491F54109B04C5836855038149B60978EA146DF46299A38794D61DA89DCB74A46E3EFED16C832884194E74EEC82C965E9DB2858B87962F48F0C094C389DFD1DD44CBAEDF14A62A709FF48A92E193472899A6876EA8B9701C1D137896F3C779A4E056820F55300524202E44F8B24D5B685787"""), + TestUtils.hexDecode(""" +A2E6DFCDB93DAEF3A2B0A3A548EA48D51157F45034134ACCA15A29E5417475AFE72F571B34545F92DE26B06F141B1A18545CB06D547A1E3D19F9006D7C0E9640273AE424EE20CDC0AB8CCD680AD1CA98047108ED0FFADBD8B568753E4FA7C74CE79F7980297426BEF9ED2C88ED43B45B92E77D47480DEB54993BB03A956F617FBC9E40EE1F726A1E095BF25AA2B8BAD9578506A624E018287DE7A844D4ED1AFFD8B013131272948ADBFB1B40477CE56FA0C94E1DA951049268F26B7544FC1CB0F24F14C2D7A51EE5AA9BCB8A0237231F7ED5F7D2DF14184DFB66CE0336233A506193D6CDDACCD1E2D32A449459DB55DB87080603330CD1A865B719C0C389B19C18ECBB240EFD582A0AA372C47CD00DA92CD0549AA7F7C41FEA9A348D6B7BB78F46DD2998767ECC6CF9F7E2545CA2CB1A18503167A85EA96523C537EE2FCFBE870E40E00E25E7C092A2AD5D5936AAC869D167D9D76BF2AB47185A6F3F64D0557D78D553379ED2542EF2A3CE45E5D97EB7046219E9A9F4A0021EBF5B87A95056F3D14F8A67130B8BDDDB7F5F6C41E189E070A914BF69154F06E45109E2725C5516D1FDCD93A610D3328E2758D5BF0FE58B51E05075D7DFF949E9285924CB3773C8A16CC09F86A0F14925ECADC6FE687C5F864B93868E17D5D3CF218B8E49B991A8CD7879194C425DB3ABAF41B9FCD5E0DDFABD24369EEAA68E50932F6C1C81A72D12DB8EF868B4CAD837EAF5FA0B5915C9BC48FD089F365485A92A6153D1A48B4B28682921C432DFF4B09D63EF3C9A692DCB8FF2D48A5EF0FA63FBC24C9CA2E26AC2ABBA339D2DED6EECC6784C1ECF9F0D39BA10AC8688408AF5B85D4FBC09B73D9DEEA0101146ADBC08004DAF9BC68E66515BA9E103EC4B062A45E733485FAFD9262CC7737999C76305E1106553E495B26F0B22EA7F093B4A543AE8CEB0DB3607F4CC023E45EF9F957563DEDF945CD88FDDDDE42826ADF24D95C314BA718A1C81462C2A4D1BBC2E9418A11954D972D386899B65A2D7D8FBB170A91EE0EA02D18DF1541D95BB64CC54AE8DB48E7B66A633051C04767D708C98BE328EF865431B29348D7306D389287BE9F41BB23BBD3D7A7A3C5D4C3A5F171D574B0640EE6927C1E96F2E9CD0A1BD90430D42A330C93CE66DFDC65B067D8F173EFC0EED00EF24F108B143F589AD94D0A6FC98798C1B63510734A7853D2EDF70A1918D2780C23B12CF5B1EF279604304160364651965646E0E223562381B36CD81FAB31D436F53A9D65EFB3A7EA2092CE202C1ED7FB9EA64AAB6FE7FE107424014E5AB946A3EFBAFDA9619CB7A603F11E9AE507098AFF80331075B06AC4936A711BDAAE97057E31521D5479E046EAD7E8F024E3B9C49A8A253C81A283FBFFCB0C1D896D99E881314C04FA7E0C9DF25B6166F57D97065E9166B37EF612F702E6FF1C9E81F0189E22ADD54B9F2880B23F1D3F88E120B89BEC9C699BFF18DCF870362F9B4D0F66D7416198864484393156D16A7069C0D385910DB49DC9FE8015851DC43E8B03132444BEB19B60DB6052379E5F41109354C0350A2078D397389228726C33DC492DEAD0D55DB917C6E212ACEEAE78A8530DB6A53C7A566E91E1AB62D3AA16F2736CDCD965D38D945E8A15EB68CC2B50A9C5E88F5C40B8F67AF4C36F241F3DE9EC66911937739F8F5C56C28CEC16FB453818178A3698D639A7E9A215D2F7400F5FA0772485BD75A58CA574CAC9BEF89F8F3B554A92687EEA5C6AE9651D9CEC267E13F84FB98D43FC7D24895296D78FEC1B2012F732092511930FF78664E926A57F23D3CF17BF19EEE27D833B88B6E30BF5AE5498FA55EC0D14FB127D5E6EE80560F540FBE26FD81AA62B006A139A065C11B7B48B2AB038B522168748A57DDB6C0A6CA0D7B4B79527673E58617F22F3C1B32FEFC787B41DDE9399549B0608478487126611634E5166BE7AFAEAB42F348B2691A1978CE61C753A049767A02E7055DBBFE771ECD8613B3AA29622F2FBC06F9BDCD9C94D0FB8C75310E2D4100C5248FFCDA8A898AD331BB4ECA6939FF31094F418BB8BAEC58AEF7B6FA33ED8588A21B437F4AD5EA5F2D86C4DCF1C4A559BE9B0C384AD2AA778EE93CA70989BD2ED681666CA8B082B7B83272F8A10E2D245628C8E1B5FF3BF8C5FA9C6E09C238482679888827D0E3D0B9A8CC36027649B0798E14390AD84D3D766DCEBEEB670E3560C6378F90A411196365F4FA6D332244EEF1016085C9B51614D8BF3BB44A67C906E7241213318B714824C03D9E8927AB2ADFFF50494D3F398F37E6BFAB3F8E0B89643FD220DA424BF2D751D07B5F335944462B374F297726DBBBF8C3A2D7B26BBACF192C05FF89F0878E26ACF8275644CB85C7D81022D1E85FDE63E7055E1202B85E0118687994931DE1617BA91CE9054327D3DC9DA0135DB676E9A4388DBDC3727DFCE71FCA2CEE2B2331DD836086D86C3F36767BD2F210B7B8CB1458CE8252DE845F507D78C93F7ECA7FD8CADA3DDDFEA34D2FA9AD31F10F02430C884F65346840E4CA5CC54572D6533A4E2417CF859185CA5B905BF83135BCBD88C0D86CB7C3344674F8A9A09BFD460CA828BACBE12B661459123201A5CACEBB6EF6E449B049552AEB5EA305B870055201B4686CB255E12BB1CA67DB46AED1890716672A898F71B5109A5C253276C42A22ACAEAD6E4F0798067FE983494752574A612969F1C923AD5718362E2AA1C4E5255A777DC6CBD53F553B0953BB464EBC29AA36E3F72B5C6614FAB08CC65F540D662599D45269754C0D6BE109BD7E0DF04D5EFF30000D8D6AF25B5AAD51057C31C4C134C59C3356B34638692222273144CE9D768196749FCE54DC7A7A1E2E36192FD7E756994E37D0078850E81D2D9C40670B77A02C9F708DA28CF2CCF478309B4279A6C45B9FF854A5F5B553CB291FEF5D1970883A064200D2C99597829F15DB4D9506C82154EACC4FEB0800D268902B462FE9D3284D89D83A7009AF5BDEFBCB310608151430B779A6FA4CBF6DF1E13C4A9DEE96D6BBC0CF989C48888BA58316FFA0114020B5C326D723960FC20DCFB01DC50982FD824F9512AE73E3676ED8040481CB536F851274087BFCB77A0EC7DA2BE274288D2212471DC7949EEF77A8333AABAFB57581CB43774E07F192B825F14AD564658792A0E235F4DB5EA6E3A84403492E209484542C2C2881042F54CD56CC00F2C31810EEC70D8386D0C8B7E4756A77B11563A42BC3A5D2A495D0C8278810D55EE7CB38D80C34E4DC58F0A8B1EC6E2193E6184E5F0793AB882051EBBDB3303D86F4A0E22090C7A957BE5F7BDF4652FC8F38DAC71257B2570D5B1DFA95BFEEB7E377DD581A8975D72398B4D258B1B9E7DA60217FF77BAD7008FBCCDAF7479573F9ED6BA8D13F83C233166D8D7A400F00840887BE510EAF1CF2E30B244C9EB6E166C98156C27A5FF0DB563A204B830C8FFC64D6685C9E3BF8968F3A2D2B329AA6AAB0D49EDEC26C2B5D7462AB465381D5431C85268EFB89F4E04DC660EBF4A0962F9C9F4EBB7F2A1EC5B3262DE971219FB56CF42CD720811EAF66DC2C428F94E1DE4ECE5F2116533B25E65D732A4BBD5221D28EFA946DAF52437AD6657703A9B454422C7DADEBF063E5FC433536CBA84E07F7086FE031A0A2B4DACDC99E5D3486E77D41D949EBE69E14BDF21090646CD9FF8E9F0FBF5E737DD38C0EED3D73D22A7C23AC781341109997594B3D1D4153AA1A35FF7AAD5636BFA9BE09E3329FB61950CB6DA58600E05DC2782B2EF58466AC9A4BBF6264D0D616968C6BAFC496F859EE9512072180172E91E3B581FF5CE9B8AC0624F221D111BBAAD988A530C0CADE0C4CC399EFAE9ECD624F55D93F9D0F0FC915292419ED119E177095880FBCE058783D85380F1F6673B7ED6702446098693F3FEBB9C9D7906391608453158C695D073B259518AA7DC5125B51E58A5170D1A68CF6CFC1A705B344911A63875080B4FACD9835AE85294D03EFF6D3B02888BC1D094B9E7374CAABBD1D0C32F1786B8CC12D0E4C76BC99694A1862A73ADB58A20908A601ABC4015ACC17E5B0AC28F3D8896F8BF0AA344B814D63CF558E0CED39D1F7B16D411E014BCB594F37CF18BCF46EBDEEDF1AECBD13ED97AD65A0674275868F34148D6E03E7D802258987937DBAA69215216F1CDF8BA2BCDA245D42A5D9891CF0ABC804595B320A774F1DE69F8ED595007A59F1FB570D6D024ADC97B121C28542E3043C3F99EA5EA4BE47E3DC0B66E297477537041CF880B5FAF2828E3DA2D2F9414297C59F17ED60E2DBA0502E8FE6B8E5B13FE2E945B2E78277C568082F678E4F4FF2E323D1E0AF996364E2AF2FC95C53F83953028D38BB168A1FE68C02E4477CF567DF6C2A72AF3F56EFFC99C0F5223E4CF32CA3B97C700A40803E3C91DA686DDF45A47208FC904B2384730F050A9E3440CF9A010044F7E8B6B0FEDA288F810E27AAC5DAF358046D8AE85AFB6020C22986C4788E07EFB41B2C18C482C72027673E9695CAB29FA04ABC0D7C790D3F32565A859696B6C036ACB5A6D1E444CC7D9D23B3A8FBE6E2E851914711EF790E8CBB097ACAE791825EEBA70C3AF28E6E8EFCCA38CF6B6F466D568100ECA07BF3B4B8E18EB791A2431A7FC2A795B4CDE07A38E1662044E81E85667BE36058095C7F0573D930CACEFE4C97B3393F8400451AAC6B55C5399826D8C7746BDE6484D4377BDFAD25CC5CC17C774B4623BE25184DD627CE8E6547788BD7CA2FABC9B7D4A602C457FE9EFD82B79E9322F99962FC7DAD35BFAF85A03D67DC7E83FD3C627160DC96640683AAD733B3D1EB59646A2533B99EAEA4E5CFDB2C94A8724B03FC4B72BB5BC5D90B0D4A136E44D64F3985A7EF7C6D7C55B61486CE529475F21630DD824F8AD4D3FBF0CB2C48CCC0DC27516733FF5BDC1F459B00B88883006AEDE6602DC51A316959DEBEDC0F36BBE8D017207225C1C2BD94CFC1CC60933CEA2ADE45BB4425578F4D28E0AA36DA346E2BA4B34B65BD7E71B9FCC3B52F8C425AD44B5CCD006E26857FC5BAD79D8345C5FACEAA4DC3A7C613D085826F82F10961AB2BB7C087FDB490B5A082B2F5DA5D9E6210D6E8B37ADB10DF510990F3ACD81CF93965CAAB334F1B2A76D9B17D758F273860B074B2FFFB88D9B5E6991EDBFC5FFB54325BFFC0C66092E7729C9971101D7CBF74491CC4F54D535936CBC5455E3215215E836500F411382CB8658BBB60636BAC343A645741FCD6C5E23433EFEF4F14967C5B742BDA45B2FAE1946FD0042229A1E462E172102124540CB203D58DF1EB8ADEBC4DCB37F8450DBD0FEC87CB4A56696141C9513F7D6E61BB117B0E35E1DD314837965004C6C86388C2D3EA57EA4C0CE9C563C68F5B3CA20043742BB5060935C23FC7FD5368EABE5C1A1B715B99B96E1B434229D3ADE0129AAD85710596DF9AA2D86C7EC88B9552F876861DBAD135B4EB318FC6FFBC3AF0C98EC57468A0F4BC3A29CF1625B03E33360D152B0B5F5706C169B68C7470379BA15D9188F13DFCF789C18A9DA14EAB56DB261F978D9BD894C84C1BD203A777DF785C82B87FF975BAE11437F9A243627A1715CBFFEED727B405C545542A7BED9395ADE1A671807954EAC7C9BFB8785F18D5D5C31A01320E7D863743BFC7852E251631A03EB671912F6138C21E1D62D88E1941095A8DFDF3B052A0104E72C186BFEA9CAF32B2FCA121FCF6A3D85FCBB9D7978EF2E227F321C1BD932A4DB007CB2DFE3BFD9578BD7AA6844611E4F3ED7E5370205A07B6CBBFCA7AA204D76CC8DCB9A1CB6FE6C4AFC5E5A79E59C6934D473BF834F69B89073DEC0D9ABD347B12BA21E308D42D1576F03CE4BE6EF8F07EA08CF1846C27ECEE7F8415C0FA756A540E42738892C7E6D0F90520FEAC6160911BB18BDEA2A1D925CDFBA7C585DAA3A3D27B12E4880A9B8C87B0EB5EFD7C07507D8C3B274738C90EB4A745C1AB3749ED000075E99277B927B1CAF2E19E8D588AFD3CF9BC0302724E71F129E3E3BE9D114542B16C4DB65AC8529CF95CAF7A2EED53548D1769F809F1780E5102D80B7E52B99203F5CA6F2A2A7608171190EF391A4EF5384D15C101895B5402E8D4FEA052872FBAF6DC9FFDCD3FF9EA884ABA4D90E202206E861B9785AC572A0013765C24B5E3AB9C4E31A6B7F958A4D3DE78CA4D4C097AB9AD50E588BDEC45528EC7B248BAA3BD3DF31F8FEB29F823123421388A2A021F37426188CF830BDD10C75BFFFDA15623B33F89567EBD2EC66EC7DF533CE8F33C32EBD6D074606380F37F3E9D186E4A93EB098B6EC0455843E7784A9CCC67E0326920223993CEEF7E4AE399E21993CCD078084804EAB9881B6C40CE2B20BEC97DF60381E930CBCC038A4A9153B2AF6AC6F743FE6E2FDA9A0FBD4C00D93C972333C8A8D99041D8C93718CA0CB864B5E50059D73978FA3FF33115880D43D93B8512246D82CF104A4B525F6F8B95AAB9C8DF02649497A9AAF01EB4C7EB1E232738557175E6090C2F657E9DBAD6F90860BBDEE0F701236C8489A7C200000000000000000000000000000000000511181C242D333A""") + ), + new SigVerTestCase( + TestUtils.hexDecode(""" +59B2371FE7BACC207FE1FEE88A8B3805A7052865691789BB90542FA47F7EF2B75FCA13DBA5888BEC320514DCB05FD26EB5541F6E572ECEA6C4F1D38AA70259094AA945F19FED0D980E65DBF65DB80F564FE29D836C5479288B55CF07F4E00159B6955DABDECC8C4D66AE688728BA6D5C0442F3C1232C782C465B9B7C5014B1464065CCD8A56D6B1C16510869E014E6933998EF725520B400913D93B0EC75E2FB725DC1AEC0C0CC7343B9E544BAA4D679860E347B2E947D8D2436F09298A7BB8336B9DE9CFD5CDBCD91C7249268CA03EFAC273AF52968D501406CD9C96159D7C15AA2900330C1189CFC2CD8B912C480E458297EF14DB694A3F1E72C1DFA3A3D2A8A69E011602B93020BACD1C2F3AD06C95A7F36EBF5261F6EC106816BB3303CC00BF4E8688D2E8548F10490D9EB23C56793B34B8406CBE443D8356BCD0F4F61D0D017D54831B9BA329F8948F25C3122F9DEDE8CECBA51569EDFFF895FA020862C5DF79F864078486B5FB228FD789C35FDE1C54BFFBF4A025A7FE7D8C3490A5D4E62D04F79F4183CA68379F4648BD5B2416DBE5B845C9F4B7A7E2339C0506D58539EAEA9451C9B2FE2A18C849DCA7EED9DACC058D005FB7375C4EF45B001543FC68E47DDB6D14FF937D1AA0D4D7489DFFA6210679CCCECF9B8551DCF682D2AF1E5BD869F3E8D400D5C861AE51FE7EBBB5457F2EAAFD093A9598EC721C69327C51930F4B9FFB2AA7F1A28436B6D808D75392BC43C1B5B859C66C54FA515C7A615A69E60921434AA9CF9F9E03C3CA35B5EBC6A409E822FE76E0924C6C062F1724C382FF3C8ACB5C1666C2EC26B7628E3D7C13DA8D758890E6CC017B7892582E95EDD04BA9345DF70FAD56EA68BF8875B932C28B32807C86371E17DCC04725CB597B524467963E1D4A61B5FBF9EC504D5DDB61793DD4E34AE082A5990EFCE801E938CCAE738E02E90599D971C2D7C64E5B6F8639F758ED621C1F21073C03EDB782C7A0F5D7C66F5CE161DED55B3E92DC27183AB083DBC1F3930AE56EDB8C53E9A7E020FFF0C4042F518B26F390C96C8183B79B53C7C7BC515187B3DE8CAB08769C5DD6FF5492112E8B0F28D09F4067ADB04194F60250E75ADE331A5C25593BCD92A6D1350439585860BB6FEEDBD2F839F317A01358876C88E898AC0C85378F572F23CDE931D47DE71D3353DAB1F810A61B18D24CD83DDAB8D53BA9C7B8274B0FE82AFF30C57072F643787CA1DF03B99EB57DBDA8C8EE8EB201F2847CBC9D34FD80CE6BC5E1E328EB6EFC83C4BD9D52F324E30EE4B5E86351E5C8C4C5456836D5A452203B3C372C787AE3332C8A5E9DC2197D9C341B9756BB1E63C75BBD5CF3E5CD4BF47BD1FEBC3E3710912D63032F6B97DC19C4DE196ACD9157715E2C14E054A9317BF96A684BB96CEFB7D8FDCA8AA477A2AF6F726D2CAC1A603CF1360EC11CA897E5BC735AB69B8647F30CED4947BA9F635D9CB2D82A662FF17A0E12D4D06D641EE76EB8B45C71EDE38C905C52BE76C6109F2612FEE6C3194465C19BA5D3EBCF1F0B5E534E0F0F1D31CB1E7A36C4303F283DBA8591CC609311A809E444E33A893880CDBAE29119146A368E4D2EDD91FE471647FFE821AA6D31C9FA49695EB9941B08F7BE3F06CDDF2739B8CAD2AB0DA4F5A3C0A26DF6A17B137CAAB3B919AB636D6C89BEDA3058898628721F2770315FEEE881595E24CF48B441660D0B2E9D5B90928C381F2B0FA26342E4C9B88C0887A4687124C012D969E1AFD8532754BA12125E9433DCF6D7BC1A36A83E6A10BA1CB7652A81350899C2DFC6E4FED38D009E6D0F1D44CCCB95E551B3AD54B3AC81E8BA4665EA428B3C861E8677890CF5F625C19A7C5943A9401CB78E7026BAE92B60A8B6807C17745415CD8E030C64C56E822139A35DA423F264336E0AFDF167430DD36E0064B2F6E8D8BB6BE99C5A9FB551CC63E508DB636667DDA53F611F02FCD1F99410F1A7A82882F9623ADDC50EB01E1F39978BF68506C71DBBEE42E4A80069B0E4C7FC4CC1471F4F1028DB25C4687B60DF4255DEC9148197A74796EC760A66AFC7884038651920973A69C203516222632EC5875EA6D838096E7FE9B5B4FB69C5E9407E70D27FA34B0CDBD6E119D87CE38581DF1D3E0DF3AE029042A3B20E923EBCE19A4958755EE2F98FD234C4413E2DBC93559A428DC37F2D1235BD4419B099E0F0DE542C46935991BE0692A6D80B8FD9886E0FA1769B49E8AE6307CB0BC1B49732D26E25CA1CD9D407E0D8864040941611F9333B6367E8300FD646AC5A71AD913EEFD808D5CAFBF1521A3062EC184E52165501E005556DE4DEE46F9E53D7DEF9909F3D5D98CA80D87707F7BC0FF8D879D65D4D783D196F2460693811CDF33358E082D81F4DB8F6C20486183A36D4FBCC8A1C6DA21AA4DD136E19FEF2EA993972BB9989AC1C38A79F31852178004123C46277D38A88FC1589F257332284CD8A873C25A1A6D40265B285DF09370E88F72FF70E434E8F66084CCFEBDBBC4B99EDFBC750CC5DEA63617F647F5F021D57D64D5EFF048634DB2209D7C8B82FB63B8823E4CA057168BAE88D9715291240B3758D7684501F861867B7A241C063B05D5E8CA6B4C79CB2435D7F994CB76915B4A548708B11B29449685941D43E60A8976F9A96072F91041F4C3DF7C73969012AE1B30E4B9C4E133558DABC46C103C0CB1DFB99B585374A54F9BA56B7248B8C3F66F1D55760D6ABB430375774DFBA2059C5DDDB659FD2E1DA9C3F0B80868C92BCAC10403DCD140D6A3D3F35F8EF1A2DD98DE1A4334238599EDAD920DC0AA698E9FE6106A0780C9C245F2C65A0C3E5CD5366110B1760FCD414D450DB9D76A22A9EAEA0C9FB72ED543CE9FA3314BAB17687E9DE5ADAD7561F1A5BEC16339269A87E09ACB29E4C439605E9572AA9B7D0E8371A30E41A0A7BDC02DA3A6121BF261EAA016A2074E4432CF63AF96BE81CEB6E0C2676A8545C66D2F30C98B5424F0FEF04B3C6C7064E2D2E11CBE60F85723FFC0B770D6866FFA589E3F9B2ABF75104019AA69CB58895B474A0ADE2B60A4AB077C3A6DF615334EBBE732E95220213994D3BDC443C8EF94AD515F45418355183314485857AC12BA1D62CF4FD4F4DE2A7FFF1ECF0D290C4CDFFA88D8F48C5B837D3A94CD17B3D169966EB038FE5A6E85DFC60A00233F10731973DC475D53BC7B9E60320BA7905D88519FA325DF5AB02B40F2ABBDB37D2261CB8148277B87AE3297976C80C35134E5F786904564C1469947F620FE09FDF3862C4057A3BCEF70750CB727F031283A1826F1381B3348E3EA4688609ECB193AFAAEE1CD97E4DDAA02C0C30E49F137D08285941528101759A7422AA499C900A379DD73B307284CCDDAF1FA1B0C4B280E3F9F1DB6D38ECF8A841F9D4E40ECA86247D6CD9B31EACD6A46F0E333B9E83D690D7E13467619B46AF9AFCFDC4AA9A049B180260D70D9EEDB8A533051AB83517AADC2CD900B3EA51260F464AFC5D2DC411029779B21CE2CBD160218DF41F661DA1AD95AD40B8C353C7F10FC23F830D117BCAEF8CECEBCBFA49D79D8D9391E8D08281F000A55E92DB331BDECD73183E058FF3FE5839AF50D8C55F22F6AFF5A33DA774BA1B3E643F5877CF549C4F908EA64A37DF3BFA4CD5F70F8CD154476D34BC853C9E8F7979E5F4EBB888AF761"""), + TestUtils.hexDecode(""" +4AC4675C96D9117D1EDEB80D7CD284A3E1E1FE038E301205B4C408EB965235AD1C85F8BE3F77CA486FD207F7C75F4121CD3CA2B23D6BCE4382A6D36121815025D5806CBEF452E083933C6E5C7394AC88262A6DE7770B2D8843EC101FFB5E84DE2F7A8B74E7674B3B2319BD6BF4112F92C5CFC0A55F7FA061F45325408D039D51"""), + TestUtils.hexDecode(""" +4B3F52F081B3D914BC7C6C073B182B268ADF5189E298A869BFB991B199993C1042DEF5B59270B6CD3FF8F907A1CB0D3B6FEDCA143838F8F81E0C370FFEEE6B25CD07035641A051944EAB516CFBB801536B4F262B16198E7DDB1D61C35A64D90D3948CEAAC8EE580DCEF540ED99D912BBA2BC4F5145BB949C73CCBD582613B10EAAE863ACA34683EB922B3DADFC74F76F47E4978602592402D9154394EB09FBC2EBCCC594732F2D8BC38350E5535A4412A77ADD7916604576FD6A3631E515BAF26A6F9CA4061EBBDD3BEC7179AD58552A5B508F31348A56AD1ADA7A05352C72C004B94C47E7049A10B3A59BF238A8DFC6C7019A17F05D5BFCB9D93D9D1CCBCB47F8C438098FDBDFE23F9F78BC28069908C6B9898B434CBF37787E1AF6A6B827E830E9F7629CD8F51070C4C8A8DEB260D07C3E41D8490484877491B39AA6D9E10D91748B64E33160629D8AE43EFD5F85781E69F76B6895C141EBCDDFEEB485A00BDBA4F7C991F53F2F84933926AF39E6964ABF2DFEBBC19A7E31C50797B8DA2931E10F3DAC493F198DFD785D21ADB2C062B097E889A20737F186008F2928F6B84D6E09E975A8F2AAADC785234234FDA03703A7C21F812D650BD2510B30F0550081047A155C848586A96F100D774F3E39E029B0777CD33E68318A11C1980293FAD3E787D20DFE7EEE7053C05EEB6A159BAAD4020B9EC3F537DA4DADAFB3B1BB1DBEB2D5B8F9D05A019798EAE0ED099DB066D73EE8E9A56DE368E878A7FF39140D8021D50085E6252941AB315309CB53AAA49E86347FBAD54A1F873E0CB4B86A8D5B1B2A95D485F37A9FB6105DF8440FDB8578F2624C079329569A75F36F2C55D8D030FBFEAA8889AD746C323B1AC4EC8C403E775A6FBE596E7E6A5A2863576625149940976F7CC93617B43FB13489074ECAC5BEB1A4DFE58B9AD2E0C6A15B76A7C2D208725A3123CA4E6F2C5847EE5FA8384919EF89011D219B257B3E4DC4F2095160844CAEEAFCF857260F1C63D3B05A67D3D0F2B0EC9DCC2723F13755750BAE62FCC361CFB584F774C09ADF9A0431B23E488C359C0AEF5B1C9787BD8F52B083BC9DBCC9B3039F777C7E8EABC80078050CE6D49C3BB70168FA2177298FB0A8F72C1CD28D662A07DAE6C7ACB7FB8E7FDD01DFB27C62EE683F4E5F88C7C1DDDD5EECC1C3AF853F1FF6B1D9DE672F1BF6473AF0021D8A3D4DD04A2FCA2325C721CF1C821676D0A0D574186625DE831C8411F64179F9167F78BCB22FB41C2CDB63C4DB5E138766D3803589598F114F41BA42CDB1341020449BA99656113990B4E022D8DA20D744491C6EEAB67B918E80FFF343CC5B4C8E58C3484B0125A60C36AEF763894D35148B578F417C3A98A143EDFE9F8C95BCC346C6F5EAF97AAD11DAE01C477C227A88D10ECFDCF450B37F881968027849D9B43E2BFF90C6A34AE41B8BBD743083D3C58786B036671CD6EED94DAE51F7613247EF8607ACF74A3CCE932F1C3869BDB35CA17FC6BA9F9C956FF1D4D88094325CABCE41233FB1D808EF41010396DEB0ECF50734D818DDAB70015A0ABDD1926DFA491F711AA85DA2A8EC60E3255CCF975C23CC4E8DAFDDED9FEC60A6467C45B03CA476499AA331B0E3999576CEC3191A9A62BC1BEAC1EAF20E18CFC3216127DE4AAE2E75201F9E427E39BF921150EAB949559C022D876FA242C2A845BCA7235F721B0056788A44ECC3EB98F0F502B89F8E7410EA5679AE7C0434F13AD816421D2FEE30CBCB2DAA6B851CD1B6E996DA7A757E4C4D8572C8B600DE85DDB65320D1CB71D9378349C0C401AD4F9E91272139228A8DA2F4FD2F48891A4DCB066D501D447483B611BB3C80550A90EA0B732D639D8B3926B6E7C35453ED3CC110BAF556CF46D8FC2177E76FB2663B8BDD171E94C0ACAF25B9153B22BCA749916756FB3ED3018E0944B6C3B9B6BFA15B9BE803AC79333CD2C3A27A26BC17CDA257798AE16B28B463B6DF3FA87C2D742D0F6885BEE0BEC6E20D01E5DADC86823E92D60FEC79B0D240248753E42048384C804289604821A57F4F9F50AE0C38527FE5A34938DDBCDCD9A1D020839BEBB62F9F41FBA08052ABB82FADA884CBE563791103AA585546EBFEB11272CC2E87A3B75B3C6BB1853AE7F9CF5585B2653CF5EEA244D204EB269C56A20985160659CB0725EE13CE35D55EB095A53414F232DF8108B18024EB0DBF345EB5CDAD0BCE7263509A341D54A7D534E553EAEFFE4E242EA23BCFE59A58A60425882CB7E3B0C9E4AFE8698E3DF56AFD6D611E9168747D8735CF9246D94F2126BE727FB42B2241A83B34F0B9EB47938D726502C54E4572766331628FA5CDA893C35376AB4538FF8717C2795B0F51F08E1137612B89B0C1E2CD1F099E88556923AE57A1DAD2AFB1230B5094A1B21BAD7DBBC333A97F179304718F3289B6DE31315B74C1A73AC7756FAA4D7EB568BBC6F7E788CD089B395564D2176B0056DFFE952C7748B048306720F602B67E8F6ADCC91F8E3AA4B8C4D7FAC233AAF93653AD2209E2FF92DA30C2D53FDEF6F4C90EAA0DE60D594ADA3915DB24279D867476EAD757B4C0264A1DB8A1F57A1B5D7173BB1A960CE02FDEFEF160D512667D655268FCC3A153A4314782A0EBFF84F65F14A0E3E12A13250C07D08C225B11A6831BC25C40467B768004DDE0E874A51144C18920BDF286090B59F51564EA4070FBBF61E3696435F28F63332B64496DF3EC8B65D54E1CF4789DDAB122DA6B264D312A711C129E3B07F4C6DA25A56173AF58B90A71B7ACFA3161A81F59D17914C99BBAC4F9A314977A89CEF7696943609BB4827964FB2976403BD4996F1E842BF5AAAE1ECCA11255B9E6001C20F72F1FD5E32CDA32D8A7AC5F62B09A0E615847CA746F489515CF8F183162859F53B97E9E5CA800EE624F729843A0009164A4A9FF76EB34E4704184848A139AD97D909F7A7ED114F087A4B2E1B4A3032391160B6F3A3649FF15AEA2B7107AF8A3B5FCAD61D43D602E6286A900870CC8CE24E39E78F0397A0D7E27E8E2D4776A44CBA218EBCD88B3C28C182A7C9F4DBB2DBB5E981563D66CEEB77E7F9034BD429D27637CF797DE82E01FEBBCE2171EFD016E402A42D78EA1ACE2CB370E75C90ADFA1A793B2169CC26522DB2F546AC1DE34C9087120C42A9F10C00D493C25730166F9D219FBDAD222C8B28115543313210848FB2F04BFDCE15D320C3634A8E4D63755515900C75BFD090AD78DD588659FBF97C96E0D0ACC8E815E608F9E861D79AF3051B942B52570B6292BF48C2BFAA9077DC76FE902683217B8BF809ED7A0050ADDBB65FDDFBD24019C9181B5AC81566113D6694EA6291D7F4A7F56A41EB91F76368DF82B164B4859259D7189240F1D8803F8107296D378BAB4D24FE6D10EF788367BCE16C5AB77FBC168B857F7BA5CDCBE5067C864F879809FE5217DEF0294BFAFDF809ABCE9532DD9DAB3448F4DA68ECA51609476278EB8C4F69EA29673F69418041D26857EBC24A487BB4B0BA63AF848545EE9BE89F139D502099B9D35DB3807B925CBA576E27170EAEC48CC2CC15B043677825D0EE81EB2CEE3A8ED14A798B879530220E50CE8C003A305382A24D23C277B99D1F4C54F9A8D33FA3D1E337E18D7CBBA5E5A47F2D5E096CF4551B23B1B86436E81B4A09D1E3D38492EC8B2A00967016AB76B9A9B1864671421DA56F57D008D5CE1B892A7E9C1F69F6C722CF109DB500E53F6BC07837AD1CD4CF4A64DA763B4A9C4929B0DCDDF7C7E1186BE3FF0C321158437820C81E74FF316AE3254E972FC197A7F0E620242AC05A4E43E987C2A8355B0357745CA79E6AE48AB29ED4FA63D3A1F19B999DE251FDE0640DD87876D55762878AD1DB12D65BAFD14B6A9A7081BF23F9F06D90CE273C5A26E012CA94DD481D32E10938C165163E89BE8A93A63034D345B74E2A94EF643D06AF9E1F5C9F104930DA00E61E061EE8C3BB17C11E05D45C1682E4D593C9198238D2BA289779E7D0F227BCB0B09972B19770FF011BF6C60D9D193CFAB32747A0095E1A4AD32514C782EF3DE7A26EA771F5530D9DE9736D0F6AE1AFB78EC7CE4884A1BB436CFCE459CD99358260906AAC99716A536CC7687A0375FDA11007618E553534E54D5B214F7AA6FC7DBE37C2BD2B64850AE469A9858987F3FA4B1FD26D954BFEC365DBE06DDCD615E1FED58A88676402D1D6B581485498B5ADFFFC42D47D61DF99384E22C5157F0178A6FDAF8F4A9491DAF298B2C3EC88085022C0A7CF245ED0FB5A38CD16F30D37DA5C4959A55501DAD50F1B48BBBDD86AB8BB522A936DDF0003B81BE16231A04E7A589C56FFFB51B07927B4AFA1DB7D48BC6FBC3F3675637184B7ADB9BADF4DE7C085BCA1D428DC9FC8277CBD85884A5921B52BB05B710615508261BB4546BD6E1FC730D16B049EA12798CE2E6DF43F5B8F3EF9AC8FBAE31B011E10C4FC62FFD7F39D16EC32CA8210ED16E041DA43D9274229514054A0F82D462FE080C6FFD7BBDBFBF0BFFC6D5ECC432A3256C0BE0DDFD5D9080C676C7955D66E44D1CE51FCC2382F868D732E85851721B48A01D08C639626EE0509CB581EFF5628FA6CCD1089AC0E12DEBE0851782E64C5049CBD6501013965CC0CA25ACAB176EF7CAB92940985DDB49021DF6C60D6C4A489116311E86BA19EDF00D74797358207CDE50506D007FE03C8804C66451F02A0182D387B759894096F65232952D183DBAAABB6BC0E191DC2C3F75FC72BD61BAB2EF19B6532B231C4AFB1A9C2CB2F3D6C451E8440D6A923CF72A63E2ED8554773887910CA5C671AD4FD5923CB95EC73FFDFBDA4B6655F55DBFD1317D024422301ED66A6E4C672085CED1F4C7B05030A100C4788FEF4CD3E494A853BDE63E9D449AE3BB6BA1083238DA3F4090515D143C67DBE53D8D507A5229FFEB2072D0BD092FC9AE52DEAAACD1F0F14B5AC84752BFD0025E5F55B869350F4B2719C5C05AC1669BB0FD3C614ACE02A270613FD3309706DDCD5B1A6AD26F359ADA80B30E50A7E50BBD3AA45D0654DD7D058B0BBF4D0D92135142214EE70511F3676AE643B5F245063B9419CF6B49FD647F27D7C41C866E6CAD9D5E2E3E331BF6B9F72ACA329BB64259C3E79783A26674B7D38EBDE8318411F4764EBDC4C7E41ACFF85BBB30318D59C42C9203ABD6636BA3F772B6725121C052DE99910D55158C6F3EF8BB7FEDE2F81E58A7AEB25E2E46FD7232302FAFA8FC37FC8B55D594B76EC4A53EB11EB3FD634428AAA5D86F839D089ABE2FEFE2AE5262FEFC7348D836692EDB215D6F8F548B885290C2403C51C3E269D493FBD339B5DFB0A38EEDA7754DAFFA16E5BCA5A9BBDE04B014B7AEA8988F3749D52D2FC1C9F7C7B2C2D692E7896E4C34F57C558CFE8317A8374409D566879A08628F644FB45B818455BCA6042B4E6187C1DD177E9E5146319904B1505F3EE00CD7FEAF0E83C3024956F77659ACC56D8D917A37E8FF7EB88713CCA334EA04B8E258C9345DA9DE26A0A366519451E1012DE6AABF4697C9DE821D70021C3250A106CF4C23A1B1785F549D3C8CD71B05FEA753E0046A3AE0A9B1F40277CF453A2BA14CBA923CC6269706DFFFD517C1E5930079912E05A5571897A06865516C86699F707E00CB38CE193490AEE30BA47DDDF3A5B4FBCEBA73DC13D0A160EA642D30D63A02964EDFDB2F29DCD32CA9974F89C32D1FA9A83C94A2770FCFCF86E64646882BD550DDD65B4E2D287AF6C196F42DBD39B020D7CDFBB6E6E75FFAAB26099EC1D25E3234F70DD972286AEA0C3436595FE49FCA898BFA421604C82D3E94856D186905076D186C684174BF4290DF31769EDC97A1DF2DFED03CF45CE678C8A1429EB978D02A79D4F8CF0168DAAB482C6C612F04B1C93637FE77B302CEFA788C11356C52C54F37A9DCFDA55927A8EF0A0CEA7CC4ADCEE459EB64DF08ED0FC29FDC3C7B762B399332063340D473966219BFC87B4A3C91C80F0E4BA86AA1879C76625C8680A227AB22780659D4B5D30E0E9A0DCE094DAF537679273A9B277ED2A2E250EEA0938204C9E963D338522A3D1A4440E2A12397A5B97D35657307BEC94CC0C72C5C6B09DAF2BAF0020B7D8CA560BF6596929AC8D4E5460F7837B41B4AE6FF12339DB8EBD7028AACFE0B42E02CDE906783ABFF694E7CBE0897ED6ED438ACDB00A4709CFEF7150EBEB08C8FF6C1543815F4B8951C3CACE499586458A73C8572389AFC9703A7FEAF673445FB4B0CCAA511D4A2CF463F57E3A6D72DA04B256699A30212E7C5768EFC151B71744156575A2E9443319232D159C6CC006FDB57C58173AD8D2C866C8887437C223888E21EF67E1A332C1FDFCC15EF17476FE0FB57D4229894725E1474C1BA1216562817F16C53ECE01C7F9E3664EEDBBA94952987431AA2A57D330EB11B28E6BF770E349ECE350C83E90DA6FE0D0A4AB9715DB28BDD397FAFA1428302151E1F222B4469879EB5D0F018606A7594BFC82C394E91B9264495C9063D505262799B9FCBE6316BBCC8D8093053636A74D4FA000000000000000000000000000000000000000000020F161B1F292E36""") + ), + new SigVerTestCase( + TestUtils.hexDecode(""" +59B2371FE7BACC207FE1FEE88A8B3805A7052865691789BB90542FA47F7EF2B75FCA13DBA5888BEC320514DCB05FD26EB5541F6E572ECEA6C4F1D38AA70259094AA945F19FED0D980E65DBF65DB80F564FE29D836C5479288B55CF07F4E00159B6955DABDECC8C4D66AE688728BA6D5C0442F3C1232C782C465B9B7C5014B1464065CCD8A56D6B1C16510869E014E6933998EF725520B400913D93B0EC75E2FB725DC1AEC0C0CC7343B9E544BAA4D679860E347B2E947D8D2436F09298A7BB8336B9DE9CFD5CDBCD91C7249268CA03EFAC273AF52968D501406CD9C96159D7C15AA2900330C1189CFC2CD8B912C480E458297EF14DB694A3F1E72C1DFA3A3D2A8A69E011602B93020BACD1C2F3AD06C95A7F36EBF5261F6EC106816BB3303CC00BF4E8688D2E8548F10490D9EB23C56793B34B8406CBE443D8356BCD0F4F61D0D017D54831B9BA329F8948F25C3122F9DEDE8CECBA51569EDFFF895FA020862C5DF79F864078486B5FB228FD789C35FDE1C54BFFBF4A025A7FE7D8C3490A5D4E62D04F79F4183CA68379F4648BD5B2416DBE5B845C9F4B7A7E2339C0506D58539EAEA9451C9B2FE2A18C849DCA7EED9DACC058D005FB7375C4EF45B001543FC68E47DDB6D14FF937D1AA0D4D7489DFFA6210679CCCECF9B8551DCF682D2AF1E5BD869F3E8D400D5C861AE51FE7EBBB5457F2EAAFD093A9598EC721C69327C51930F4B9FFB2AA7F1A28436B6D808D75392BC43C1B5B859C66C54FA515C7A615A69E60921434AA9CF9F9E03C3CA35B5EBC6A409E822FE76E0924C6C062F1724C382FF3C8ACB5C1666C2EC26B7628E3D7C13DA8D758890E6CC017B7892582E95EDD04BA9345DF70FAD56EA68BF8875B932C28B32807C86371E17DCC04725CB597B524467963E1D4A61B5FBF9EC504D5DDB61793DD4E34AE082A5990EFCE801E938CCAE738E02E90599D971C2D7C64E5B6F8639F758ED621C1F21073C03EDB782C7A0F5D7C66F5CE161DED55B3E92DC27183AB083DBC1F3930AE56EDB8C53E9A7E020FFF0C4042F518B26F390C96C8183B79B53C7C7BC515187B3DE8CAB08769C5DD6FF5492112E8B0F28D09F4067ADB04194F60250E75ADE331A5C25593BCD92A6D1350439585860BB6FEEDBD2F839F317A01358876C88E898AC0C85378F572F23CDE931D47DE71D3353DAB1F810A61B18D24CD83DDAB8D53BA9C7B8274B0FE82AFF30C57072F643787CA1DF03B99EB57DBDA8C8EE8EB201F2847CBC9D34FD80CE6BC5E1E328EB6EFC83C4BD9D52F324E30EE4B5E86351E5C8C4C5456836D5A452203B3C372C787AE3332C8A5E9DC2197D9C341B9756BB1E63C75BBD5CF3E5CD4BF47BD1FEBC3E3710912D63032F6B97DC19C4DE196ACD9157715E2C14E054A9317BF96A684BB96CEFB7D8FDCA8AA477A2AF6F726D2CAC1A603CF1360EC11CA897E5BC735AB69B8647F30CED4947BA9F635D9CB2D82A662FF17A0E12D4D06D641EE76EB8B45C71EDE38C905C52BE76C6109F2612FEE6C3194465C19BA5D3EBCF1F0B5E534E0F0F1D31CB1E7A36C4303F283DBA8591CC609311A809E444E33A893880CDBAE29119146A368E4D2EDD91FE471647FFE821AA6D31C9FA49695EB9941B08F7BE3F06CDDF2739B8CAD2AB0DA4F5A3C0A26DF6A17B137CAAB3B919AB636D6C89BEDA3058898628721F2770315FEEE881595E24CF48B441660D0B2E9D5B90928C381F2B0FA26342E4C9B88C0887A4687124C012D969E1AFD8532754BA12125E9433DCF6D7BC1A36A83E6A10BA1CB7652A81350899C2DFC6E4FED38D009E6D0F1D44CCCB95E551B3AD54B3AC81E8BA4665EA428B3C861E8677890CF5F625C19A7C5943A9401CB78E7026BAE92B60A8B6807C17745415CD8E030C64C56E822139A35DA423F264336E0AFDF167430DD36E0064B2F6E8D8BB6BE99C5A9FB551CC63E508DB636667DDA53F611F02FCD1F99410F1A7A82882F9623ADDC50EB01E1F39978BF68506C71DBBEE42E4A80069B0E4C7FC4CC1471F4F1028DB25C4687B60DF4255DEC9148197A74796EC760A66AFC7884038651920973A69C203516222632EC5875EA6D838096E7FE9B5B4FB69C5E9407E70D27FA34B0CDBD6E119D87CE38581DF1D3E0DF3AE029042A3B20E923EBCE19A4958755EE2F98FD234C4413E2DBC93559A428DC37F2D1235BD4419B099E0F0DE542C46935991BE0692A6D80B8FD9886E0FA1769B49E8AE6307CB0BC1B49732D26E25CA1CD9D407E0D8864040941611F9333B6367E8300FD646AC5A71AD913EEFD808D5CAFBF1521A3062EC184E52165501E005556DE4DEE46F9E53D7DEF9909F3D5D98CA80D87707F7BC0FF8D879D65D4D783D196F2460693811CDF33358E082D81F4DB8F6C20486183A36D4FBCC8A1C6DA21AA4DD136E19FEF2EA993972BB9989AC1C38A79F31852178004123C46277D38A88FC1589F257332284CD8A873C25A1A6D40265B285DF09370E88F72FF70E434E8F66084CCFEBDBBC4B99EDFBC750CC5DEA63617F647F5F021D57D64D5EFF048634DB2209D7C8B82FB63B8823E4CA057168BAE88D9715291240B3758D7684501F861867B7A241C063B05D5E8CA6B4C79CB2435D7F994CB76915B4A548708B11B29449685941D43E60A8976F9A96072F91041F4C3DF7C73969012AE1B30E4B9C4E133558DABC46C103C0CB1DFB99B585374A54F9BA56B7248B8C3F66F1D55760D6ABB430375774DFBA2059C5DDDB659FD2E1DA9C3F0B80868C92BCAC10403DCD140D6A3D3F35F8EF1A2DD98DE1A4334238599EDAD920DC0AA698E9FE6106A0780C9C245F2C65A0C3E5CD5366110B1760FCD414D450DB9D76A22A9EAEA0C9FB72ED543CE9FA3314BAB17687E9DE5ADAD7561F1A5BEC16339269A87E09ACB29E4C439605E9572AA9B7D0E8371A30E41A0A7BDC02DA3A6121BF261EAA016A2074E4432CF63AF96BE81CEB6E0C2676A8545C66D2F30C98B5424F0FEF04B3C6C7064E2D2E11CBE60F85723FFC0B770D6866FFA589E3F9B2ABF75104019AA69CB58895B474A0ADE2B60A4AB077C3A6DF615334EBBE732E95220213994D3BDC443C8EF94AD515F45418355183314485857AC12BA1D62CF4FD4F4DE2A7FFF1ECF0D290C4CDFFA88D8F48C5B837D3A94CD17B3D169966EB038FE5A6E85DFC60A00233F10731973DC475D53BC7B9E60320BA7905D88519FA325DF5AB02B40F2ABBDB37D2261CB8148277B87AE3297976C80C35134E5F786904564C1469947F620FE09FDF3862C4057A3BCEF70750CB727F031283A1826F1381B3348E3EA4688609ECB193AFAAEE1CD97E4DDAA02C0C30E49F137D08285941528101759A7422AA499C900A379DD73B307284CCDDAF1FA1B0C4B280E3F9F1DB6D38ECF8A841F9D4E40ECA86247D6CD9B31EACD6A46F0E333B9E83D690D7E13467619B46AF9AFCFDC4AA9A049B180260D70D9EEDB8A533051AB83517AADC2CD900B3EA51260F464AFC5D2DC411029779B21CE2CBD160218DF41F661DA1AD95AD40B8C353C7F10FC23F830D117BCAEF8CECEBCBFA49D79D8D9391E8D08281F000A55E92DB331BDECD73183E058FF3FE5839AF50D8C55F22F6AFF5A33DA774BA1B3E643F5877CF549C4F908EA64A37DF3BFA4CD5F70F8CD154476D34BC853C9E8F7979E5F4EBB888AF761"""), + TestUtils.hexDecode(""" +EA707F27A8896AA860FDF5D5897B58538D1CB6096CDF2AD5F583C5D4FCC2C91839C1AD44920216F8D027AAEE2E563D779E86FAC4B2502497B41229BE823ACF0BEB232CC6F3F7DA88E0685A9176DFE71E42470FCCCDB43C6688A03B6D8AF6612AB821CD16757FBEAE52C779EFB6AC38EF7FB4B5E365882CB83AA246B2A52D5059"""), + TestUtils.hexDecode(""" +372BF9FD2061BD26939A23C3DB128746EA3346F0C0E75C4C358405C12CAC9636D241A5E555ADF1B8C448152326F9248EBE31E8C171B3CE7C0079610C6C715BF8DA26F4344C0F043EAE26E749E56BAA190E502BCBE70740A8CDED41CF2FAB99AF00A6D788FF05C30CB8B9ACC125FEAC8C7CDFC1DD7226C819BE3A237BEE81FDA6B1DEBB83207B53BBD1E3FE07D3919AA9B3505F3DA78B7AF7A61979B9C8290563B7ADFB676D06C7AAF545452D3D7C9262AD40456D0333B362A68207D0273F488AA60F87543B4E4F4B0BFA36AAB42D523AC1D6691B680C673832888480CFF337B1590A8544A3663515198481B17D0839944754E14D565A8C32CA1D2BD4863EAEE16AC0BF8D52EFAA731CDB0A3A25D2583424F0F57E08E2018247B610F843B1ACBC54B3AE0E880B994254B4DADD9652EF5E36D3F1CCAE76DB8FF110CB3AEF24EA7B00E32278A05267C3A3319EB58E92172DC5C7EE748739C5E19AE54F7A8D714CA642958B820CF8C71F20E03730641CBCAD74E1956A1C50562E27F21FB03F44A3F032519E2E20577D4611764159405D7BB138F34126A4E5C8B3AC1A8F19817061BFE1C50A8A6767053677F1B507D70B56BAECB8BBE2F54DAACC13AD373020C13B103D2079B140ACD18D3824C03205C6198AC1603CE63602EE853B08395BC749B0DA7ACCA6DE54D1D742442C81ADA46C3A21F8F8B4A1E3C212315E6D19D290D139E70C037D4E64D3630996606E443414A371A96B19433B1DB4B5EE677113DE2005ABB42CC8DF12C33DC7791FC7AEE807E7946B023FE451ED32FF21ECA246AF26B535A11B4C6F380EF56DBFFF984ED15818EEB08578D045F2FCF39C3CB456C73EFB76C66AA09E6F9458AF39BC5A9E1E9D6E8826AD3ED681DE22E9AEE77FAACE34385376EFFA306098EDDF4F122106EEBDF32AC04884554BE6945753E6B831FAF701B4AEA4F48A8D490BDCF33B0E1630C94F756A1C565D2554F5081EE3B4EA5C33EAE04F06BD44CA0D0671708E9392EEB6C4EB80AE8A17911B27CAC8980A87A3ADD2F5E2FEC71FF711D89A6F96EA423411E81B292668F60AF44F0CC83BCF835E78F2F6BC503F54C2C6CE827D97023B98F23A85D269238013F29E9AE8BE2FB54C9AA69BB6FCCD96916918B8E534D3CDFE506A2AE474B59589CCC730A0A857BEE1F4CFAD0433BA4D34E8888FE2785A7B6331C1CE3F66E0DCC2F801C112DEE85EB869567C387305922B252073023259E1C042D3A245D141DFB0F2A1A5CE0FB772B12A0AD875DE56A8A0151891D4D4D2E2DD4E025D8BA25E63E44AD8798D495CD099B57CF73623A2FBEDBCAF1ECEE43AA0882E553F5058C50AD9C4FFCC59D93F51DA653DDDA17B14EF03D86EE7234A3808B54A1BAB7FE12154816735D62BF3ED4CA9C180D6BC050EA3937EBA6F8AEB4A7811A7307FC7A0BDB24360AA517A2333FE86CFD05E5924923AD390E6F0DC4E757AC78A754BC6B3C15954674F4AD41D05007BB984C89C198C4E4109683BFD1A1E59FD8CA36040090764B81A747ED14CED83ABE341473BCBA6B5629044DB6CCD65CF6DE91C91AC20875565440194FDB3D21CA637E019636B44F69D578C1E1CB12312FB109242C228B02A70FF001095801CC2D308A5E802C34B102F174C6C0A44D14A76B9D82D8B97C01205BDB22AEA9B2F0DE6507C0FADD1321BA71157C203DFF28207B5CD7AE18923DAB57AE263BD26A97210DAC238427857AFF7639195EC13CB74D511B40A5C5855E1EC1223B6B44C5B630AD94050B573FDF919FEA24AEAE8095AA8136D15294D876D1ACA1F862B038F35265BE879A0F1FCCE07FB76884DDE073E73785B46DC0EC95B7859594119D272CBDCEC3FFF7A1AF8B5076C977B76C7FD640B834B92066257EEF27ECA1699A7BE3ADD1746624C27256BFF5F9177C01147585D1D5CBF576F381DD6DF2320F24293F32BAD164E474CE9C741EF87302331AA9B67D64E95527C4BCFB601699D68F1F712222BF00262BF4AE8C49E098A8EADD108288EC0995D068315CE39C6429CCCB00E1D94477B76D866AD7B7968B5AA98A590782354EA512344FE58290DB10717E5C6102BC7EDC1CF85D634439D5D82C1B5A2A9928FE389BDBE4FE9AA859DCCDE68392AD6B35F516AEA70220B0D6DD2A91239EBC0D15B5930937207E0CC5AFD925A4B8BF5A0A4DB25BF87294CCD7E148684F331508A752386A0811B606B91283D865B58B347084CC01C874C046861ED3FD8DF8C5B07E8A2F27176685A39A9BCD955645F1EA58B4811DFBA16C98BA52BC0EA443D592756B00CC4CA428511A7F8051E94C5C273CC6E8652F3E9132E0ABB003C31DC61A8802D2CA650EC0B5AF5BC3E983C2746F4747AEB1F6624F010C5104F7A577E58D5D527CA58BC838C60049C99270A66C846258D32A5A5E4245088E7C6F824671AC80571DEFB07A21B64A688100F0BCC7F28B985DD9B0A1F6780B561BAA8616909555E6BF656F1E02691EF83E475E90FCE338195A88FC1DF0864B5375496B5D8FCEED265163ED2EDA2CE6CAEF6583800F225084662591706E1F8AACE331689219268A591379219CEAEF219A02CA85AFED70C96CDC7B50905EB6C2BD0E1B09DB19CC8728EB108123228628212EC1A591148DEDCEB7F4938F0A99B727B79F230BFB96B82E03AD90B6EF858CB899AA2549E0FB1E8919AADE94580A530479C140641D6620676927DFCE0DC4374AF05B379AEDAF0BFAFB0A4EF6FE04E2CD93DC6F0F4B8B680804F296FF8703219988FFD69110830F3C66555A33026EB524E75F9D4AAAFD385BEAF64BB448B2CAF9546ED326E0690948EC06BC7FC9204315D68161EAC551F228373C86BE56208DAFF85C71053355C6FBC677C87E1BEEB1D0F03B8B77F86315F98CBB8FE07B17762D9FA93E484A6E991D616E95476FCF1EF1659DAE67FA92A30CE609127DFA818CB109B5C33615BFDC647B7CB8F74581BC90EA05071E7F4E542EC1940D0E8B0BA4772DC4AB89A3F0989BD4EECC4D026BACDB44AAC9524828EE59DA8F9AEA5323F54FA60633F676B4A6537BAEDAD0B8492695D7333AFFD413DB2134328568B5B7B892585ECE9E5618F7573F014EACD05289DE2404E2A2B7CAE0E79E7AC7AFFA74CAE66B956A7F6BD9FEC4D4E10F3ED7CDD8433A35D785CA2217C5D963A29E9389928FBC1BF380E37CF1242C47342B58AF18CF83F209CD1932378C02538A5C07D369120B3B493B28AC4202971A0D2C7ED6B65E3098107ED5B20BBFF10ADBB33710DC13064C1ED6A289559FF7CC3CE77FD7A7C8701D4F9606FBC7E554E0047883EC6CD106616BF8CB821E0D17792622310BD3FDA8C5C7088C395C6272D8BF06F8F33DB65333F097211A05E2DA3E07FD05331241DD2A1DB878124F57237F5DFFC021263197B10B9352B6BA8061C58BC1BEF2DF186C376E3059862CD9AE36DEEFE6F8DC72D43BD043DAFBD54FBBB93EE72D0E792BCA927E785C9330E79C39581F408A4DA9CB0B4FEEDEB5DD9D8DBF08A736C0418284C41E9195EC680D5A9B56843E87DD76A7519CF03C5A447E407386FA81A38FDCAB479F7F239202DA95D64EA059C05DBE730A5AC672FD3D7C854FE0DDED4340F4FF0E7536F640ABBF7FB1E12DDC7CEEA34FD46BC24918A52EA55FA6FB1B91456932BA95897C92CF3B805994EA5B4C7FA069135F19CBA85E3BB73F55336A9B6113B798BCD3758E1CBBE09E7207345B6DAC55E358C60B6C9768AE2E6DDC15CBBE058B6EC06F1E99D4797E66AB0935B340D392A4C4726D8265B9C5D58B0C7FC77B367495D81518492650D37EB852E8B4672453330E30727F200646E6BDD6D70CE290739A06081F433E27D87C09ADD00E217CAEC0CAA9493AA681C777307E70EEF7184FD658F4B77B88FFDFF539E9284047787AB974CAD538FED6AFB978A38959D02217774C1B3BBCF36C805C17AC104EB27AD4E40A3F46BA2B08ADC30B713F224C18D13F83CC60B59CFBCBFE0E7864BC7A7CAD976D3BDB8CF71DD5888169E85639304D759BBF6FE7C3C6CBEBEEDA02E819A4DCBA188407295AB2D885B34EE22572518BFC0E9749192A839CC08D4A160794AE52113AA94A09258DF03A7A4DCA3EDEF6CCDC720A780DDB561B319B574F2A22A15341746B4DD6281328B3667786AF8B729C135BA418DEC122D3E119F3950FD6ADB0B0C773B90ADBC4B9E8B27043BC5D287BA5B92727FF4759F4F64B620BB226646F08414A0513F72FAA4401E371465EC7E6F4A867A47183ACD434159BBE352FE1C2D8E30BB3D7E08E25D15F1C3D996C811B9AD35A8D5B4B6D0A9A606895E4044E9ADB7A6427DF47C48614C6431F72897E5052B878996C520E9D33AF693BC69F879B8BE87BAE0564701438A51CCFAA342663927F9B2D2271ADA3CF44D8C4016020368C25FD56CECC6EE192734753D66A97E13C2327AC71E5726560D4800B26C604F1A9629F451454C86B6F5AF4CC3419AAA120BCF19671D577927E1A88185D0457DBAEE168A9A45F9BDF0DEE2A35D5E66C2DDA27D6B4EA492BB88D4EEC6CB68B23FA2338530009D9C9CD1041BB0592E83EBA03D39C7FDCEAB5C1654470399E6B85E63616CA705FDA4EAAECA06AB3F87857F15D2EBA75A3A2EEC060177F74009F5943244913E1959820D0D92A0C2AF7844881BD408F4A0CAD81AD6EC9243C8CBA108C8F58A23D5971807233173F1B98AB5C3C73B72706131C9AE644F46FDA74839D497236F152D15B97B93BCC9ACF405C1A1CEDDB9C2F03CE111977426D3438F929219E859CFF3EAFB5D2BBE48E00DF7A4B627E181A8982A3D0E640677B6F3B419B5E2AEC12B8E306253236B5D3B0C7252C2D2F7637610F07094570431E129FC23B631DAA0B6A2A6CB3C75FF8D2ED1CB906EA9CBB20956306E4EA261E10DF1FB7B3FE1D63CA8EA742104DC678AB572D0792DE89CEBFAC8E541E91CF2F7E8CF7A767365FB99A57D2C259DECB1957EF6AFAEDAAD93AB7DBBDD7341C73AC40D25161A103888C8CA74CA0EB52E195848A006E872D0BE5F5A6B5E972444E925B5DA4A3F8F81AA168B836F17F38977ECC7AF48839978A1EAD106E0C3A8A715C86448E9CF4D23703273F4CF00FCA36DAF8834DCD97655B95E6ACF495D4CFC9A7F7D5499260794107B331BFBBD211021B9B7E4C9F947BB9D338C6385B9BF73F0FF6C97C7BD8EA33228EE939BB17E11B3C9D182F818055F753C5356C5BF371E21EAF1CF14B0CE8E3EBFEEB28010DA0B7EA9E0A4285E435FC06B70F4E6DE1DA12D871C3BC8D0C884A7A99DCF2A2C8561CD445B852ADE1A11217A9658D210050AEED89DC18D71D7906389D4056E7DF99DAA462D4C77E7F93874883F33BD13BBBB5E1AA8CB86A981B5491DFCFE2B474F63EB68D923F2D43FDC21E9A56A535347C021B65E54D7935B8EBC249903C7BDC69419E683F3E1BA7450DBEB2F175E2A5593A202543E0655B909D6614290DF1792FCD7B17CDBDFF0E9121D185A082EDBB630369AECBA8C6D4C642ED0AA644832A234DBD48B4C6D8037BF97AFB75626FF28EE1206DA462ED05FF43B23D98D1790106D88C3103232B82DFEDD8B62C8006E2717C921C1695E49B742281AF1CC870CDACA295F867BD72BDAC03CFF02D406A1DD6C3A3E59E8DCF93A5BD54ABB022F9952EF1906FA66ADD7124AC3CB35209BA7958C246AE6AAEF91C5C85F844AFA38335AB67C0735F634203AACA2272994B719B655629E54537A1E75B316E22FCAE758EC85D4D968CB3242510CCBAEAE4AAEC63303EA8E1DB841893CA1BEA38EF797C756A2A75D8C7A823C2DA46FB9996C3C2BA27E19BC5D23005D97BE4D2B899CBD0748811D6E920D535BA9BBA33C4D08868E70AAB6731982181C784EA4D4CFF1D20137645CAEACB27D295F14334D102A5508DD586CDFCE93CFE4D6B5B948D16AC6363B4DF5D7DA3E61D9E0966BD23D46B2263277363524437F18FDCC302540A58823990DF6A6214CBE9FD47F336534E89BC307FB0B030FF063748DEE749FC7907F78588DE4E099CE3D9DBC4ED4F254E7B4B297F5A11999450E485B462C83E9D6519FA1BA4FA39B25D195ADC14C1B862DB6A2222FEC7A4DD09A5472410758B85AA8AC57BDFC80BB4786B2A5C3091B7D24B6854EBACFAA87FA6895E81554AE08D5EF4B3144F872CA9644FD8E7A0C613CFEA146275A72CA3F68AA2F67FF49ECA257FD912F48C6637473EEBADAFBEECB7019B99FD5FA050811ACC255F02307835771417C782D43497C7D2B39B00220396E3C5B02696A16AE562E2E57D227E71502A3DE95D88BF98492035DAE2D468795DA1C32DE795717D43B1BB0DED8C450C34CEEC27AB138D303A083980F535D9F63EEF8D8200A52EE84802B5C6D4CB14D75CC8A719202363F97878B3E719FB607897C49752875A4C9CA7CAAD5511DB6523AFDF0CEF8BCFD96AB239044FB53EEBF3A70001C62E9B86E1A604709082330081EE7538C474D94B0C5FB2664787C85CCED00080E1349869EA6AACDF321546FE415268A8D9195B6C8DDEB337887A9BCE20C2C4178B2C2CAD9386F7C000000000000000000000000000000000000000000050C171B252B3336""") + ), + new SigVerTestCase( + TestUtils.hexDecode(""" +59B2371FE7BACC207FE1FEE88A8B3805A7052865691789BB90542FA47F7EF2B75FCA13DBA5888BEC320514DCB05FD26EB5541F6E572ECEA6C4F1D38AA70259094AA945F19FED0D980E65DBF65DB80F564FE29D836C5479288B55CF07F4E00159B6955DABDECC8C4D66AE688728BA6D5C0442F3C1232C782C465B9B7C5014B1464065CCD8A56D6B1C16510869E014E6933998EF725520B400913D93B0EC75E2FB725DC1AEC0C0CC7343B9E544BAA4D679860E347B2E947D8D2436F09298A7BB8336B9DE9CFD5CDBCD91C7249268CA03EFAC273AF52968D501406CD9C96159D7C15AA2900330C1189CFC2CD8B912C480E458297EF14DB694A3F1E72C1DFA3A3D2A8A69E011602B93020BACD1C2F3AD06C95A7F36EBF5261F6EC106816BB3303CC00BF4E8688D2E8548F10490D9EB23C56793B34B8406CBE443D8356BCD0F4F61D0D017D54831B9BA329F8948F25C3122F9DEDE8CECBA51569EDFFF895FA020862C5DF79F864078486B5FB228FD789C35FDE1C54BFFBF4A025A7FE7D8C3490A5D4E62D04F79F4183CA68379F4648BD5B2416DBE5B845C9F4B7A7E2339C0506D58539EAEA9451C9B2FE2A18C849DCA7EED9DACC058D005FB7375C4EF45B001543FC68E47DDB6D14FF937D1AA0D4D7489DFFA6210679CCCECF9B8551DCF682D2AF1E5BD869F3E8D400D5C861AE51FE7EBBB5457F2EAAFD093A9598EC721C69327C51930F4B9FFB2AA7F1A28436B6D808D75392BC43C1B5B859C66C54FA515C7A615A69E60921434AA9CF9F9E03C3CA35B5EBC6A409E822FE76E0924C6C062F1724C382FF3C8ACB5C1666C2EC26B7628E3D7C13DA8D758890E6CC017B7892582E95EDD04BA9345DF70FAD56EA68BF8875B932C28B32807C86371E17DCC04725CB597B524467963E1D4A61B5FBF9EC504D5DDB61793DD4E34AE082A5990EFCE801E938CCAE738E02E90599D971C2D7C64E5B6F8639F758ED621C1F21073C03EDB782C7A0F5D7C66F5CE161DED55B3E92DC27183AB083DBC1F3930AE56EDB8C53E9A7E020FFF0C4042F518B26F390C96C8183B79B53C7C7BC515187B3DE8CAB08769C5DD6FF5492112E8B0F28D09F4067ADB04194F60250E75ADE331A5C25593BCD92A6D1350439585860BB6FEEDBD2F839F317A01358876C88E898AC0C85378F572F23CDE931D47DE71D3353DAB1F810A61B18D24CD83DDAB8D53BA9C7B8274B0FE82AFF30C57072F643787CA1DF03B99EB57DBDA8C8EE8EB201F2847CBC9D34FD80CE6BC5E1E328EB6EFC83C4BD9D52F324E30EE4B5E86351E5C8C4C5456836D5A452203B3C372C787AE3332C8A5E9DC2197D9C341B9756BB1E63C75BBD5CF3E5CD4BF47BD1FEBC3E3710912D63032F6B97DC19C4DE196ACD9157715E2C14E054A9317BF96A684BB96CEFB7D8FDCA8AA477A2AF6F726D2CAC1A603CF1360EC11CA897E5BC735AB69B8647F30CED4947BA9F635D9CB2D82A662FF17A0E12D4D06D641EE76EB8B45C71EDE38C905C52BE76C6109F2612FEE6C3194465C19BA5D3EBCF1F0B5E534E0F0F1D31CB1E7A36C4303F283DBA8591CC609311A809E444E33A893880CDBAE29119146A368E4D2EDD91FE471647FFE821AA6D31C9FA49695EB9941B08F7BE3F06CDDF2739B8CAD2AB0DA4F5A3C0A26DF6A17B137CAAB3B919AB636D6C89BEDA3058898628721F2770315FEEE881595E24CF48B441660D0B2E9D5B90928C381F2B0FA26342E4C9B88C0887A4687124C012D969E1AFD8532754BA12125E9433DCF6D7BC1A36A83E6A10BA1CB7652A81350899C2DFC6E4FED38D009E6D0F1D44CCCB95E551B3AD54B3AC81E8BA4665EA428B3C861E8677890CF5F625C19A7C5943A9401CB78E7026BAE92B60A8B6807C17745415CD8E030C64C56E822139A35DA423F264336E0AFDF167430DD36E0064B2F6E8D8BB6BE99C5A9FB551CC63E508DB636667DDA53F611F02FCD1F99410F1A7A82882F9623ADDC50EB01E1F39978BF68506C71DBBEE42E4A80069B0E4C7FC4CC1471F4F1028DB25C4687B60DF4255DEC9148197A74796EC760A66AFC7884038651920973A69C203516222632EC5875EA6D838096E7FE9B5B4FB69C5E9407E70D27FA34B0CDBD6E119D87CE38581DF1D3E0DF3AE029042A3B20E923EBCE19A4958755EE2F98FD234C4413E2DBC93559A428DC37F2D1235BD4419B099E0F0DE542C46935991BE0692A6D80B8FD9886E0FA1769B49E8AE6307CB0BC1B49732D26E25CA1CD9D407E0D8864040941611F9333B6367E8300FD646AC5A71AD913EEFD808D5CAFBF1521A3062EC184E52165501E005556DE4DEE46F9E53D7DEF9909F3D5D98CA80D87707F7BC0FF8D879D65D4D783D196F2460693811CDF33358E082D81F4DB8F6C20486183A36D4FBCC8A1C6DA21AA4DD136E19FEF2EA993972BB9989AC1C38A79F31852178004123C46277D38A88FC1589F257332284CD8A873C25A1A6D40265B285DF09370E88F72FF70E434E8F66084CCFEBDBBC4B99EDFBC750CC5DEA63617F647F5F021D57D64D5EFF048634DB2209D7C8B82FB63B8823E4CA057168BAE88D9715291240B3758D7684501F861867B7A241C063B05D5E8CA6B4C79CB2435D7F994CB76915B4A548708B11B29449685941D43E60A8976F9A96072F91041F4C3DF7C73969012AE1B30E4B9C4E133558DABC46C103C0CB1DFB99B585374A54F9BA56B7248B8C3F66F1D55760D6ABB430375774DFBA2059C5DDDB659FD2E1DA9C3F0B80868C92BCAC10403DCD140D6A3D3F35F8EF1A2DD98DE1A4334238599EDAD920DC0AA698E9FE6106A0780C9C245F2C65A0C3E5CD5366110B1760FCD414D450DB9D76A22A9EAEA0C9FB72ED543CE9FA3314BAB17687E9DE5ADAD7561F1A5BEC16339269A87E09ACB29E4C439605E9572AA9B7D0E8371A30E41A0A7BDC02DA3A6121BF261EAA016A2074E4432CF63AF96BE81CEB6E0C2676A8545C66D2F30C98B5424F0FEF04B3C6C7064E2D2E11CBE60F85723FFC0B770D6866FFA589E3F9B2ABF75104019AA69CB58895B474A0ADE2B60A4AB077C3A6DF615334EBBE732E95220213994D3BDC443C8EF94AD515F45418355183314485857AC12BA1D62CF4FD4F4DE2A7FFF1ECF0D290C4CDFFA88D8F48C5B837D3A94CD17B3D169966EB038FE5A6E85DFC60A00233F10731973DC475D53BC7B9E60320BA7905D88519FA325DF5AB02B40F2ABBDB37D2261CB8148277B87AE3297976C80C35134E5F786904564C1469947F620FE09FDF3862C4057A3BCEF70750CB727F031283A1826F1381B3348E3EA4688609ECB193AFAAEE1CD97E4DDAA02C0C30E49F137D08285941528101759A7422AA499C900A379DD73B307284CCDDAF1FA1B0C4B280E3F9F1DB6D38ECF8A841F9D4E40ECA86247D6CD9B31EACD6A46F0E333B9E83D690D7E13467619B46AF9AFCFDC4AA9A049B180260D70D9EEDB8A533051AB83517AADC2CD900B3EA51260F464AFC5D2DC411029779B21CE2CBD160218DF41F661DA1AD95AD40B8C353C7F10FC23F830D117BCAEF8CECEBCBFA49D79D8D9391E8D08281F000A55E92DB331BDECD73183E058FF3FE5839AF50D8C55F22F6AFF5A33DA774BA1B3E643F5877CF549C4F908EA64A37DF3BFA4CD5F70F8CD154476D34BC853C9E8F7979E5F4EBB888AF761"""), + TestUtils.hexDecode(""" +EBDA4B4198C041F515BA16E227F1491F54109B04C5836855038149B60978EA146DF46299A38794D61DA89DCB74A46E3EFED16C832884194E74EEC82C965E9DB2858B87962F48F0C094C389DFD1DD44CBAEDF14A62A709FF48A92E193472899A6876EA8B9701C1D137896F3C779A4E056820F55300524202E44F8B24D5B685787"""), + TestUtils.hexDecode(""" +A2E6DFCDB93DAEF3A2B0A3A548EA48D51157F45034134ACCA15A29E5417475AFE72F571B34545F92DE26B06F141B1A18545CB06D547A1E3D19F9006D7C0E9640273AE424EE20CDC0AB8CCD680AD1CA98047108ED0FFADBD8B568753E4FA7C74CE79F7980297426BEF9ED2C88ED43B45B92E77D47480DEB54993BB03A956F617FBC9E40EE1F726A1E095BF25AA2B8BAD9578506A624E018287DE7A844D4ED1AFFD8B013131272948ADBFB1B40477CE56FA0C94E1DA951049268F26B7544FC1CB0F24F14C2D7A51EE5AA9BCB8A0237231F7ED5F7D2DF14184DFB66CE0336233A506193D6CDDACCD1E2D32A449459DB55DB87080603330CD1A865B719C0C389B19C18ECBB240EFD582A0AA372C47CD00DA92CD0549AA7F7C41FEA9A348D6B7BB78F46DD2998767ECC6CF9F7E2545CA2CB1A18503167A85EA96523C537EE2FCFBE870E40E00E25E7C092A2AD5D5936AAC869D167D9D76BF2AB47185A6F3F64D0557D78D553379ED2542EF2A3CE45E5D97EB7046219E9A9F4A0021EBF5B87A95056F3D14F8A67130B8BDDDB7F5F6C41E189E070A914BF69154F06E45109E2725C5516D1FDCD93A610D3328E2758D5BF0FE58B51E05075D7DFF949E9285924CB3773C8A16CC09F86A0F14925ECADC6FE687C5F864B93868E17D5D3CF218B8E49B991A8CD7879194C425DB3ABAF41B9FCD5E0DDFABD24369EEAA68E50932F6C1C81A72D12DB8EF868B4CAD837EAF5FA0B5915C9BC48FD089F365485A92A6153D1A48B4B28682921C432DFF4B09D63EF3C9A692DCB8FF2D48A5EF0FA63FBC24C9CA2E26AC2ABBA339D2DED6EECC6784C1ECF9F0D39BA10AC8688408AF5B85D4FBC09B73D9DEEA0101146ADBC08004DAF9BC68E66515BA9E103EC4B062A45E733485FAFD9262CC7737999C76305E1106553E495B26F0B22EA7F093B4A543AE8CEB0DB3607F4CC023E45EF9F957563DEDF945CD88FDDDDE42826ADF24D95C314BA718A1C81462C2A4D1BBC2E9418A11954D972D386899B65A2D7D8FBB170A91EE0EA02D18DF1541D95BB64CC54AE8DB48E7B66A633051C04767D708C98BE328EF865431B29348D7306D389287BE9F41BB23BBD3D7A7A3C5D4C3A5F171D574B0640EE6927C1E96F2E9CD0A1BD90430D42A330C93CE66DFDC65B067D8F173EFC0EED00EF24F108B143F589AD94D0A6FC98798C1B63510734A7853D2EDF70A1918D2780C23B12CF5B1EF279604304160364651965646E0E223562381B36CD81FAB31D436F53A9D65EFB3A7EA2092CE202C1ED7FB9EA64AAB6FE7FE107424014E5AB946A3EFBAFDA9619CB7A603F11E9AE507098AFF80331075B06AC4936A711BDAAE97057E31521D5479E046EAD7E8F024E3B9C49A8A253C81A283FBFFCB0C1D896D99E881314C04FA7E0C9DF25B6166F57D97065E9166B37EF612F702E6FF1C9E81F0189E22ADD54B9F2880B23F1D3F88E120B89BEC9C699BFF18DCF870362F9B4D0F66D7416198864484393156D16A7069C0D385910DB49DC9FE8015851DC43E8B03132444BEB19B60DB6052379E5F41109354C0350A2078D397389228726C33DC492DEAD0D55DB917C6E212ACEEAE78A8530DB6A53C7A566E91E1AB62D3AA16F2736CDCD965D38D945E8A15EB68CC2B50A9C5E88F5C40B8F67AF4C36F241F3DE9EC66911937739F8F5C56C28CEC16FB453818178A3698D639A7E9A215D2F7400F5FA0772485BD75A58CA574CAC9BEF89F8F3B554A92687EEA5C6AE9651D9CEC267E13F84FB98D43FC7D24895296D78FEC1B2012F732092511930FF78664E926A57F23D3CF17BF19EEE27D833B88B6E30BF5AE5498FA55EC0D14FB127D5E6EE80560F540FBE26FD81AA62B006A139A065C11B7B48B2AB038B522168748A57DDB6C0A6CA0D7B4B79527673E58617F22F3C1B32FEFC787B41DDE9399549B0608478487126611634E5166BE7AFAEAB42F348B2691A1978CE61C753A049767A02E7055DBBFE771ECD8613B3AA29622F2FBC06F9BDCD9C94D0FB8C75310E2D4100C5248FFCDA8A898AD331BB4ECA6939FF31094F418BB8BAEC58AEF7B6FA33ED8588A21B437F4AD5EA5F2D86C4DCF1C4A559BE9B0C384AD2AA778EE93CA70989BD2ED681666CA8B082B7B83272F8A10E2D245628C8E1B5FF3BF8C5FA9C6E09C238482679888827D0E3D0B9A8CC36027649B0798E14390AD84D3D766DCEBEEB670E3560C6378F90A411196365F4FA6D332244EEF1016085C9B51614D8BF3BB44A67C906E7241213318B714824C03D9E8927AB2ADFFF50494D3F398F37E6BFAB3F8E0B89643FD220DA424BF2D751D07B5F335944462B374F297726DBBBF8C3A2D7B26BBACF192C05FF89F0878E26ACF8275644CB85C7D81022D1E85FDE63E7055E1202B85E0118687994931DE1617BA91CE9054327D3DC9DA0135DB676E9A4388DBDC3727DFCE71FCA2CEE2B2331DD836086D86C3F36767BD2F210B7B8CB1458CE8252DE845F507D78C93F7ECA7FD8CADA3DDDFEA34D2FA9AD31F10F02430C884F65346840E4CA5CC54572D6533A4E2417CF859185CA5B905BF83135BCBD88C0D86CB7C3344674F8A9A09BFD460CA828BACBE12B661459123201A5CACEBB6EF6E449B049552AEB5EA305B870055201B4686CB255E12BB1CA67DB46AED1890716672A898F71B5109A5C253276C42A22ACAEAD6E4F0798067FE983494752574A612969F1C923AD5718362E2AA1C4E5255A777DC6CBD53F553B0953BB464EBC29AA36E3F72B5C6614FAB08CC65F540D662599D45269754C0D6BE109BD7E0DF04D5EFF30000D8D6AF25B5AAD51057C31C4C134C59C3356B34638692222273144CE9D768196749FCE54DC7A7A1E2E36192FD7E756994E37D0078850E81D2D9C40670B77A02C9F708DA28CF2CCF478309B4279A6C45B9FF854A5F5B553CB291FEF5D1970883A064200D2C99597829F15DB4D9506C82154EACC4FEB0800D268902B462FE9D3284D89D83A7009AF5BDEFBCB310608151430B779A6FA4CBF6DF1E13C4A9DEE96D6BBC0CF989C48888BA58316FFA0114020B5C326D723960FC20DCFB01DC50982FD824F9512AE73E3676ED8040481CB536F851274087BFCB77A0EC7DA2BE274288D2212471DC7949EEF77A8333AABAFB57581CB43774E07F192B825F14AD564658792A0E235F4DB5EA6E3A84403492E209484542C2C2881042F54CD56CC00F2C31810EEC70D8386D0C8B7E4756A77B11563A42BC3A5D2A495D0C8278810D55EE7CB38D80C34E4DC58F0A8B1EC6E2193E6184E5F0793AB882051EBBDB3303D86F4A0E22090C7A957BE5F7BDF4652FC8F38DAC71257B2570D5B1DFA95BFEEB7E377DD581A8975D72398B4D258B1B9E7DA60217FF77BAD7008FBCCDAF7479573F9ED6BA8D13F83C233166D8D7A400F00840887BE510EAF1CF2E30B244C9EB6E166C98156C27A5FF0DB563A204B830C8FFC64D6685C9E3BF8968F3A2D2B329AA6AAB0D49EDEC26C2B5D7462AB465381D5431C85268EFB89F4E04DC660EBF4A0962F9C9F4EBB7F2A1EC5B3262DE971219FB56CF42CD720811EAF66DC2C428F94E1DE4ECE5F2116533B25E65D732A4BBD5221D28EFA946DAF52437AD6657703A9B454422C7DADEBF063E5FC433536CBA84E07F7086FE031A0A2B4DACDC99E5D3486E77D41D949EBE69E14BDF21090646CD9FF8E9F0FBF5E737DD38C0EED3D73D22A7C23AC781341109997594B3D1D4153AA1A35FF7AAD5636BFA9BE09E3329FB61950CB6DA58600E05DC2782B2EF58466AC9A4BBF6264D0D616968C6BAFC496F859EE9512072180172E91E3B581FF5CE9B8AC0624F221D111BBAAD988A530C0CADE0C4CC399EFAE9ECD624F55D93F9D0F0FC915292419ED119E177095880FBCE058783D85380F1F6673B7ED6702446098693F3FEBB9C9D7906391608453158C695D073B259518AA7DC5125B51E58A5170D1A68CF6CFC1A705B344911A63875080B4FACD9835AE85294D03EFF6D3B02888BC1D094B9E7374CAABBD1D0C32F1786B8CC12D0E4C76BC99694A1862A73ADB58A20908A601ABC4015ACC17E5B0AC28F3D8896F8BF0AA344B814D63CF558E0CED39D1F7B16D411E014BCB594F37CF18BCF46EBDEEDF1AECBD13ED97AD65A0674275868F34148D6E03E7D802258987937DBAA69215216F1CDF8BA2BCDA245D42A5D9891CF0ABC804595B320A774F1DE69F8ED595007A59F1FB570D6D024ADC97B121C28542E3043C3F99EA5EA4BE47E3DC0B66E297477537041CF880B5FAF2828E3DA2D2F9414297C59F17ED60E2DBA0502E8FE6B8E5B13FE2E945B2E78277C568082F678E4F4FF2E323D1E0AF996364E2AF2FC95C53F83953028D38BB168A1FE68C02E4477CF567DF6C2A72AF3F56EFFC99C0F5223E4CF32CA3B97C700A40803E3C91DA686DDF45A47208FC904B2384730F050A9E3440CF9A010044F7E8B6B0FEDA288F810E27AAC5DAF358046D8AE85AFB6020C22986C4788E07EFB41B2C18C482C72027673E9695CAB29FA04ABC0D7C790D3F32565A859696B6C036ACB5A6D1E444CC7D9D23B3A8FBE6E2E851914711EF790E8CBB097ACAE791825EEBA70C3AF28E6E8EFCCA38CF6B6F466D568100ECA07BF3B4B8E18EB791A2431A7FC2A795B4CDE07A38E1662044E81E85667BE36058095C7F0573D930CACEFE4C97B3393F8400451AAC6B55C5399826D8C7746BDE6484D4377BDFAD25CC5CC17C774B4623BE25184DD627CE8E6547788BD7CA2FABC9B7D4A602C457FE9EFD82B79E9322F99962FC7DAD35BFAF85A03D67DC7E83FD3C627160DC96640683AAD733B3D1EB59646A2533B99EAEA4E5CFDB2C94A8724B03FC4B72BB5BC5D90B0D4A136E44D64F3985A7EF7C6D7C55B61486CE529475F21630DD824F8AD4D3FBF0CB2C48CCC0DC27516733FF5BDC1F459B00B88883006AEDE6602DC51A316959DEBEDC0F36BBE8D017207225C1C2BD94CFC1CC60933CEA2ADE45BB4425578F4D28E0AA36DA346E2BA4B34B65BD7E71B9FCC3B52F8C425AD44B5CCD006E26857FC5BAD79D8345C5FACEAA4DC3A7C613D085826F82F10961AB2BB7C087FDB490B5A082B2F5DA5D9E6210D6E8B37ADB10DF510990F3ACD81CF93965CAAB334F1B2A76D9B17D758F273860B074B2FFFB88D9B5E6991EDBFC5FFB54325BFFC0C66092E7729C9971101D7CBF74491CC4F54D535936CBC5455E3215215E836500F411382CB8658BBB60636BAC343A645741FCD6C5E23433EFEF4F14967C5B742BDA45B2FAE1946FD0042229A1E462E172102124540CB203D58DF1EB8ADEBC4DCB37F8450DBD0FEC87CB4A56696141C9513F7D6E61BB117B0E35E1DD314837965004C6C86388C2D3EA57EA4C0CE9C563C68F5B3CA20043742BB5060935C23FC7FD5368EABE5C1A1B715B99B96E1B434229D3ADE0129AAD85710596DF9AA2D86C7EC88B9552F876861DBAD135B4EB318FC6FFBC3AF0C98EC57468A0F4BC3A29CF1625B03E33360D152B0B5F5706C169B68C7470379BA15D9188F13DFCF789C18A9DA14EAB56DB261F978D9BD894C84C1BD203A777DF785C82B87FF975BAE11437F9A243627A1715CBFFEED727B405C545542A7BED9395ADE1A671807954EAC7C9BFB8785F18D5D5C31A01320E7D863743BFC7852E251631A03EB671912F6138C21E1D62D88E1941095A8DFDF3B052A0104E72C186BFEA9CAF32B2FCA121FCF6A3D85FCBB9D7978EF2E227F321C1BD932A4DB007CB2DFE3BFD9578BD7AA6844611E4F3ED7E5370205A07B6CBBFCA7AA204D76CC8DCB9A1CB6FE6C4AFC5E5A79E59C6934D473BF834F69B89073DEC0D9ABD347B12BA21E308D42D1576F03CE4BE6EF8F07EA08CF1846C27ECEE7F8415C0FA756A540E42738892C7E6D0F90520FEAC6160911BB18BDEA2A1D925CDFBA7C585DAA3A3D27B12E4880A9B8C87B0EB5EFD7C07507D8C3B274738C90EB4A745C1AB3749ED000075E99277B927B1CAF2E19E8D588AFD3CF9BC0302724E71F129E3E3BE9D114542B16C4DB65AC8529CF95CAF7A2EED53548D1769F809F1780E5102D80B7E52B99203F5CA6F2A2A7608171190EF391A4EF5384D15C101895B5402E8D4FEA052872FBAF6DC9FFDCD3FF9EA884ABA4D90E202206E861B9785AC572A0013765C24B5E3AB9C4E31A6B7F958A4D3DE78CA4D4C097AB9AD50E588BDEC45528EC7B248BAA3BD3DF31F8FEB29F823123421388A2A021F37426188CF830BDD10C75BFFFDA15623B33F89567EBD2EC66EC7DF533CE8F33C32EBD6D074606380F37F3E9D186E4A93EB098B6EC0455843E7784A9CCC67E0326920223993CEEF7E4AE399E21993CCD078084804EAB9881B6C40CE2B20BEC97DF60381E930CBCC038A4A9153B2AF6AC6F743FE6E2FDA9A0FBD4C00D93C972333C8A8D99041D8C93718CA0CB864B5E50059D73978FA3FF33115880D43D93B8512246D82CF104A4B525F6F8B95AAB9C8DF02649497A9AAF01EB4C7EB1E232738557175E6090C2F657E9DBAD6F90860BBDEE0F701236C8489A7C200000000000000000000000000000000000511181C242D333A""") + ), + new SigVerTestCase( + TestUtils.hexDecode(""" +59B2371FE7BACC207FE1FEE88A8B3805A7052865691789BB90542FA47F7EF2B75FCA13DBA5888BEC320514DCB05FD26EB5541F6E572ECEA6C4F1D38AA70259094AA945F19FED0D980E65DBF65DB80F564FE29D836C5479288B55CF07F4E00159B6955DABDECC8C4D66AE688728BA6D5C0442F3C1232C782C465B9B7C5014B1464065CCD8A56D6B1C16510869E014E6933998EF725520B400913D93B0EC75E2FB725DC1AEC0C0CC7343B9E544BAA4D679860E347B2E947D8D2436F09298A7BB8336B9DE9CFD5CDBCD91C7249268CA03EFAC273AF52968D501406CD9C96159D7C15AA2900330C1189CFC2CD8B912C480E458297EF14DB694A3F1E72C1DFA3A3D2A8A69E011602B93020BACD1C2F3AD06C95A7F36EBF5261F6EC106816BB3303CC00BF4E8688D2E8548F10490D9EB23C56793B34B8406CBE443D8356BCD0F4F61D0D017D54831B9BA329F8948F25C3122F9DEDE8CECBA51569EDFFF895FA020862C5DF79F864078486B5FB228FD789C35FDE1C54BFFBF4A025A7FE7D8C3490A5D4E62D04F79F4183CA68379F4648BD5B2416DBE5B845C9F4B7A7E2339C0506D58539EAEA9451C9B2FE2A18C849DCA7EED9DACC058D005FB7375C4EF45B001543FC68E47DDB6D14FF937D1AA0D4D7489DFFA6210679CCCECF9B8551DCF682D2AF1E5BD869F3E8D400D5C861AE51FE7EBBB5457F2EAAFD093A9598EC721C69327C51930F4B9FFB2AA7F1A28436B6D808D75392BC43C1B5B859C66C54FA515C7A615A69E60921434AA9CF9F9E03C3CA35B5EBC6A409E822FE76E0924C6C062F1724C382FF3C8ACB5C1666C2EC26B7628E3D7C13DA8D758890E6CC017B7892582E95EDD04BA9345DF70FAD56EA68BF8875B932C28B32807C86371E17DCC04725CB597B524467963E1D4A61B5FBF9EC504D5DDB61793DD4E34AE082A5990EFCE801E938CCAE738E02E90599D971C2D7C64E5B6F8639F758ED621C1F21073C03EDB782C7A0F5D7C66F5CE161DED55B3E92DC27183AB083DBC1F3930AE56EDB8C53E9A7E020FFF0C4042F518B26F390C96C8183B79B53C7C7BC515187B3DE8CAB08769C5DD6FF5492112E8B0F28D09F4067ADB04194F60250E75ADE331A5C25593BCD92A6D1350439585860BB6FEEDBD2F839F317A01358876C88E898AC0C85378F572F23CDE931D47DE71D3353DAB1F810A61B18D24CD83DDAB8D53BA9C7B8274B0FE82AFF30C57072F643787CA1DF03B99EB57DBDA8C8EE8EB201F2847CBC9D34FD80CE6BC5E1E328EB6EFC83C4BD9D52F324E30EE4B5E86351E5C8C4C5456836D5A452203B3C372C787AE3332C8A5E9DC2197D9C341B9756BB1E63C75BBD5CF3E5CD4BF47BD1FEBC3E3710912D63032F6B97DC19C4DE196ACD9157715E2C14E054A9317BF96A684BB96CEFB7D8FDCA8AA477A2AF6F726D2CAC1A603CF1360EC11CA897E5BC735AB69B8647F30CED4947BA9F635D9CB2D82A662FF17A0E12D4D06D641EE76EB8B45C71EDE38C905C52BE76C6109F2612FEE6C3194465C19BA5D3EBCF1F0B5E534E0F0F1D31CB1E7A36C4303F283DBA8591CC609311A809E444E33A893880CDBAE29119146A368E4D2EDD91FE471647FFE821AA6D31C9FA49695EB9941B08F7BE3F06CDDF2739B8CAD2AB0DA4F5A3C0A26DF6A17B137CAAB3B919AB636D6C89BEDA3058898628721F2770315FEEE881595E24CF48B441660D0B2E9D5B90928C381F2B0FA26342E4C9B88C0887A4687124C012D969E1AFD8532754BA12125E9433DCF6D7BC1A36A83E6A10BA1CB7652A81350899C2DFC6E4FED38D009E6D0F1D44CCCB95E551B3AD54B3AC81E8BA4665EA428B3C861E8677890CF5F625C19A7C5943A9401CB78E7026BAE92B60A8B6807C17745415CD8E030C64C56E822139A35DA423F264336E0AFDF167430DD36E0064B2F6E8D8BB6BE99C5A9FB551CC63E508DB636667DDA53F611F02FCD1F99410F1A7A82882F9623ADDC50EB01E1F39978BF68506C71DBBEE42E4A80069B0E4C7FC4CC1471F4F1028DB25C4687B60DF4255DEC9148197A74796EC760A66AFC7884038651920973A69C203516222632EC5875EA6D838096E7FE9B5B4FB69C5E9407E70D27FA34B0CDBD6E119D87CE38581DF1D3E0DF3AE029042A3B20E923EBCE19A4958755EE2F98FD234C4413E2DBC93559A428DC37F2D1235BD4419B099E0F0DE542C46935991BE0692A6D80B8FD9886E0FA1769B49E8AE6307CB0BC1B49732D26E25CA1CD9D407E0D8864040941611F9333B6367E8300FD646AC5A71AD913EEFD808D5CAFBF1521A3062EC184E52165501E005556DE4DEE46F9E53D7DEF9909F3D5D98CA80D87707F7BC0FF8D879D65D4D783D196F2460693811CDF33358E082D81F4DB8F6C20486183A36D4FBCC8A1C6DA21AA4DD136E19FEF2EA993972BB9989AC1C38A79F31852178004123C46277D38A88FC1589F257332284CD8A873C25A1A6D40265B285DF09370E88F72FF70E434E8F66084CCFEBDBBC4B99EDFBC750CC5DEA63617F647F5F021D57D64D5EFF048634DB2209D7C8B82FB63B8823E4CA057168BAE88D9715291240B3758D7684501F861867B7A241C063B05D5E8CA6B4C79CB2435D7F994CB76915B4A548708B11B29449685941D43E60A8976F9A96072F91041F4C3DF7C73969012AE1B30E4B9C4E133558DABC46C103C0CB1DFB99B585374A54F9BA56B7248B8C3F66F1D55760D6ABB430375774DFBA2059C5DDDB659FD2E1DA9C3F0B80868C92BCAC10403DCD140D6A3D3F35F8EF1A2DD98DE1A4334238599EDAD920DC0AA698E9FE6106A0780C9C245F2C65A0C3E5CD5366110B1760FCD414D450DB9D76A22A9EAEA0C9FB72ED543CE9FA3314BAB17687E9DE5ADAD7561F1A5BEC16339269A87E09ACB29E4C439605E9572AA9B7D0E8371A30E41A0A7BDC02DA3A6121BF261EAA016A2074E4432CF63AF96BE81CEB6E0C2676A8545C66D2F30C98B5424F0FEF04B3C6C7064E2D2E11CBE60F85723FFC0B770D6866FFA589E3F9B2ABF75104019AA69CB58895B474A0ADE2B60A4AB077C3A6DF615334EBBE732E95220213994D3BDC443C8EF94AD515F45418355183314485857AC12BA1D62CF4FD4F4DE2A7FFF1ECF0D290C4CDFFA88D8F48C5B837D3A94CD17B3D169966EB038FE5A6E85DFC60A00233F10731973DC475D53BC7B9E60320BA7905D88519FA325DF5AB02B40F2ABBDB37D2261CB8148277B87AE3297976C80C35134E5F786904564C1469947F620FE09FDF3862C4057A3BCEF70750CB727F031283A1826F1381B3348E3EA4688609ECB193AFAAEE1CD97E4DDAA02C0C30E49F137D08285941528101759A7422AA499C900A379DD73B307284CCDDAF1FA1B0C4B280E3F9F1DB6D38ECF8A841F9D4E40ECA86247D6CD9B31EACD6A46F0E333B9E83D690D7E13467619B46AF9AFCFDC4AA9A049B180260D70D9EEDB8A533051AB83517AADC2CD900B3EA51260F464AFC5D2DC411029779B21CE2CBD160218DF41F661DA1AD95AD40B8C353C7F10FC23F830D117BCAEF8CECEBCBFA49D79D8D9391E8D08281F000A55E92DB331BDECD73183E058FF3FE5839AF50D8C55F22F6AFF5A33DA774BA1B3E643F5877CF549C4F908EA64A37DF3BFA4CD5F70F8CD154476D34BC853C9E8F7979E5F4EBB888AF761"""), + TestUtils.hexDecode(""" +4AC4675C96D9117D1EDEB80D7CD284A3E1E1FE038E301205B4C408EB965235AD1C85F8BE3F77CA486FD207F7C75F4121CD3CA2B23D6BCE4382A6D36121815025D5806CBEF452E083933C6E5C7394AC88262A6DE7770B2D8843EC101FFB5E84DE2F7A8B74E7674B3B2319BD6BF4112F92C5CFC0A55F7FA061F45325408D039D51"""), + TestUtils.hexDecode(""" +4B3F52F081B3D914BC7C6C073B182B268ADF5189E298A869BFB991B199993C1042DEF5B59270B6CD3FF8F907A1CB0D3B6FEDCA143838F8F81E0C370FFEEE6B25CD07035641A051944EAB516CFBB801536B4F262B16198E7DDB1D61C35A64D90D3948CEAAC8EE580DCEF540ED99D912BBA2BC4F5145BB949C73CCBD582613B10EAAE863ACA34683EB922B3DADFC74F76F47E4978602592402D9154394EB09FBC2EBCCC594732F2D8BC38350E5535A4412A77ADD7916604576FD6A3631E515BAF26A6F9CA4061EBBDD3BEC7179AD58552A5B508F31348A56AD1ADA7A05352C72C004B94C47E7049A10B3A59BF238A8DFC6C7019A17F05D5BFCB9D93D9D1CCBCB47F8C438098FDBDFE23F9F78BC28069908C6B9898B434CBF37787E1AF6A6B827E830E9F7629CD8F51070C4C8A8DEB260D07C3E41D8490484877491B39AA6D9E10D91748B64E33160629D8AE43EFD5F85781E69F76B6895C141EBCDDFEEB485A00BDBA4F7C991F53F2F84933926AF39E6964ABF2DFEBBC19A7E31C50797B8DA2931E10F3DAC493F198DFD785D21ADB2C062B097E889A20737F186008F2928F6B84D6E09E975A8F2AAADC785234234FDA03703A7C21F812D650BD2510B30F0550081047A155C848586A96F100D774F3E39E029B0777CD33E68318A11C1980293FAD3E787D20DFE7EEE7053C05EEB6A159BAAD4020B9EC3F537DA4DADAFB3B1BB1DBEB2D5B8F9D05A019798EAE0ED099DB066D73EE8E9A56DE368E878A7FF39140D8021D50085E6252941AB315309CB53AAA49E86347FBAD54A1F873E0CB4B86A8D5B1B2A95D485F37A9FB6105DF8440FDB8578F2624C079329569A75F36F2C55D8D030FBFEAA8889AD746C323B1AC4EC8C403E775A6FBE596E7E6A5A2863576625149940976F7CC93617B43FB13489074ECAC5BEB1A4DFE58B9AD2E0C6A15B76A7C2D208725A3123CA4E6F2C5847EE5FA8384919EF89011D219B257B3E4DC4F2095160844CAEEAFCF857260F1C63D3B05A67D3D0F2B0EC9DCC2723F13755750BAE62FCC361CFB584F774C09ADF9A0431B23E488C359C0AEF5B1C9787BD8F52B083BC9DBCC9B3039F777C7E8EABC80078050CE6D49C3BB70168FA2177298FB0A8F72C1CD28D662A07DAE6C7ACB7FB8E7FDD01DFB27C62EE683F4E5F88C7C1DDDD5EECC1C3AF853F1FF6B1D9DE672F1BF6473AF0021D8A3D4DD04A2FCA2325C721CF1C821676D0A0D574186625DE831C8411F64179F9167F78BCB22FB41C2CDB63C4DB5E138766D3803589598F114F41BA42CDB1341020449BA99656113990B4E022D8DA20D744491C6EEAB67B918E80FFF343CC5B4C8E58C3484B0125A60C36AEF763894D35148B578F417C3A98A143EDFE9F8C95BCC346C6F5EAF97AAD11DAE01C477C227A88D10ECFDCF450B37F881968027849D9B43E2BFF90C6A34AE41B8BBD743083D3C58786B036671CD6EED94DAE51F7613247EF8607ACF74A3CCE932F1C3869BDB35CA17FC6BA9F9C956FF1D4D88094325CABCE41233FB1D808EF41010396DEB0ECF50734D818DDAB70015A0ABDD1926DFA491F711AA85DA2A8EC60E3255CCF975C23CC4E8DAFDDED9FEC60A6467C45B03CA476499AA331B0E3999576CEC3191A9A62BC1BEAC1EAF20E18CFC3216127DE4AAE2E75201F9E427E39BF921150EAB949559C022D876FA242C2A845BCA7235F721B0056788A44ECC3EB98F0F502B89F8E7410EA5679AE7C0434F13AD816421D2FEE30CBCB2DAA6B851CD1B6E996DA7A757E4C4D8572C8B600DE85DDB65320D1CB71D9378349C0C401AD4F9E91272139228A8DA2F4FD2F48891A4DCB066D501D447483B611BB3C80550A90EA0B732D639D8B3926B6E7C35453ED3CC110BAF556CF46D8FC2177E76FB2663B8BDD171E94C0ACAF25B9153B22BCA749916756FB3ED3018E0944B6C3B9B6BFA15B9BE803AC79333CD2C3A27A26BC17CDA257798AE16B28B463B6DF3FA87C2D742D0F6885BEE0BEC6E20D01E5DADC86823E92D60FEC79B0D240248753E42048384C804289604821A57F4F9F50AE0C38527FE5A34938DDBCDCD9A1D020839BEBB62F9F41FBA08052ABB82FADA884CBE563791103AA585546EBFEB11272CC2E87A3B75B3C6BB1853AE7F9CF5585B2653CF5EEA244D204EB269C56A20985160659CB0725EE13CE35D55EB095A53414F232DF8108B18024EB0DBF345EB5CDAD0BCE7263509A341D54A7D534E553EAEFFE4E242EA23BCFE59A58A60425882CB7E3B0C9E4AFE8698E3DF56AFD6D611E9168747D8735CF9246D94F2126BE727FB42B2241A83B34F0B9EB47938D726502C54E4572766331628FA5CDA893C35376AB4538FF8717C2795B0F51F08E1137612B89B0C1E2CD1F099E88556923AE57A1DAD2AFB1230B5094A1B21BAD7DBBC333A97F179304718F3289B6DE31315B74C1A73AC7756FAA4D7EB568BBC6F7E788CD089B395564D2176B0056DFFE952C7748B048306720F602B67E8F6ADCC91F8E3AA4B8C4D7FAC233AAF93653AD2209E2FF92DA30C2D53FDEF6F4C90EAA0DE60D594ADA3915DB24279D867476EAD757B4C0264A1DB8A1F57A1B5D7173BB1A960CE02FDEFEF160D512667D655268FCC3A153A4314782A0EBFF84F65F14A0E3E12A13250C07D08C225B11A6831BC25C40467B768004DDE0E874A51144C18920BDF286090B59F51564EA4070FBBF61E3696435F28F63332B64496DF3EC8B65D54E1CF4789DDAB122DA6B264D312A711C129E3B07F4C6DA25A56173AF58B90A71B7ACFA3161A81F59D17914C99BBAC4F9A314977A89CEF7696943609BB4827964FB2976403BD4996F1E842BF5AAAE1ECCA11255B9E6001C20F72F1FD5E32CDA32D8A7AC5F62B09A0E615847CA746F489515CF8F183162859F53B97E9E5CA800EE624F729843A0009164A4A9FF76EB34E4704184848A139AD97D909F7A7ED114F087A4B2E1B4A3032391160B6F3A3649FF15AEA2B7107AF8A3B5FCAD61D43D602E6286A900870CC8CE24E39E78F0397A0D7E27E8E2D4776A44CBA218EBCD88B3C28C182A7C9F4DBB2DBB5E981563D66CEEB77E7F9034BD429D27637CF797DE82E01FEBBCE2171EFD016E402A42D78EA1ACE2CB370E75C90ADFA1A793B2169CC26522DB2F546AC1DE34C9087120C42A9F10C00D493C25730166F9D219FBDAD222C8B28115543313210848FB2F04BFDCE15D320C3634A8E4D63755515900C75BFD090AD78DD588659FBF97C96E0D0ACC8E815E608F9E861D79AF3051B942B52570B6292BF48C2BFAA9077DC76FE902683217B8BF809ED7A0050ADDBB65FDDFBD24019C9181B5AC81566113D6694EA6291D7F4A7F56A41EB91F76368DF82B164B4859259D7189240F1D8803F8107296D378BAB4D24FE6D10EF788367BCE16C5AB77FBC168B857F7BA5CDCBE5067C864F879809FE5217DEF0294BFAFDF809ABCE9532DD9DAB3448F4DA68ECA51609476278EB8C4F69EA29673F69418041D26857EBC24A487BB4B0BA63AF848545EE9BE89F139D502099B9D35DB3807B925CBA576E27170EAEC48CC2CC15B043677825D0EE81EB2CEE3A8ED14A798B879530220E50CE8C003A305382A24D23C277B99D1F4C54F9A8D33FA3D1E337E18D7CBBA5E5A47F2D5E096CF4551B23B1B86436E81B4A09D1E3D38492EC8B2A00967016AB76B9A9B1864671421DA56F57D008D5CE1B892A7E9C1F69F6C722CF109DB500E53F6BC07837AD1CD4CF4A64DA763B4A9C4929B0DCDDF7C7E1186BE3FF0C321158437820C81E74FF316AE3254E972FC197A7F0E620242AC05A4E43E987C2A8355B0357745CA79E6AE48AB29ED4FA63D3A1F19B999DE251FDE0640DD87876D55762878AD1DB12D65BAFD14B6A9A7081BF23F9F06D90CE273C5A26E012CA94DD481D32E10938C165163E89BE8A93A63034D345B74E2A94EF643D06AF9E1F5C9F104930DA00E61E061EE8C3BB17C11E05D45C1682E4D593C9198238D2BA289779E7D0F227BCB0B09972B19770FF011BF6C60D9D193CFAB32747A0095E1A4AD32514C782EF3DE7A26EA771F5530D9DE9736D0F6AE1AFB78EC7CE4884A1BB436CFCE459CD99358260906AAC99716A536CC7687A0375FDA11007618E553534E54D5B214F7AA6FC7DBE37C2BD2B64850AE469A9858987F3FA4B1FD26D954BFEC365DBE06DDCD615E1FED58A88676402D1D6B581485498B5ADFFFC42D47D61DF99384E22C5157F0178A6FDAF8F4A9491DAF298B2C3EC88085022C0A7CF245ED0FB5A38CD16F30D37DA5C4959A55501DAD50F1B48BBBDD86AB8BB522A936DDF0003B81BE16231A04E7A589C56FFFB51B07927B4AFA1DB7D48BC6FBC3F3675637184B7ADB9BADF4DE7C085BCA1D428DC9FC8277CBD85884A5921B52BB05B710615508261BB4546BD6E1FC730D16B049EA12798CE2E6DF43F5B8F3EF9AC8FBAE31B011E10C4FC62FFD7F39D16EC32CA8210ED16E041DA43D9274229514054A0F82D462FE080C6FFD7BBDBFBF0BFFC6D5ECC432A3256C0BE0DDFD5D9080C676C7955D66E44D1CE51FCC2382F868D732E85851721B48A01D08C639626EE0509CB581EFF5628FA6CCD1089AC0E12DEBE0851782E64C5049CBD6501013965CC0CA25ACAB176EF7CAB92940985DDB49021DF6C60D6C4A489116311E86BA19EDF00D74797358207CDE50506D007FE03C8804C66451F02A0182D387B759894096F65232952D183DBAAABB6BC0E191DC2C3F75FC72BD61BAB2EF19B6532B231C4AFB1A9C2CB2F3D6C451E8440D6A923CF72A63E2ED8554773887910CA5C671AD4FD5923CB95EC73FFDFBDA4B6655F55DBFD1317D024422301ED66A6E4C672085CED1F4C7B05030A100C4788FEF4CD3E494A853BDE63E9D449AE3BB6BA1083238DA3F4090515D143C67DBE53D8D507A5229FFEB2072D0BD092FC9AE52DEAAACD1F0F14B5AC84752BFD0025E5F55B869350F4B2719C5C05AC1669BB0FD3C614ACE02A270613FD3309706DDCD5B1A6AD26F359ADA80B30E50A7E50BBD3AA45D0654DD7D058B0BBF4D0D92135142214EE70511F3676AE643B5F245063B9419CF6B49FD647F27D7C41C866E6CAD9D5E2E3E331BF6B9F72ACA329BB64259C3E79783A26674B7D38EBDE8318411F4764EBDC4C7E41ACFF85BBB30318D59C42C9203ABD6636BA3F772B6725121C052DE99910D55158C6F3EF8BB7FEDE2F81E58A7AEB25E2E46FD7232302FAFA8FC37FC8B55D594B76EC4A53EB11EB3FD634428AAA5D86F839D089ABE2FEFE2AE5262FEFC7348D836692EDB215D6F8F548B885290C2403C51C3E269D493FBD339B5DFB0A38EEDA7754DAFFA16E5BCA5A9BBDE04B014B7AEA8988F3749D52D2FC1C9F7C7B2C2D692E7896E4C34F57C558CFE8317A8374409D566879A08628F644FB45B818455BCA6042B4E6187C1DD177E9E5146319904B1505F3EE00CD7FEAF0E83C3024956F77659ACC56D8D917A37E8FF7EB88713CCA334EA04B8E258C9345DA9DE26A0A366519451E1012DE6AABF4697C9DE821D70021C3250A106CF4C23A1B1785F549D3C8CD71B05FEA753E0046A3AE0A9B1F40277CF453A2BA14CBA923CC6269706DFFFD517C1E5930079912E05A5571897A06865516C86699F707E00CB38CE193490AEE30BA47DDDF3A5B4FBCEBA73DC13D0A160EA642D30D63A02964EDFDB2F29DCD32CA9974F89C32D1FA9A83C94A2770FCFCF86E64646882BD550DDD65B4E2D287AF6C196F42DBD39B020D7CDFBB6E6E75FFAAB26099EC1D25E3234F70DD972286AEA0C3436595FE49FCA898BFA421604C82D3E94856D186905076D186C684174BF4290DF31769EDC97A1DF2DFED03CF45CE678C8A1429EB978D02A79D4F8CF0168DAAB482C6C612F04B1C93637FE77B302CEFA788C11356C52C54F37A9DCFDA55927A8EF0A0CEA7CC4ADCEE459EB64DF08ED0FC29FDC3C7B762B399332063340D473966219BFC87B4A3C91C80F0E4BA86AA1879C76625C8680A227AB22780659D4B5D30E0E9A0DCE094DAF537679273A9B277ED2A2E250EEA0938204C9E963D338522A3D1A4440E2A12397A5B97D35657307BEC94CC0C72C5C6B09DAF2BAF0020B7D8CA560BF6596929AC8D4E5460F7837B41B4AE6FF12339DB8EBD7028AACFE0B42E02CDE906783ABFF694E7CBE0897ED6ED438ACDB00A4709CFEF7150EBEB08C8FF6C1543815F4B8951C3CACE499586458A73C8572389AFC9703A7FEAF673445FB4B0CCAA511D4A2CF463F57E3A6D72DA04B256699A30212E7C5768EFC151B71744156575A2E9443319232D159C6CC006FDB57C58173AD8D2C866C8887437C223888E21EF67E1A332C1FDFCC15EF17476FE0FB57D4229894725E1474C1BA1216562817F16C53ECE01C7F9E3664EEDBBA94952987431AA2A57D330EB11B28E6BF770E349ECE350C83E90DA6FE0D0A4AB9715DB28BDD397FAFA1428302151E1F222B4469879EB5D0F018606A7594BFC82C394E91B9264495C9063D505262799B9FCBE6316BBCC8D8093053636A74D4FA000000000000000000000000000000000000000000020F161B1F292E36""") + ) + }; +} diff --git a/test/micro/org/openjdk/bench/java/security/MLKEMBench.java b/test/micro/org/openjdk/bench/java/security/MLKEMBench.java new file mode 100644 index 000000000000..a013aa1bab97 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/security/MLKEMBench.java @@ -0,0 +1,1240 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.openjdk.bench.java.security; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.InterruptedException; +import java.security.NoSuchAlgorithmException; +import java.security.KeyPair; +import java.util.Arrays; +import java.util.HexFormat; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@State(Scope.Thread) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@Fork(value = 3, jvmArgsAppend = {"--add-opens", "java.base/com.sun.crypto.provider=ALL-UNNAMED"}) + +public class MLKEMBench { + @Param({"ML-KEM-512", "ML-KEM-768", "ML-KEM-1024"} ) + private static String algorithm; + + private static final int TestsPerOp = 100; + + @State(Scope.Thread) + public static class MyState { + Object[] encapKey512 = new Object[encap512TestCases.length]; + Object[] encapKey768 = new Object[encap768TestCases.length]; + Object[] encapKey1024 = new Object[encap1024TestCases.length]; + Object[] decapKey512 = new Object[decap512TestCases.length]; + Object[] decapKey768 = new Object[decap768TestCases.length]; + Object[] decapKey1024 = new Object[decap1024TestCases.length]; + Object[] decapCiphertext512 = new Object[decap512TestCases.length]; + Object[] decapCiphertext768 = new Object[decap768TestCases.length]; + Object[] decapCiphertext1024 = new Object[decap1024TestCases.length]; + + Object ML_KEM_512; + Object ML_KEM_768; + Object ML_KEM_1024; + + MethodHandle generateKemKeyPair, encapsulate, decapsulate; + + @Setup(Level.Trial) + public void setup() throws Throwable, Exception { + + MethodHandles.Lookup lookup = MethodHandles.lookup(); + Class ML_KEM = Class.forName("com.sun.crypto.provider.ML_KEM"); + Class K_PKE_CipherText = null; + Class ML_KEM_EncapsulationKey = null; + Class ML_KEM_DecapsulationKey = null; + Class[] dc = ML_KEM.getDeclaredClasses(); + for (Class aClass : dc) { + if (aClass.getName().contains("K_PKE_CipherText")) { + K_PKE_CipherText = aClass; + } + if (aClass.getName().contains("ML_KEM_EncapsulationKey")) { + ML_KEM_EncapsulationKey = aClass; + } + if (aClass.getName().contains("ML_KEM_DecapsulationKey")) { + ML_KEM_DecapsulationKey = aClass; + } + } + if (K_PKE_CipherText == null) { + throw new Exception("missing K_PKE_CipherText class"); + } + if (ML_KEM_EncapsulationKey == null) { + throw new Exception("missing ML_KEM_EncapsulationKey class"); + } + if (ML_KEM_DecapsulationKey == null) { + throw new Exception("missing ML_KEM_DecapsulationKey class"); + } + + Constructor EKconstructor = + ML_KEM_EncapsulationKey.getDeclaredConstructor( + byte[].class); + EKconstructor.setAccessible(true); + + Constructor DKconstructor = + ML_KEM_DecapsulationKey.getDeclaredConstructor( + byte[].class); + DKconstructor.setAccessible(true); + + Constructor CTconstructor = + K_PKE_CipherText.getDeclaredConstructor( + byte[].class); + CTconstructor.setAccessible(true); + + Constructor ML_KEMconstructor = ML_KEM.getDeclaredConstructor( + String.class); + ML_KEMconstructor.setAccessible(true); + + Method m = ML_KEM.getDeclaredMethod("generateKemKeyPair", + byte[].class, byte[].class); + m.setAccessible(true); + generateKemKeyPair = lookup.unreflect(m); + + m = ML_KEM.getDeclaredMethod("encapsulate", + ML_KEM_EncapsulationKey, byte[].class); + m.setAccessible(true); + encapsulate = lookup.unreflect(m); + + m = ML_KEM.getDeclaredMethod("decapsulate", + ML_KEM_DecapsulationKey, K_PKE_CipherText); + m.setAccessible(true); + decapsulate = lookup.unreflect(m); + + switch (algorithm) { + case "ML-KEM-512" -> { + ML_KEM_512 = ML_KEMconstructor.newInstance(algorithm); + int i = 0; + for (EncapsulateTestCase tc : encap512TestCases) { + encapKey512[i] = EKconstructor.newInstance(tc.ek); + i++; + } + i = 0; + for (DecapsulateTestCase tc : decap512TestCases) { + decapKey512[i] = DKconstructor.newInstance(tc.dk); + decapCiphertext512[i] = CTconstructor.newInstance(tc.c); + i++; + } + } + case "ML-KEM-768" -> { + ML_KEM_768 = ML_KEMconstructor.newInstance(algorithm); + int i = 0; + for (EncapsulateTestCase tc : encap768TestCases) { + encapKey768[i] = EKconstructor.newInstance(tc.ek); + i++; + } + i = 0; + for (DecapsulateTestCase tc : decap768TestCases) { + decapKey768[i] = DKconstructor.newInstance(tc.dk); + decapCiphertext768[i] = CTconstructor.newInstance(tc.c); + i++; + } + } + case "ML-KEM-1024" -> { + ML_KEM_1024 = ML_KEMconstructor.newInstance(algorithm); + int i = 0; + for (EncapsulateTestCase tc : encap1024TestCases) { + encapKey1024[i] = EKconstructor.newInstance(tc.ek); + i++; + } + i = 0; + for (DecapsulateTestCase tc : decap1024TestCases) { + decapKey1024[i] = DKconstructor.newInstance(tc.dk); + decapCiphertext1024[i] = CTconstructor.newInstance(tc.c); + i++; + } + } + } + } + } + + @Benchmark + public void keygen(MyState myState) throws Throwable { + switch (algorithm) { + case "ML-KEM-512" -> { + int count = 0; + while (true) { + for (KeygenTestCase tc : keygen512TestCases) { + myState.generateKemKeyPair.invoke(myState.ML_KEM_512, + tc.d, tc.z); + if (count++ >= TestsPerOp) { + return; + } + } + } + } + case "ML-KEM-768" -> { + int count = 0; + while (true) { + for (KeygenTestCase tc : keygen768TestCases) { + myState.generateKemKeyPair.invoke(myState.ML_KEM_768, + tc.d, tc.z); + if (count++ >= TestsPerOp) { + return; + } + } + } + } + case "ML-KEM-1024" -> { + int count = 0; + while (true) { + for (KeygenTestCase tc : keygen1024TestCases) { + myState.generateKemKeyPair.invoke(myState.ML_KEM_1024, + tc.d, tc.z); + if (count++ >= TestsPerOp) { + return; + } + } + } + } + } + } + + @Benchmark + public void encapsulate(MyState myState) throws Throwable { + int i = 0; + switch (algorithm) { + case "ML-KEM-512" -> { + int count = 0; + while (true) { + i = 0; + for (EncapsulateTestCase tc : encap512TestCases) { + myState.encapsulate.invoke(myState.ML_KEM_512, + myState.encapKey512[i], tc.m); + i++; + if (count++ >= TestsPerOp) { + return; + } + } + } + } + case "ML-KEM-768" -> { + int count = 0; + while (true) { + i = 0; + for (EncapsulateTestCase tc : encap768TestCases) { + myState.encapsulate.invoke(myState.ML_KEM_768, + myState.encapKey768[i], tc.m); + i++; + if (count++ >= TestsPerOp) { + return; + } + } + } + } + case "ML-KEM-1024" -> { + int count = 0; + while (true) { + i = 0; + for (EncapsulateTestCase tc : encap1024TestCases) { + myState.encapsulate.invoke(myState.ML_KEM_1024, + myState.encapKey1024[i], tc.m); + i++; + if (count++ >= TestsPerOp) { + return; + } + } + } + } + } + } + + @Benchmark + public void decapsulate(MyState myState) throws Throwable { + int i = 0; + switch (algorithm) { + case "ML-KEM-512" -> { + int count = 0; + while (true) { + i = 0; + for (DecapsulateTestCase tc : decap512TestCases) { + myState.decapsulate.invoke(myState.ML_KEM_512, + myState.decapKey512[i], + myState.decapCiphertext512[i]); + i++; + if (count++ >= TestsPerOp) { + return; + } + } + } + } + case "ML-KEM-768" -> { + int count = 0; + while (true) { + i = 0; + for (DecapsulateTestCase tc : decap768TestCases) { + myState.decapsulate.invoke(myState.ML_KEM_768, + myState.decapKey768[i], + myState.decapCiphertext768[i]); + i++; + if (count++ >= TestsPerOp) { + return; + } + } + } + } + case "ML-KEM-1024" -> { + int count = 0; + while (true) { + i = 0; + for (DecapsulateTestCase tc : decap1024TestCases) { + myState.decapsulate.invoke(myState.ML_KEM_1024, + myState.decapKey1024[i], + myState.decapCiphertext1024[i]); + i++; + if (count++ >= TestsPerOp) { + return; + } + } + } + } + } + } + + static byte[] xeh(String in) { + return HexFormat.of().parseHex(in); + } + + record KeygenTestCase( + byte[] d, + byte[] z) { + } + + record EncapsulateTestCase( + byte[] ek, + byte[] m) { + } + + record DecapsulateTestCase( + byte[] dk, + byte[] c) { + } + + static KeygenTestCase[] keygen512TestCases = new KeygenTestCase[] { + + new KeygenTestCase( + xeh("2CB843A02EF02EE109305F39119FABF49AB90A57FFECB3A0E75E179450F52761"), + xeh("84CC9121AE56FBF39E67ADBD83AD2D3E3BB80843645206BDD9F2F629E3CC49B7") + ), + new KeygenTestCase( + xeh("9EFF3FF8252400827F3B4389E4EC07E67948257C744278048C889D0789C5BFFA"), + xeh("5D473027666FECF7024ABAF175B9BC42E84768C00AE2C5CF27A668121B02CD3A") + ), + new KeygenTestCase( + xeh("C6636E8C2F87DD52A7F165A2A3BAD562ADB28CF738AA56B996B6062E95F66148"), + xeh("7A7FC526215D5AE3262985D17B00726462D1479CB038DE8C8A8FEA896A037B2C") + ), + new KeygenTestCase( + xeh("EDE2E63FDEE6ADA2FC6EA906AA8D92DE87FA6199AC15446B0B6F075BF9F76148"), + xeh("6E584B168BB5399D52B458A8BD122DE14EEF214515B70F38F972F41783005755") + ), + new KeygenTestCase( + xeh("CD568FB1EEC23C436C011A55BE2FD4362EF000C890BDE7611EB5C4618AB74F8B"), + xeh("37B87F960BF862D8B81AB5F56E9E24ED8EB011A05867A04DEC9BAA519AF45E22") + ), + new KeygenTestCase( + xeh("35DEE1F800CA85E482BB12AFDB882FAE62CC77A338E65CA2265D77243ADAE3F3"), + xeh("4B0A877F51434F70E2D8DB0A51BEB0A7572EF0DB7AC26ABC5D333C503B68BD5E") + ), + new KeygenTestCase( + xeh("D9502C86FB461300B8D142A906B766B0B42481EA9C83AAE2BB74390F882B0509"), + xeh("B1EF909D94C56C134107B913B0ED29BC0851CCE424D0FB69EDC04C685A540871") + ), + new KeygenTestCase( + xeh("07A9BEBF21C83F6E5417A73D8CF5B527568C903B5883CEC8347B4ADE73AD92D6"), + xeh("671C8C054A52A67BEF8015DFDB5711C9197E84A5A553E794AE0811C8432FEF6A") + ), + new KeygenTestCase( + xeh("F682949EBFCFA5DA31368E3F177DD146448D0E62178959FCBA4CD4F02CD8B17E"), + xeh("C02D5CAD9E565727E19B2EFE4FA2E083F93EA0F5ADAF97522F33F416F786765F") + ), + new KeygenTestCase( + xeh("170CA6BB76C065255DFDCA3EB93C772E57EBEF8C9A291C8F0BC4444BF008C868"), + xeh("70567D6DFD6622814417BBF673812F2D02E5BFA897D464957AA4219841A93C19") + ), + new KeygenTestCase( + xeh("176719D76EE1CEA83F7751BC4E3DDD00868B5C504C79AF8730B9F7595E7914A4"), + xeh("71A6E59B13B36CAA406DBEC53F3FF2F0CC529098A4C8FBFD032C8BDB8B0E16FE") + ), + new KeygenTestCase( + xeh("3C90FC402DA953172300194876B3B3BC958268747751346DE7134566CB8FAA5A"), + xeh("B63478F2FC887334C707E9D836E3104892566B3568CD32B583F8C9A0DE1A1F0C") + ), + new KeygenTestCase( + xeh("24B783E39214CC39910799ADECE53B32408C19CD9ED10DEC039A9FA2CFC1CA30"), + xeh("4EA6EC5384C51903758B807395181F6D6B4CCA3FA1CA24110B08A8AB1742C411") + ), + new KeygenTestCase( + xeh("E4F2972F746E028108A5BB98EC97A307DC9363909DEAFC491F040B964675B9FC"), + xeh("9FA6AA53F505506BE269CE201A1A6EF95692DD1350A7188F468D34C5DAE5EAD7") + ), + new KeygenTestCase( + xeh("C5C26DF5BA8BAB4A293292BD070986A8063F736469F6ABBAB684F7127575172B"), + xeh("A9EE7619E4F0250147ADC188649A45EB6D82DE5EACD5643CDC52E6DF8DF2F8EB") + ), + new KeygenTestCase( + xeh("EF0F6EDB707059073378E3419C8D9031D0732CFA931190EBD07FE291B1A3EBD3"), + xeh("80CE5D65D1795C90B637C10360B04A4C21A70851F0A59D4D753F54CC00103FF4") + ), + new KeygenTestCase( + xeh("BEE40356679E3EAE8B0C3FA07C1BFDC8835CEC26CA194D5EFC4301481C256C0E"), + xeh("B923CFEEC804B8C6A9E36B77B38A2886C45B1C731A33528ED2CB5A1F65E792F6") + ), + new KeygenTestCase( + xeh("C6D5B35B90FA9AB9A7B438B57942D653CAE67B314C7FD152013B4E90BEF8201B"), + xeh("1F4863F16E38DFD2C42A9322FA1ACB941DF3BDFA000A202AC621936FCC5FE33A") + ), + new KeygenTestCase( + xeh("5C6051E18E28FC5719E3172B967D25BB1649D87743440F7715E860AA212A256C"), + xeh("53F5EE39A553E831BE32EB490A6E1DE62FD4FE486EF58A4B99F6347759BB8905") + ), + new KeygenTestCase( + xeh("CA351B0F454DE9DB364E1DAB8AEF6E49C2E69439941935B24C00BB9952E65BB3"), + xeh("9C7C3E68F827936D8DC435942DC4925D180E6D5C911550089E1337D8BA77A06C") + ), + new KeygenTestCase( + xeh("C467A43BF9E9CCADCE4581B53F8CA0B605583775AFCD0EBBB587907B3A813D94"), + xeh("97A4C9A65A82BAEC15FF165E10490976EBB19FAFBA8F9E8E0DFFBDB4D5E1ACE5") + ), + new KeygenTestCase( + xeh("D732CF45D7F44788E17C3B6DA9987495AB1AEFA233F74EEF8D3BE5B6C0C04E00"), + xeh("973DBB6EAF76AF0C96F0F24EF9AE65ACD854301B5F7A7892A17FBB8601DE78D3") + ), + new KeygenTestCase( + xeh("B670CEB5612A1287C4653B158A3CC522AAA1AA45B34A4C770DCA1E5BF3988F3D"), + xeh("D525CCE60C3E300ED36298A1C0D0165C147CB84197C4028257DAF39239E6EA5D") + ), + new KeygenTestCase( + xeh("3236CB10279681238E5B0E2F5138A7F743443379F5F1A845F3D76B75D2C2A9DF"), + xeh("9F2FC49CD848BA72FC17854B18D88ED65B630BA94A1BC5F6D3A458E1087D3A13") + ), + new KeygenTestCase( + xeh("C155568B6BA74DA317388423F8FB28585977EB858EE306CAE4174120F02A8D72"), + xeh("0FB831AFA34B124F7456D0D09E4ED8607DE407101E6E75F305F9D67EF7C2FAE7") + ), + }; + + + static KeygenTestCase[] keygen768TestCases = new KeygenTestCase[] { + new KeygenTestCase( + xeh("E34A701C4C87582F42264EE422D3C684D97611F2523EFE0C998AF05056D693DC"), + xeh("A85768F3486BD32A01BF9A8F21EA938E648EAE4E5448C34C3EB88820B159EEDD") + ), + new KeygenTestCase( + xeh("444F032DD19AE7518C4B35B0732A41DC567845ABA8BD7B04A9C413A0CF2DE0B5"), + xeh("DF0F282411F4A071489A8F618E2AE5AEF40131CAC5233D6D731522720C2FEB1C") + ), + new KeygenTestCase( + xeh("092271D05CA63C60880AF404D60BC4BB9539E2EA12969581898D56E0AC9A5A68"), + xeh("5AA6DC620A6E9A60CF19A7B4F0FF805BDA8219522A548EE5857C3FF6060C7A2F") + ), + new KeygenTestCase( + xeh("BBF7574CF5F32BE49E1F39CE33870D9D6384056D60D223003B6B0C10D5C42180"), + xeh("7CF50F7237A97072F03F31CFD59FA8E863BCA3AF7375E0CA698FF665661C24CF") + ), + new KeygenTestCase( + xeh("D12CD9B65B7C58B2195AE0BE0282527BAC06C2D25CB0472628D64715F7F6A378"), + xeh("C593627807074684B7D363441F80F6A3D185D67878702D33A4E0BDA2000F857D") + ), + new KeygenTestCase( + xeh("79C006D5470C229AFCE7588546E52204B09F5086974865B426AAAA198C6CBA7A"), + xeh("E01702E1228F530AC96DB053A415BE97749A109A1FD4057BA128649B17EC07AD") + ), + new KeygenTestCase( + xeh("B04F631B330D83991B5C01E7F69452DFC394F9689632F8C7F60DBFAB92A9CEA5"), + xeh("AE51639EF7F26FD2215AD11CBE1EDEB3B943D668EEEFEE13ED5B0DA3E0A5F3ED") + ), + new KeygenTestCase( + xeh("3D63BD6C310AFCF684292E5F8E1B98CC75B5A27B21526268444144AB24AB2967"), + xeh("6F9FF5654FDA78774498E2643E935D21412CEB49BC393532C80C47A982418F66") + ), + new KeygenTestCase( + xeh("249D48941ABC01C9290719FB34D91B05E774E70E6F0181E1783F2586E2499536"), + xeh("D083E6922EF0A818308FD7FE7CF5AD3A96942442BE327B0A307685C2D4315901") + ), + new KeygenTestCase( + xeh("E1CFB8195877B2D4FF3363BAC3B4E7BEBA6DC3CBB789B1B24215393F6C9BBFAE"), + xeh("A20ABA8A8DDC212DE825BE0D3BE57701A6B5B3A46A300D9B5945F579A59AFABE") + ), + new KeygenTestCase( + xeh("ADC4DA59D935DD87420ACEE52AEE19CB371FD0BB498D79BA680159EF7CE37C17"), + xeh("7FB950A8F51DCEC4BC7A573EDDA56ECC049E5688476BD5FD6CD076A8F99A019A") + ), + new KeygenTestCase( + xeh("76CDCA53F781806D55CA8D3BAFB3F4D389D712F1221E85B5E29D6A46580F978C"), + xeh("51D509CF26799741631099039F713B22551E2B0F0297BB809DF0CC8FC3E47EEE") + ), + new KeygenTestCase( + xeh("78AB6C49354A018BD38A39926F822A1AC4ACC4FF32DFD7C047CE0887A3AC182C"), + xeh("9C330AB4257D7B87C4742C6E95B66BDF805C6A145BF444836092C6B1D2C5FFFF") + ), + new KeygenTestCase( + xeh("13B75620E4CB9AB9A6689F6E2BE44639BAE6C9CB7DD641AC1C9377242D99679A"), + xeh("18EA1C7532F706B06870D0A1047AAE33D9E1FF9E9BCBBD302D8817EB7B022A77") + ), + new KeygenTestCase( + xeh("7C345819C7C327AD9571E5DF882449DB243870D686A9764D4129B21E17AC86A9"), + xeh("C71F7E44295978FC63BF8F6A68F8609E98D155FD7A74E1FB7982733FBF8A6C25") + ), + new KeygenTestCase( + xeh("8D6DF2EB3DDAF961FE5EB556842B758BEBC7ECB312B6D4628B323F483B77D6F9"), + xeh("EF668FB41F49E82EE0FE00919CC06507548321593A7ECD1D2112342608D95FFF") + ), + new KeygenTestCase( + xeh("DB4ED8E9C3E1AC7A35EA4B67A4EFCFB46972A984D161F79F084125D6D4AEE7AF"), + xeh("26345937ADC9104155275E7114E93D9F5847EEA73A9359358585B2D42301A294") + ), + new KeygenTestCase( + xeh("C6EFA7D5D500E5BF857D80EAE2A6EE6414159947FD4BE589350724FAE5E51805"), + xeh("63435E06C2AA3DFB3477120710D5E7FF0DC0DA68D4644A24F66A8012FB193697") + ), + new KeygenTestCase( + xeh("20859B01DFC60B6109E0234F3CAC7A247D8386099D83D2D447E9A21AF9DE48BD"), + xeh("8C2942B7207C2C59BD56FF9EE0B120B1DAD81B05602623623CBC7E0C20C9B709") + ), + new KeygenTestCase( + xeh("409E9F3AB58D736E122EFCC4240BF8388FDFDA6759004D42457018014A335BE4"), + xeh("EAE318341D06E0801C0CA4B873520C714740AD017FE5A158D3BD40960D907AB7") + ), + new KeygenTestCase( + xeh("CE2CACEBD54AF1B4E71588DE9F22A6AF2C2E2AD7FD66B9FEC0DF19182E7F57EC"), + xeh("EF38264520685080F52975BC957C5FB609FB0E1BD06D26F572CC5425CAE7DE5C") + ), + new KeygenTestCase( + xeh("7E03015C5D55FD9888E730C1E60F90C5F6C2E3B1E8C7C08D869F0C1D15B540ED"), + xeh("17E5AE70771674BE8903CC21B3A90248D993C261B6CEEF2C747873D113869B55") + ), + new KeygenTestCase( + xeh("8590BFC9A6FC25EE7E6DAB4870DBF4B51A1F141B7C9E96230C0403E799BC68E0"), + xeh("BF83E3048B021F22DB57076A885729F95119CE63FAF51A69954BCCC51E014686") + ), + new KeygenTestCase( + xeh("D5FD815092620DC42A223909E387369A74AF7DCA285138CF217BC29F29C42C41"), + xeh("F42861EFF7691614C3E8975AFB4E353F8C8C39E6F41BB637EC79BAA976D1ADC1") + ), + new KeygenTestCase( + xeh("D21D5AFED9AFAA3B49FB45245B2BCA1505E4000CDC29094A3600F5CAA49A7B3A"), + xeh("4DD0E86091649A0A08EA44DAB85DF56797F8BF46222C2DBA7DEC6374B9B2268E") + ) + }; + + static KeygenTestCase[] keygen1024TestCases = new KeygenTestCase[] { + new KeygenTestCase( + xeh("49AC8B99BB1E6A8EA818261F8BE68BDEAA52897E7EC6C40B530BC760AB77DCE3"), + xeh("99E3246884181F8E1DD44E0C7629093330221FD67D9B7D6E1510B2DBAD8762F7") + ), + new KeygenTestCase( + xeh("2D229AB46354901491476CCE8FA96E4A5FBA65AB2F538FEDAA528E35687A782B"), + xeh("007BF379B97DA0947F2E9BFDE3359E282C9CF1D2E68A80209B533104E90F432D") + ), + new KeygenTestCase( + xeh("1D65D0290B15903371D616D7AC3F2FADA8CB24E6C84D52C039A10BC1288C1110"), + xeh("E94F4E83E6CAABCA9E319D40F6CE0E3691B77C92D9E3766BE9B6F4B6DF2E640E") + ), + new KeygenTestCase( + xeh("22D19527844F3CDB8A342620A96E902AC7C36E54677ADA6FE8DB08DF4EF3B36B"), + xeh("EC54F6E1E7FB12B796D0E56BE6FE3BA6EDAAB49B08712318B27D229606D2AC70") + ), + new KeygenTestCase( + xeh("A00D1EE4147DD57B5E76C58A928DED0B720FB2FB6353780B380B5FBC76712E5C"), + xeh("5B78F8D30AADB59FA617EF807D5C23113A9908342F08E898E02991CA1D7B934D") + ), + new KeygenTestCase( + xeh("2C34B1476753095D0C8A48A00136F358A98D1416E5069CBA4540C6E26FA3634D"), + xeh("384509DB0E97D4689A3CED953CFBFFA9D3B3B87CCB0C6A360FC0DF3CBCA399F9") + ), + new KeygenTestCase( + xeh("F742E7B69E27A57A43E1034CEB5834CAD57C380ABE259F432F96FAAF27F981A9"), + xeh("63DAD9B127F98E72A3C65ACF4B172FDBD9B9C39F24F728D1F40EB02C9949419D") + ), + new KeygenTestCase( + xeh("3BFC9A057D979EC03A705A9CC406DD8A46C106941AF6777B1D7F79C1508D7B24"), + xeh("0A755A829F05597B2F2A90974F22FB1AEAB42892101222967E3A0AD612CEEBCA") + ), + new KeygenTestCase( + xeh("7C43F2E7D9B1D8D9C41D9F315E052A254CE3A1F098671773B53717A95220AD55"), + xeh("681F088AD6962FC397A1B9071852848CE9A7EDAE65A81485CEC87D0974707B7E") + ), + new KeygenTestCase( + xeh("C2E1A3161F3734F44F3C2F1736E149803F71321122242A1E95E55E5652A91F55"), + xeh("40BBB2C581B2D694E369C0DA567371E8E53C328A59BCE775A625C9F5CC185E0F") + ), + new KeygenTestCase( + xeh("ACB7FDB596B44A88A60ED74A3FAD9EF745BF5BFA4902CADB891EC5CA45F685F5"), + xeh("E15F322315265F9B847960B7185D962761ED79C62286A0DFDB13DBF550CE0107") + ), + new KeygenTestCase( + xeh("0AA4E8D918201BB98464963B076E35337FF3265810723E01C435954DB18B14FF"), + xeh("ABD71039AE2E2700391011D9CC8265C2D5C9779002D54E1BDD9607402054CA95") + ), + new KeygenTestCase( + xeh("F43EC0E96A791317938761FFBE97332D5D85F52D22BDA6303FE7E7107DB608A6"), + xeh("177A8DA7AF8DB3F712E1653D05A47D61B59F4F4950549382E56F761D7126F8F9") + ), + new KeygenTestCase( + xeh("0596F1E214B29A0CB7A641EA0BB157FE01FAB73B4A9BCDC165FA44C8FD5FBF71"), + xeh("79E3B0D4F4AF344ED06FDE8BF4E104753E832294A3D2E4B66BE59149006A7B95") + ), + new KeygenTestCase( + xeh("D7349F9AD546CFE9830E1197072B6ED9CA21E8E0423F145F1DB84A5AEBA230EC"), + xeh("EF0F95F630F41B3AF911A30E543822DFA6B7684FEE36956D2BCF8FF080C9FA26") + ), + new KeygenTestCase( + xeh("F05117E932CA0E0C202732DFD4F674BF5848219A76C64A0650C27E2E55095513"), + xeh("DDD4871080BD4F761D972085851DE0A0408A2F5EEC3CD3786297A782402CA440") + ), + new KeygenTestCase( + xeh("A405D9B07C5771A5BBDA2BE9F8A40D9566CAD7DA1761ED8076A289063DB4A8E2"), + xeh("FA29BDC28D989B8C4BE84706A3CF21B36A1C6E355C88A361C7664818E4BC8E03") + ), + new KeygenTestCase( + xeh("E66F17317C40783CE0594CFB5920FF86062591C5EA4254021495749642C0D968"), + xeh("08FED872D91297D8059743D3E7B6EE47548357E7F882B5BFE2F04314187ED424") + ), + new KeygenTestCase( + xeh("F8CF49DA62AA762EC020F3766237520E7FDA4CA3AC11FBE50E6C5F9CAB3CA7B8"), + xeh("EB8EA5E8C5EABACCFF162556DA53F0C02F72EE7A7DEA8E9EB70FC51C777645E6") + ), + new KeygenTestCase( + xeh("08E36AE8586A59B8249A80D7F43506F9711FA4B00A49D182CE06DAD0CF985809"), + xeh("DAC056B9A373687E44CCAB8751BD334F4942696B9076155F9D0E5BC0E89D85CF") + ), + new KeygenTestCase( + xeh("A491FF48028B67A407F1054D5B1CBA733B665DE667E22596EDCC31C227C2DE1B"), + xeh("4D727ACABD44DC48980691E0268B5B3FC1E476B3FDF9571F5CBC8DDFD400AB99") + ), + new KeygenTestCase( + xeh("7B2EC50C53A67E0BCCBA98C2E319F5AB46B6E593D2465F14B23FFA03D0E5BE0D"), + xeh("4E638D8AC3662450E09D8500DED751060B7990D54F137508B9897277F65EA952") + ), + new KeygenTestCase( + xeh("16858AA7C92EBD72FB8CCD0A99D0435EDB2A6EB1B936DBCB637CF43F25D221B1"), + xeh("7459AB99D24C1254EEECC035874BF19A64EFC8EDC9D369C11F5DF4DC83AB5FBC") + ), + new KeygenTestCase( + xeh("F788F3E21D62E74090582F310BD4FDC8065E56E8D946142B9B9CF8F338F330E8"), + xeh("4CC1CA6B662A4CE499EBE66D933CEAE58EE244CBDCAAE3C1F45A0D6947802B76") + ), + new KeygenTestCase( + xeh("A72608DF0F025B4FEE7D94BAE77BE94CB974F20DD55006A70FD39F3397A8EF90"), + xeh("D16CC70224474A4D71E1F950C2D5CA72D8F08AF80E0C7F6E292C265A50CC30E8") + ), + }; + + static EncapsulateTestCase[] encap512TestCases = new EncapsulateTestCase[] { + new EncapsulateTestCase( + xeh(""" +DD1924935AA8E617AF18B5A065AC45727767EE897CF4F9442B2ACE30C0237B307D3E76BF8EEB78ADDC4AACD16463D8602FD5487B63C88BB66027F37D0D614D6F9C24603C42947664AC4398C6C52383469B4F9777E5EC7206210F3E5A796BF45C53268E25F39AC261AF3BFA2EE755BEB8B67AB3AC8DF6C629C1176E9E3B965E9369F9B3B92AD7C20955641D99526FE7B9FE8C850820275CD964849250090733CE124ECF316624374BD18B7C358C06E9C136EE1259A9245ABC55B964D689F5A08292D28265658EBB40CBFE488A2228275590AB9F32A34109709C1C291D4A23337274C7A5A5991C7A87B81C974AB18CE77859E4995E7C14F0371748B7712FB52C5966CD63063C4F3B81B47C45DDE83FB3A2724029B10B3230214C04FA0577FC29AC9086AE18C53B3ED44E507412FCA04B4F538A51588EC1F1029D152D9AE7735F76A077AA9484380AED9189E5912487FCC5B7C7012D9223DD967EECDAC3008A8931B648243537F548C171698C5B381D846A72E5C92D4226C5A8909884F1C4A3404C1720A5279414D7F27B2B982652B6740219C56D217780D7A5E5BA59836349F726881DEA18EF75C0772A8B922766953718CACC14CCBACB5FC412A2D0BE521817645AB2BF6A4785E92BC94CAF477A967876796C0A5190315AC0885671A4C749564C3B2C7AED9064EBA299EF214BA2F40493667C8BD032AEC5621711B41A3852C5C2BAB4A349CE4B7F085A812BBBC820B81BEFE63A05B8BCDFE9C2A70A8B1ACA9BF9816481907FF4432461111287303F0BD817C05726BFA18A2E24C7724921028032F622BD960A317D83B356B57F4A8004499CBC73C97D1EB7745972631C0561C1A3AB6EF91BD363280A10545DA693E6D58AED6845E7CC5F0D08CA7905052C77366D1972CCFCC1A27610CB543665AA798E20940128B9567A7EDB7A900407C70D359438435E13961608D552A94C5CDA7859220509B483C5C52A210E9C812BC0C2328CA00E789A56B2606B90292E3543DACAA2431841D61A22CA90C1CCF0B5B4E0A6F640536D1A26AB5B8D2151327928CE02904CF1D15E32788A95F62D3C270B6FA1508F97B9155A2726D80A1AFA3C5387A276A4D031A08ABF4F2E74F1A0BB8A0FD3CB"""), + xeh("6FF02E1DC7FD911BEEE0C692C8BD100C3E5C48964D31DF92994218E80664A6CA") + ), + new EncapsulateTestCase( + xeh(""" +49469911485CB1C06A48A449F1A43B0456406243AF447A7CECD5467DF322A159AF32B6C59CB05D200CAC34DA66D8DBCFF8326FCCC08A77C9286F590F33C06AC36049B91442F18AC6C00C240E713D387C8BB2BA3780E6BBFE90A4B1D7B155360ED9ACBD63205BC3482B8953B3490427F28392B083A47BE5B18EF6AB51B9859FDB659B8424BA93A8F470014FCB6AB9E61FACC61311BC1BCB098469D9702FE54F8F931DE7B2B57543750A346367371F3724384261B569AB5D8C870A01822BB4E6C617F17DB6EB0D0989C5644459281828EF4AC11A119EF794530436CAA0E28B8CB5365E4854E1AB4BF87CA018AC6A8E62C36C97117014A569AB472DEAC7E7B1108BB8BDBD710AE8D033A1961917E171AAC6841B5A9C5D869E68974D79B8C70775955520CEC21B5EDB05B60FE230EC143BFCC15B550370E1D58E76D1B5BDB0747412B952131DB306A4DB2395CA69CB9912C0A1660517553C92A7210056C4B6F347CDF33C326A27155CA1A7BB809F8A4A46703537B6530E5987E02A9EDD83297A1218C68699E5A898F9487279D35BD01B57B57A30E85483194C68069BAB0FC4BA0F48880DD1089DD21ABCD07228D9B213C32EA184291A2B12E3E19B4E4B7CA51879C46AB93057AE748236265935F0B16CB456256419AFD82147C9247CE6A7CEE4F349AAA59DA7A4AEBB2B0ED225775CE085A9AABBF49B756CF833CAF22B39AB4D9AC4A26758430866C9D76C5EA68300AF90697FD304AD715C591798C7948FC1A954FFB40301A432B29726884266A3D8B8EED13F3A33A106349FF58075C9D67923A59E06322FC7258017179E7859ABB2A83234D81330B1297AE842AA1C0C8543972E5B3AEA4490D4B0CCC1F9681266A6A0F96DD955924EF25E39642556F18443497D2EAB77AFC01B1D2003F1981C92060743141458FC606BA85DE9DBB1BAC78D6ABBBC73BC7F4E0C6BCE13C8B49BA367E60929C61C34FC7BFF013D4743BF92A70B4683C724B06717237A76D58F81EA39A9F96F6D627162299BC82A355D06C766318BBFEA3386860D683AB75FA03A87B1B2C1D99A30EAAD78A79CEEB43C1621C54F79AEDF82C7F8CD5FB11F119FA35CCA71B4CCF3E1D83F07C3A66C3E82F2D84F640DE5"""), + xeh("4660985A5838041F2E50381CB4E7AC908BAC83CC1E074220C6705E3F5FBFC2EF") + ), + new EncapsulateTestCase( + xeh(""" +C70876917C9AC2A2CF2110000910898E21804D940D6F761A525578E2B0399F1C0800B62C8720060F88746122C948446472E73AFE78A205857C6D32B6C01CA0EC742311840A36A8BD157B1C50A944B4C213FCF9558E3068D9714ACDBBC88A1538B59764C1F59C079C5BDA31BF55EB731BF69717A9CA63DC316636461CE2CC42201C359B88D044156DA30AAB932F902030BEEA6D58998FB2363C8223BE3DDC437AAB4D1BA27FCE058E701B10FD211E5862542C058F3DE33D5561B8BB3A83D6C55377862181150173D2135CA3C8084615668C38ABE8B72F193FDF96ACFA3470FAA53450017EFC36882C5AC722659D229225E01C5F976171E19172BCE5290073AA08276FFC85218F208BA3A1108B62545941C8991C4CE279C697D8CD06436134511D300C3A5FEB963D36CF29D6065E085C9663443342A8388763B16566D99C5C5DA4A451C2688E10936293948A57C4CE7B73BCBB698D9B71E2974638D5433E56A411E4089F966F603120D56A48DB653A5CD373D42A6AF3117D71AA4D26A1639D63A305B8BE1DE15C6F678519FA671A91483E46AEA26C0C59872CDAF57B3A6453CD660A0D9A0A562BA23678CDCDEAAD1CDA5820C65EC480347FF2872EA9574C4148C7D59980C584646409793190BC721CA6EA9BF029C695563B0598BCB357A1A221CEB3AB96F2269F45C24108E137D1BC34708B1B66352627340CCAE6CB22F41A75A0A55F58701DC4157A1316FF968CEE300FD55A37B5957F41220BF547933C67201D67B1AE278D9649BCAFC68F082B7D1C6016EF360D200CA0EBC76046DC5AAB171A0D544719E3411B587DCE380D467BC13368A25FA51A3E9B4EDC77561408B776F83A76B24B489310E3B608F1B40EB7395470F86C1D0622C1545065707462D89B364CAB2CEAC9501157F91BC52A2816E9598846B56C1F7B1A6D06195F92BD53931078E923C9D1552782325878832224B21A1C26562245B636943803ACBADC559D3BB6DEC54ED360239F74695ED3364DE562751892F2B2936F6895C166697A4A44D10A49C59C53DDE4B2631705440B957100AF4E1BBD47F2AADF22780AE0255D0AC18A87A28D282DD1C59C0C51D373C8F4A912400D5C87B499E0BE8CA991939F160B"""), + xeh("0D643FF311D83CEDCB3A95BA0F76216A49BCA389A225396F708EC9A51BF18517") + ), + new EncapsulateTestCase( + xeh(""" +E868A60B3888165A293FDBAB8B75C008E2695AE85A1C839CB08290AE87200868623049839674CF8E87C8D20C5C369B17ADDB344E263045017370D6885DD25785A0C430250795FC4AA1AB215109692B44C530005054020B32D73DED4B06AC32CC1AC47571B7244F2A05AD063DB57BB285C03C465A5FECB4489F82908EC72908B942153C318509C1508556B15B3BC7A671F6A69EDE283C5B87C2383324C3183B645086261B7CC4B53CEC6C5694106142A12A108A29D749AD47B93583020B3CFC328CCCA1611338A8576BA98659D9181607C42D7EE9B0C3174309FA7B3EDBC6BE422515C203B208C9AA1B3C387909EF511FF2A47AB03A747E0A83326B894168136BD6361D170B8D4087C99552D992929D832D58F26BF3D707B6D302F741456DE30FA6509A1314773FFC079AC94AAA10376ADBB70D857E556272F2A32E68485F84E28AD9326F656A57CE234AD2826298BA4C1CD4960BE4523126A405BC3E772121B1F7AB256239E9761B0EDB5C8D746B4D3323134742D69182091170E08C6E0D3B1862E202F332C7A70A25A3E2482113A5A2C257BDC6AF93C981E5ACC95118CCBBDB5B6244C1D060C9288BB2BB1A6791F748C4182B4AE6A68E060E2028690DEACB1E887A9213C693D57971FB6EDF6A95BA3821D445479B142737887BAD938B944376EAF87B15B210CF273B0BE07707FC52475C01B4485893710D84F5132D025E82630F8415330D257E1642ABFD8CC878E8B199C44107672FBDB8330F3C8CE8154E4E8036E86CCDBCE4B693B0C513132B8B740FFDFC51341BCFFA0BC204D63D6696B2271BABA633A572143E74382346C701F92C099B4371D18269A32769889C61AD428FBC110D450ACC95892791656A7DB39868E03FE6F97420910AE8476D43851AEC9A03734AB4E8E4087DDB9626F36ABF7480705C0E81C3887A64794CCB29587593BBB435C2377477B7A0E6A3C9050A84A99936B94C09DE28B018E73CA7C48B083C5BC1E73A24E20D16771711A863D1423E884808E0C8B6E250986AD4BF1B8592F8EB1549DACB4117747F2994D1808B65DB2AA5B05EBD7A0E614888EF86494B93822876C351BA487DB0D0C6F33C353B368BDEA3BC149CB74DAFCBEE209C50B88354"""), + xeh("AA28DCC71FA83D9997DD733D8B0D0394D84D33A3D3E1B74CB74DC6049628F861") + ), + new EncapsulateTestCase( + xeh(""" +76608E0B9539C1B6470F9ACCCF5465C6B355CFA9424DA750CC085477B4A0E9F671DE185995FA38088506A8524D6384A8F505058800B3F14019DF2977E79436D81B8653B844920BB927D2CC7657666DE99C4D865FCAEA3F18302A36961ECA216740075244215625419758B8B8A82C46FBB79333E56D8076BC2F98610FB3474E75A471AA6D746708037020D3578381CC7C959459FDF21839E8413B44C218643CAC49A0179B2DCCB11235345641A10F3D369FD03C8FF733589607616A50926C176CEB45217A0A62A1F4AD3D06669EEC8C947372E8D082E34789A8D9867C0198E5B06934D904AC5318B58A2A5F3AB2522C611F7BA5A1351231F836881116847551D834A310EB82E0B2C6E1728196B7206D00094AA928AD8138F97879B56B55FCDC0D35C76C336526CF52C6192B0793745658E53155241F46663A8DC153ED12862942674B029492D701BAB56D2468C4B165B588D2A6A94C515E9BCB91A55BD372A613590CD76416C6A0AFC40A60669C90BC3A228F05A6DCEA473688CCB80A4CFA3C9BC5157CE4D37BCED562D5B52B70A48294912BD127BE37C39EC4F23F7C3C01A521C56D121D6829A76B7235C2BAAA2BC841634521D8F360D5B7B31B0648FA442C546878A7CB2FCBA5559F94A90308CBDB72C60551409E364CEC93CE24D16593609159735111F918FEBA4B35465BA14AB8AA1A705AA9ABDFC596864347C6E445F23B64B81AB330B454D14413ED47CCAFA49946B828AC3056CB4195C5351FD65A4BAA57262F9A85A4DB552D939BF539B8C4C547B801C1D99C7044393A08143C332AA440477258E04A83F6089C864B1A69418D0B4B739A4BA729B3FCC9C10F9834BB9409950449A8EC09ACAC79BA0681B31A2C7E687793C352F496010AF4A30CFBBB89CB3012216D8E2B489676B05E4B8F142825C4C4552FF7A48802C3E8040C4B2C744AC477EA84901A27BACA79635BA6C0ED28947BBA8B788ACBD17CBB01CA931E4BCF2BC15EC01476AF0A5F8672897AB5A2F9F850BB0ABE6B61A2A4C800F5671F13D712E8686C780677952A0AF65B463CD0289FE3B56F89A6F7D1643F0823093589FC76619ECC2590076DEAA2D895CF1A81924A0490D99446E364BBA45C3BAC1D40"""), + xeh("A4BAA4C603DA1368C1F2AC552A331F77BF1D598C6BCB540D43CA1E6D4B8BDE77") + ), + new EncapsulateTestCase( + xeh(""" +E331342D560ED6120D12B8044C013C5A8A1204164B00130354015213361BFB439417F5AB35A18A4D1600ADE0163F6A1760B08B3BD8A16C3A82D253428508216E3952923070BCBC922FDA6D0E1A734232194EF979790828A110B9F096CD37B5C07D758D3D68CDB9642FAF100D732031DEA07BA884ADA7D4436C490924920D3B3B7B67297E5D8A984DB9136F44557C6BAA5023219048600B8550DEE669A9F38858D79BAB8682FFAC37B0CB9362723B7A1087A21C477513BD386A30D92A5F52F008A32784019B61E0C8C22B096B356C65CEA631CAB14632A2B978A40A91BA7544559A116CC74C28332DC745EB19AC5EF50425E59FE2C777EB0AB7F4EB49A3393CEFCBC846B63D399A6B86CB6168958E71045208C81F07F62CE826729BA2162C2B835185759CF4AEA00025F4AB46EB56AEDD408B0E016C6ED538A1280F6A0CAB2CE7B573258937F0A265D663F0F33495BC4852D73C774061DC388C3E75ACC69A84DE303EDB605CDBB238DB265AA26A8267FCB4A0922A5413CB65783CF37CA2051071FF00CF57BB6000C6057BD93D4DF31EF35CA5A4327CA8AA2EF7D33A04E5261E732EE8FB819AA446E02CB4370B2934140EDF17BAF6040F71B34F251C6C65B766D317C4DD181AC04103409B65C6A7ADA248549BE72A2B43B2E4B85B58CB5FFC0B33C675C0E0D50B2020BED86005BDE97B9862436CF7A7ED687591F9719E4803254BCE195185CB3C9A48DB6F148A0876B00D1132AFDFBA1C91F57E980B96F1906439489093194F2CEA56C46942796749926B36D498B026353CCBAC0BFDC84C208502E0518512D427DB058219B35DC793B789F5C579D9A5E7285B3AE90F71FBB40FA39C5AACAE582211D9130B7D309AB3C34FC279AD6016C611F902AF959C984564BFA565891A5D1FE13C9D27181A512EE1CA31BCB55114C316BE427B01B6A519E441F66B926CE959A90A712DA1B81DCB0AE6D67749987B3E541A59D2680B11AF845234937B63065B32BFBBC1C9086C7DCA12E258C21E7AC52F812CE4A16E347C5CC115C2A16355F4745B810A4B5140CAE72248B554725D9C186523CF625013D5CA11B7951425CCC18E014EE5E94C2695BB469BD83646256DE038ADDF203E0B60B1F6"""), + xeh("C08584D2F5C950E371668A4FC8F527E20AF1532CC28EE6B5620729155B06389F") + ), + new EncapsulateTestCase( + xeh(""" +83B08010002CFAE6362BC02EA2C08809E5031C213F78795391E4390F4A4F7D8403B79458B792B3B2A0BA0EA82811912CEA1C2553B264C03992D28A29AFC0C50FCC0343DCA764457D7F1A73A975044752CFAE0101AA47A3B706594B403B5561A451013EDAD45B60E42905A97D2A0288510B66E9E75CCA8A6B2E5504A9380785DB36B21B5B1839111A543B18E3B41F30232E1BC816A1992A01C51C32CEEA8B4CDBD4C30CF792AAA5BFF2D54DA6B988FD8C14534B2D24334625A68CACF5897B495D55A873AAD557C29957DA2644714303CCC8744640C932B8307B8A08C2403A94E17387F4BDF786B38276756D95C0B9FC4E56C7AB925643A21A9BB7BC6AC58262DAAB33AD09348F7C569147359DCC794EA4673ED1ABDFB71EE199B31FE1CADD2579F94682FB013039B935A3167FF8460EB3006DC7EA297B643B150C5CE360BB197732B7F9198F4A7479EBB8CB97A22010618E22200E896C807C5056D78CE088A8478A751B95750A849D12677C6DCA08CDA502EF603FB5C67566338EB13114FD10622BF8B0212C70E92C68827999ED7177CEA44A7A055F12A00231F3C5FEC1BC07812EA902CAEE99B899B39E88FC7FF6973311483F2A9BAB7917A56D2CBB549AA887E545A7554910947CB9F09423C75EE63B626E8BAAA7A00890340DA33B7C2CB6052B5CC47CE65A0873CE9126816D8BCB6A1C8D39265BD1797F610244C565670DF05E58760690D52B6882A9A303582AA03ACB3B2D857CA0D7B8A2BF859860DB729D2740FD87AF798497D558042319638A33326E3C5CB0D3CD6E71A346365B308221A1DC2E49F51E818B22ACF66FA0C586958CA78204A1FAF135F17977ED2801C4591F2893A756A0C4988BCCB011B389D0656A717A069BBBF1F893A3BB64FF28B66BD2106FC23C2BAA2E4495580D08C896A92F2AF36CBB13CEF4AB94E4CC9D866459BF6CCCDCE7912B3119EEF0AD4CF5093CD85674679A298272EAD6B14F2950F18C602C52AB821234F655419B843C31491C47C596596967F1EB036550A941A03790874FD8498DAFDA127C8B0561116F9D414171778C7C36012DA9BC543158A00352A2E39D802CA5254FB4A43FF40242ACA967C85D45EE0F8E13DDD9951336DADD5E"""), + xeh("1D51A0CC52E85972001B77047D97DF5F47AE11FFC6C31B4AF42FB0791A3DB40F") + ), + new EncapsulateTestCase( + xeh(""" +28D9320FC6A5EC10059D3A531C364A99CA5A13CA98FCA773FE3B4EC6851E29EB8C0CC19440922CBF26859DAC0801FB0D0868B7C6C2917C51B7F644B4CE2C9C8AD9697D1102496B9B11B012105915C1A897065B05E6E7713740A391FC2B486249779864C74A1820F34C44063E47C87278C696DE5260270901190A5A618CAED0DB8B21D15C2D0552678833C1793070128DE0E43257413E99A1A58BC50323B0C722D69C36E82659410683CA4107C51D2D2126156C7357586EA553CD88CAC0E4530EA66B1FFBA700EF3A85259B5FABA131517CAAA0383028E125DC1670FF7C62D74775EC58A5B2B6074794225BAB8BEE7C14FE950AFDBC33B9A6CBE8492B3EC2BC16734EEADA20A45C07ADF81FE3401547F06603018BF5C4AD908AADCD9B5FA1D08244D922EE3AB1B3C693335AB64060369E328D31EBB3699BC3F390363610B2333A61BD67CB7DE4C6050C47D6D1402E7B997EC2C2E9B76AE5C77DF610A893183A1117747B3927BA7BB9B9ABB00E0B7E376C3310C3A63CBB03A2CC4BE1265CA35BC4D5C0CEB4187E9F686290472E9B0264B110C80F7A5D5C34678A746A5C4623CF8B54021A725F2C96E4923C2F531A7AC1405E275C44697A9C794625878F4CCB5D9DB9CF903C4F9DD180D0CB25D09AA389675A972223DBDA0435169C8652967C74C583223398F34E86D46DA0D026F5D661A4C4A85A85AD3DA358ACBA0B7E6C9C25D2CCB1A89B5D35A4F6516349CB1E983B793A04BC495311FF7433CFB8BE2722965308014D914014DA39322C0844F3C657804F9561274936B6556A639903808F8495F13C1138DBA65B573327490D8A772961B70B5C6CB4F8906B1B92639AE1AD25045CE5401AAE924491108B81044ED9E6B996A991AF83011B39021FB177FC8834A244B38C850C6FFCA4BD2323F896431FE64658B45299C280CF02894DFC03593135E172CF5B523734153E3CA24D160CCD64340AE6D021C21B8D5B98AEA0D9187F85AE1E5B0D9B06B1D1B12EC223B35FB2B07D81A42B11120A869C0B873831A41632CB0C1D819418647BBD92712920CFC2F24DC7871A194860105A6F0E10302C391E1DC2FA4BAA0C8576BC6E55F40A12DE2944202C00C192B497300E587946F1FACB"""), + xeh("BC2D661E6283B835BAEE160D1448957AC2366DCD087176E252F81F1D11E28781") + ), + new EncapsulateTestCase( + xeh(""" +70A72E79BA178F8951F762242A240036093906A0AC1F2501402779AC6315AE8A0BBDD47A8F347A7E8840269157C93A00CCE5A27CBB16AD9179798376BE8638FD97C976D3513F96B2F0542B78893644793185425864C7950E23102BBA9A4BC9B14F2B4981B673F8C55480FCB4B834490C9BCBCAC7566747A38777CAA5FCADFE9710D8627236E52D9B5463456586E4F963A7308040EA243E62A8EF87B418D92F95D41A57AC468ED5CD51A2B643D11E8F03AAB4F43F2C8160A89B5ACA63C7C9B59E2602458AB103AC58085EF7A98465884BF16A662342BAC721C1E59EBEBCB2CCB9A4FB8A3A650C52B612243D133F870613BF5A9F30095456247C34C779C899B6CD17A181903E0BD1A13AC73BD2848724F25EC2EC037852CD6A960E2A3509E982513FBA840D28BB3B732D76C5909B6612A6650548C709961368F8116236B6709AEC97F7C625094B93BE5B11E9217C8E845ACEF8ABE3742724969C74622C5CFA7776135CC2616B5079AE4535C39C1A3154866AD548C950052B88888761D846C6240C9B3BC0EECAA284ECC4499660DD2BC1B3959AB943612F35610EF1688C41105693061BF16D6E290BFD4941C0460FC173694538604CEC6774C9614EF16B08666ADD3916CFBB39B4BB75EFC166C7E8BF70AB8B872630AC554028E8C147BBB56D3BA312029A68300CC743B81BB35878B26892696F538334BB0A22DC91391D71CFDE723D9E813B2EB844B6A534280880C37B9421572A6B85AFB8AAAF5AF0BACEF356B7F32636B50B3336B7636ACD6C685ACB178AF9986BCB93BBF1C4C69AF1AB569B60B133A480D39B4BA319A6535CA92293D5082ABE76204C7420CEE02C1D372D0413B9F8368098104120D432CD184550667A976C9DDFE0916D423EA2221E64FA95B3F254F59359BE711087732B7D8336B99CB95C7BAC714742D0595BE953273E551D1122AF9B49495DD1B935255726A643D2F8A4EC9A6F573A97C8507FBE6754179A9439C33B0CA5BE3DBC9F19A18C3253A6830C6B69821C86E38A71CAB632E0A578F57A5377015FF43DEE85BF9C67591A1CCAF2C6917387C4B5193404C87AEED269310ABA894FCF51793DDA786F80CA209AE909B8147FAF316B06E4AD8C516BC83B"""), + xeh("6745F4F0730AE3F14A428A95C9CDFE82717EAA94F65B00A01566A4DCC9ED1E5E") + ), + new EncapsulateTestCase( + xeh(""" +5E101D0614A50B307E1AEABE717721690422A1A97C1D05713ED3B206D57919AAB32F6096A503C5C1C1BA332063489038FD1BC7F7B816F6F343274C19E01B1F9C088B311A0C8C09864BEA142BA2C829C5B74C988266BC9F12D37EEAD97FFD48AC5DF0C7C595A5626A23E20663E8F11A6BB66BEFF4A91D6C7CF551B34DD541D3DBA1F16BAB95312A60F9625DDC4FF1C6690E9B05FCC5CE05742D65D5915740AD9A7B60F9D098AA62A6DD3968DFAB5ED93A54E305596AC8B1E4967A5AAC15BB4B540C421571EA324FB422990C2B9B82A12915745C24BFF841731C6C07FE705CCC9B4C15EC42193472A4542ED5FC0B0CA98A91B7CDEF68A6E7ABBCD07B984795151D72365F31BFC76793FE485FDC663C6B7CC43F5A9D410BAAFFBA43CA968988337C9BF802CA221B3C366A22E66F703C695B178830473D7C372D338A4548E7C88A9C4837860419A2B60A3CA9AA19A21B570BD22CA228C019EC6420E77B340F32265BF86A666C9FFC75B64FAA22860B205DE33492B1720BE514BCD5A47496BDEC246D97ABC377430528940BA447579A90C9E18152F69BAD12CB7C51C48CAA8BAD1EEB2867F31691B32B75528056E56955BC4400A249550569C722410FA2573007BCD2B7331648AC9B424667582131473C2E8B11D1299DB6927384B257A81B6E7868AD00216C8548739EC83485CB330B03BE99DB38EDA338C6240828D7A5FF463B1C0C88092CBFEF3A2598993C72F922F2EBA31FEC317570B73DBC53C7F04810878FC9718552CA2C5B7220B6B7298886C94D9C8762A4BD05D8BDE7E9483850C0F75617686174D42CABA69B2968004992467D1CE078B03884F9E00B901473E7059195487C5E3BB0B938049A257C8046B92D129A906669BB1B92B1A83FAF951A9E8332A1833D665A720D0451801874036A7A5133318CA94015A63FEB52C40158644C3869F2E37BC18160C8ACA2381BB9B20B5A58961AF2E8593884ABB47A6D968A8C6BBB83CF089C6B75B6522C77B2B4064EFC50C2948A18C85B1436787C3A076547271F33B864D5CCC585B317193572428FEDD54B923973A11287B6527F68535DA629C904AFED0646115879DB4F48777D2CCDC3784E28834C7E503964FBD58C3652152D"""), + xeh("C3ED79224CB07A8D37DC9C789BC7AC8E278968E429087E5B2C0E878934DAA53F") + ), + new EncapsulateTestCase( + xeh(""" +F3007CA415887CB8294B07BEDD802012CAB18EAC1E58268C821BA9A63739E64AC4ECA1A1CFCC7E61E73E72214981ACC725B3040205134A998E3B0168F46901788054FB20C88EA08F8A96B1AA86CCF2D778E3363F4202CD8C655A14C13D8F954709F46FB78175DA1C839C612CC94984D33A40A2B3CE56C28302E9C849CB51F8C60B614924E21B374A381F473344847CA1E4C610A538645EBB7CF3E1894CB2AA2EF2884F1CBF7734426AA315BD52569E533D374A91EE6A8BF8E05393EBC1506BA0718C40465A7F24483D933926EBF49E9A65C56A1B25F1A122D03A14F150C62EF186EE39335DB1A99D2498F8C552F32568CF714C678943D74651AE345513A4B4D1460040831603874CB281CFF1F49A3FD43EC80724560136C07C3392D4B4493726AB25CC00585B1966B8E73246ABF05D78C43293670F18B02EC5D107A8518F014ABC1108B60B3781AAD6BB5152B228A5BAD5D81FBF0ABADFC1B89047C3EFFC77FA5ACF0FE88CFBD40A5270408F20601A981FA666B1FF9B6324A47D67DA9621F60042C593725A604CA25483714AEE23A38B01AE7EEC4BD2422D7231157533B819F554BB76BF26D9A2EFC10C758B584B1B663CB91023C1869E5283FE13144CC3149F6A2037D53008F720337A58534360765038AC222F97B9C7551004740A5F526597712504FB2B102906A35375943C011C8BC4B44323CBC690A5814A385CAAC581A8530CB201FDC902546C924E1A51B1154EA2D56C3D898394A722FB3B962102262B9A410B12AFDCE8250947BC13A88B40399E05B025A9770D6381206D895E2D319D6C2A237A26B06C7302B61C1288EBABCC439A2B8284B81407BE18674102AA5569A10461C8B1E550ABF41F5773C7EBC8B2E2B968EDD56800B9AD3D95057CCCBEF4CB143489C219A6570B9A4CE23B6044580F7AD2CD2597B8EB5300AFC63C4DA2A98E1C7ACB57C2D7A06E836781F5CB86BDB82AE4CB1577A0AE5540B4D23B8EB100B02966C440B68CAFF36801B99F38649D3D8A49DA61C719D196888481C798B76CB0BEC1AA037AE4271E04BE54075AA51569D700A95254A8CFF1874522935259AF76CC7555A056505D0ED973B075E185A37AE9EC366F52023FE381ED83FB42486B"""), + xeh("41C74E66327238C6F7B2ED2683FC5E88CC35083512BC285CCB7165499F34A0B8") + ), + new EncapsulateTestCase( + xeh(""" +A4F9A7CDCC7E700196FFF92085458D7D6855DCEBC5D98260E4C32C94DCAA47606619C6C02752333D30BCB0E82909D7657FF199668B8824C7B323A50D51203E97A944467930FEDC000C69496751C3C69A4FA4492CA6454665E56C9B677845D6CEF70A21DC7028C4D487629B9738C300D17995F839B59793A0A8813BF9012E0139BDD0EA31582BA31E070BC7F2B44FE57CF5F36CB9D92C6926B271C290CA44BC3068C2981C6CC7932A82E69C1AA9616D99C36CF37D8DE7642F2A0A615B6B85660224ECA4AA6B4779A20A2DC93BF31BB25582705B56B04FC1898CAB5FF97B6934158B4BD9994B4A1643F8A185483F93AB349536A29A3445250575CFE07122021AEB450DF71943E0818B664951137880AA5586C66260B835BAC540378374869084B8E3CC91B9C12248E2A75C060EFB6925C35A3DF34BB5A8E76B4FC4706DA00C2C0331502A3B4030A8CA25AC07EA139FB8B4733957784551208662250B542FFB6B6985A130C109FEF00E30D6C238FC0A10E567737B8776B94D3FEAC0FD9B055FEC78BBC4961015033CF78805872F1F9899F69492AF6A35180C8F8393071BF020F746506FA50E5AE7A675542610F883B24A103A32CC407933CC2160FBEB0375A514A2D405992BCC8FCB82F3799365D238E02C1886B9499CA2C90D8B33FF32AF51F5933F721FAD5CBF78EC78802C7DD06777DB8C0FA3C0CF09790F65630E772177D4D9A35718ADEA8758057601C249C92876799167604664BFAA93537572A6A1425BC0AC53C85AC64DD9A7BE436F110C3AA68BA0552994DC019F9AD80B2767B879C8B7D4664AFA6C937276AB40417AFDC2895FA756909864C4E1867A537B42E271C86953B16279843C88DB9385EFF67FCB8A6BA13025B259398F149B49E1A4A9271CD7C1B5F0C6BD7AEA36CC6739C2660E262A3189E9AD342215FB5A95DB2B179CA763A8AC500EF59A4A243F6E6C96C278426D472161C1069A31992ED9AF9B88275D21815F1584CE7381D487457CC15E04E13FB4B93F309588D238BA0B59867680585C043857516395BACC287491B0E65B1C175B41045F2B94202F888B103A6683BA958FFE411135C3552BD546F9E3AAECB8C783AB074E809056545A8F7B89E7BD8DF0"""), + xeh("6DB6A3F134471A89ABEC3384BB48A3C405DD3B2A5EF53821A3C1EA74DD562799") + ), + new EncapsulateTestCase( + xeh(""" +34166E98297165A69FE3818A3857B7D6E97180D938B8B56ADE8C361F010DA4E933F85A911214465BA7A0432AB99A519BDC81647CF72C4498A220C5B5CFD28566F4AE2CDB025E6270668153AE8B54C22BA5270A1DDB5660984A9812C32E6AF44385C494D55013814900FDC0CCECD7963D9945C4A7329FD5038F382181507D43A96402A973EF683499854D29BA964A530763A09DFCF4B97EF549E5A60C1EC921F8A2C9745B364316784AB27D96F8A9980727E5AB1FEC832DCD023D1774807BAB6D02E898EB0CCDC0EA26DCD16518089BAFE96AE395348481427788794D357B59E4421355656318B3984623C472A01C215CC13B74A3A154FBFC4DE4877ACE367B20397F6FD29E757354E6542A31E48E01B43EFED71BC6AA3540D3093E5794D889B74CF73C6096AD1CE46F4D5A912BB77C10C8CD2F92A6A952B7EE647D7E73C73185942CC331AABC3CAEAB4E0F86776DE4B5EC53B571B818B6F9BB31937EEBFA22C6E9B486E0CBC8658CF2537B6128C939A477E5376C59024440C56E853994FC588EE3D883B3A369D6CA24F228412140BEE37C11E8718831B24C91C46A54D09F75B99015A92AC7049697260652A4288E49A25F8C223709A035F36DAED2749DF387F6C53DB022535E729A10C8542D84B79AC5B44029BAAA360EAFC90CDCC754835A207378309045B7DAF6B8C5B6462A3B777150BA65C73B68F75089E79F1E820889A7705F4B6C7E404436F68DE4B50F0A082C0A8258E80B22646C29E7C732D9489AEFC11AC788593EA8C865970F83C3957829A818D1734DA277871493B45B93DBFBCDF0366C3635C0247358B1C7B8EF81B4B2EC8B4AFAC90E1983FB1C70121691E5913AC3B2689EB28773179E7225788FC319490393149A352EEC56732BB61B1C086CAC906D422D05917F3F1C6F3A57A7B61BAF9A852A8859B5B4F183B36715E578C63DFC347F86005FA11B407494AC4B19A7FABF59D10A34C58C6308768CF88BA463AE8BC243405277AC935D1C5238335B47066910917183444C79E959AAB64915C9609A5A12461F9125062C2536B73C5A5C1002269B0C023E7228AD1084918A247167D0CA5D87F83ED7B3EF523CA41BB22FA002ADD4DCDB3E7B68C892797481BC0B"""), + xeh("121DC782B740EAE666E709EA6E3CC6CEB8EAD204CD7D85D2256839E98CA57003") + ), + new EncapsulateTestCase( + xeh(""" +F3BACC6A8C9D390141981325C2DBA6EEF3805950199468661ED4BA300174FCE35411963B2B07599E14524446892603BC300AA3A25B45B41A857D50C06595B40B80159A477D8AD628F455038960BB23B0BC32D90D48E014BBF0AC12F93F17E36976A8BFD1E7B682212815A18B10B5301E0B88A7C17C850AAEC549B98195532C9323559591F9DA52703CA2EF921B1DA82D46A5B522F69109AC83351C46BBC375B61A8E7FEB0161423D5246362DBC8C866A899FE42F3C3C52EF82AF2CD05C11913B87E67B060A2200BB60D8B94E58C1B609DC9FE36A147B5C83CBFAB3C5F59F2032307E5745B7C68E324CA91EC987AF771D9D774B49E18E1F828E3D17641C51CFAAC9450D3A4404141187546AEA64939D94B884868876C86348E27DB0F66BD1A06ABD331B8999A446370982EB25979C35733791A49608D412500E9A144036970C086F15AC90F1699CA79928416858389908F1300356B9C382C94A2AD5491E86C51905BC398CA41FCBB05951A54A3681C806CC4868266E100EC2A334DDEAB98BCC5699E192AEE81DAB58C5C3D24C564C9821C7C0F981A500D91E66108C52013134B9440591AAC5A9BDC6208B22BA88F269B823DC08BD0C4067B7BDE01B5B12985CFA30C9172C9A2D95A33D4BC4EC181F17CA7A294989F0306FE2A7C7F16BCF301752BDE3CD3F2CB81460C0E3B0373EB8B79FD84B05A783E14454A2F2ABC693AF0AB78A0095A3695158A2B6783D32BFF25A4F6EBC4AB5010C0E394437D208ED001CB3B2C92A794607A6BC5EB580E7D52342B004B3A17E20FB70A4C5C2B8CB39C9E265E012C7D03540E7B47681409E30D169AE1277F1230D97B432E4276406D0C4FE52661E69ABD03472F2A56F52B51A5A317B57D229EE0898DE0CB2FEF71DFB71A85ADA97E93B9F2CE3113E838AB458A9FE826090369EA0F496DBB2A21D98981AC4410CF698CCBB6EC6724E498ACD1AF8C480A6AB1A67907D0492098015DB80A98FA8CFD79A74AFD439B4327C07A03C71AA7589D757CAD8BF86DCAC20B133A5511A47DC74B12317FB305098069DFE360250AB29A4239B1792352C3571978B708323BD2CCE72D18392A9C3CB7F504A14014231E9B4F65FEC62AD3125780D51E256CFE1"""), + xeh("307C7DF0692D264A8186B8D844C7287B236D0FC7EC148BCFBF261A16B0FB7B61") + ), + new EncapsulateTestCase( + xeh(""" +E3F49934F999E0884E019B9299EA5DED8B5374851D9BC24079FA481C534793D328BC3B3563D0922098B98AE26406BB81A48AC0D24102E1D3624F974FCE49786890AAF9EA2E9CC058133C66847B67EFD61C7B469DC8E983ACB6ACB98C25D2A84A6EA82DB780531D0A4FA3A84400C70DDB48CC52406CB3155EC059894A4C01902129D1614C3BC25372C730CDD6CA8B204B9D18793ECA8B080881119549779A67FD456520B1011C6609CD4329C1832F7ABA7997D79B9510409C920E8EBA32A476B72061CE58A8A0A8B369315A814982A519E88E8FB25B3C74B527776C671C7B48C3C9EEB76F2A60BB39D5722A71459B180BCA9A9FBA14B3AB764E5F931DA0A55FB247A93ABB8509334050A029CB7145D4141990929A7D224FDC905419D62828625E316778E1517B151CAFB1B8B8E5E96958447944E266F808017C7CCAED571C64D9BA153709C303C92DC69B808941A8C3C760E52EC7388E800159CBF8626F953E356A827AB8692FE1982F07884FE3B094ACC0075128B3D54D85C39C08D065B6E40B5475CE1F269A2227AD4B368C683A7E797A7857C26EBC1C5207E6113C8B17F1A77186549FB63617611C33CCF38102062094F12EFD292A7B0B98A1423B92DC318E919B3DF441E58A36C04C7E60B270A453707DE23958974EC3A455294168D1265EC6E606AC40C79B690E5829A0F72910A0F5031ED1A5AEF841C58A036A10025B419E0E2BB4C6782EC317786BC1CD538C18B7223345699D44860D0BA04413E70B7D5126D2237545E550893427E34C6FFA40200AFB5D527B80C4A3A32B42B49FF5043B14AAF6A69144D58388A254F7F05F1DDA51F980A3D5DA436540A67569042E6B42337A712FB65A208392016710B8FAA763321DAC533BD06219AC6C48B6929D54D7B6A4A46280D2B242A8C1BA5B2BB42487AB031558BAC899EC3188A1459DB434C5463DEB43BEA974C1167B83C657C93A9604114128256156EDFBC604000C05C84FDEFB2218203131F40483F9C3B06C0FD524129FD65D0AB55714052A24588184164AD4B5929668A5A6F26F9CF44BA946874A21827E5B68A71B21F20785308A3F8DD6EFE22012FA9F25E348661EA987E6455F85D1A368EF1789708DC7AA8E849A"""), + xeh("60363F5CDB16BC516A1367DFCE1B72926FB2189B88AA1DEBFD22F440B9CAF0C2") + ), + new EncapsulateTestCase( + xeh(""" +964B324032B0EA05C8042A49F702AE0FCB19257B1EB97079994A9C67043D99CB08708A2F64E694CCA51B71431DD20A77BAC80AE5A259EB99517020CC8CD53D525454A1B6052D4C598D9C504795835D9A45CB5CC7BC6313B857B1884067B0D97961108E57AB00DDD8AA5A69356093348948208947ABEFE117AD92C8562B5DB7DC037AE89C76D00C4315548372A272C32B30168620380CA0A697724913C173AE31AAB4B3B54F3760246A310F199027A72BACAB7046AA702710C145EB9A6F312B3B8FC291762BC301C900E7AB41D298A01D890AC3C85A40D0BE406000C6537BF9503E70986861D90B2EE3C8B0047E66B8B88CAB3AE9FAC382C23D06B835789BBB47A94823180859969535D058E7946C69438F89236AEEA110E404B51C1C22ED04CBB2EA32C957795797806F179A38642023E8AF6516A11393A0256A7EA3C27A8600A669FABB89E144E30A839D391E6C1A1F7F96A1E5FCCA889C8B09C3779B407075D97EE893AA4CAA1F5E5CCF3C5CC4DC361C8C80525BA81C05488012CB61D3EC87720A2CF0977BBA49B8F9D81D3EBB50FBFAA420E27AFABC387EDB87F114C1688830D4137BAAB10D1A6554179398B2D939C8F4387AF0007CEA2AFA9BC56E2766182B0C8D876123FB1A64C405CCD7A9869466B5825E23F41C4BD1747D5CC95C27912DA559535B195B96879F8C14F6030020278DBA6CA371C76F6FB7059F0B7E1EC67AD410B12F36878274C0B19A2F571A49A0358B945BBCAC5142F131C94E05C6A96C08DCA52819640431930D4089B2CA85A4FBA62F2B2614ADC7C4C80B06745320F837CFDBCB0A2885C321738C2B4233085A1B5F4AAAA658354078CCD008C496F0006AE08FE917BBE35433570B4C1838AB48593466D58F18A43A025355ADD4B333EB8146251E32FAAD8742BC847A7916212D5DC69329D0A3AE57147628928FD0B08752A21AC308515229EDC169FB6141FFAB3347F427ABC759C40C8D29448A273441A9C53654042967087F470024EC714B0708C033436995AC4FA678A9FCD724F703411454C04C21764C1B243146587C774897C6752BF79868846811106552C8AA574AD8DB7372836844DA6BABBFE62263107076C4CB48CB256D359D08F68375BC"""), + xeh("579474C123B3381801867203E0021E2B7F15E5F9426D75A3EDA6CBCAECECCF43") + ), + new EncapsulateTestCase( + xeh(""" +87EB24113349A40704B7243F2AE3653F24B87EF50E2220924BE06BC1E86E8AD9011768B255969F4F29C21BD38D6687756D795F07286B4EB04C30143C4F76810CD3233E630417F86EC751CAA87806CDD93EC0B5332758CDEC3A37B4F84878F89A4E687F0E457E45602517B676FC944E0BF9A9E9903EF895800D019304AC223E37623EE0C7DB798AA1A7452D298036A4197E89B0F279A385DC19D20BCED386352FE512A9EA90F973B6890964490538FD82A1748C98384C38C1434EECDB6EBF561366C228AD0086D142966BE1B8E1025097509E460850087935CF543A7309342424394267032A84358CD76E4F98C34B0005B39811233CC425A237AB49CDA9A884DEF6832B1A2031F5AF07DA4C23681B561C7D91A22C65129206187EFD2926016717F1F318EA95CC037208D2B313E0BBC59257710EE99F9B81187837861404CF4E930D0A4185CD3779CD4830CE2A02049AA0BBA0BF06003DF8A358CFA4CB2D3B7C7A508FEA1B930D1BA379E246B9BB793D1C2548F8BD908315BF521200261E42C843D963074CE4CBB3A5898976815CF3CB0DCC137F0CC414ECAA8883CDE897649E81BF707216FFF23B124B3FE6A39A45EA317BA5ACF8116E9825BE6AC518B4658D5D23CAFA600F94A9ACDDD38F303978BD64B4CDE34E73334C1B212060E29085925E6A3319EAF72097826F4233CEF2F4AB1BC9CD99B9338FF43BB9EAB9723140CCB86741C44E5D083CF6FC97D071CAB3135F6B358172468DAD6834FF3A1AD0750F06837EC25C6AA4F179D259A0FFBCB4E6756B627BC1F9F76DFCE2712F7340F6AB2109F023D6BAC5F0A6A63063BDA11625FD93B3E8C7315D387AABBCCF763237D785A89130A3DF63AB2F587D8AC4BC90B795C3639EF2352D0314AD638A532E625A78F296B5C5A38BE65995F8859F279795D0795433BDDACA847140650A72637DEB3529E8179CC056FF58C3FA094678526E12E791272BB623367D0103A68F6811B0636AE101090B2480EF8C6C59B51426E6A3E8C5303C3200EB783A9A133AD2E5261B5371FA338B6D016367650BE0D4A93BF3CD9C48629F8A448AD9AE86258F454BB2F60B1BCA578FE20B26DF0732C3222BD4B8A71A2F5038031BEF9EB0DFEFB2666C"""), + xeh("E2F0D46B6C4A43E94CF967EF2BAC7B68C6E0424A37DB52F2BC0C1695D1A66B67") + ), + new EncapsulateTestCase( + xeh(""" +FC93AF4B238968BC258C1CB5B94592501A51C3368DC9041A56DC5E5D230343380E287396E9B821270633DAD37C920182C82C9236FB28BA025DE94A8E552A605AF1393C988E08419BAB6C8709EBB41076192435699F1C48DC149D3F040A5A36ACC7C869FAA5AB3507B8B32A6847EC901DC8B9B19A04B70865955C4B3B01676DBA6B463C36397B2A42218BE0DA0B55E1A5ED8975C002A9520C114CB672DF5B3A7F838911F7869F148D51DA2584AA0C15F4C2A8C95653C95970D2BB4805928DC02D3DB050D6338A50B6C76332911E639DE912656B72619DC66790F491E0DB15C258C000650DE47268303BA52A49A9179A4DBECB45E7B47A74A35DAB781F52D27CCD2B6C75474474DA0374E25D21AC152E5AAB5225BC7EC5A16F5A1FEE930C300A8A15C090CEEA999D045D80CA73B5484C9E8823604AB464404F9A9609AE920ECDC688E17090CA6B7DF2108151E04BEB6A27F7EC8ABF95BF84D23CAA254A93F89DBBE133A6B1862A20B2B7241ED0695C31B17A7AF1A6A557BDB431A3D2DC06580A8DFB52C91592A80E3C1995E5B69D03AE3B8C13F37AC4852C888E077C290928420A4170A377F0A519DEE8789FB7BFE6A214C394038E281B56AC36B5474286A23142E14561D494AC2CCF95322919A34369B94D79BA787194A471F3A3271BAEFB4019FFC040C831447FDC9BC19B948A0710471A233F0B7104826A83B881CBF4764B1BB4441A843255A8445A034AD6972F4C66C906550C1C5E0D30B718C339618B3564456EFDD0AF36A14D7B705E62153F5C880F017740288545A6D51B13A671EE00970217BB3B33B69B56C823148A60499CFA960B06EACB3F9224275BC907D89E4722C1E35C425DB0ACE65B7929F66F82204AA2F0148BC0B7126B4EB13C4692EB3732E3B2559AB0B833AECF072C2060B1DAB6A9F8BACE386A098CB9B7B7447E6957B6219C6607B3CD83BB64A4B12C973C28DD7933A4B95AC3C7C59824A32E271007ABB369FB06FCC82B20D38BD436B54B155A5FC25381361D13B41D0C4B309E3A4C295C18B4F845573051C81B0E6E37A0D7869D23412F9CF55B3AF5121E491E45292535577EBB8EB2CFF39D783AE72D468F687BBFD838E6A61F5C5B95FF1F20379091"""), + xeh("7B34969C65DB28996B6F9C440DE09074CC98DB4F08BD43E4CD948EE4ECFDE8CA") + ), + new EncapsulateTestCase( + xeh(""" +894C58C872A67C630143FB29F5C2533614AC1ED6CA436463EFB38C7BF8A8DA348DAF4BBEF00A8E61E650CA9C6BCAD30CD330CC2D032ED7E42F41A9967C3AB568A0301A5A12EF70A2A6EA97B187691AEAC151029CBE350065B0C2239B67E303050D92A692237E21900BF2901A69231B14F04901ABA8D22A881365B943BA429AE31A72B8701CB07029E129B5D3BECF9090A70A5D3A86BE1BBABCBEF35592A7A74C2CC0560C0EC2ABA3095589C7DB2A5849CBCD483730F479ACD55B212C942F900407E46C0C584200C1CAD7D05C7DF467FD31C31E266A50C375689CAB1BE672774C77062018E74CA1BF6BC5F223802EF93CF7A1383F548196A9B4DE958C49014EDA8501BC8A56B2E1A2B0D46E18101D68816EFCE2297CAA5CC509399A0152232026B754A90FF104B9189426742C2FD8055191BC162B04A262C3D23B996C2AA867F3154521BB19E0A69647718FB76EA5B487C930A454943F0FECA6FE163F40557AAFB9785DA0B6450B0BB4095BA23AAFE83B731356B290DB64B4C39DEB5B30FEF38086E6841B660D41EA593E1C24028C60BC44A6D83696F88772425235A4F05A1847AFD5C84DEDC0B4C1D003F29AAC29710AEDA5053A4C0AF556C4F5508C45FB20141B1FB641AAA6EC6E88D0859553896C31A0206631750C954EE73B415CA163D30FBB75CFEB15714E3330AA346F7DE02014214C2EC5AE550906EC5632CF429BF3467FCB0327017703D08A7F3E9A7785D0C9D6377FAFE527259A0ED5894E2A8C766F688FE2574DF57108C81C60A8705DC7D102891437CB2B9988C879D7403967A83A70CA48D6F1B18A3408BAA13BAD9C26297CC10D920F0C53CAE4D85C6EE0C95DF22321F0A05894CB97C4A45F79CC002DA373AA857B65C726F54B03184934B11376852E9FF58099C72BBF531943EB5626C2C3EF6BCA145A2896B4C1BD29A353F49EC2FBB746134C1F50AE6D771160E64848396A5DA65EC32014F9669BB83AC52298B24DC2AB0BA2C82C0B4017B34F9D979D7D07659C4B76160999C47221DEE91521418948CB2EA72532E6A1C273B764D3160EA072A48782336B648C12B6AE93B5AFF289F81236AF0F9A338E8EC35154DB40386949D6E32A71D635053D5F55990C92"""), + xeh("4F7798D88974637071717FCAD2C0ED5333945D51341FBA4BF1962A3915D986DA") + ), + new EncapsulateTestCase( + xeh(""" +42803BF789094EEA7D875BC10D50C7D3947CB77CA48A301323B54FDBC94E480372E54AAB12C9680765A3E22988FF42184741A440E348C8D19EE8E7CF87B23CE6944663A4B28937160B0C25943A8742F811D0E417CABA034628A11FA2A06E3A5F51E47EC26A9AA5209582F73F1C705F9CAA74F1F300FE9049030061B9C61DB9999E1498BDC9250EBD324F61827463A6A5104796EFF25405AC687092B78248A2F9171E891729CFC11F86316AD6754E8AD249E7849958B2AB380783CC4123BBC087EDF1075BA8304E339F01242C15385A4007616D873587FCAA5AC786731447DB8C537F0CC64731A790E1BF23412AD9342F9654B87DB07E8EA506C534611F48A9453855CA669EC8AB548F648F8AA9A715D0BC09757A285320DC666637950A691AB8E2630A08B59258205BFCAB9DD37C94B9F4706A1114FCCB806E54751A12576063666252CE7F5041432C095CB469B5A1A634508CF1E2398716272E9570C1790FB53A3100D57B5EBCAECC6CCA50B4656F5219DF477C8AD4B7B727BC2BE25246C526D06B8DCC30423421667E554DB0ECC21837539F43A719CA8952A95B143745F79899F7D1C79BD546B6559B1109BF6D60275CBA5DBDCA608FE34CD96369D67B880CCB00F4B3CE6D3C6CD3A35DB44A6F8E440215B027E03109A6546662789B6A096784A0C64A1A4F07F981CFD201F3687691955184684E22C872400749A180CB5B6317599316790A7ECAB711861469EC794FC894AEDEDB90E45164413B82F18CB162769EB92A47630A98FDFCB09C94456E74C0FBE345ED88A43466860CF0472B6C9D4780AC4CC7189F77A19684C54789A9CB99CDD46534914B1990659E71F2662933148E13272E723C46B4809CB32A42D378DA7688F21CB53DA08AD3897ACBA940640089C73049B1E92C94C943D5EA32EAA19AE7EC072527912643ADCB591CC86B97696B98386615AABC1D32D23D4D22919E35786E77A4E7E30C2F6730DF129089943FFCC1678AA600AF4C3F40741867DAA06701A8DFE6421CD0A5DF34C32C933C9AC2B141C5134A7BBD469266D952AFF44995F8904A148B363E3C2A13978A049B968E24051FF6E312DF77FC5663502B0187A5588C1D84149B2DB835045F9BDC1F70"""), + xeh("E20AC1D70FA6A2C8A286EF0E3665C79668A5E6AE80197BBF13A0D0EF553ACF1F") + ), + new EncapsulateTestCase( + xeh(""" +39B893D833BC95E37373D2C71FCA4336AC84DFB6460F156174B7B95DA92351468EC97439F2B88656F9B0B944850F499415981A66B76333402D43EC30F511AFDE7623BC00A1C58136484350A15824AB0A434561CDA2305C815318D204CA0315C5C9703954224522E76DAB0716719A06F723006D66A2916941139B1F29E53783E6BCC568628D6B0A0E72A44D3C19BAF35FD6FAAA9B2396CABA9B3BEA5C901B836758671391304E5330448A62CBAB155811C5018064FA002A73A71EE6146458DAB896B716560649BB823BA9F73ABFE44E80E1C4D0D58E8C9B397A5841FF9C93CB8488851C482C534BB710B27C6C9CF7A15356427EE8F1B40815A9416B233F4A05065495D4B88BD2A42A36DAA392A9CE49D67F4017484368017FB91ECDC34488F463B99A6CE60359A7F3C32D3A3DFAB70817726B73BC1C36FA4CAC3A0EEC9C6BD3A63DF9957502076150C4759F5362BA493F71D669A724C79788532DA797445942FDD214C3A9103738C00AB54CDE3639497A951C03A70A0B01182B2B9C8C889052857A2A541EBBBB77C78F90377EADA6CF21796E44EC4D5BF03BBDE6773E571785F1847252B1D7182BB4B08B41C54C889072CA0922A56C19CAA890D7F899EA21C9186A3A7106458BDA086FE017640B77FF554FEA32A2C2297D82144EFFE20D7836180CE46FDBDC18D357B6FA7ABDDB2858770598C03169BFCAB9B8794BCC48B779E87672D83F62E04D2B42B7E31451273BA0362B682C955C382442C010005E66A2644550BF9390FB427E4839616AD8C8342ABB0944B3ACE932FC134BC6EC7C16D35427E22DBC4A454D9B09FB49AA496BAC88909F54CA88E1747E1081AEDB23BF370394D3492F5B6AB02C721FE3E0A199AAAEA03A91EA1C44FCB70BD4140912AAAEC9F779DCB4A8C0CA9D903C0FA15BB7E5335ECB3724CE621D602772255775EEF07ED060734E7365ACBAA557E25AEC10A27EF405E1A431AD8052E0B752A08346D1961134C77CE4FA356D66094856141EC05FD7385D009000DC6C4F97A91B074CA154773498F61C646951BA5B6B5D50C4E35C6206A6C33043308B474A7CF587C0F07578DB4D6FF52DC654A5BCD997296C79A97F8C16E5667F527DAA3ABEC018CF1671"""), + xeh("AC25F29AF8D8A2DBD359600C8A500144D6C0236D729DA016C3F116CBBF621002") + ), + new EncapsulateTestCase( + xeh(""" +0AF62D21757B6AF2C9853421D2D74E0DD86A416A228A9035299C27B32528CC526B371C56ECE17C93B7CBBDBAC84D35441E6B3A17811F3C0A6556825174AC3C2BA51D53F176F027C20FEC424F7539ED3C6C7B964260489C3D8BBA94323630B87E856064E3BA81D3F018516971DFA54AC903C9AD9747AD8C5DB35780A033C385C23CBCB21D26153F93626C41237A02185C41C3935B306FDF568F453B255072348D9716AE9CB9B9ECA6FB0B78DF7927D093A3BCCC7F7BA711B27CCDC0051BE4A31BF3A0B224E0770BFAAF26F599AD190173A4A012A52C29DB006CD37076A12CBA65B679C10455E5442D92609DF209F6556CA36BC852D3A282F14AF3EB2A852AA268B1AA92346631953204F4ABD9726338B8B275A26ECFB80428881613C952545B082AC2BC75699F3285AC10905A00449AE6A42B43D1A4890155A9080A587090F7C91FD97833E13B601EEA06104CA41C408EE73C055EB1CD9FB0934E25660381518758CF3A8C95BB0397931427FCBA515D320D423A7440459C614B9ACDB25A9C143A6F704541A339D9811409D6BE200429B33674F61CA6626C7FB879001AC65F08C18310A4BCE685C37944079DA907316060A64069F87CC5D9FB3B56604AD8A52E72A1405AF5C549498F147CCA4A7749A37B5D96084B01AA3241288BD22592AEEC778FAC1C4A2BBF6085C2B5DB7D9C00B9864C480D8826C2E02B246AA945EB61F9425DE8E604B7D76486418FF0F5AB59BC6EEBB4932D6075F667A6AFA74BB66255F03C6F15A63818E759A4B05F480A4C0CD1072E26627513BCB85474E89676501AB2ED21A8F487780CA8CB8560B27A766213092DCA0B02ED3A24C8351EAE88947A764F142C0E24B192A2421367265C0B37093E0A69AE31756C5906845A8C7D01550E07C72FBB18DEF56E1E8B320F688110C4C4DC7680C9FA05D5B1AB63EB65450283ED6A52F9F535FDEC31C207A483413725022A2256663E2657977660AE63CA8671A8C343AFEFA8C43D9B8D0B93B458416CA4C5B87D121469EA5B520ABC0C079546BC1353757AE2BB1D301974BA03C86F624F34A4B481B29036F59F37DC2D5C1721EFBE0A0C22A966C895E5198A91F916DE62C0FB3A769806AE5827AE6F358D8CD6"""), + xeh("7114A4B4195826CFF174FCB75336B25D4D1BF2224D585014CBADB0C4CFBF7729") + ), + new EncapsulateTestCase( + xeh(""" +F568158F1981259934435BC2BFD38A4A100BB9826E429312EA3CBF04A5397A723E740112859C74CA0C2783D5CC9798AB3C273D3AD6911FF76BF7235AEA38C4459761FD4262F483AC5D081900FC1EA3337439A3B4A2787E0D5763DDD2100E6A60DEC12B07B84FA8226017456B7F65679FFC31518C172F93895CFCB75FB74054116CA5662886BBCAD5F6B63534703E8B0DC807952EA32577389F94A7355DB079639AAF39B13D9F95CEF9AC9BC4B3AAB0F7070358644ED38C401A73BC2B2270D01D1C207D7FAA5233D74296302A90E4551D380C715265DD0B22F94681EE6093450186738B32BAA1B1FCC3C1F0A309312B662D25120F6B6D31B2B29809537C4A220D303DB4E5CE51B606DB64CA4B86947056015E8857220B8AE4822F28D31A37F63A89644C4E3A797FD7236A52640CDA3DA6D1782E933361A74B2CF665D04A07DC3843A40A0D8C526BE790721FBA16492557F51B6B6904998422B6848C93EA5043A782312C1250D81C5BD0407F5FFC99DF3993D91A71AD8499BDA29427E51BBC93AF43AB49E9062397F58CFD4B8048392AED850D95BB2F26DC55D3D8AA2A7249DFC35DD145569BA276ABA90B78BA143A876C3D97A66E02BDA3A34BD5DC4918F776E2E2C09E46047771B8C6FAB8C5215BE7514900A77567896899E94282E326D4848606FA8F2D350509B19251B4CA4B5B016C4181E8091D501327CCB9AFACD14C6FE4808E6802A8875FB786A52B70359845634BF1C185C887F1BC6FB8221347DB1DEB6C183C412C6D3684A3CC244D37C1C503B69DE67D4B02773DB8096DE18BC717CB3FD9CBA06A370EE84B9ED13597E6BC4CF88474E6956370C88078A56383799DF76621183C70D522DCB8BF07A9546D9CB9873997AFB51F94B49EDE924643900E201097D9853593F2A7E430AF5C57C754142AB462A12D327D04115540B505B8146BB64347A22BC71C02BD2E9C8CB360AAE5C9B173BC2E844CABA9659C2CC695D0019C135963987A5F019989B3064F8A0A8E4CAC8C7909AC4BC028C4AC4750E8C4FBC1433826AEFDDB2315002A27A2B43C539935649890B31710C56BCDDB64E7866BD07009CF11E676BD64E680645DFC88E803063DFE292C2047525EE37B4F3BF7AC"""), + xeh("C78E7B1E5EE8F20EF0B67089306E1ABAFD15760B2DD2D7A59D2C00D496FA0FE0") + ), + new EncapsulateTestCase( + xeh(""" +F9238B1B1744FCE415242CB135300B13831D95854E3CEB49E72074B4C09B64859AF81A0C078418C79150D0083B8F9834B14116AF308BC7194C92575119371AA9C74C83350519C0108FC18620453E4820810B5A89D42B5B84FC134F0741E4C0466B2C4B58758A3D561EEA095CB3F469C3A34F19A29F3D20C1381669A6AB1857D3859561096BD8B7A917B40D4B754AE5CDDA47002CD870867203D9901AC5B852EB778705360DF4D35DA7B217951CBD2C026A4AE15221368DA5635D17EA307EFABED74342A6C387D29B59868C4955F6A5B0786AF5CB03F130AC7420663E343BF00998D83B9BFD6458DD63A3B5045C467957A729417CC133FB2048B8DB71BE36905B213A1D8C1BEB76BD27A7CBE281C305F44769746F90307B01613080D50F96CB451D717EF5F372D488B6FDCB762927B910936F161764131C80F09316526CBE62EBB07DB7300D7A81890557000046FD7C098999994FB87691A59F437A7F6D3690075921E973805693AC1CCBC6637471B2C561437A8E30220BDA078435455FBC368DFAD026F85417A5DA96D8FB6272D06F785929B38529D5990DAE3C7596AA72B9381121C6C94A7A593A5AA62BE830BFC0BF5B34C57221AE288302559045F3686D8941576EB41F32516763A90553A5727697AAD39B46C5D84A2382980FE3AC0F904DD10C97078B197B0BC4CB8764F22943F584BFA9F3609D417D65B3C367DA544FAB84AD16025CBA7CE7794CB3ACA32F3042CBB4C25605998A74BC16F80B91C5635DABA3B8AA0D90B1B59CC042BEE19709A747666348577088DC4C5C3168CEFCC5C12C3B4A06C08CFE4CBE21359F03FB99E1C6CF8C84ABDADB1DA905C4EB605FB9C8CE7979458080AC594759CDD82A6E164A9EB781F4BB24147039CFC98889C077698B2471417504E99BE7F283B0929A35E14E3670291DD728599181A6911EA2912B48515F88689A73E9688957473B0CAEDE73937C7BC385D6B2FCF6B76017A8F23A2A7CB54E8A98004E0C97EBC826D1A1142D8162EBC9A311C325AAD94900D9B115276E91DCABA8D015D8A549F7F56A4B182CB3304FCFFB3232F64C2FCB839420663E9391828968D6FEA820C57B8816E1F5D3B414481523D24B81E1E2C429FFF401"""), + xeh("D23A22F6DE6C0F3C28F5A7A8E54581BDB312A56BC90CF3B22A5BB39C9ABF420E") + ), + new EncapsulateTestCase( + xeh(""" +305988FF211E278150CE00B65C2669A14830AAA1A4EF2973101443E2A73A1BDC2CFD5AB88C54539573A7A5FA705C573693599C850370CA4A66E853CC283CCA0D2B52084C054C420ABC71ACC2C10D34C61C9CB0459331511107832B0A3BDEC7A0CD941D15A13F193162477211F29345414987ADD22C0FE95AA734745FB32F1114081957017B479108F626EF004D08AA327F0274B1DC2AC9963D8F557BBB58A9E16B7613DB8E379679006119B2DCC441DA80F9AA7F0BC2A8456CB78713A13985625AAA3AA9C6375BA06395F66EC3B63D4EAB2524322979A9B9E1178C4A966FB808C75416338237B3165AB20135ACB0437ABCD96251218F0C382731C45C9FA8141943743C1B1F5D77A064FC7968CA1F26B2B756F0B623323A01D8B0E8DCCB714441D7D5647F6C4338477926B248FAFC997B77C4A2BA625A3A5AAAC60C7A57682DE39D91D46778790CC5B45738D7866F7A909FEB27F70C9C4445A534C0AAF7A487CA8499BA372D3380A13C87978D82677A37C5C7A4490B716CCA2BC262C8853CB60CFA571D2DFAC83D428A010C760FC291E390102E3B6384C35067886940336AF5751E8BA399D11CC9788228E1E21A61F69E2AF7409CABB70DA8C775AA217EACABA3B2BFC7D608B374A47A2C96F56C57748B5137F8093121C0150C1A61803D5C6B42CA439E81A8C9926084F5B98931B7079DD44E2C9376DE77626EB543DF071C7A2C630A995502535FE8570EF7C987675C70DF8525D495C5F93B0B5EC7CF59154CE08A84ECCA36FADA9962160A1C2CCD3A728B148CCC9DE733719387D6C166BD9691E3EA6B22550A85A09989A49C90D68A51F195561A4F424CBE3152652272200FD642DE292A2061065EE1B962964BA33281B9B88222B122A3247AB9C247A9A6342F5082A685C8C355A1F96A0277BB8A97979937C17A47A2C36B3040C6B437BFC28B8DECB59DD9AF1B6818C146B74B0AAFFDCCB710E6BB3AD5A5F6AB7F8B2C2AD8980D6B569A5DD523E20379A6005695033260ECB823C7579E610F00A30EF745811DE05762A874A1986764A399B5CB1212403F6E7184028C5B2C47BCBA1A6537F180F096BAD9FA53AA495443314B91B46600EC339B950E9C4F1B1AD5E92385E3F7CA"""), + xeh("C0A5ECA859643D0134F2231C8F3764044B7E6073C92C9CDF71BD64FBC59ADDB9") + ) + }; + + static EncapsulateTestCase[] encap768TestCases = new EncapsulateTestCase[] { + new EncapsulateTestCase( + xeh(""" +89D2CB65F94DCBFC890EFC7D0E5A7A38344D1641A3D0B024D50797A5F23C3A18B3101A1269069F43A842BACC098A8821271C673DB1BEB33034E4D7774D16635C7C2C3C2763453538BC1632E1851591A51642974E5928ABB8E55FE55612F9B141AFF015545394B2092E590970EC29A7B7E7AA1FB4493BF7CB731906C2A5CB49E6614859064E19B8FA26AF51C44B5E7535BFDAC072B646D3EA490D277F0D97CED47395FED91E8F2BCE0E3CA122C2025F74067AB928A822B35653A74F06757629AFB1A1CAF237100EA935E793C8F58A71B3D6AE2C8658B10150D4A38F572A0D49D28AE89451D338326FDB3B4350036C1081117740EDB86B12081C5C1223DBB5660D5B3CB3787D481849304C68BE875466F14EE5495C2BD795AE412D09002D65B8719B90CBA3603AC4958EA03CC138C86F7851593125334701B677F82F4952A4C93B5B4C134BB42A857FD15C650864A6AA94EB691C0B691BE4684C1F5B7490467FC01B1D1FDA4DDA35C4ECC231BC73A6FEF42C99D34EB82A4D014987B3E386910C62679A118F3C5BD9F467E4162042424357DB92EF484A4A1798C1257E870A30CB20AAA0335D83314FE0AA7E63A862648041A72A6321523220B1ACE9BB701B21AC1253CB812C15575A9085EABEADE73A4AE76E6A7B158A20586D78A5AC620A5C9ABCC9C043350A73656B0ABE822DA5E0BA76045FAD75401D7A3B703791B7E99261710F86B72421D240A347638377205A152C794130A4E047742B888303BDDC309116764DE7424CEBEA6DB65348AC537E01A9CC56EA667D5AA87AC9AAA4317D262C10143050B8D07A728CA633C13E468ABCEAD372C77B8ECF3B986B98C1E55860B2B4216766AD874C35ED7205068739230220B5A2317D102C598356F168ACBE80608DE4C9A710B8DD07078CD7C671058AF1B0B8304A314F7B29BE78A933C7B9294424954A1BF8BC745DE86198659E0E1225A910726074969C39A97C19240601A46E013DCDCB677A8CBD2C95A40629C256F24A328951DF57502AB30772CC7E5B850027C8551781CE4985BDACF6B865C104E8A4BC65C41694D456B7169E45AB3D7ACABEAFE23AD6A7B94D1979A2F4C1CAE7CD77D681D290B5D8E451BFDCCCF5310B9D12A88EC29B10255D5E17A192670AA9731C5CA67EC784C502781BE8527D6FC003C6701B3632284B40307A527C7620377FEB0B73F722C9E3CD4DEC64876B93AB5B7CFC4A657F852B659282864384F442B22E8A21109387B8B47585FC680D0BA45C7A8B1D7274BDA57845D100D0F42A3B74628773351FD7AC305B2497639BE90B3F4F71A6AA3561EECC6A691BB5CB3914D8634CA1E1AF543C049A8C6E868C51F0423BD2D5AE09B79E57C27F3FE3AE2B26A441BABFC6718CE8C05B4FE793B910B8FBCBBE7F1013242B40E0514D0BDC5C88BAC594C794CE5122FBF34896819147B928381587963B0B90034AA07A10BE176E01C80AD6A4B71B10AF4241400A2A4CBBC05961A15EC1474ED51A3CC6D35800679A462809CAA3AB4F7094CD6610B4A700CBA939E7EAC93E38C99755908727619ED76A34E53C4FA25BFC97008206697DD145E5B9188E5B014E941681E15FE3E132B8A3903474148BA28B987111C9BCB3989BBBC671C581B44A492845F288E62196E471FED3C39C1BBDDB0837D0D4706B0922C4"""), + xeh("2CE74AD291133518FE60C7DF5D251B9D82ADD48462FF505C6E547E949E6B6BF7") + ), + new EncapsulateTestCase( + xeh(""" +F5841D6AEA683FDBA16308BDAB828DDDD7735B8B7A0DAC6A57EB5134B91D8D6CBD989580411144E1FB5A6A559A7056376210A8284742D22A5881C5214C90023FC910D5D02A869087557900273BB875420B5717CD0B23064AA820CDF372F3E4778D70AEB5D02B6182C4D37110D782B6E80303332697B4C610A384A0C632C0D9484A1D3B5EA921525BEC5755C839DF942F24A027DB50B2D760066D10A117BC9A1B65C448CB9ACF3B4F644316E8941C449803F6851A74D832A739B2C0EA9258C7258E98BD3E833D879A6845EC4ECC44B6FA699388135F5E4830F2625E9FA5CC982C578B2593D350B06288A854D3349C24586D3AA2E68726A873B1E5AAA3B22671D8C69AEB180718CB456B942E4B6678E620A00BCA310C722DDD499EAD9C6B66666A3DE39A45D7AF0BBB7AB6A0BEAF8BBCBBA17B1D097ABB09A70E410352D2084423AC53ECBB4C196021F01E662A60C68B3BF48A5F0864A25577912F52620CE6347BD27FF68A17D4B92CD7D01B89E3487A5BC2859781F3EBB8B5B4C2D682636C486A000A576A4B63AFFC05082B5ABE3CC0B37B1E586C2107D97157E325A067BB86453414A15594A510DCFB2FE1A0074483120FB83440DB1B8C3B41E36364F92056083CB9CF91B39F28CF00F6AD098AA10FDB4B4D9B64ED1338E0D5B7A5169C3D8C0184B19966E54272F765C0337BBD307F8C97369A7A87DA44A5BF468DB8A9AA5EA598F885AB50174B0F9025A4EB53D2323D202A05265331FD836DF8E02B4595458551ABED8A3875B83BF976942372CB37296C813ACD2C27B41A5514B66AB25759009DB38A9D0473D5B7A9A7D6795F1188A079B1792A01141347AF2194CA681055D36E954C02D6935BBA7C2EF7F4B5E47C8B0A0069F29575E863967CE4C53105230472172FB79E69089D5A7BCAA95784BFA279EFE67DA145308BAAA1A5A303757946C2866B4841660A99C1968B8F7DE799ABD71806EB9F091397C1CC4171152A6AFC36BD733FC6C53545361AB6258CB45C9F1331BAEA85BE4558935984C081F73E4B377E0251CA7C396BBBB81D271BB9F0589E1BE3218B0B5840372253AA80A5DB79E11199C0832B2433880B68BD84FC02AA3CBBEC205EBBC7B050967B4DFB11E2FA63BCF6B7656A8028AB607CB084C21747ED573A055166F82215D7201D5D439A19F584F470B4272962C137B38545309547CEC25B09C96459AB7B4DA69C8D7B9277BBC4B5568813DA904141A011D9B45AC1F181273149F3C46F45CA9735221B97CB528E8AB59C5711A57C603F7A91803254E8CC4A37D84D1F6535E5A791A50145E1E073430810B3AB79DF4053538C7DB4826A1B428A84553BB881A23507385271B32F854706BB2D3E884E7B391985B39B7BA373071455187B3DD7DA75F6988BBD6BC39EF2808C245AEC9C024CA16546A16F63831A7B6797951A40894A5E38422F30B87E70355CCBE960B216592D0073F1240C21BB109AE76C9DE5B7835BC08AC6601C314A82232FA6F6896BD7834F0254BF112602022844F0CBA9FC3D2E3A58EDD56DDC498ADC9A03FCB43CA138640F85397FD5731F537D6BDC3AC76563D6516F1CF24F84B7C957635DEFBBB70071621C8B2585380A63660EF2CB6CA5910BAD42A1B621CAB8C26780D4251DFD1C6370EF12193C3CEF0223187A4557BC08F4ADD382"""), + xeh("76D04F481E68B2F901ECAB58B6369A2CC31A9DCCED82A1BBD426BE0AEE266AEE") + ), + new EncapsulateTestCase( + xeh(""" +92D1A81751C40C606885C737EFD2B599413311EAAC707939B37500699131A44535F21C5AE596741F7668525108B4B7AFBA814FAC8AB0063B6A9060CED936CC6DA2CE4131695A89C35F2BA2F39A27D3925775FA9F43486E4C95C165A666FC3305AF30B419611D291775E0F08F34A65EFA146E46D207533B908F744BD246A94A4A35137731D02AC43E779E262A66F668784B30B231D83E4369400248AF3EE28432821F07B5020725C8D769B305B3AFA685A42E28C4F0E35BF407549361A67D7B6699CA0F293CCB776019585759502792F8D76A3698872F817A0C621084E53695701795ABBE16C466017BCC02B518EA387103C59D17127B844350AE428929810559A08BC91C2A29DAC3D6C14DA0979DCB4210142C6CD5B7CF18CB77E2E13029C3C23D2089C295411560024AC2AF25B94FBC14796652CFD8A524B6ACB8D9A262B7C26A279BBA7D4995A92A5500E081864200BFB51D46686AE14130E3C5A728FBB76944BA658718FC041DFD3A2480B9B6658A9D595BC4CBDC105BE019E128909978240EA29DA7C66664E17183E0B44969B284DB06D4311751DA4ECC6CC75C06395D5B9537078D24E2091AA45A92D18378415F1183C6B4E7546A1A1792CC07384106A5D5C8B1A369D3D6A8C83B927B72C1FDC7CE27449A5228C85BB6B0CFA85954C0CE5A5BB947F68C8107C1FF3B7D3D4900FEE59206B4CCAC5A1B4E65465609692F76227EEC0721A59B92262DB0F735E391343DC5836BBA779D6A558F8BC0001388E8363E3CB63CE49C4C7669C82B2B650B4611D094707571065B943F2108BCA33747367AB953D9423AFC5609591BF49B8A99650E4D8010617CC58645080DC0A141C34DE1D69E5932032E7B1BAB0CB2A8BAC3506B7D5E713DA79CA4E177A6CB27A545C9A80B3A489941A47AF84F59F292E314302ACB8EF0006F50A539E319951F6CCEE9F478773A8B0AE73C14B729EF4C0B89A99B87F4C9B8BAC735D31BB833342BD501EF458F955496138A6D07D1777A9489A24C74A5799A70C942FC839D20A8C228F7453BC29C02BBA3B0827801143F67691EC3481F9609BF79D9A8B7A1A7A610B05856B5FC8C3521968ED9695A00D71FE8C390C60A59D6734C608B7AC0B4643F7BA1DFD05B5BD853C9432269A9555E3912E9B263C7B939384A1794A50F8688296869AADB4B853091A291E42F485A6F93547E03BC1B57A603C81B7897198DC59252F9805A6266435EB2A26B6300D22667A878C3401800E6612C026C4F0FF99C889531D637036126227B674B95A38A2A93497FF83C8D3143A5398BE9C59909800B02C677B27A42621C190D865AFAC05513F72758B494585435F2357B97342D951A2AB23A1CF8A229BE909487BB2B8F521B09E0C4849632BFCC821CE30025B837A455B2D7D58EE4B0AAE1A25F8A5693F62B1AB77C229890899264BF63189ABBCC80AD1B8ADFDB21B0C2481342A137FCAE8A64B1E21C805B187AB7C1B637D57FCD8811E49C1D2A065848A769B7F02D99E40F4BE3783DE3AE4FE97E23CA716AFC0814C935293641D7C40EA1088EE89C2A43505237A593565A05065081F6181F35C55338C427CA628727DAAF8F5B5322E34488904949E45C61BB915525676ED2659EFC97C6A53376478B629FB32D49047412A49E98F186564A36EEF1CA4920C912B1211B"""), + xeh("FD3C91294D8C974930B4B6135AB647D4A7885C83FCDCB30CBD38332E14094491") + ), + new EncapsulateTestCase( + xeh(""" +CB2468A0185567F8A60ADB33CA5239C11C4A3E0C031D385DCFA28C3AE2A9F71904BF379CB9E0BEDEAC82B2A537357A9C3AD33362602A1CF6458A745ABED9233A092B962BBA2B0A66DD4A85DAE11B0C28230AA44C40F2B68687B7D54833062CBB5B0233E25496D1C84204B2BAB06050C00C308EF53DD8345143BA810AAC477C8119B1C595D964B13F837849B58D8E1BCE56437F2ECA84B86C91173670E0995D9769642B0AB0BB0713D313AEB7C41C9B2CC411B3B62B110308D94F0DA1BB69D406DFE7286519692502BC83E15BD50494C1047980AC6043B18D7CB72EECB00EEDA515C97C0ED08B5D4BB001BBF08D9821B9A75C02666C357F00278279348462759A602359F5A953247C1928172A013E3C53B7E95B81A64A6DB3AA86CD7670CF7C38AF357A317B71671B950E2BB85EAA6138A5AD93A1640618BD98092D85D36015C0B0DFF6059F3B09AE5007F89AB551230D8B9A2BCA59238405372BAB7F4D8069FF7457EF3720A171C3A6312CC8D69191CA909A13946CF8577A96086893C0C59B026A21835543B8583A05F569977E072299BA580C179EA2976810AAAA93F57DE223B97CBB4CBE559E18139372EB1A2095B8B509AE2CEA5B4944335ED385B23B5EB7D0847A557AAAE89611937495C825B7236280ABB6D409CD513A03C91139A251B3278C929DB23BD815BF68007D50B8356C03BE88F86E410ABFF6CCB3B11BC5D41C7839D48F365AB4E9E29F0B0094A4C4ABBD6761527850286432530241968122D2BC877DF5781D17AE12095C177B69BE3B989E81CB539A2FF2E28D623303FED5750C58B9CE051A6B813899BB3C74D82B2F127E51030BCEB396EF547ED37ACAF1D46A77F7B2B24B48AD399B53FAA69C079FFEFCB9F8367F7C513D142C8392A8BE6089CC2301685460BCCB19BFD6AC821DD840A3DA30C3208668C7103EAB78C6520C1291239DF8217C25450B70302020A4BFF384F0619142A04C769C9B18D27E42FA30BCE60A1EC2AFB618752A3917EEDC37BD15C44D0ABA1FA3A40C23AA14C98E016A592B459BF4C13C07354A1DE0539445882E21B97B1767015810325086AE71CDC0B5C0D7287BBD99B381680BD6559B04FB84835C4419316FCD223B84D03816D86C738334FDC894BC81B1E26813A2159D426AB1FB70A88FFC1782E649BD860D148B33F7607083A5928F1C835F880DC9E3235EA51E78A403F7BA726D17951CB7AE7630AA7394A80D95A1EDB1059F140F3EBC8D1C9BA9F43B75ED90538CB219F8E4A2B202084E049473D57D987CAAD2B51DB009CF8A538F8205B0B4049F41ECB344F84C538CA49F5A8FF309D036C6C520932F08072F5678CA68568A41330D9BEB34BD308F963224F80B5DB9B10E54D146CFAB5AEF84A7F9C62B7BC24A26A578FCC51E36738BDCC8AD24410155AAB74D8691C1E699E3722481BA074EEC75DAFB723863C308F60E10D195617BCDB877153D9CAA775647A83B1DE113019CD6C3A7CA38554023A6BC7EEC594FA6C14DA8353737F0A549715E39C49FD9625F187C3BE1602B6BA178D1784B52690B1E1380847203C13624418C1C1DAA0B231AC0FB39293843CC3D6B48C32B15098748DB0B3672377407EB7441B82371B56EB3E90C983A895AF85D57E76C53088D944840CC309853814266D66DCE88915049579CC45CD602"""), + xeh("7DB18CA35A53AB3A65E4C17FA096DDECB19FC7747E657B49D1C1710DBD1D197B") + ), + new EncapsulateTestCase( + xeh(""" +0F613B04128F82A73867D9185891C29D6C3E1381843BD502D86099A740BAD5BAC68C590510CA3F6F2B5463B264BED34952F10C784A92AB7696268410F1F28C06DA7A18416A7B1B5FD23393C33592248C9A8B3956A999483E000F2A2C6F796052FBB22F7F182A191602FD93AC066355B71B7E6BE36E531B1D34F0382E34A4CF623B7B1127519A7BC4EA3FB0D1C91626A417B6129DECAFF2865273F759B4DA1A95F79FAD0CAB09FB61D34B9AD78B8046F5601FB53D28951AB73842B8921B2FF10417DB4F9964A41EE820FBA83D61D30D0EF2C2CBCB1F6CCB9E77523DCCBC37ADB8B9E31A0F0E1C4192911060E8677140690EC671A5445F42FB1A68DB4D1678BF9B60129D98A859837599ABA0DF465DAE76972946C73E8343A19A3C03657806574F59D2611163334FDB0EE8B0C13C679C6D175C22807C86F0C199C89CC43C0DBE6587F0A36199143EAE30116B3B0D49839AA18CA49E2992740B5DBF1C91ADA352D39AB7D0C23FCCFC41E783CA0A333FFE00074E72BC834669931630898B718CD5304E253071E730F1EB067F94861DD98FD9A262FAC919FE870E3D21BCFBF67180C57A5D2797F6C7B96F544CDF92C3FA8B49EB366C02885140D128B88225750733E6105868AC48A468002F35C34C38AD70A7BEC9C37713B98D9EA8A716CBC85D0C3EF5B4BF8F20BC6BBC61CE8150B4F842CEE0A40E0A7FBADB76BE9B5CF2B39749F51BEED8400822044E2CB01C021B0D9B7FE67A8AFF9B227C120F643B85152B40EC4A1734E2A141159A5A96C8B74115A0C92E6B913464994E980A8A304194A595BAB892801C15CBC5033FFAE70F368A62C65A598773C199E20EC07B73B1ACAAF48CC963A6986D9A3D2D236352F66065025751B9884D7CBE3A5538A9B90372D4C22797659B5CA8D357CF00B27C5714344374A5131B261D948DE22390D0521F50553E78223388903CCF241FD608CB4FC1AC7C44A2D3141F0B998B99E704ABEA1E634C1F44231D347254DC2CCDDC114AC4488A549BC4696400F0BABA18198F46E8CE43C93581FB661C745AB5A5520D4450982569BA1B192FEACF37EA8EC8B8B267271A042022DFA177A7C1CC1CF6765492AEC59729D6F61690F27B5D010F22C30E44D15864395BF01771158BCC5F8B48F656CE5D9049D6F1C11CDA96F8C724E0460BDAAA1DD9CCAF0C46162B943461B729AF3543BC9A8CE3B34971B39DD25A6051D41A248BBCD5555D7E2028A5B453FC4062DAB1337B134009C71BDDD705C2E44C64E15C18F26361D8A7A2F7A13D3C31CB3147ED777024B8A90B558812B47AC861BE5B894B989200BEDB242E559801C164003C6EFA61AC34649993F782CCA150DEE1443892BA3DB87B094C491C798B5FA1AA30491B7C7CC3769476D28AA17E754773390316647CF33076CC6CA84C804B26E75295D2A4754B505A3831DC793ABD874C6C1451911B97AD39825EA42D65DA63C42CCE1EFB1397167F1E8933399C2E288AA57E000406A4C66B5A357AC59036F37A52516701B52934C6A1109593809C0F72170A0EC9AD22EA6DA64B0028680B405924287280A8C49B2D516DC9D6B93D42A9B544C6833C0340865905EB00F4661B200686A0A47FE280937BB00F8022B8F0E64AC251BB62D09FBAB3E7C79CCD450EECA94120B05A0B071588E2150EDA6B14150F"""), + xeh("876B17263B409171B746C6936EC65FC94137F958DC974BF98110A1D07F6D95F9") + ), + new EncapsulateTestCase( + xeh(""" +C9CB9FD04057EB96006455C062E3C0722346ADB366DA0AB980C782C417B360EB1C1F6762EBF967D713A0D93A28CF9206E95451E91373805047D8A14FFD2041B4468B26C79B697A14EA75A33876BB865096C0289C1AC4B91A4399821349DC66496DF02B15CA433FD97D96F46F72E0B23EB561E809601C053A35F4171A963EC3F542B423BAFC56134B7C0C5927C746E6C8055B3B70B31CAD6A168DD78F63C64FE3044280297C6630562C48A822B570E3FA8A76995BEFE67734274337F14FE00C723AF55D596BBD0B2C04E5AC6D52A0AEDB04B2BF09B1F9736E9456C40D5976B1EC2CA21C28AC761E39C583CDF256AA3262C3264250B1C19B00849FA83BCB6614DA0BB19752AE9BCB7BD16A71017066F73804AEB3C7F9213BE4634401A7AAE7BC56E603516FA2839A791EA89C58052030DB4AA2887737D9BC9AD21ABB94246546892785CBBBFBD45102C24D2F2370BE91923E732892E599D3154502E878CCB990CE8383D2F5ABF021BA424008D07685B8B54C6A6550D9CCBD93066A5A651A9B2710D25B382E72CC57096900E16B7B9868A06909F441104860BF03134316382F64D4CDDB596C57866E0776C04F8C0F67F2286B7242477059EBE022BDA200B6271AF875A829FC368E1574F4F3C56BB39D7FF61131F014FC59870FE45466D968C109339F0CCC67F6A7092372CB977C75998EBECB68A46059D7146A2EEAADDB258FCDD404D6E95E5400C8432535EFD635AEE5235D3B8ABA4153B46C7D234AA94DDB66B229456C41B2FBF93F39AA048C158E50C312FD623DC1E818A494980A34C41568942C30373E430DD5250D0CC27D4AAB2AAFB13CD719ABC7F466B702A983318B8D0C3040DC56B0960291F30EA75986917A17BFB76BC4B4AA8EA396F127A41F73219DD06F27126A5F06519E328B5CEA9D67AC122B092FC3613D99F403DB86CCDD760BF8398C1AD6BE4B5474C34864F2B10D97E265FEDB464E01CB3A426A3BD8B3457267317B7649D62D4847C3AADB7036391CE068758BF1847B96C5F3A69BD36A9468F9CAB27476456B4EB510BB063C46D529758C6680B4588CE4F5CD9D225BF700B27F53C13D49808D561F0413315C01989B1582755CC4CC765391AA68A0617F39B843526081658532C2C0025CF378B31411E867C978109454818916F8052336CFC9788F87E53236DAB54112B876042FE9054D9C07B80F7B43AA900BD2580F386058CFF5624A9A062474990C2C126E22BFB300C452306B859201B3C67B7356CC7DCC36CAD7A7BFC44DA0591D8CC45BC7765E405A2F2373996A72433F332CF77A5C9F3146DE121447264A84339A652960109044B1FC707680AF70E457B41259A1B84C37892C1079B8F08204F218CE85796701B05BEE5961F55584FDD3BBAFF25F53F78D0B48266EFC4991E090EEB28799C002CFE902D1222EDB8A026813295E604921269D0E0A1F4CC70F4E528A092B4E15300EB67808ED20995EF3A80CB999553456DEFA4769791FE24C934DDB490AF61FE1FC0027FB10AD260A7C33BCFBF212D3B50568844FB022B7DAC9509B308A0040C9B5482D89EB41A655B7C193C01BF96E5CF8A08B4C1C344336FF53CE9F79009FAA3A3921807D9B4C25739C38568584367F5D882E4AFD33697EB22AD03D369E37C0FE3B981047BED55E0BC0999976E4A36C"""), + xeh("E0AAD46FDDE0B8E64361C3233263D8A751F5583DBE91AAA6E69E6318FC7A8EE0") + ), + new EncapsulateTestCase( + xeh(""" +B7F522438A05310B12921A8ABE79B4887CB548317B23A21A4213A0F940BC3268464343C89540B83155C980698C657251CE30C75073C3D3C73AD9902ED10C32CB101B0537827F338A94D9615154370165B9D22707693C5E0657BF890A1C5E820899087683D176986162156ABA109CADB1729A0B0A057C8007E4A6AE7E272C860190ED4CBC126082C1992B9F541FF68A419226A666F6A9439CC82B3424C3515ED1821DA501449B84B1D6C169B9F336AFC9109F4B0AA6A069D5C46095B40EC7C886C1B2BA060CC8C0A1B2FBB53FC102701FF33BE42C92FC8287EB311CBE4BB5D523420850B9D962158D14188C4A794E4C0A8A065757EA0C9A65429F114A983B4D55743FBEE267ACA76C14B1492E2CA839AA5B4762868FF2123A30B76D858B0EE4CEB0B9ABD3A2711BA5167B73226C3B96C184A1681A562F07365D686E17F10EB75545F4E0C52CA6BF41627B8D6A19787A3676159EF334A3F4C538E50484F97CBAA334C5B800A34C642D097549D8AAA6E6E16261E038CDDB816CE46BA2B8B821445209E5AB1CF71B008965FBF3A2673B5074943D2102092DF603F2989F32085B96CCB2BA245A7AAAC06C763640D11730E828A0BA3129A43F6F0825A682886D8CCD9E84B93999474B63CC8D272911D72729E79E2A494AF5EA20C1CA8434323164709090382644B11F0F6C806A5044098BB936F5CECB28A81AB516A1857B651B93CBABB6E3D76B7F79AAF6B503762A10ED8499347771F221C2A96A90049C73E6E1132AF53A88D38EA817CEFA29848FCC0AAD125CA1C829F03896CBA635DAA33ACE7C7EBD18CD7AE03A0F9A3659090F5F9976D600B451BB6C1F3281D6C2884522618AE20CD583AB9B32344B6A2C294B0684E6BAB686A39431292F70748AD02AACB57CC3153CA6862D2B15108EE71FD51C2B7F81ABCA9367D4619964EC7C63EC653FD1374EE3A9BF22C4819264C2A750DEC193D5CC836430B18C535D3E573F4574104D471D972361A6955E2E10AF34D95B4A123218667685B1AC6D696053966F3C56297B844657C85402A357649A82E4579B667A36734B665583AB026699D2F6B8F4F1BB25186858543B61260BD3CCBBA264A30135088C0422ADB4508A60485AAB3C63ECC9AF981A1C5913950CB8949B5179E48C7240CD6C858E1144C7EE92A885008209A055C1C3795FA3C49A98082CA077CE4A75B0021108454D3B0C9F01C00CB29166281A24BCA77ABB471A036C9DB1B8946B930BBE8615CBE4AEF6608DEC389BC75C443753C56F5A62FB6C532BD13D89506C4C5985307A53B2403B42265B35B1CFFD6B2CB443A359D75587B2947C7076EB2A2B5BFCA8B1CBA865674C1A2C1A5EB4917BFB9707590434ACADADC92CC7739933323924B17FB516974714A42E38BFB7F20E752AC6464503170C860FD91ABFAA4C6B70CCBB8A2FE3EA91C94B26D5C64CDEE57F936C1AC10704D473AE10479D798BCD6026BACF4C599DC104D70439B0E2A32C91A5D58010ABA9984A34689E360C7B296486A4C681405EC3FB92B44210D5D3CF52534095859E42BC9BCA7B3864D43CB9F46E685C0BEE8853FBD31285DC2EDF129635C70437B612955B7E56A128DEA321298662F4F96A8E1ABE81B54DA4292AFD5FE45E31E16B17919D9EBF8E87B38D48053AA9F6F41C5B55AB86C4E0BEE558"""), + xeh("90347D478D5D964D66A54BE930FD9F7FD3C2AE1492DAC35A6CBDD02616BCE14A") + ), + new EncapsulateTestCase( + xeh(""" +AF98338A682D431CA0E17775EB170E3742ABEA300D6A46C567C364DE8939831695C59BB7686729C9001E25A85FE926CC6E584E2BC86D3B25BC9D6ABB97EB7F15AC23656B3185CBAFE0C39FA0789DF0678FBF5A43E6E0C53EC38076572D9D84B1ABE742E2F6C0C8CB08CDCACD23B71D57D06708F32D50870D9D636DF1DC01A8378A211A134BB255DDDC0B62C75812AB1677C50DF56B1FF62024FD722D3E732F56A2C6EA10CC31F280ABC8347788CB291AC5A1820525B9A33A7089DD689962A046B652AD182639278279EB884163E2B115A29A3899CB0EDB4514A0836BFB8A51D834C1939B8DC108B6138FB88B9199DCA5F7F64AFF36B9296613F891265778C7963C3E702B81C54834469AC8B59920BEE7878F01052B77B0F54B6DC61AA3DE695D20786F7D309C3B16A8D2C90A921CC317E91C015AC80DB106D4810EBBF2C5A1530506AB1E28B7A32BF67A6981185F98B44CABCF6706B134B5537DC697D16AC003808119B0BF94C84BF569422C8BCFF834237B902D83BC4C16F5CDFBBA5CDAF0A69FC87DDC885DD3AAA852342C1EB8179756087C678EAE2878A777655FC19719593FF600789ACC6322018791874D33D9284EA512AF1231D4CC87F1BA6F6293A653036E590A892F101CC518110C984AC55C2931C976828283F0266609A45A8C7CBF8C23CA0279B133A38F9DC797D5E58011096D45441F11DC59AB5B66846A87059314FDC64E8CF50040B57432A18F46078AF5A6132B006856604CE009128FC5445BCB6891E91A8677060F39A2CAAA183FB8A0F6751051AB85474A539A4183A4486471418FDBEBCF40055AC46075C3B2190248A8202431DB828B82E1320DBA47A23A94DE5CC378B48FF4B633E2D666B561827F8013429956D3F5947FBB848B3A511452870D00BE30610D0ACC418F8536686ABF66851707D89FCBF65959BA3062F6A16E268488D04BE4E370C4247947FA823B27133ADA76DB58CF3ED1109CE433CA0042CDB809AA1B5D5E9C4258C6067B0004A905786473A0CA4B3E9D90443891A148407A8D89121379A1F37C70770586365A74FFE5C6FF170791681E5CE10BB88BC0BCCA82CFC81424AA5BDA072D1BB5BC62F6687A05A949C2B04005284FBA8ED0646A394658A5868304C42C05605E9292801630129C76A1FC083DC3696DC4E904BB1916BA2287DC37232AE2C962108F245C3A0B702F53271F6BB00363D88690A7BF37B345ACEB5426F34BCD7670ACF15955401A20F938A4407E00D8008C147DA00C080A226F71F15DD8DA20D0C6AFEE431B6B2733513BC877F5545753305E8C03FAEA935C183BFC1C40561B59FE80956CE2C5BD3C28F2248249E2A0527891B3B64BF0EB89938A42008C32D668054E508871012FE8653473FB70CAFA0A8F1A509948A2A967CECFC7B5DAE34E166086433C5977208C45D97B24238E875A790C2779974B4721F573C03C4D20777F1C4589227765E8E7AFD0D59EDDDC722CC6230356B477C490234CAF858893F0E446727CC88E1411242344DAC6AE6C2CC1D2B1AF2B8C32BCFB253013411F18693ACAB9A7A86CA5590964D39A8A50768718BD948566A2822206226020165965F7B68871AAFD3474FA306A2DC31A98C60FD2E5AAA8A0B72BDD2F70D6D5DEDE7D679758D8A325B6CF11E7922902ACD92A3A8CB43863CE98"""), + xeh("119BC36B5F856C0A2F136B3EE42041B817125A600E829FF6B4B402131A26ABF1") + ), + new EncapsulateTestCase( + xeh(""" +463B553102898CA297E0C205F3C9582273ACFBDB13BEC53341BBB6724C774C741ABB16B2F992C878114FAF67C248603D8AD5842E7230E59B7537119B204AA8B2E0830CA3511886AC5280242A9A817D9A8C7EC8B95DE23254174D1F507129BAA49CAC9C6800CD1039BA2F6625584B8F3AB27657E6B7BA2A58080591D572C7E0B5ABCBA3BABF0525736ACA427A1F13245426C08DCAC5752891169B1A8373B4BEA8A49DAC3B8163E78E74195E8AB54007534133C02AD1930DD3CB066E7114DBF4CC9545C3616B1895469A1E08A57273B235874AEEB32EA3433DBE8732B871B4D0E3192ADC30AC002E4B82798E0C9AF004973F5749456605B897C5AA9938C38343B3690160615B3406AFC6FA20D04AA0214B9C224AC7E64A6E85F38AAC01632A501A6CA1A4D3E0ABAE384AA2A50911E8BFE945792C9283F9A898A1CB2E2934550E3CC52E9BB4C2EC125F64C28B0B12E0805A031824F423B7CFD9A11086523F1305E4C130C17161AFF366472875645BC8A1B14DBB104494C746F84B4599C07FF4E74A3A1408CC983CC2C6CC34BA04333659C1F960E06B73257C5EAD5B3406D70C3DCA05B9EB1E0EAA89EFF046B58471FB7268BDB6402174BF03F92D4D22C7F204A35AC6551455603D8382CA3AC726C1BA3ECB5D4244BC62F10989B4B9851C4346DBCDB959516CC260CE2599EB1232CFD65FDF39AE7EB0763AE47A359367A7720D02B07A5A634DBDF74F4AD589EE2691BB4862D06B6836F70BA8C582F3A7996BD7BECB998CB1AB1564C812AD04920B9121139817E8F06172B217481C379E2C368C0A12194195A03177A822C76B0C7C79AB700FD5C24EFB24BF29139F4930E6515E7A1880D971644ACA12E4278AD22CB96370AE09614D96CC0328265F27E2B2D60465C8A370736632257B191B72185DA1A2E6FAA6759580C6E51E6290B76944C2A8743610424DCAB89CC9B79AFEC512DF9CC5B4807B0C93A889F872D1D8950CB4B371335718035709F36710647157141E6F596FF677B132352D3C35389903375999B2A0D460CF16A581C3CE5A057DF42051A7BA167D6647BD683290ABBEB3E67277C055C5E70674555B98D365442BB8D2859FE47C1309178537E78DA79B7016890C94864328CACF327746D0E32D65D9C7C0574FA5BA9E1FBBA72D990C62E1AD74759BAD3B7F9759B334B10EC8A1AC3D8453783A621C898C99945195928445D21B6F40215724919C3959D77731C2ECB171489AF6F545C7055D55778CADD250DF49913A7769D14774D87940D9C0C53969BB2AA151E063CF78CC541EF643AD7C916B961983983F886C7D7B6A016391C6B9C64E95A03FD1F65B6C924B2353678D3079676C25E236745955CE5A9500BDE96A1287B6A795B3382B438E64C588878CE447530D174B53641416E328E428BBC347AAD32342C0F17D1EA15FBE147E3D0009C1CA0C0E5A437F1708A602026F0252BBEA8B7C70445A456678E0777994C021F61A8C689DCDA40BB196512C8C53FC3B0EC26B3E2474419AD79EBFA58087AC8987BC15C802028ADBCFB37722B0999F6EF71629AC2966FAB95A5A2D3F74300FE668F9D912F8815561C53E1BD24455E58FF3F7BFBC2207D7966B1414CD0D695C5BABA93618A89F32CF29B33FE97EE961F5DF14FDCCD0E81878F6C76D5651730F6456DB0938BF"""), + xeh("697CC7445AE2C9ECCA2569B7871F0BBB364E63E4B782F734FAFED4FE33E4AF14") + ), + new EncapsulateTestCase( + xeh(""" +0387B2D669850AD9379CA70B3EF1BBFD487214F08616824787C4506C83740BE76CBE452CF99369CA80674D3B22D3E04FF95093BD00369BDC5C8126133C5A15B8A99A912132B19C275489B7914858E806CF4CB10D3FF33E018CA8776A88FA30C8782179D289132E0CA4A1BB19463571BE1977109C2BBE4C9433D6986AF12E7079C4B5783390C95C8468545F48A5D669CC0567CDBAC54420DAB1DA63456C692678105E08A822D0F99584D7A8BC76CD9038C2768663FA11A8D8E7B86BA52DD21B323EC22AC2E7B921216282233039546803D509FFB12BA2FB7D3FD38F4B06B848233BC90C2ED68AC41FF24C6425C6C9321A7B697BA5588B434B1B5A49CBB9FC479BE68257498A05865A7A0217B8319E7BB8B55C15967319CC510147BE9BA5511A967CAA2102C6A41298C0F7620E626693E976318E6A7635536B2CAC9DDDFA58E2382401AC778D145774494D2F476F43E0C3AEE004D360C4A65571BA02C7DA13002661B4838B22B9378F34579F46653A30A88BB501B325956B0B5A261174360F128850908B5A3CCDB5B611CAA26773368B13330C48C6667BB351A2AAACEC4B2A2C70601513CC3A18B5B1DC421C5A056D1645FE9312507AA1D52929AC289F6D75269BA42061D556243B34C638A72DEAB939B496435951C53B22095906C68B1299A288D5F5CCB8762E76477C5A0611EB468ADA9073C79B09E80621CA9C4D69A7146A812133B9637F074586A5BFF4AAB6CD0140B43A1B6E2ABEE7AC50489B9E5270A93541CE03B72C00A26E274A7CD3793334CC04E9285FDA673E0241BB9C9A34AB7935508739E52A29F22CBB9664251C6068FD3842C80B17A0C1772F285525B22C65AC1DCD520217DB5715381C9A663DB0E512B9F9711537BEF235313DC46B758839321341E95348A75972A7FB1DBFB183910A442E985628843B93505534C63C8D8A5358B61D7353C2D174AA1416677172ABC66725E7317ECC83BFF257819790C9F9C506DBFC647DB27BD9747673F666D1239845744BE742BB27067BEC53437D48A528F3221D60C3E1EB00D87045D050BEBCC2B433F2BB2962B0E2E70FF0CC52A5BA7412E39194AA226872184108C4FBC459090C59E4A27FA4823ED8B3CD3C59C2CC6A81D3017A08234206C3854EB3B75BA441AB8C321C55CC8574A04DF42E201180846982333A92D057C61140874A9A80A46037DC2A3CECD534E9EC39943BB300B1772510B7E8186C2D5B6555584F54E39A2AB6473806B9C9E71ACDC8C15E43A885A4C9B42763766C49DDDB890C8C7B22159DC91865D0E79AB10372A9F45963C59D8C1857CB654B2BDAC0AF0A24A663C71B744DAD1AB68A90462BD79F6BA55376125562A5B1326AABA7C19E593B7D0CC1C8711B8CFE3547A00ACCE1646E766BC03767CF5BFBAD8F08590E2165C7706544DB5A942925070A878D13418D31CED35092F19C197DC2A517967E41898796A51AF8911A1857244C085045677865B125573CA5E24231251243682C6DCEE524088572D2015D9A25691F2532E75907C107323731591BB061D525757540338BE19913323D08A4082239363CE4741C92AA29F8CAF146AF1D277A76BB22CD54663914647532AEFDA02406099A75A63F7F2CA5BEFC74A6724896CAB84D12376744CCB1C6ECB1DCABFD20AAEB88BDBD04AA5A7E2C867B"""), + xeh("52CEBDECF06579F4A9351F77CA95B5CEDD034D812F3FB7FB50320CA80E4118D5") + ), + new EncapsulateTestCase( + xeh(""" +82DCBC98650A04861DDF15380C8644C6B93F197A5B10702CB944439BF7AAFF090C49E8CA58DC507E5643C17A4D2912BACFB76454D45FD6EACD191910B472463C49B76684777BFA71BC18973677256F649FA6041A6158046F75268E7CB72E8A974EB2CC7DF1B8AB45B0C651BF3D99211C071D55B9443E6A4A65B976962300E5F7325A228A61727D8733C0B3012CC51C2332FC5BEDB05962B771A232B55B4BCB41AC4D85FC6BE5380ECD3259CDE1B809D8B6E67978213798A828540ADB86124B6F137CBEDC4B64E7CCACF78031211A300A79C59508A60A73ABF93580AA64A7E661C282F5C00AD8784B002F5AC79EC4AC85E0290FA861B9D8B30D9E56CB934C6F4CD5C033C7AF7FB55F20C5A11574B3A460C7A3D73376E6CA77AB911CA118C963B97AB675ACAAC6BB73B0080BB5E0261F79E40C0FCA9129A9C118EA705B0BC7A2B45FF06CC15214A807D3521026BFF008024E951AA0752BFEC022CCF92A519B8D1CA910809B63CFA57C341490BC673243B7CC3E2A6AEA2BAD2B885E39738E3973011A67B266C438F2C2C1F63B251558947C00741939278055ACB8569F91110D895B97DC07BACF1389EED1271051CBF6A7B633A47848FB57BEF485993C5462E3B5548B96CD161D58510794CA60951A2A046C8743807619861D37A420DBE94633877134A92180C05B14E10615783C7B32B135428E59311BAAA32FE37A7C35C4390D1185F2931BAD539F08A02198D6450DC55BFEF625E3E209EEF2A7F38074DC681126CBBEE6AA3C974BA8D7ACCBA719292CFA33E4D5094F527BE94AA2231A762CC0970C7C81793471295B9B2A58810952A63B6589B29953C942CE49C87FB7B49B400210FF645C88179FD76BA408DA81C7464E76FCC3329589AA99855564329D8914E34A7B0D02685A92817C28B2B3F8A7A7615BBD569F2DAC20E161077EF46C6FB926ACF3C94DCC9A4B0A27641370B4027AB082896E188BC5CA32BDE911C5D865C87A22207AC35B72B0B8FB342E3A53BF735796F3C8930417CA84CEBDA48FC1E34AF9610F88C18523A4037E3540757162875CB5F82B1718B32EE70A39E5B216220AB3148CB1CCD118CE213F2D5680EBF865AB018631C88FDB6C763C082F59C6CD95156595E22FB0DAACB56341B7645027845813A59DF203104D9C8B1F647BD3537937F59030979463BB63F7C9B69E57CA17491F3618CDD162A9FE1C3F9B326F567C26D1AC6050685FC68A93CF59178BB87EC8D8B703519E60A22702BB5FBCF3BCD6D496B79B65415C175C554298572AAE35437BF899ADAA5C4F513E9F220553093BEBF1769743C6AB0B9FB64703C6305CC64B84CD76B7C8E61429781A822990B698852A3B583AF48C3B22092C513A223110589941D530C8B4CA25CB4361F2001B166C85CF910F006C5B0B71A109AC5986F8264BA26563E69D122644B6348818145CC026B783D917E74C4F46E0C9BF86250F521C21B64D50E910D1F1CAEF4B05F5A50491E9CAC2F3B5CE36407D9937D0E28E47B52AC460103F272642093CC9EB18BAD44AD36B8EEC367F155159ADBA0251F195E52032F1B0514BE83F8DEBCBBFDB5755267E76B028BD07CB8327CD431A7B73D289247210EC905A0529234B2C62C7A66338C1D381C88466B4832204B1B05CD1BF8E0A4693D941A178F62E9E09B74CAD5B"""), + xeh("161889F2E92B1BB28A257B45D179FB76847B664E6D7B5FD9698204A426EE96EC") + ), + new EncapsulateTestCase( + xeh(""" +FC964FC0820E5DE7A73BC507469B013F2C81A225C8C067C4A9351467847DC4D38FF3237A9A38A8F7C273B08B260C5A9B20F8493A668459E0BCAC480E0BB50BC62941720283F758B7AB13B444E8A1F8366FB247C3CC339D413671ACDA6354220B9CA0515881A688063FA87487356C842324B35B064B5847A75509AFF086086CAB80DE6C7218D95877313B0663031E867610107F1491A9F069A2DAA4A88F26CD6CB97B43B51FB7156A47550434421024CC360500AA7595BBBA99116057A64A98C76D61082ABC47BBC2614D2B23EEF8A68D1065ABBCC057B2717DBA5D6B82BEC6683551F082C85C3C430580D7125D1EBB1EA410748D6835C5BA080D1140F9574A4460752C5278E5F24DA829235DEACBFC3663FF71421F3B4C3F073764D11C39C9AB6B6B2F1F24A7CC84AA73A976721AA7BBEC515D0A0613D06F80FA461A032A274911B82CCB9B9A4AC86C3555D37A267C54137B141A043E9C861C58D6A88F5A47B895ADDCA736D11CB227D190481B4FDF680943539437B04BA202B21B19C06BC8037B93681E2121E7A49DB8271422834CA4253F5B96AB7E723FDC599B8BF0567C176BC7C754B6402642921ADB8C30CB8329A1E3CCFFC8A501A077E34495D9333B897C41F9E2A11151902A9B19AEE16BD4038DCFA6118192CC3B09523BD89C0DD158B87276A6316DA118785551B9E1078C22949D6D5302EE5945F87C5A8EBB6220B673B8B7AE6499C993633E844BA8A14CCBDFA931D1145BBC260EC933CA2B8B861F505A9691CEB2B5716CDB1E07DC6ECA0693CE0B8BBEACB59F705814F2C46B336C65240BA7791B10226D3892AC60D11F67F29283ECBCB459CADF6867F41847A99A2E0469A417078AD80B1BB35549FEA2164B8B557B5610C64C810E211DB697ADC43034DE45BF407729B9F8CCBE3379D471367DE881E6EC741A4130C78A90FF24C7C3899129038851069BC68B9EB533354AAB155F829F6AEC9EC9D82B20B4927EECC243F014EC846D59D5C8F3517F96873511967408128A1705B834F81C4F1169EA500A66EB21682A09CE44CE4C9541FD506A6AF12CA3634733E4661681871717A560685794685DA121565671B50FE866B0A565B0A9728A97C6AEC4442C498C54D77184C44D919083921204334CB058FC5EA4765C0478104770B743A5093E842C013769F16B02A46083872C58D3D678DCE87A3799381DF117D0F357998C853606692ECC1F087C0883CA575D9159BE882045E60DDBA38ED3BC8660121FB8EB2D6049A5843A2D2A53BD529881799487B30438B4A585B2E77768E87D060C0D676283431A55BA9C129F036751835299D78CD2D85748C246F8915927B1C9A1194BAC1A103B5A1BB69370C685B15AA264C436683ABA9F4A03C49DACC5A1D3CD5C133599EB16006850BAC4108239144CE682B7301EB220A363032FB608137786898375366B002719580EC7F7733BB2C3DE27974FEB56C72AA61252A2D63CB63D380F1FE3142439AD1151B543591AB0915B514B3E97EBA17CCAA73FF0A3459393BAE20B1D8A8961C0615B180DECE602335A11F7617EBCE0A3A0B3AD1A78A3C8C682976388851285D83BA9E358AF22A14039CA015FE1B42F8A3EB454578504153817455045166F24D6DF0071E884AF76ECBBFA430FC31D1F77405F4B404B538725F561884EDA"""), + xeh("3349557DA70FF69886ED032A91D8FC23BE9E5245406670679A6E92AED870D369") + ), + new EncapsulateTestCase( + xeh(""" +ECEC377523150E39B8E5A4B85F8237A685630EA7A3443A9249D4B90E1BA3438CB095AB5555706EACB3A61D5143029856C7E80B0D9156BDE63AB4632605F6009450B1CFB6B81A58A43687C4DB56BF087A75DF047237E9A9B79408A8369CA3AA1731A7190FF3C11A7699E3F83A1F655B3E2C252D732BEED0703A642BA3500859AC70C51C3DE886C26BAA47EB221074F97FB74957F9C61A02405D2E2B95FE198C2AA24AB3D649A3B6803C3636C03B3E199AC07D103960577738CC833CD42CFF97C55FB4BC577B70D1A8642ABB77A1530ED0F1405B2245347256C0D47005A634C9237420574130F607BE82CD00D81E15562AB8461F681159737ABDA7441F7871AE7B28401A6BAB14412A5BE5A4BDA22A46425B8B51964A673278B873C4F61DD8CC5A7DD3B89E11652C677E052643A32139AB971B5B0061D600440495B96AA3113725640F6A91DA0B4B651630EED446BE53C6C6365BDD2BA0F757CEFE05C1231B666404199937736E6A5FB3466BC4590767C2BFB2041DCF254886466288BB45F8E91BBA876B9C093BE2616BB3D2B516526495E74BD19B1E9C36543697ACDA981687111FD05A1B9F2255E8809152138B983790EFE836DD7A68A8A150513699969015BD65B05D364FBC851E11B506C607BE0CD116910C94A3E3258AD263683462F5826B85B4BB1DD2917B4034AD25210AC26F2355B05681015C9A2BF622BD28431CF2868ED213124F124C7C6797C34952870CCEA4970AF909BE10A57BC7AC37A536B7DE2A8B0C4459A6223B4EB781C2462ED3AA135015754BE56F2B501AFE68022C81C16D40726B8C77B0845209FC4B77B64FF08609C0567390F4C9A8187A15C719FC5C9C01433CA77809D3F9195D8BAA94B24CFD909D6374B8DCD2355D1723400AB552F264C938B4E1E8033BE2A0B6FBA03729B38FA39F285AC01A136C07D10DEF390BEA5688C41B155D81174662AE48766D1791C60F1606BDF9177D995D9167B755908A68E7A7CEE4AF53A42EDB486C8D119FED00BFA643ABEB12666E2CC2295B8336122E7D9601F4DA405B7666EA276A172026264C23863665E2C21FF72A6CE4186016D88F167A358889AC1F8B028CB4622CF07474181BBA6BC5D331088B88A1C185B28B90CBDDD54D88D4A911DB638EF236D6D06EE968B8E5FC11F2D9AEF14A3248EC921FF0ACA4BB1369F7B5B3991ED6B16C3A918FD9397BA4E454FD209567D97C8BFB47558B6AC7726D6C83768E0A64B034C0EB36C8BFB0BB86C52B51FB7DE503C390B97B00A4534206B267C42333B4C05BC90C7FD25609548B2E7087E792BA21E360038A6218872F94035E5F13149CB440B302A591817EB0E229AFF03CE9005535978F930622DD422722C059E0BB855143053F348B23D5ABBD49B7DE9478EBB63380E75F9054922AB65F4E897D02F9AF641CC6A34957B91A7969A1270E4264451053267137ECAB8C8C8B9B76354A63E1ADFDCA087E54A67F8A2DE4AC6A636348017C6203B4A27322167C2ACC85F63335E8AE4D1909DD1C3DD228C0E3B84470446EDDE572F7924DD409764FD98F43A20E5AC15AE9202BC1AB58BADB3D06B6B77E81ADF763836398BBC45433015B6523652751B8292AC51230440C112C6317A66F24C4BF927C7EB8C186C9DA10E1BC25A4DF1CCA9B6C3407955972448DEBDB284B"""), + xeh("6F1694589DFFCE022DC4DF1852FA49A41C6E8AB9F7887E70DDAEF4232B045DFE") + ), + new EncapsulateTestCase( + xeh(""" +48E11D1B0572F2892B8F81A8BE330B16C7353B5C319A34874F959409E6A41A71585BF36AEB651869AA87D400C6AF32B7F8270BB9D5C53BC3B600F493904AB000149FAFA1B090B544EA0101EE940EFE878DD64739CBD78D317A09A45775B2AB9E0383C75D049083BA64019658B4F44573C1B7C0B3A59495606D9162438B1A0A000C3AA5834AD5BBD11893598052E5B543E209215E41B8D49C4107F5658F7685CE53459F21452AC66F0D2398B6971A5A23A056444947220E95454A404C7213686E58A42E346CC0C44759504B2FA07198D742B1BE01A66C2BC64498CBCF6482DAC99DE7DA703EC1441D08C4A701BF84FC956B11411AD610146C59DA6454A8B3B742D91DE3C09A5317A9DADC23ED0A922AF339C090060B869B55FB3AA1C603C40868337687EBB27E37B804EA834D4D0084B21307DB0A64F69B7B49B5B0D237AC428ABDFACC01D1012A04008CFDD336A06B9728A036B6C60430A8CE887C4B006AA7E7C54834E2934F8400D030AA63E61FEE96C22FD49685A7C3DC2287EC2964CAC78B40340200C3AA6C8A67BDD30FB7605F0205CC0CA043A4574235B342FCE51195873F7FD99077CB31229B91D5923B67D391B457198125B7F198BC7CE58FD6B96BC35CC3D0281957B4110A011262B1C4CC0445722CB5E8C102408593CE6445C4584E373AC890187986A49414643CCB2861742466939C347CF021D1C19D36398A82C64D1FBA4C44B56CF384C04A1944449258700A66B1E2C9185A5E8B17772538B33B038B877353DC251952DBB899F04A6C677247D4CF4E4A5D2B22313A33A6D49237E7C04C61B2B0026531583C6CF6332C4C7853B7A8C6A4A5783D1B79FC5725F9C7157600747C0203E313CE91976CE44CC4E0D67DFA830448999357F076F2D41EE6FBA68C53C9AE5C025DF867E3060F3CF164218142D6C2B5B526BCE6789DBCBC5765846565575AB154C545FC3A81AB8FA1353B703B72B011A0405588FC0B8C20D13ACE9A93F6B28EA1C05CC686CB0AE722662A9ED902AE87D48B8A9667CBC0BD75742CEF313F1649C42C760796C979369736CFF05516A72BA36849D2E213AA497A6E7774EB9A896AF0A13387ADE8F594DEB482D9FB9E4C740360B5089CD101E5450C837C8214247243417C05ACB9D319809D33168E707BD1168709F7829B584053B554D95557DC032683D885AB406E205B6F495C23EB673E05651ED9DCB87C4967987B7B78EB349F4AABD35C7242079FB30607ED82A0503173A1B785CC36A2181892114003E2D33D17AA3B0A5CA47974B8F1C93B35107DA3900A87792433F154C643B34519941CC60710F07A71E4AE09A7539E72B9235A07D5DB53C048493B4AC8B9F0A3696892A0164DCE38B7F8E711506A9220A5C6C61AC2EF3942D3984907E59DC703ADBD93B6B509A156CC34B226188778BD191402DC94124CC7981151934F68733D131540056466437CE2B31C1320362AE5247C35CDA6E13E5D9BB89D0C8DCFB16BE8BC355A0C0C54E7ABAC12621ADB1EAF82B3D1E915315A3B7F3C98F6CC117BC3C850258059737171478E3AAA7FE5D7B5CD218CB428153C07AF80667C096C96656C85B8B0BD1F606A7CEA963717A18AE642E9E8A853D938C66651EE31034CAEC7DA6097A3C35BA420022324EC00CF53B53E9EBADC6FEB57C9B5BF5F53DA"""), + xeh("D8EF97421196B1A91448B2BA7E2B4D4B035B91DD85AE4E57E8FE3F0B0D524AE7") + ), + new EncapsulateTestCase( + xeh(""" +AE742E0C4761E7731F98A96F57374EB4E321E1D33E3133C031355AFA974E82F50E7EB36084471D94490150188B34A113E300B2CB65BB44E6940124BFE3E21FBB4B01A7640817567949286922A22A8EF654D8465CA39722AE9A4D0054906F52C79428716971ABA0703C2A3C497DF73D0D0C8AF3BC36D12C80AC2701D8C4689E05645B2017B7EC830F8CC3C3419B1B14AA890B2A8B274C5316185B26473456A196D8C836352B437A4EB0E924E9D5776B528DE1BB433B7C703F302EDE284C9B22A6A502A7FD6B17AB5546B52C86DE883C80F74A9A7302E7270B73C521FCC51EB7E02BCC68CB257A1FD6EA63C195610AB8A8AEF2486E18AA081056B5F474FEBCBAA48560325C06DDBCB79EFA10589A62D9D54268062CC8E3693373066E57C876558FF3180C632269E77A96F305175F3A2F9833BDA9C43BAF62500C202D0DBA91B28CC6473703960785C8711604C9CC04A98BD19904189A6D62A159E6A83F25907EDCF457A080C70627C6F5B0612AE84D4317261BE728B786A111B74478044B7CF192DC6490475C9AE1E5C0FF97B812E0094A63AD818C5BE5304AE8981B52867912787114A14088261CF0747732548EE105927DB086088B89DA4773F3C4CCA0E44431D98A8EAB89C1D6C1D26109EA32CE99473E509B9D478614D26B06387B89D64C6785A50DB4C78FEB65786550647EA30C9029884DD34FC9227596B091E91766F8389A82B01623D7721F2069911128C309602F047F44825EF6A12BEDC72880AA3BB91504904276E3E9583228A7896570676B8DA28723EE17553A156AD5884AF0E1066E518D19951F98079F2244009369157E1915B4FC99254C4691D4A64A0AB0129BB235B00552C5B606220E45683341086F2DB3ACC16C8DB563259C6C8E6A360B9CBA54D048335E455FB406415D147122903325B341727C76ECD2C16D33188055534196C071F6B6806B9E057B5597158E036C3CA90174A83B965F8C3CA7562A3A24AE99298A10791D38FA3E5F30B5CE3A8438E6708A156FD51C055EFB5C65759D76B1BEBC231896095F213148AF839B4DEAA03C9628D0C943B0F14770A9A223FA3CF05C7EA983BB64501885A919678001E9219AEBFA71E5D3CB5BE585E7B939194C87C1EBA5BD56A953645D28C21F0E45686C9AC96F820A3AC26F69F705EC920392601E55FC1ED2B9BDC3C6BA00179F9DC687C2C01C29EC05D8BC5A3145C1F936CB8B20CB2015233E01184AE68BB0F96728C27521118466A5CE602CC4419881DEA62381D7870C14209B6A874FBB498472B3420A3A2A4203938863C7610DF73325B5C12EA5D2CEC78610F7237C4453536D7180EE7425C9DA6C43604DC6A074E2B203A0FC6B44679879AC2D94427746041809D84820379D14168BB0E816FD241598195CA1C447C2EA5D5B455A28E66527088E24163C6DE46D36DC1753CAB7451A6ACF09ABBAA1223E7A3B07E801F84071A7A3ADE760C7A2A12F4D12734530538D2179EA204ADD3A40222467649B4245942E80B50EFAF60B83E4591951101D025B05CC1EEFEA996BF1C015A6CDC9325EACBC349592B881CB3C3DA8C096127953F0B9697561DCDA6BA3D566FF3C14BF718ADFA47877A12E390A6CD0544D9524AFA37069C8ABA24F918FDD15986F9B1C6471A5C7A495588F79B71FCDBD7376406E5DC064"""), + xeh("132E7CDAB9CD5199FF0937C266D50BC50BE764AD027DE45C858E3C2F79B7F07A") + ), + new EncapsulateTestCase( + xeh(""" +11A62A8896CFDF943396BB8F58D9CE2C8A4DD07ABB736CA309614224E13CBC2A4EECE6A9E134B65625BF7332A0B978921F4B9B689736C7A90CD77120FB33124BC272EE9B656952980077BA0A2108AA34355C391118E2ADB2A1A6A61498DA2B3E7A6B3477890A6EB74CA66161979B1C44D10ECA94CC26C93B43E42FC68A93B85AAF0F9381DF309291E2160CA19615031576D1448AE4A36DB5A7EFA99542DA5F633C4A75470F9369AFF4D20FD2D96B62348745A46C81053A17FCA3FB927871E88E996C3555B696CDCB7639E13E1148397F4845364A7CCD245DB28577C678B061555A8F97C7DC4C861201C69106CA2F375E94B597BBB09067F4C730606D2AF3B6FDB98C14CA1A339B3D23174AB19C0849836C33720C9A04821F59B929D72421D7583E9919531327B296BD2325B5CB172FB7E620647091A99A053E20907588950E303237FA68F57B1A305233B6E931F22AB46769C4690420A94C3C234B564DEB3052C4ADB3B08A1F455E2B1B8132E6232E42CE33904146AB6FFB693158AC411DB0C49CA3990498BBBEC8BB06812A31E67761FC26AA861E328906D5B873CD2A8C92778260BC84B50703EAC6BB10432BC0115AF9FB60C8F02D90D6A2CFF80A69FC0E23A3068868A7A522CF96876FD1170BC8552E45EB65656740CF2AB106A553CC61112B659E6862346F64359FC6B58FAA70386B955DE918C5B641F9EAA2BE559A5BEBC40E113BB6B63058A80C1FE1664A81873BE506F8A795D9A8B4318342FEAA2A28C7ABAF1C624D5A8DCA352906D037B883AF54295328180EEB06C910A0B7945A14371C885EAC006E24B6A8F95936763B54C89BEB2379DE061AD5D0A65D8398310A5B8844A81F2C8C77E71F974BB0297ABB1C02442385621D607BD3138E063AC36D728ADE7AA6A90BBA32DC2FEC1498F3D68DA3290C17618E35DBC43262B009357CF6F79B04004316E82076961DE4B47F2E5229A9008D4CE902D9F26E5011A4B044AB0FDC668DBB6813479ECA3B0B18E028B1622A9F6B899420899FC7246CA86C00E7C4E1434365067544D02C44C840EF34CDEA6C3063BB64F18B05EE379A18F125514A6A94A95AAD315A55F0ACC567BBD0705B0AF70643F318A7C70EEE059F52C7A67353C89AB55BB091705F3059C93B7EFB305C7716A86F1363E977827C57713622236A365014B87E030BCCB3696F42E6365201CDDB5778951736BD92A4D78BBF3AC4939D3772C0D58F3F895DFD124AEF4B6C454140C002568AC4298062C1C755B99B5113F0AA2DC742077B3B6BAE714742C04789FA3BC12B83A9248092A0452451A7ACA25504EAB21073744EA7826260AB03C84D22066D2199A72FDBC6F818613FC16E45F00B1EDB2F07ACB5E653731F8B701BF0833A258F12B648CCE74A0DA79DD4CC08B2209042F478E897677871538B90BB0C954312574F90A0B189897AC05C5A2E345D91574C6051766DAC73B7B38A3414714C24B175C302CB095F79DCC430438069541D6E9835EAD22789900C2E56ADC602559D595906C8B5AE01A03572183283533C64064290BEEB0A73B9E2137A50C05C1BC635710C3A4525E9C87054CBBE986B49ECC2706C2AC3AC1A474CCA723208CCB6AA1BB7C5851B390DFA3B0E09B6AE60159D231D59DAD26BF5AD617218FD68D6157E4A276122133E14BA4208"""), + xeh("E15BD4603F0EB64E32B3F1D1FA8EF6CC25D673A1D0BB659CEFBA2C153724C1E1") + ), + new EncapsulateTestCase( + xeh(""" +E65223F4AB1C53267449A616AA32393E441F346887329AC4B9D006F61A25BCC3779C740EED0BBDEF0A371B95171C70C60F2387265469A8E7C612353FC51968AA43C04D1685EB27364E26065EDA53D2879D36552E51EA01BD818DD57319DFB127F2A578CD48BB6080C5AFE13ABA7808B5894893BB414A532C5223B91EB1CD2392333190054DFB4722F5B548E570FA19C7C485790AC4913892249E63BB324C620D835E5B8C922924791B08937F139CCBEB2D5C9A72F344888BA37B8CD7B06349A310BB71B06A3EACC1236AB03A5FF9B923FC5FADE54C5A1A2E803424CF9C42E5043305127F3EFC956D97946E6BB02EB913D6D21695A0A88708B6CC5611FEC61932774E462C18F4726FE992A301B74DE2F56E9F791E90992C3C109860474FBD6C5EB81CBFEC4A0C7F154E5C2375A2A379A83B4DA4C6796102B20C553F015AC5AC49785138B2460925BA3B156EA337D31214EB942EAA27062EC07328080927DCCA3CFAC51A243645D5055EE0C644428C4715032DB2757AF2AE25D727C78B08D7B59D8841B9D26139C3717FFED92E09FC5286BC1E1D290366E183FD2B5562859FC9C321B73132635A532DC3541096657225082CB37DDED92C8C480B5CA68F93AB53168B1FF2F08D8265AA8035753C96897DD06793A145EFDBBBC4518E0C87AA90A895E6955E5B62929999143CB16B09E26433A1C0D761051AC3776EB126A8C890940632B4C50DA7FC181439A11B483554E208D6FAA627B11DC6BB5073DA156D2A4A08832D2590873672066B9A35C65515B4CB5602753B26C9C865716A6BC3C059272F0DF54DB6395F59012ACF2A783BBB03CBBC3A95F65E04A0BA76149A8DC4A305901418324885D44780F65E17E4C6AAD08355A59C21558B0D206C73F59B5FE49F8C5B86A6747DD9E8CB9D560B22B51B5A6AA82277B676F04399570402818A97881EAE8A245E1B75FA1AC50BB0A952E319E523A292316DE3E5C4AA271265B79D37795AA3596CAAB1072F3775D06502880359D73C5EE0C782ECD04ABCB1255B8A5051CA51EC6C17EC955BB6E715659B4CCC4C74484313C4F5149A288178C49F99586AF54710BA549C09CAC0CDC76D15183C8748146A07C72049108E86C0447B371B844C3715A914E3853F4184337381320A02F94BA1D9EBBDB0033D377254E4EA51AF455A775CB8E85336A761864239426A449FFCB967B82461F6F5A21D7A36DB8B54A5AA3AEB2297C30463064C8AFA12908D4B2D1E5B0F1A23B1D55A5E96886B96C39E10C6A68008B0527703EA2799F42B5098C4178F47490983793DF4CE2B0A2D2B56719256206493C395C54292E516D4F8A5C906736C89810BE0846B8BA654C86A355B56736B9144853286D65E61413F7DD26D1D2ACF6728BF6B028F912602CD132E3D6603DCBAB4CF65B0E961A8B597A0810B9F78A14F0DFAA108811CF22C394F21BFC56155A67B85722C755351576B0AB614B7C9C2278DBAE211E33839B55383C5744E6270C92D65BA82590AC613BF1493768E7ACE60A14644C9A02FB30BB1A6B42A6B69A142BF670C48EE03077BA7A2964020D528C51CB17B0245AF11C4A8EB0785ACC738E4F0CF0FFB838748314CA51C81331DE2596345B44F44BC516EF123CD8997E1FBC93AD95C0A9CB71D46C5535A99B75122E5E710DA961BD873E66DDD"""), + xeh("D176C0836015362D1DEFFC1901127B5C41C14AA518BFEE6C62F2EAEA1F226AB5") + ), + new EncapsulateTestCase( + xeh(""" +6453B4019A8E77C7607ACC6DF337097A9A10EA4836DBFC7C796A4E73A236069C2005C2BA2D5843AE7A008A337876182C44B92E66EB5146826B246CC7C3F44D40B0C88A98C11B873A29D7A4C7336512E00413EB519AA39025AC463C7CC289270A680B88A7FB9CFF592FD65626E831A019EA9E4C9BB57BD34B8D28B8855616FCF15FD6138947CA36D863510E6B3D4B22B8F812249913143F7CADBF15AF991C7E36C1A610879D9240398A1A1224837F904C65F0C1527BCCCE8459B594739F4BC243D2360CAC320AFEB5B2F5A310C90B42D3EC369F64C0FD2118D0359DBC3141F602CA8D7507EF830F1E47682068ABF22593563A071653ACAFF19506B5630F2B6401B78953B152C7A78D33216695B7778F9467FA239E4ED089A1E6BCDB682C4EC1B7CF407B37B0882777B12436063AC0C47CB7A58BB7CF34C5CDEC291BF1EB851DDCBE42535E0639580B191CDBA9AB22F0243D1334048964968941E7140C44A1658FE20C8AA023D2CB133D5B06FFD99FFD4751EBEA170F9C30BAD8CA39C64C7FF357F0FA2585BB13645682DAE24518517545175E38D5276FC442FB2143FFD2A7B61903CD72583FC64DDFA654081A4533457D36A366BA538B6772C5FF11674F0A702340C542357B80B2C206BBAF2CF6406F339436A7A1050792AA674C2E9C9B7986404C94CEEFC343E0781155D8B737978BFAE3C8CA64723D0656E9B89D23568AC6658F0732C332096A217CC6FA3A09FEB16552F5C982CA6B540C3AC96C8D0AD576820CC46DD60EC82BA0CFC14073424902578AFEBB44C321A4A6B7AF9709B1D9F05EC9BB6B928C936B670543E1B05E649FA7C2B3B9FB441C976FDCEB889FF63019F26EB2326F36F82231A68F230C9BF384710E11CCA858970A33445FF05CC4399DC28B285857168DD388F0B95B7E3B1699830950022FBA81984AA1B1540959EC1469DC696D7BB9A3C42153540B24A350CFCCBC33E5D9136824500319ADEE626BEE22A53FF8CCE2FB195D38257DDB8C305949D720342EB58AF72236F2275F98D335DE35A0C0C66BA752BEAAC32D113AA43DA092C4888D1750A59BEC4EB14A94A84C9947660891457B52F1BC3EF33C951A1DE64ACAEEC99F7795B8C94A0320F40D0ED92EB7FA346E042453995F2394B714A372E6B678C0BB4E04670B347C156794672FCA87966B26F0EBBD2B8304C9B6560459019ED95539C7C0C20999971521F8F7537B13937AEAB1E23736186C672AF0B084D4C5C3E1887BDC0BB281B7DB924BFDD9034C6456C427B9643C89FEBA3440947DD6B0B4BDD54C38215371E1A74E543A6073CB46118DE3B2BD1154AC536652BD2666F5F710C03CB6ACE948FB61692FA3A3E2EC4E3AD971884412640342BBB4C09D1C11856825D79A8E5249243062033E379DD1EA6526676A2492520BC55A4533CEC47C54CDAC7483500C0751BA84F0CBB020CFAD07B6F4E893CAE78DA0C7082F7A9C78D2BAA064C33D20644431BEDCB9B493D05C13104B88870361433490927B015261B63B1ABF2B59777359F74BC2597238DE6729669383E8188C0DFA7235D935657B936101BA4DA9CB90F1AED0F06C03700574B99159FC3E59EB3258A9BD5F47439B45A30163309A6A29CDBBC017840C5655E3E8FAFDBCA14293B91C07EEAB7E6C066A6B8BA7EC5FAEC0350B9C887B18"""), + xeh("4E302EB2BB5392782E7820868DEDB61F5A6AE558CA307A01ECDE4970E43EB448") + ), + new EncapsulateTestCase( + xeh(""" +409471E1024944D5203F82C62D1CA67E96567F3A525F6AA22683C4D537BA87DCA66864C88F292630484CE6C2592BE194A59B9642B0C0C1C4771DF87710F11FC8898573BB874965B774C3BCF30920312BC3C1945876AC6CC1221C9019677087951EF43031373BE34492CC5638D530A4D01C86F9B70296162950D92B5D97724BC1B7E9056C78D16290F3BEA459AC21395FD8A60EA8551B5D935510557CC36CC5C42605A4459CD7CC603408C3AB2380F7F00F44EB0DE7457E6F40B8DA2042F34C18554606E8A274FC8B6842F299C1E80068F11870907D8D44269BB7789AF0C8465B72CE64B5431A885A00B0C200102C811E8ADB7893502277FB87213AA89051852E896B3A170A33CA8F44A7367756944760B1D3C37318AB76EACBB47BA15DBD83CF8151BD2E3672934702C3A21886B27BC3506DFA8CCDB77C818734A18230868092186431221E3020157374ADD138C8F3C69D7709BF60C5A06BA3E410AF156B2175020EBD7603AE10C76DB7C2CE066A98A0AD4131781CC30311B38A78CB809BA48136009C36144B47AA2052E59F16E0216561BB42062817C67D81C96223C37DA9332B261152ED90350BB2BBEDBC438641CC082C8E4A4181628253734CB262061E40143BA11BB5AB75A89270636B330E922C5298068C85C1352FA5A133C3900A762F57B831A907AC37A6C9CBA9C915290E10A447A8B454A0F735DDB8852D79B0FCEB207C25568F44CE9568305A9362ED584D77123A3716A667CA2952CACFD7382303A69A817B17D895441D0A9AE1F71ECE1277C0432A7FA2A63C81A545910B4B212F1D983DC634313BC4B3B1B39190438D47B16747FAB48DE4777911B8D3FB65FAC68CA096919267783B0497868A9F95E89A1A3B2861A3BC89CB77F6976463CC7B1CA6CB8D447AA65463174A384217CFD41B4B80B7AA4072B10BCCBFA73C53E45684C542B031288C1192AFB1077B4E2B560E248169C6B741904304B06D23C86C9434AD64C67D92FB872D28BF9F745F2CF210D6D0C9C72176A3242447E06925718FE6530E2B5018833831819C23D3402BF9DC22FA7B1B754C6CD5A5C610275352D8B0A04159713C26422C688ED70B14209DA8EC23E8A2B285D61B8C5993739707386B4A084B22F70BA9EE3073644521E9B60D77755C30B36180B6B6A64A94ACEA2AFAA784C53C0C78E79203F36E98016CD1D109E17952A49021572B5F43857FA401BA617146E09450C8F392E423AF9FA294B7E2C2D772784B157FF591A4A13919C573713312291BC02F0F0C93721796477608E8E69FC64262D404C95DB98E548A767A184047A92C8FD8AED972945E676D946AA0DF5A88C7A13D03E501D228482FF97D62E27529372CCA9681F0758C2B500BB5D691D1734859B93E8E177605729337B39860E256D61C75BD462A6607692BF74A4CCC346240058B766502E740AF864531301226EBC3B8B5B1378846190AAD61C9BEF1362537606DEAA531EF97582DD1551E7A5F960B8DEA7A1815272145B25C7D175CDB568A68F05058F255B5B586866278F3AA56568179DF4B848FE535132B7C52D3AA3829686EA7CB6FA1BF07099F055416B8041AA9E2522CD23FE29981B06B6556432ABEF02E0780BEAE777D26FC062D94F1BC4C683AD2B92303D532101461FC0B8115556C3D2F2B855D1009704611"""), + xeh("7B334E045896C00F90D811489D491E8D72C4E3A22ED831C019FD4BD967B7A802") + ), + new EncapsulateTestCase( + xeh(""" +D0F1B584A87CBA7409D8B98B49B1332ACA1545B29FA2D42BC537CF959C6182305C95E06F5040B447D00737B0BBBFD9AB0A6062FAE209B24959EB83C2F0C5A2D8AB36161B90E2A92C5939059F8B9586F071FB1B26121604D5252D136705D33911703B91DDD85ECF80A7A1741C29FCB06F321E8BDB8166EA8C899B8064B69D77927C0B503989101F1A6941F4DAB06BAC9973378C2E6B3B19D9506B2C9A6BC29A51582C8B47B46306C1B35A438A097B07405645FC66C2660F4C14457A41B91907CB2864338C09C0CBAA7A877A9543F775950487DCB8CD8A105822B93882271A17B6936912A55FB4109B45B09BB14EAC2134E0D7471DE891CA984FD7B194B1529EBDA3CE0C24C1A9A170D76145215C8CA7217A138C9FB7DA8385E8A0C56B5342DA66F9FAB03AACA4E3A1BC5495C7AB0AB0E451A22D480B00FB29CE641C46E7A5EF16867101A26911B0A49140F70B8684845850DB8E15CB7BF842CE712480B19343077674D8A7B7C47A5E1170A629E53ADDD10F4BB35A601A843B49391D7337D7B3B592182F3A1636E4A7CEA14676A0DC508423B94B115041EA5F925BA0F2FA8536AB11E6D451321450CDFA076EAA3577D605A7E0B354754B92F1B411487FD8122E8DAC14D8464EC4331DC746B5693451B52878923649144182C1F03DC4281A7991C60F4A4076117B50C21670809832F3A67DC82E448A49AA3A2002B1A8667CC947253015A6A88FFC133554746256A103D11C7BC98013264D5EFC15A0B2825B37C356A96F0A5B701B4CBABF57640F2A92796C5663570B30FAC65BB79ACB59CE5C4CC7757920496B85CF938992EB32048360559745368854EC7A85A8E862A973AD50D67938265D3541161BE9C4097323F5E77EB8F66887A89FB7DA1A2585A4DD52782AD221B515A1D37778B5911AC7C90FA7722FD5A9484486A6210157188ACB617413516955F5EB91D2691E1E38CC2D10638330029D033005A88606E6A941962F3FAC506FDA5211609138E503E3382BD71640364066A2C27780898AFC1CCA9509C23F022AA77546017B1943360FAE24A54A0B965BAA7966F45AA7F3BAA7C6271CD28D4E0263BCCBBFE4FBCDFFE05269B048E948BF2EEA1E3C1825FBB3AA8F182B2B7BA52877B2304434DCD561BF365BCDC6AE0960211BA14EE1F9C8CBEA3750472A02271BA7E79C4FE6C9019B25470962315C4F50332414F46233A354928980A7752D7A07215EC24133446521DA5E4C50B615AC4E78F07B6EEA141AE146FF5BC2C63167483CCAD311B847996339AA50B2C237B4486E3B538C75B14969676465F106B9069A6F627938690139F011F5FA7D1832B96A0309FC85920E142C9C57CF64852E4564334281BA63068C5666A71B194319E99FB024AD33F879D08C16743B34038AAD20D2C84CB7440EE04C1AF4B944227FE94B5D666C3E51523248D913B9A3693DD1147AD7064696CE5B613DFAE1B83A207742264E878C7804D603BDD71E56C5CA7F887158E805161C959F072CBFF82DAE020C80135A8D1890F1A9A839032B0D69B9A7A97785DA5C201685C683844DDC99F4A97E00A063E15122AF22C27430328EA1435ACB07ACDA0A3B6B784EB19E30E08353CA26118AC4D5C4A218A262C4BA135AAC24F1EE7C5EA0E13C86749E5E72541CA6CAA1E1C05174B08745437FEED0B9"""), + xeh("947AFE33934E8150B06BDD1EAE40CF82EA99C0C0106B101283EA382EDAD94A8E") + ), + new EncapsulateTestCase( + xeh(""" +28C938C98060954AA557102D5BF39C17444A811156ADB2554562C5ADE5666704171AA3B19964449E1C12E721A30299307EC7ABC2CBBC82010E3ADC6DFEB2C497DABBDAC973021C6535773C127B3793792EBC717D392BBFD4906D4F21C62FD6C565935DA98550A2A310488956799AB9743B94446658FC97A9E1C3B263C23022132D33D2789295C994B6A441000F7FBA45C83A920739A17312AA97B1625FE5118ACB1552B647FA91C93C11182D9B9AFBFCB1A0D1412A7BCF92FC2E1A197EE4E728BB1812B88A87729C6E117A45E4E0ACAB2BC4E4A214DBF3BB4528316718C477329DFB1229AF9BCF0A00317FF526B8E4828CA797B354A0BD304FFFFC3E16C86A49355A54A0005CB1CE532CBA6A19267451ABC9C645A3F49FB075922BA931B1F139F8C627113B5358E02E81E71C231A41C1D647840B5AA96937B22926D6477E5B3A5D1C00485BD91FE5679CEEF18670223E670879EB3B02D03958A7751C007564EDC37DC0524790C8A0035AB30AC310F8419897597721D6B4EA87300453CFE981440FF0C18A323A0159B47A9C262545359F5031EF8B24A0080BDF0B55E1606355B88FC57803A3E25AB5ABA59582054E184FD97CC3E4635BC77AB797A748677B52BA76A16A9564BA218655A0070F20BD52B0A8C512A947534BBDC99D38621C655970B209C6DC8A0033105060133B600367E62366030810062387BDD120CEA00424C4C307E64EED5A3685F7B78E51138E02C4FAF51AE359499E2A97BF3799E216377EC3581AC81C12CC8B41AB95EA98C6D0500BBC3960AC05A2292789844602CA7528B2B91EAAB7A5F21399E13927C58BB030F492102B4361DBB4B3023961117099A7648EB11B2BF25703972CF778B5D8AC087BA59BC5122DBA63AD03EABC02031EF60CC765A0478F2C15DF31165903CE56680C2A62CF7FA8459D26C2D3C346617C51042351B321BEDBDC751D9080E0F64D2673C17055BF5DA53D74A0088357C1BDB8589AF5505C40CEEFD7140B95780BDC9B31482C75F5C6F395264A54C2A54B3EB6454C879510BCFB42DCD9548C3A53996030CE76A8A2435316CC227B591FEA7A0C12405D27936A0326A66A6CAF0B271BB64337D9DCB2E2471DDC632F3E0300F92C04B288191F0856C59376FD755729F195C264824657725E221BD017350982BB982078CA7A6783C64C5EF462F329BF6BDAC685D1BE483AA78B7BA7F2A0BD0C0C3A24341C9AF09C72D82674B0849BB70BD4861E5FEC25375223F5E4A4E20095F330C43A3AB23B633A0DA04553F69043A0B6AF862A94835AD284C31F82C23E80C2A488872E4B314636094C70A5F7614B1174AE46C11F45661256D566C6801985A2A91990889999631FB5BD4072C884B85BA79521BB2C7A729CA3CA8C18F5EB340EB84B00CB991D17933B3212293828BE1734F21B775BE289F77CA45846B3B6F029D6C610A0738F61B5C80BC808A8A506BD1022940AC755A7A4765A1C4A36B42DA453AA4B516F78B2C48CB94500401FDC654C1BA5C0D58FCE894E455667B25269A429671B668114181F06060842D16980F7A772480F3EE46D58C01682AA538DF1813CF95B67D9156D945E2FD84A7003CBCF265CDC12AA7148B7AA55C66F44A82E4BCF7D8C7B1ECF22E1BD7033C0588FEB6A1D553CF8BC477D94FF875323943762AB1B"""), + xeh("DC8510F45528D6981E59C1AA6B743BB844377D7339E359036929F0EEC54FE63C") + ), + new EncapsulateTestCase( + xeh(""" +4A6C1F1A816FB66471E6C18CE6126CD02BA76C730E721572DC730566496B3AC28F92A15F4C534C48578C18B443F24681BA2B3C3B390669A288EF7676C9A6B0970340F567C90407617B28A9A03274D8288006288B0A5B686FFCBACB273536941CD06927BCE109BF2330CF65A3CD0A2706EB33150A88504484FE182BC3C78CC5A7711845C3A277C763DCBDF16B19F1001727D5677687ABCF4B32CD161350EBA4206B2E1A65848528B7E1A90E04165BEE054F43793C23B0660FE7AF3E5964DC7C275458040AFC05EEC71A57E67C2BB794CE2680E7C4170FDB67F0F36DBA809F724B805BE66EEC38181FF1B0E9F94F7903661ABB17FD9BC0B0B19BCE2560E2C2C764F4863BCC40B5FC10B6513483A827C1668CCA8AA0B68039C8ACBE81B639E55AAACF2C761D78A77C2651573471434A14949943D945BC0ED2187DB442E41B901DBA0B14580710870B81B78D21996AFDDC6ACD1473673414E5C7C35EE60EDE3579223A7A2A436667CC51DD366DEAF615CAA4CAA073B60718B1E5B62ABF50BEBF4844EADC2ADA98CEAA8CAEBF187C2F26882673307A13CF83904607A8865A65592866499505051F10A4DE52893E07BABEEBAA4272B14EA974B5114101385AF1A011A488BA25179A118B312D8AC86FB58592D328941A3A0DEA6102C86F1E237DDB321615297A2BB660D5E0705A6672FD08A5CF212AC9B5B7A1306C87952B1C11B7D4E7C5B5FCB7030725C2A14AED641D78453E9FE5C6E6280D2CA57832FBB091C4418303CB4AA32DCC3C211DFC8A9BB429E750B2251149727ACBB112607EAB9B7744173D795B06D10EF8B1AC1AE54DA30A05188B0164B6B6E9223E93D377259163D62530CE9A0584F82E59534AC3E061B1B48BAAAA9DE1F8BEC150A63EB579DC528EDF977E7E421743F6A4C5DB61DD31334D3C63ED7755529064D67A4BA3780BC7C87731B86509738C1F7215275ACFC6E3B651FA91539B2B10111452570639E966766B64477C3F1E255390840FB9635500F2B513281E9D8B5BCCEB360F05913591899C1CBF95D23CB8D714A007990BB344C3A62446A80945D0CA84D3727CC8C39E0553A13B7050C12A1FB8BE6567930E0B6ABF6C484FD340CE916596B36BDC4085595CB2CF088467B0BA7F915A4E9581E7269C9A234F1A004A8BD0A2D7654018E55D6861B4067A29F6425FF1F5A00A804E3B3461DAAB9265D15BD530AC10686FE11038E772BC1CC46DB5C401FA76C1EE70165FB7C67C5025C2515E4182B46B92194FF361E252CCC43B060F50A64C79750BD162A586C5A63071D6E93DABA8BD525548F444C621A77E3EC583218788E3A7113DE38EB2ECCEBB0CAD737BAD9C21B39DB255458B8D6EE70C250CACC74A3A19C342B052A0FA5B92399013EEEC1BEEBC8E02F80C137030BA0A5DC8C3028B550925367BC732CE0E09570AB1AF01B7CACBB78A89BCC8C674449B932B98487AF0257928E64AD06967B38B30A0620FF9D49D2D63C2E7847E5B26046B457A7BB37CF012A7F18AAE0CAA41AEF72937B35AFDAB0174688B0724B25D67563536950081931A3ABE89B59297F701F246A6462B6016EA4EFD42A15C984E7157B5B4A335064809BD7739BAA23519098233C7454E241B23C4644A2AA1EB16E456E23567C4C3C6662ABFE76F52FE97F07F1298BDB70F62A5650A"""), + xeh("62A2DA94F109C0DEF56DFB275B1A0EEABF82AF8C6CDFFA94085AA93015BC1821") + ), + new EncapsulateTestCase( + xeh(""" +36C053F748B3A0655C3BA86303E099538971AB05BB4B2167D84B4F8BE79CCE515F28A90A5AD5CBC97B84CE10A39BB59AD2FB4AED7CAD205200A3C688AA32AE73F552A33B7DF1BA197F16CFA853C7FF24C1DD586ADE74CB0982449AB9815A63672C32420C1812326554C7219CA7698324115615C41D2E74A0138A42356232D7218549684CD9800F1A8413F3D952E78C915AD56FB0D1CC76D48F2ABCC0E6D79C67198D53B3B6FA57A4E9140D3C4286C97C7CBE48C3FCC81C6CD1540B12A077BC54F6F46711C844B46559194B5597A815827307E0E58AD7C4CFDDE826FC3594002A88C83760B56331A61C542C7B4487A851D7FC4D6A4072B7FA7C77647F8F252337252B1C9709517A7E217B26F26984D8D0AF75C9C1012977A3996D855A86C47266224C2167E585C9687C0FC5259E5BA10FA23DC4A2C163E74EFDA01956965A5DCA57BCCA2EBD4606B810882A337CB33347820C937E821E75A5BFBCC75BD1E37D81342F8248366945C0AA2B98F6E228A3AC6EF9CC28208470A3FA56C2F51AF83418E3D13212BC2C64304B4EC55001BC3620635C989CC4E4ECA06A453C8E5689BE8CA010C4026FE201EFAA271C2A772563CE7147932DFB7256F28975E2829D454BB2CC64AF8684B9ECAE285A93EC2212AF4CB65E484461D2B2121B15B37AC9446A8308437B887271564BC8143A8AF1F912BAC58E06AA8E03764FDD823180E30D47056A6D217ABA6533AF4399BCC798AB59AB0880913E14895526AD2F06A6D6536A0DE701D7DB9B2EAC7466FB85AC0020D961B39B88A8DFFC3FAC57524170B70490876F3A6FB16020EFBBA26E17C012AC4280C46E7F643CC334BCC302BF3BAC10A3891FF0F2BB81D29D8E421A71272C0F2439AAF29916461DC24B4899325FF005C0E30085AAAC7BF21B58B114BB0025305C8A1DADE9A1811329792713C5236B44B52AB8791856C535DC8B0E4DD0753689BFE0636DB99697B074BD2D3A8C4AE69929F00B8B256617FCAA96C980E8A629BDA58CF6A76DA49A004055CD4BE21E2C02B5533A7FBBC4525A95167175480A7B09BAC2BAA47A03D4872620C191287932029C9B53737A69148B7F483C607148DB23594DDB2F149ACA20F13AE693C2265A71E911A4D22ACB1ECCCC4C96B1A2C0CD45A5AC25533AF6829919D93770E42BEAD230BF8739B48C9990ECAD9E679C501137C49019C2F857C9D08FD533B01D50AC6BF2398655A1CBABC670299ABF46B95913A845151DE2796666BA6824237AF61789857CCAF0AB0F4B430FE966C85818B11E469CA2D7B705833813B8A775C77138F91700C64BCC6360231B1540F77113A33DA08189E454465474947EAA7F6731613BF9AD6BCC6D7DD1B62E1A3AA67C647A62712BC9CF67FBB690205E6E6997FDA7719EB9994D199505342D42FB3C6AB1936825534980768102619D79B9F197CB05C16A9922B4AD752C4926539AE184756114601A6ED90443D2869D0FDBAC6F447D91F37FD4E6649A90B70C73182B6162375610E9166AC76656A9B9242DA02CEAEB970A1803BD570F48B7B7557928CC4AC5D494BCC9386078183675D760322A91A1FAB770198A437C052EF366F6C905062010AC09AAD9594F581036A7E11B0D6C3B40BBBBC340CBF6D130BFB4E7CE4696BDB01ABE0436AC41B279FD576FE86BE94D213F70"""), + xeh("F374D3C7172C308D7AC5AB1F1CE5BB9785B98AFCBF4E9120B42EA83BD3BB1867") + ), + new EncapsulateTestCase( + xeh(""" +75F91DC864B819E71CE8CA50A7BB41AE94818BAB31B7F888ACE44071D2795361CA2B2666704721B02558212AB41A300B6D80B332A50448E36786D101A68A94D42325F718CCC4EB3521424C35E02A0A1A7A3514696C547E1918982B1066A3CB633E2B1D23280CDB333AA7B3C4BE7C18AEC44678D649C8774A4C552E45948801681F883165EB2C5E9D43CF38628E8C934C5F30819D4287AE4A51A797BDB0769534169E293C3A76A76361D79DEDA8068FAC187EF6B647C148E919141F02564B0AC4996B27794915A2D1C669DA50DD9B6E9BB57612CBC83765AA962068B8477D703848DEA456592A89B3CC321C3B86C55AB980BACD2F2605395BCF9E965B95D59DD608A8B8B85F66C8822F5B2DEDD36D3F97BC1503686F74991093A5799A146B434C7C2A6C573B3AD8C44FC517C92D042D623A7414D56DC45454CD08919FDB8D79A7316A4C14AA9961DA76C9DDC4CC6CDB37B474835E9A86563212F2B3908875588E2484BE8C4A49E3BC5EC609FB4BCD52D62AFB1B713B556CDDCC8BBD3B322E1766C627A0410A3D5E0B6F3E499272FCAFEAC90CDD100AB5D686F22023F8413F64521D19E38EBAB1CA6E31CC10278184F50843DA5CB1BB5164DBAB23374065B1043B1A7B1A241DDBD4BC6EA9057CC1A995644AE73231348414414C7EBC58BCB9B538A091434DC9010904BAB0613FA640C0A903BBE57A100B08A44A70507436C366268E7531C84A977B9EA2263E770E98306537B505A01284F653C066BA2F9FBC6CB3740258892076C01FA5CBBC8BE97FF0830BC746BA27555305D17A931371D04873CE2B89F5694BEF68515E7552EE03BB8E0517622768E6022DFD1044CA86A715930530E504D8031574087572974915885CD0351AF3610A5154559F688492579BB723A22F791B089C2CE3A383C09CBEFDC151DC266DCD54C196F25F0EE34092109C6AA6CAA76373E9125E143B2D0EA0874E4A35F06961DD812E60700F598926FAA7C1F7CA579CE9AEF3557F74E2039059258A001FC7F3B4A4ECAC6303672F12B9CC366E448124A27CA6FC43C6157A378535817B8B0C981809ECD54D92F135D0126480804EFFE40134E6C2190B95BC7C5E6A72B6487A6A454239DFE10AA99614AFA6A8F0E12FA86007CE464AED4063025B213D8597D412C9617AB62D9592D4320D7F97A6AC4092DCB311C21636358172C43B5626642336A96C1466BC30426DFAD5C0DEA50F715B19827B1935C79CFA1C9CA1F799F3954EB1C0720D134CF9A3122263B995E9268C3A1BE18A7112ECA0C4914F2659734A31A5D5708F3A145E6801C18761A280465C2D4600B9D968B3CA61EF9C7687FB1597499597ABADA930AEA4666DF40029F645A601984646144DB4CB68B3466CD7DA154C027536886A390234CA792FF6AA5C7CA258831AC1B0FAAFC21890BFE522A7685837A550CB343B79B2955C4ABF4939792133AB0D4A77C909BE0F0233AA80AC6B6AAB0F8102F374982C6BA88563ACF7254760263D7EC8C302F656BC227B3B558BBB444365A2CD95B421DA5914417C50E84311C6A2218A49169866518C201622F10970D75D38815787355A0C6126EBF189AB30321C15898AB117F6183C47174DAAB7BB8F96C3F4F239B642516A48F015E838A3DBAA500DE409C13F28FCCE5F266A98ABCB2D92E1BE99E438BF"""), + xeh("DD252F728FC9553CFEE90924565E984C8E1462CDE58AD8C4ED8DFCE98A7F39B9") + ), + new EncapsulateTestCase( + xeh(""" +19E628A96B033E4358CFA8C3C4A642D7127C16A50BEEE5C57A25476D8BB86D019DAD84C613D96A389802EED2031B1A07D478612DB405BBE9BB42A4BF9E7AA91CF2950D00013C4CB7A9B0CF88A87B19E41995EA9EB09660746B1A81A2C74F0BBC28287851CCAE8CB8118ABAA627F44289A9C355DB863095B397D1C449C20AA60B5F1EF94F9002B212C733D81C5A92631CD3B661B11056C9026E84A34E19836411A76AA53089071194E2C9696B31BE8351CB735521A42CB83C52C421724F2FB76D245BB5571358314A2967604084F64AD30911600B33AC9B236DB66487058F35611D0894051F31C032972A03A1CA5822317F953F91A74885E21766824F0FB601C593BC64253E7C36639462721C232D32A076EE245B9A7BC96C0A70ACEA36F8F41E1242AB2D00593BDA4C550018B1345D0806A3D1E8C7A8CC29790127370754A24A73E3A4B08DEC3A88C04C2022235E55CDCAF80938B579B63123E306603C781FF3ACA1105076AA2BBA1D966BC28BB3F3A7340D210D7E7A1735B01E749C0AE990775E2306AEB80229B918542608B7E281B6BB696E1C82342BA196D15EBEF20D541CC57CA928A9DB41E972CC1CD333BC7A64952247FCBC578860191FA67971A29E40C06B81CB5A765C7B26522C19A63C40EC31EBECCF7DF44CDB8B4E7BC805D42A28ACAC3EB2684ABDF46DB7E4C5B01A770B4C0D79D7190B97461BB75CD4A78574677CE26BC30CC25215B1C20C290A1575790C86AEBDEC7993CC94CAE23D5FA2871A184E721886BC920CAC11607FE96878971F161B788E5653698A9F8981339E581969C1B61A6073C02CC3822A2A2D0A6F5BABCA0D57175B86942CFAC2B0FC9F1684324A4139CB1342D7A6B26643A923FA14988173E58A82B67532C6AB89C0D5AA1CB47E44703FD7AA6816501023229B1E76833D7948F0743BE373BCD361130899010727CDACD4347B3A6645541BC7173361860953E61F5824BA2ECB94101383DA6A95CB4591C1BAAAB1B221F43B91D7985A173A0FDA756FE9B38ED1EA4F2A428E34F352A37A45EA83998B66C4E60B40650A87FF5185DCB0055B9C011378442462C285D18A0DBA658DC5B17D1620CE566C86879F38754CC8C1BA014827B444CCF8E9029A7763318CBFE0220DBED60F6720C6F96B4E70C712B58091BE3A6C1C4639D1ABAB09674D2E653DEC768D728BA593AA3C61B17DE17A07B3E85558F38DBF848D65AB3A1AC183A62AAD4CB18344E71BE4C97FEB59001F4ACA46342AAC389B22C47C2A216D9AB50B1A02405DA01494C44184363C31F5C39AC90507D94093F882E6891E24571BF39932DC5482554C12AF6A5F0B3AB4CBD276D6D850894CB4F414196D511731D23C8E039282F6C11D089BEBFB91F0A766935B3ED66458842B4C757585FA6657947529294930C886A50689CA5DF1AA39B8346A14150F051E5462A99E56CA383BA5ABD455F00AA9BBBA660FCCA2C5A8A74299581C274B89E4756552570A33514CB46CD7A3AED34A2DA42C49DE1A8645D64AF3D644BE586068A1B5804965BB7A6134CC8DACD82FF2E954625C92B0D9763E22CCF7450A8FA70F5793400D2832A03A5A75D404D1E2822DA607F6F9C4FB510858978372C621AA72399A34B9E2618F97EAB82B56D93E51FD73A90A78E2AC85826B8E6335330DEB8C644A29A1"""), + xeh("297ECD18E2880A596F572B66458410A0D827851EFA55F1C9CC513F7991F0DA0A") + ) + }; + + static EncapsulateTestCase[] encap1024TestCases = new EncapsulateTestCase[] { + new EncapsulateTestCase( + xeh(""" +307A4CEA4148219B958EA0B7886659235A4D1980B192610847D86EF32739F94C3B446C4D81D89B8B422A9D079C88B11ACAF321B014294E18B296E52F3F744CF9634A4FB01DB0D99EF20A633A552E76A0585C6109F018768B763AF3678B4780089C1342B96907A29A1C11521C744C2797D0BF2B9CCDCA614672B45076773F458A31EF869BE1EB2EFEB50D0E37495DC5CA55E07528934F6293C4168027D0E53D07FACC6630CB08197E53FB193A171135DC8AD9979402A71B6926BCDCDC47B93401910A5FCC1A813B682B09BA7A72D2486D6C799516465C14729B26949B0B7CBC7C640F267FED80B162C51FD8E09227C101D505A8FAE8A2D7054E28A78BA8750DECF9057C83979F7ABB084945648006C5B28804F34E73B238111A65A1F500B1CC606A848F2859070BEBA7573179F36149CF5801BF89A1C38CC278415528D03BDB943F96280C8CC52042D9B91FAA9D6EA7BCBB7AB1897A3266966F78393426C76D8A49578B98B159EBB46EE0A883A270D8057CD0231C86906A91DBBADE6B2469581E2BCA2FEA8389F7C74BCD70961EA5B934FBCF9A6590BF86B8DB548854D9A3FB30110433BD7A1B659CA8568085639237B3BDC37B7FA716D482A25B54106B3A8F54D3AA99B5123DA96066904592F3A54EE23A7981AB608A2F4413CC658946C6D7780EA765644B3CC06C70034AB4EB351912E7715B56755D09021571BF340AB92598A24E811893195B96A1629F8041F58658431561FC0AB15292B913EC473F04479BC145CD4C563A286235646CD305A9BE1014E2C7B130C33EB77CC4A0D9786BD6BC2A954BF3005778F8917CE13789BBB962807858B67731572B6D3C9B4B5206FAC9A7C8961698D88324A915186899B29923F08442A3D386BD416BCC9A100164C930EC35EAFB6AB35851B6C8CE6377366A175F3D75298C518D44898933F53DEE617145093379C4659F68583B2B28122666BEC57838991FF16C368DD22C36E780C91A3582E25E19794C6BF2AB42458A8DD7705DE2C2AA20C054E84B3EF35032798626C248263253A71A11943571340A978CD0A602E47DEE540A8814BA06F31414797CDF6049582361BBABA387A83D89913FE4C0C112B95621A4BDA8123A14D1A842FB57B83A4FBAF33A8E552238A596AAE7A150D75DA648BC44644977BA1F87A4C68A8C4BD245B7D00721F7D64E822B085B901312EC37A8169802160CCE1160F010BE8CBCACE8E7B005D7839234A707868309D03784B4273B1C8A160133ED298184704625F29CFA086D13263EE5899123C596BA788E5C54A8E9BA829B8A9D904BC4BC0BBEA76BC53FF811214598472C9C202B73EFF035DC09703AF7BF1BABAAC73193CB46117A7C9492A43FC95789A924C5912787B2E2090EBBCFD3796221F06DEBF9CF70E056B8B9161D6347F47335F3E1776DA4BB87C15CC826146FF0249A413B45AA93A805196EA453114B524E310AEDAA46E3B99642368782566D049A726D6CCA910993AED621D0149EA588A9ABD909DBB69AA22829D9B83ADA2209A6C2659F2169D668B9314842C6E22A74958B4C25BBDCD293D99CB609D866749A485DFB56024883CF5465DBA0363206587F45597F89002FB8607232138E03B2A894525F265370054B48863614472B95D0A2303442E378B0DD1C75ACBAB971A9A8D1281C79613ACEC6933C377B3C578C2A61A1EC181B101297A37CC5197B2942F6A0E4704C0EC63540481B9F159DC255B59BB55DF496AE54217B7689BD51DBA0383A3D72D852FFCA76DF05B66EECCBD47BC53040817628C71E361D6AF889084916B408A466C96E7086C4A60A10FCF7537BB94AFBCC7D437590919C28650C4F2368259226A9BFDA3A3A0BA1B5087D9D76442FD786C6F81C68C0360D7194D7072C4533AEA86C2D1F8C0A27696066F6CFD11003F797270B32389713CFFA093D991B63844C385E72277F166F5A3934D6BB89A4788DE28321DEFC7457AB484BD30986DC1DAB3008CD7B22F69702FABB9A1045407DA4791C3590FF599D81D688CFA7CC12A68C50F51A1009411B44850F9015DC84A93B17C7A207552C661EA9838E31B95EAD546248E56BE7A5130505268771199880A141771A9E47ACFED590CB3AA7CB7C5F74911D8912C29D6233F4D53BC64139E2F55BE75507DD77868E384AEC581F3F411DB1A742972D3EBFD3315C84A5AD63A0E75C8BCA3E3041E05D9067AFF3B1244F763E7983"""), + xeh("59C5154C04AE43AAFF32700F081700389D54BEC4C37C088B1C53F66212B12C72") + ), + new EncapsulateTestCase( + xeh(""" +16E08D929596ABD2BA47558090531AA277B00DC8337AF578F3A18B3DA8738CA434ED41B537ACCC58182310352331A43A0CA85C606823C824602085B2338142BE48A00E068289310559E9155C6A991CF457F098C61C6B79C584B24C883296B03F9D100489C546ACB28B2DB181BF7B4EC80140F1ABA4130512BA2A0F96C9453DFC479BA1CA9689629779AD731B159A61582CF67989266EFF84455D191032486242E6A9CCA6314B788A3783A0D003A4BE1AC50700611DA61476962E48E38AA5250CB4E60E44B52F00C5233D0A72E3D010D65ACF50CA1704CAB0EBA28D084387DA4BC8BAF7BF3212954652577CE52CD0E9768B3CC606000FEAEC499CB13AC1CBCA0F5B6A0BC7B8B9C140DB83174448050D72C51F18BF1A570FD6314ED91A4DACA6C231404250704A86561F5861785F4B47A15420975225300C621EC11FB6F04C8613982CD16AC85A8EAF62B07FB16A2BAB515D84941AB7AC45DC58D43ACA35697DC711BF8D7BBB41B95BF48716A1BC462F332DB93B67CF858D694B66D9899069EB795B4C1E407ACC74493CC5908B21441838702A3ED0683AE0599CB487A2AC154727A1CFB30104A9B0715698D5E51417832AC67139EF752BA77B7C27217472C62AB8099B4EE2A1D6D98A37EA56058A94D8B86FBFD17972E46A496B2530232F821B68D306AC78BA8D719C6DF278AC79E6036CE55D4E3995CC772E4538BC99E5A5AFF866AA733E6A15A4C7D61ABE8A315E908B588566DBF922C17B6ECB773B59D15416935EB8197FE751A4A5C49AD6FA5D087489F299B20E6721DCC297990751A57489C3A9CB59745FA51191A37873A166C84AF394D280982FA2171183345FF5BC17077B5432236108C6537CB68465C08EA6C98D4B1B606B73BD2A6036B16922B712B68553CAE23630B926276762E3D55DBC1A2FA1CB1372C9460B7727E2CA7382F0B696D005E07AA6C2C763225C30D846710D2286244BC2C751A5BB5CB71F24C75B40C3D1DC0369506D78D39BE3564358764A074567C51BB81B1090ACB301AB95864406B500CD04A2517C582601057328C8467847B4A3248A4BB63251317A9AF93475063CA34D382C4AEC93164011882A6AEE1771EFC99E84E1B68217281B123672999431BB1D4DAA180E9202372C8CD7150FBE3166718AC3746CB0E020AB0A349F88E21D319394676919CB08B29203A6EAC112B63178C7B8C29CC28C4C085A7D6660B12BC64B10A00C038F80076AF0769FB6D42240CA010843AA33B5C534A1C3391928ACF90132D0598E35BFAB062F771696C93696A351C5322C6648CB539660902526202AB34BED4ABC9DA427A1602ED5278897785A9375110A87529D74B951750649DC2B03C0642755132734B808897B1494C98F87376F223207C267A9D5961BC6472B3B8EBBE9ACB9A79A3E2A3FFF428282BB1B79525B7DD265A9986D362566E93886B106C7DBA07FD1C78CC24008852B152822120E73807D8B17486067FAA964330BA67027A84E2BA8A91801D46A059DDA37EDD31875600794E3588AD44331741CEB3990908A57A7C1CA8D7AA3D9864F8E501E9B5603C1FA8ED23327BEB22B08BA26E79C90928B756F96771FD7244B346CB18415CD3CC5BD845E394BCB5C6399F96338534182F015947EF7230A0AB825382957F8950B31CF94F31C0867255A597D9501A76DC2BB7AE455D8296953C51C7BA03A3A0A769207082F45A5100CB49C86317B1650B5898BEBAC512960830A37022CDCBBABCA0AA6DAB3E452A12C1040D54C1BBC372F1997C0DF75BE5D1C88C1618F1833B223D02E2B0980FC187D93A75B57E0487D2CC36AFC1838519378E5634502106AA7B3923830C9B9BA6717694E340B7B51CD63917FF9770635F42F212085458A45BFA09265F074036545FB39CCD08522135AA522670A640B3AA37782D9C7794DACAC86D651B030B33F14464B9CAAE3E883E9582F16558B03D77EFC01AF01E2327CAC368268A4A7141F375C833AD3B4369533FA727FE051C33A1ACAEE8832E32986067468EAD91D79A90058F608F97A1226CBC26339540778B3C1B0421E88458CF69C8DC73287A36D80B57F7FB5B787B66C22658863DB1F60985156BC28BDA25C56C5BD35812020880DCCE46546965817DCC3F1667496F12589065EC68853863C1C581B7F378C82ECEB88D1AB88CFD7DE4C88E0E556D945755EE2558034EC6FFEFAFC68E26128BD7625563BF279"""), + xeh("2E2C821791D3EA49D0AF380B97AA24532F6109D85360A751BB8B4C048C48D26F") + ), + new EncapsulateTestCase( + xeh(""" +54570A4B2AB131F9139EC171AC5ABD140863A6A0C5C13C8AF54094E95620E4866BCB8483EBF0B21FF9987B44650951750EF0BB76334235651CFA85153451B1975380513552FDC693124617F395121DA27F86AC80AE363707CC3F264CBA1B703DA67348BE45BDB4293C69E31EA73B0DFC35083F2493185B108E09467B2BCD44AB17D7BBC41F73057FBA8C2732730EF110E740AE75178890746FE149C8898B467CE116F68743A7B35453720BC5D9261946CEF3D9931A4C5F2F271041F0C4BA277778D56EF9DCA3E8CC2A4937BD9A276D173258B70C0BD9A0C695732CED11079D816E9D00A1C44A095F746D4EF14C53C64399964884977D503961A48C14E02A4B7055A74A31C5C55AA503C9927F017A194917F3AA13B33BB8FC86126A8B33EAE53CC2631C15C39FFE2615877084FE0C94BD5013A9CB467FA66E780A46EC5BA392D3C7B6579F63F2656796622AE9428D128BC546B33B26C697392B57A240338117107ABB0C146B2F789FB1A4552A4747C520B161C6A356F1368F2ABF7340BFC8031535876A185C11BFF5176B474B3812BE1E7603085453BD5B289CA97F20B82D88E30064B39872ECBC35E447E8431D5A61B25220CABA58594E96CAE054A791736B51E42F3FCC1F2F7CB8C86C9B67FB5FD53C93ABF3123D11CF5AE491B25703AD386839F4B0370C3AFF50903724C592141B88EBC6F61732F1DB038B15528F1389FC574634071CFF89B39D5A3F50D5B8E6E932C434C9BEF450E42765EE1486C3FB1221A3B3FC42C5ACA709602BBAB9A9BDE4A9716CDA0370B767D1E29128A5560164ACF0D03EC60833AEE125040B5A5D45827C1A2E2B3CACA923BD51134E216921656579F2773C4F0002A285A9EA975670F02399626D65135119754F01F09E204C305C880E93816516B0CCF996076AC93540144231F54ECD27C7C3DBA3DE988E8BC1838F68550ED8BA14D35E14586516BCCF459A3E63C9C69366A5A2992302092790341E7FE08FCA4B77906C839FE929635B89971512EB73456462BA9DB473770B9689446E4D69848E21670CD76F04896456E7BCB4352B086979DBF4905F656C1D67169D71933FD8B827EA5D0B5B00E0C3476BE53F56D11FE47C1BCB5727C51198381916572257D9E5A811E6601191477F45B2244BAB96943B16B28074B7129337333BE218DC114DF16A83C4C1B76A28223489384CAA096097A26B0C17E1E6686D52214F756A12F3C5E08985843909DDC1C4FB99CBB552C9D2594B85C796856C48A3D99A2B93510425A90B4AAA035150DD1394174429B6A394EE495E060812C6044678CA6F5DE9AAD4C11CB4060225F07F004969FFE991B7442176E00D7AD4C6C266435764CAECC34DEE027ED1CC4B80BCA242495378F0097B797C9A0C3F49D7BC2961A41D751728915166730DAE7A588C550F64F06CEA7A868640157F05C69C781682967CD4720040060782500C97593FD5715CD84A05AA10958FB482C38C7DA01A910C5B0C055BC2252B6FDC659A94F36422285F2CD477E350575C4AB3048C0F2AF83116BCA3EF65B0FB73C77747C3D585AAA478945288CDB0853C14D04DAD16052B71C02AF9A3CE254095C26736E6235CD6B0C340812DEB282249AAC87C7E35639E31A5943F61CE43728332B9280495CC9268825AA923DD5155BCE616B3675EAA5891FFA7A6BBA07F14196001253427E8BC4C609318940EF31030C5C9965A26B7B5A2440EF56BCCB424DC75350AA0129E05C83C19856CD93BC9928A8D674381E6B79EBB0319DA1BC7F427DBC1830FF1CCC468B5E68B23AAD73526D16DFDFA30D8CB3559296E35449F36B280B191587A692DBCD610D75342DB7A919F8ABB1E12BA44B185B7560AF79200427150D34601EA5A929025855B34B3067A01BB0B9564C186B2820917D5BC444B30755BAB812C89D201AB6D376135F2220F37AC35876B6012975731077F464ACBEB7A1E7764AD8502A68C9616B09C33FC6688166E1E3170CF6534C0212731049A31D4353BF80A99390064953419E9CD1DECA6F3007D31298DD335B69B971E4F5261F4888318A6A0C0E2AD79C19A827436E87886E29768AB261863243EB5D101A11922B2558D8F53BBCFC1BDD652CA6B10C123C41575F609630C660DD9205E571B276A36C64C770CF3B2D362064F0C94E2BBA158F235F27464280CA9026DE7D64D513C6120035933D3067D03AAFB1021A78860771BC04B4652"""), + xeh("5729B2AF60A4A5EE3BA6D7F255D7D2437812579942FF2C6F48611669135DD695") + ), + new EncapsulateTestCase( + xeh(""" +6914CE520C02BF6687BEB9330C704296E40E350303EB356AFFE66FE8C11A83102472EBC96B6634E76C19B89A5E3E4078AC751480B66288120A0D9B69D78387CFA44F32C08BB7768B292BCC03141D77871F5405ACD1403564A27EEA55298AA0544460CB1C8AB9E4C006EC2A1FB5B48F39745D66FA899C456DE0CA4A5CC4B2E4979820F635B5A286ADB3B8AEA97855504935E21C37E226DAEB41D2B1778EB84F764651B66ACF2E7B44FDD43E037400B50C97485047B06BB5B3D1A16FE95AAB462305933A3C730EB43CB6D5C10D9DC25FE0F8085A689C0C611700F894CAF593BA4833466BAC987211BD548C81A2BBDFABB5CCA192FEAB0E1AF3774F851A646281D1841681A40A1FC34EBC8BBD731BBAE927C403BA9E2993588B885008317965F9967D249EAEB85C650C18251AC22930A6A68366F72037B2250CD9B5A568766842A812C3C7BF7106CCFB122007808A84236C2E5A88BB111EAE388F3756B2410776C6D745F770208F5B8BDC087F16F86D52098B7EFC2416A786772124D41187546BB8681672951960C6148591713C19783186A189806CA9D6EC3BC0BCB49404362B82B311E8C970107C9B7A3D6D526BC59C48BE93C699C79167C63A45289AF1773BA21A9A2F99C6A982034914B55A301C27C73D27B50AF02B35B6307DE2F24B1453064F847308836604C56C1ADB3306114AEBA38331A56E6C126445EAA258E25FB692A761EB62FB1BCC88AC79E5EC8CB583CD8ED799D00516B1021958333394B30166718EA0A600CC37403115516768BA1F110F4F27042D589E719350931735023604BC6B0412B67423826EB91711ADB11AE8067C688B080CCC3939142CFE33C9D58710FDEC082A88903E9238D3276316018D38A841930C919A2493A06051CD9CCEF8E46D62F61AAE1A8600A291B55C35EFA8974F1CBE0DA10005A68659904E13631BBD92AE617ACB7618223931C989EB45C5C88FCD74715DD17AA86704C57A2A2561533B562FA7E5B45BF7212682900E70CB2C8227BEC67CB1D7536B405EB6424CF2F5A5593AB77D579156750B78148C33E79BD9E798BA162FA3332A6A7AC354CA3818C174CA0B354B4C13564111DAB79A0BB95FFBA8A71355558A303FF4E9333A708DCA860915B19EC026B7C4022635E404228776931683467337372B7FF7665E9DF38CD11921594C899AA3B55852B76FBCAD0159254B91B06C412DBB5C998A283314A673FDE81009A6C27F733554914B3582C31D3B2B7FA80B9BE6157122ADCC891B21E43AD0343CB014455BD00DFC2C5A671A86A884A5757336D267ABB2F61E18A68CEBD24E09311AA6621B09E4437CB8C6FFF7A0930771D48AC952E317DCE9A5C1261DD83287D7B950ABEBA6C5300105188DD4B4A992840FE996AE2C3B20D7BA00B11AB9396C73A5DC5477FC0141171F6BB05D4806CC9B244A7AF264D84956FFB8A67384CC522BB1335737D5A680ACD3AD478191638A92A0E7292672A75982AAA8A93E321CAB0DCC616A4B9C344735BF6521FC86B0AA3CB1568A9EF7B19AFFE9C352B5B84BD7B66B07C7378B23B601B88C43B794E25DA22083AAFC52682B2CA90302453AA595C6B43E24A84FF07BF298CE2FF1CB22C6BAC6511784AB4FD5AB1A3B376684867951AA4C78986E04A639E8770A77BBA187F08F7E910AAC433FB5461D374C7022693594FB0E25E52882D310495B1340820AA5FA13E187B6335460C37B0DC1848D7CD6C85711CD292994184481560837820A2B9E3A09B34ACCD1E296BE3816B26764DE9B0B16ECA200B21B9E338014FC5F99A8323C657061C59683DA62B22A370313BF5150476DE36B09912283544E2DB6398B1168BC6A33A257605DB863D3C4A6F190488C402D07C754245C804AF6CE9E2589904666AA335B09C35B78731E14739EE2829AFDC991EFEA87BCB3529EFB1677D5378E59B31167792C89449F2A7BDBE01C8B2883C9B880E626AB1837836BD9216118302690148308A944B1B20D92089E113DF5845AD2F489DEB51DD4D4906E93AB9D027D89261C0317561710A033F55B6D19756967159D70870446A48E6B1B26E05258210918C38DC5985D832556FF6872ECB2BDC1A009F8071DA7992F3249AF49C675DB4502F3D235A63C6321B56DE227AC0AE436E44723FF293FC2979DFEF64B9686A3E28597D5954DCF3594F10EB4D23B649636B79B831AD8AEE1E86B66A18D9A3E3F249BC38D79AE"""), + xeh("FE8AD6E3F3EF1FD1890FB7FF75A8CD9B2A04CAFA7ACEAA99D06D116B81039DEE") + ), + new EncapsulateTestCase( + xeh(""" +DF970CC655479D5361B2C99F4E6A60F9D15D9941A36F126062564EEFC3C75871437C021BCE4314A243236FA06A1657B68526652AC65AB05712A1381084254D048670AA24A995096D139236D6A7AEC6A830A4CC259EBA039B6A6E451A0B29D0B4D5FB5FD365B2D81C0D54FBBCFEE19993FA70FB5C92B29C95F0065629D84760272076BC11C3B72B96BC15B3651093DC440F6876E8A27834560B61B8A041499172045ABB4223F0D1AFC71616E8B6958653A08CA776B8916849C81A45A8BCE158B055B69E2F7487D4962FE31061B4B60034567E85496503108CB70167AC4BCFE402A50763941A15A3AB8CBA7DCC220D707ADBE4983A16C3484536EFC860833A527A7388CCB89693FC21906B932BD21584B046677AB9C4E0A54325CD3DD5A78E17CBC3D8CECEDC096CE167E9048C35973F359B7E9B729F95535408919958790427B1CA951080C9A45AA451CADCFAC9FB5804F8CABA9F88C09412ADA0FC2553B5921BE60FA01505BBBA2C33A22B73A69EAFB530AA090ED1734D7561C25299AE954ABA49A0464480B731198A68F9583CF0663322A1A493B6E2A2A2B06CB18B84C701E4AC73E91765FA72641B86249C5817511565023B6719252268585F2B077A3588C0291B36D9CEC74A1DF4FB33A4B95DE0FC7EB1746FD4E17401133F583954B9C947AE6A9AB443CC99924913646F70B29387293459F6317919C177F87EC01CA9E3210455EA25429ACCD4020CF4E43F98999D3739979CE39DECC5361F152B330255444A05F13406F6742BB51156A07854BB0A91C0B45C0F1678FE034BB7B2558232C14F83C822A22C7AAB6934661682E23CADB26D9D9284B519A4595954BC56CBDD0062BF657898B24C80F3010B849E20B269BBC68A538749A6F06DA2D62BC7FA8A25074629D12D22C6517BD4A20D8531B26BB13D2C9B2AE1639243B803D30455A1C0E4CCB5E3C206F4A6BB5C65B3205C56BFA678AC4189CD108DA5C654F4DA7EA30B0D7B23985EE80EECC2297CDBCB6A2A6B3A3C474181BB42F9150CE57FBC6C8ECCE43990F8C31F5579C71C7DC9615D47506666D05BC59339052BB090078E58858780671A65A14CEA22018661B9945A0D0EA2679388C308460AA9367CCC97CE6EA3960AA04BDD28B1B98158E02BAD3EBC3A97F2BB3A1319FB6178B99B42016826F4814960355722B8CE3338BAE0E97084613DBE41064D0A6F3082CFE25A18978975AFC04D0E1C9CCB0C1DF5C9054B22912844077DBAC39E40CC18C87179D420AC782D40E3AB5294C5B5E786814918D048835BC5333F421B366B26568C20E832AEB0410605C3B78394CB1CF5108F5C7538630C8EE4A611412F75F1691133A93EF744D36ACDCE302516735B09B05776049DEEE674F894580A55B792CB4ECC5916D0E3042D3231C8E70DAE111AF3A386ABE5A251FB9F18B6AAB4D79CF16BC884BC0993266C35CB267A9AAD057CBAE4ACC071123CD8D35C86A7C23A6771FC5799CF29ACD8F08E6C0B719E3173162418CD6B008C52A29EC5A701C97ADC906BA4852F7590353B190E96BB8A6C67AB9245CF45BC7DA31B5888B5B6FD77912E81A9CB522946D77305303B6F28B6A89469E734B5FFC4009C341114768EF8C0489E66C7EA3106F224A9AB4B0E147911757521BF39587BF211D9DB8F9BDC9EC21B881AC727810B4D1303A38938A70AB3248BC547B3783F68A84C5C77053726B808825FE17BB8D5672D77E4A178AB3C8EFA8AAEE419A09BB31CD40692A4BA273A137530CEB7198C5F38CD960049BE317AA924ACBAE241FAC48AB540C6CF7A4E58CA5AD3076DD7FAC09DDB1B49DA3D5FC751AE812A416B098CD712ECB99CD0567AAC9BB48DE700120584FD09A201D49A77D16132527F5C0138868C18FEC89B3D593EFA912FF66C79A2832A1B0234F5F0B67091ADFBC507913A41A5C22FFED19109AA9EC0F99395685682F6934010056543AA88738F1D88ABB1BAA21D35585F5534EF6241D81476FF33B434B4C335323C77318156F75370E1403C390242E6C7A75A9D800C0CFD84AE2AD52B9A0A492D441131B68C27DCAAEA93C2E3E2C661E054D8228B03243539649B861927947C76500910A5EA0164D43865B62BB1B30D032334EAF296ABBA4780DA5F12EBABFD021C3FF3A164B0745C09328D5BA0F6127807824E2A7C8012201510C3368067847C71C50A9D8DE22AC182D1644E25A39ABFCE37DB3224F725F065"""), + xeh("0AA3B1F8FFA63F89F949DA18B6D8570BC5811F85A4BFB293E9D411ACD43C3227") + ), + new EncapsulateTestCase( + xeh(""" +8FB403D0105FD0EBAFD6505968774504C7823474A1C26280A178BFD33368E14491C100CF58379A55575D753B75456196B5257D2B4BCBEB586EB0397BDC20B798DB6F12A8245FE80DAD6026DCC76EEC5B6DD6F9B5EEAC5211D408CE0553B11394F1440220F03FBBF4158A1C31F4735BB2296AF336C4869713BDD14D686940EC57CDAEFAB8FEBA2FEDD2C51AE61B4D67C5FA6B444FFA2E150788F1D4A12CC7875EF70711A38207C840C2A0337BC3CF42EC1F81464F731C5F460820CD473532983EA710846279B000586140A9B8F2B873C200B8F8D55D1A422F2668103FA8169DB77EA5957C4FA9A72259B60DC27EA16BCD31A051BB528246F05DE7B22398EA32C2230FB520A0D600CD8C049DF9BA6A5C665961344974385FA55525AE340342757BE2831807C552881C13BA133CB9BA2394453818D579787A6CFA356FA560BBDED6182A676126494D98A80161A4987B126DF67633E7433BCEF68690A12DE679512507AC1B9186367139213A3023418C69D0C67DF320C2CC88BB7045543C3380E4A953A03E63854FB986BDC898111F6A7A8FCC74A4F3971F21850E9770CC07CB0C5122CE8B2F873813AC558D9D4474C80084F0A924B3E2B7F4F4137EF5007F0C5605658DED4677A314A44D783C2E3222683B4DBEEC349FABA4430AAFD49160B6C91F2AF4092EF63EBEBA1937705F18A387A6307A733773206B8F2D4052D4C36D2F557FC0E226266116CE41B59233363ECB728C0343C0648AB1045CB03A1C225B89FA488114A060AAF48A68CB7B20A3C55A71ACDD7742DD05AA8495815646353DB21D4A7235450076CB94041D94A5D0245BBFA3598E870FF0E30FB81213B6F9916B78AEF3D43574CC07C9B5CF257A92876C49ECD73B5AC24DEC0BB25FBA54B29CC4A410AD40B5C6FAA398CFB82D2401878C79AF021CA0653A0FDA4B6474F942F93700ABA364AE3611B7666EDE2A8B2EBBA701AA61387500D674A9A9FB0351F06A5CB699EF73457A8ACE9E8B63184768363C50AC000220F2CB708AA27522149975BC951553EFD5B577D507279346E5D00F2EB31EF1DC1EECB59007027E65D28F0D10B7484654241984010B224F174EA69B1C36A302BC20B3244B030B231FA5532A4B206D3B3398E9EBB773B9CD9821BA688C06BABAB29DFB6AA2D427A258693BD1AB13276990B1775AC94B6BDA89F8866AA3A94003B3985086232A4A61CEEA8B1B711609B3285AD158BAE4C21581AA1541CEC7101AB7541098EC7093E442B21296ED172540972F52C04EAF6581EE942C6ADB287A2AC956D84B7F726158D8637962A40986B1F2AA1AD6762C08412F67D1A7F69B6F0F87AB022B1A48F4727CEC2277D1B157932B860A156DE79FEADB99DA7CA0D0B7A4A9D0B3686A100505369C47AD5DF8661CDBA888FC4C7EB1CBF9555548D87755C3232BC3467727AC4625B49145BBD95537585018A7FBA2A8834ED587CCA5F44884C87BF5B5AF8857A188B77A36A01B16F28934E38C9513B5A44926FF41212B13629E2986B8458AE3E9975BBC40C69214068BB78C127FFD4A664DB90BFC068B67106A43F1BC7B094E6048A529B974EF615517ABA2ACA75C97093487C2A265330EE5454985C6435FB989E100B5C9B80DB0A49421D6A75E1632F4B03F5AD96515039D8291C67A15902FE1C027133939183EA0434AD25B45CCBC0C69162CFC1CB527E392B1756E64561F4442BC5814098F33AC673614A8DA326F8818718603110836AB31778536A9C47BA820960CF181CA829A9911792D67DB209E9A66CAC38BC57A4CBD4AA3D07C3447F72D4231A69326AF512314D9AC918DA0BE19B624E5446180166D05F607B1EABC04B2A442DB33C71B66CAD3AA8E559662284807A69EB0469E8B321C73900A74C4A66D40B3CF382D53A12FFA26B9C8888516633E9F292052FA231404483FA41E42A9AC72312838BC7E17027C5EA055967497F3C9988D5A6C4076913DAA9D33C11D4335C850121A93C25A89E3AC0612087943A35E23204EEB12921675AEAB244BB53EA24C969DFC2A0F99BF925666C9A69F123A756104CFBCC88C5A2C8AD7A21956272E22F58035C140BDA371DDE7329D6728E2A05A150719C2D578FC511DD3361DF765C83BF2B04BA7546E0CB5C28C211489C96265335FB5BF6B3C3779E3CFF1C77379E336F3481CEF55F2F61A3CD1F98B88F29760A2BBCCFA7BC9270DCD07F290CEB1D75B0F5941"""), + xeh("2429F93D29E48EB6A25ABBA3EE2F3423CDDDD0ECF4B2090C6CA5BF4883F4F3BA") + ), + new EncapsulateTestCase( + xeh(""" +FDE545438A542588554452B13FB2092F3113D0DB9541437B6ABB3A02A713871AA479A1B6F5C20F208226A0028B5A680AE845335DBC9B9C3B91E833C8FEECC89F0CCCBE4216949684E094A96A469EA2B09F5EC49A352084CADA99EAC591661A1A2C468CCDCC4C374310E78BB0FA38803B1B1B078C9BF0D9280323067BE76B1BD3912901695FE1C4AF4A1BC38661AF797F9D7B9D8EF091EA3A0A53210C57A706ACE6A33F09083B728F767B51520BBA7BEB364817B820DAA55877CCBA3CBFEDF60E48FC8A0B5BC6D223CF56C3392021A6DE432F4B4A3E58ECBF462376BB62933D6815FD085653D5C3A267C150697BCDACC54E336D7024662BCA1782E531DC339851B33A0778A779544F4B081C05998787916A802436DA982B79164C5A5823D11AA271187E8F90790CE95C1E474E2861960F756F3191267E0158C1150608B5CA7AF09C23579608386822ACB02D559974FC6FED8558CFA6383ED0B5FCA318648699DBB7195F24A000E6A99FF8B4DCD0C3C7B84E59F7CA21979F646B4D8E7A61289605FB027DDD3A10CAB301B9918C365714E1391C42185874980328C04900AA9967627660C6ADA737260D74A1CEA5578A254FF0F203DFD6C832E86EFDB25A08AC5609DBBB469A7125A7C1C8644223AA51EBF9C98DFB64FE530FBF47210BB3C142360EA864AEB447459C6B361757AECFCA733CA2C5EA485B0AC065E2951F145CCA4FB6951579B4A19CB042A3B34419CF29B99A6E579945EC357C7C7BCD7578175BBD51444C1DC9A7AA54574A32623D2C90146B44F2547EE9930282F25447207B03C04EF6AC1294B9BAC6C36AE1666401E318B730020A832ED789199CA8445239B765D48610C6B25DC4C592DA7906C130A6E356C066534388651A0B4F495C39962C9F20DB1224B40AE0642091115BFCA34B5455568E97B0D45B74592905E02BBEB8FC1E2D1C49051242AD000D69009B12A206B988B8CB26A91DBC6305777234FC22142AC85B828D1E8B9E589800214173E858497B964E6DD98997576F5F4B9C68090563F1B004D38643E2872B196B1F607AAB3C22D73324DDD49CE4214F13065405767348A20BC82329EAE2283FB65ED1EB939CF25A7B1762E9686DD3576602073112141ED315300BE6B75F860884E0718C7596FC39172AD9BA4EB837393C49DCA98AD8CC15B849965C017CECDAC67161A7DE6863698C8A64E23A19402E977539E834887954867A29CD2F46B0FBD6240D89141FD8C9ED390099D905C5101B63B30D4D61AF14965FAC227470B38642064412747BDDD2063A942EB0F02843156C1D637D2D8C6C5161CC3A21A69C6220B39CA03BE975B81921C56C140422A8791A9CA2A9AFEC49353B65AC2440C31E2084FACC6F7F23A027A682CAAC402A69675305363BA85947BA5275B6868660B654D91264870FCBE39BD2E68B9048C29732A3A7306AEAEA8A08BB65E5E078105424A3B8803EF9C62CD65D8A65CE6D528A1A818E1BAAA4139CB451F5A20C135F8A231E843531CD700A2E69BFFF186DFF49108562361F353A8E5A23C900043034BA6B9C6CDF2A7C67847F78E0955F7C49EA94785AD3495CF4562EC86F72E22B562382B82B392DBACC1F536C18C20086A879B82C291F45CCB4C24221836383D03997C43EDFE165A1A046405A193E0ACDD08B122AF6925DB303491BCB87DAA36CAAB91197BA64A9A9E3C4A760174129B080FD18339E07ACAF00CAA118A84360AF0333755B869694D07BD108AF4A094C51A9165CCA9ABA36C2E3E43FE4DBBDDF257E08D03B333773D5E051F8101B8EC7B80FD1AF5E9C053FC71C0A1C785954C3AA4C33FFC95AF6CA3B248B5F050AC11B3998C51C8A294544CA4A60DC47529EE1A3849314AAA62A05D3557827AF57FCA1DF9435C4014669B9142DB620AF044C195B6BF046582C52BE435473C74A34CBE751599412B96480678B668B238DF373302076856BA63AB627CB21F3707BA18B999A3A27DBC727EAA8E0497FC3854A4A926905D0968E3886FFFC4F6A2B4273993282635B9BA013B4B8C91E7A47AA624F8262A14C42B4B8A36027573D4790BCF5D386B9181FA0F357230A2185747875970C668142E3673087AA02A5B7AA058C7527B1C0A1C9B05C912D49D1BC8FF629FA77CFEDD1A7F6EA52F9BB49A82B38C022C52C87C346482D42A797BD3A972E19DC352C66A0A315C04CEDAE314DC0D335EEADEA8ED3B75EA17EB388"""), + xeh("B65043CD3672CF9AE2CACC94F923CEF63B5127ABC63C2A5AE6C064B8C6FE7C57") + ), + new EncapsulateTestCase( + xeh(""" +E7104DFD284FC4B28110B06282BA8EB859CD60F8934CBA78B1F1653CD4A9613B4BCD5C32A3B30EF863A448D3A17FFC5908438800C5CE12475F3D5445761CCB25541FAE3653A8B8776256C7F5384481772ED0E3C4E512988E605E1C75A85606AA574442888B87F0A77C08824FDFF2B5FDEA4834112BF77C011F7855AA065ADEC66F505A72EE45300E2C9B18588E2F6B57B1C2B26F491166AA9D89D9BC2ED26DD311A81E4232FCC720CA8A788D5A00DB696763256F58B2B68BC32653C71F84088383473F19A76ADE5CB5B6BB466561AE7294770F9148E9E44B2FA1A23B1B99CEC1327F60A002728F21CB9D25AA79F526CCB4EC1531864AA550C72336509FB3061717BADFB2682EB59053333CEC75BD6E244F002D0BC2B1C8008737AB62CD42D2BDF9CA2FECE31DCF836264F84F76569A16046761885C163CCCE986122A11C8911C9257B88FA2CB792BE55FC14048BB995F11606E4C3C82B3113D99B451686ABB1F129E22D63EB14C6C3EC2479BD0243F57876175B138BB0D42313A28C67F1134733F76977BA87B5A11523953947B684282905F2AE90F5BE1CFB0088539313A9FE2A3AC9729C2FB5FBCF492C5ACC90A74C934B1A29AC19D2E20CE74436742A1415A9A0A4CE3756C199AF7593A7685C02F19768C6A1F4859B04B0186C63580916915053404054929F8B417F6A3919882C8D31B220F1817DCE08267DB0EAF61301C2844CA4556F813279D122C43A8820560A09A18AE2807163547B9A3E22F83E14AC4DC3FE69A25FD5C2CACB6A67905C9C754565EB5B17AF089C4653302AA830375B9CF0BB6D43904DD8277D50BBF4D43ADE05918ECFA74DD432CFBD829C4F9838DD76EB75813DCF397E3507FC9C6BD69C2B220644D3EB8839769CFCED608F98874EBAC4367A11274317297DBB424B95B9062ACB4C83CC5E879E6688447F26C0D2BA3763406318BCDA3228CEB0641C7250DAC193A8713744A6ABE5F6C106DC4049CDB49FB946DDB7A08D2D73556648F4CB82E2AE989ED61677B805F3A61344A14A2F3DC3964A90E4B83CC22AA8E7CD532BAB55880F212751C4CFB93AC14F564AFAA723FF6B31990A88DD32A557AA86EC2ABC114745C8038F4C1C924258B5BF02134605923E865539425F10424319131B0CB17D72C2981A944FCE3CD85A2509E93BE3AB5A65E53380772A56D74945D60C57A112FD87A2EB7989CC14A973CD05590495122811A6D8992C0064C77A78C7E390C43FB695726B7582C96C50A8EC5B4081CAAB6E9B64870166326A8ADA4731030290CD444B9E28149E06BACC7A79C5E7B24BAC292B7F92C7AD720F957013E1B118B3A40095C705DB33DE334ADD011CF3DCCBACCABA3B12A6FB5962E01C7C8D83912D9F98ACF8B1BA073B25AEA0C177074E7EB08CFF3CC7D7709E723340BCC00B014A0B313008DE52533B72393D70B3EC767A8B6CBAB61B8B7A9C86B263A1528A9FE366D60104C0D320CEFB76A688B407C0742F8BA4AB8007A3651C0F26B81E92746DB701837B575AB00A6B6D56FC5C12C956685ED0AC3F0C6A5870935298640E5070A8B74AD540CBCF273705C68115A828F72B09C83551714D67455EB46DC0BC14145CC38F5C1DF675A3677ADD28C69F0D462B1F1A0ACE8AA30B877382280F903B7DF9503E4C5048F4368B2A58565552EFB106E9AACC75562C31E3A3FE7790EC9269987C627EFF798A9A0484F215A3968525A0915C4B4AA7A8170EFB1466936A8B8440DAD499CB2F94373CC91F62673B59A90C728A818247513445D5AE25D85AAAB0036135DB5BD74D106AC557E0E8754D1E071B5B62FFF7575847B47905BBDCD5958A7A86852C34DD01286CBD50F0CA4628E31C5EBA531DBC02C9DE1BCD82C218C2CCA87A42A28D98ACFD1103F80AA9073C127381B4584C923492960537A28B868F214251E328FF44CC984972949003916B76D89D472B97013A52141FBAB0939B03D8D57364A387FFFB4A59D7B5D586680D7F54DC27AA7BAC39580103C74621E6D8970176AB2965ACBF453A7217A3C21769449E9AAE851090B52390642C467C9A233501110F059EF4A1A02BB06CBE1084A08C85AEA6237DCA55E2698D177716E662E2DC711D475C2EC9745BB061A90432C6463BA827BC32E0B0FA6B015324C9B574078AD823ECAB9010D0BC640C0A20E17317B2A30AE8AAC4C94695EAFDEB2BDD14D78D1CA07CEB411455C0EF10D23FB50CA"""), + xeh("6C8C075658F4257D42010EDFB1D7EA290D3344EE6E4C43DA799366985AD52243") + ), + new EncapsulateTestCase( + xeh(""" +F1E27E473692D70B178B466FB72CABA716C2468B308C0689615A0077215741D70A633734F0140F4479BAC081370D3565D24A4D0D7AA189F1C28792BAFFE9928436B9C0215FC655253D645B3B84C237212A7868131AA623DCD8BC2ED65A2E082C4EE29A978B0C458C9E5BD656ADFC68BF64291C387886493D12825B8363932AD17B8752BB49B63D074A508AB3CDB7341ACDC5AB76B8C5F9C93FD4EB74CD9891BAA467DDB28E1733A4260A2A4D496A3F705E318A042AAC818E408DC7A9BA20520E3A4CA237C1C581598D839B67822CAEE8C04E7BA6219ABB23D9455917B84CC5C94BF8594A2D1127601BC3E76B54155B1AD8C5754D13B564906E3688C3DCB9B963B7295310341EB0A36917919D289C2A1B001CC4360285A40DE87978FC532A242422829BF8079D71F347EDC072B9884A5D26C84E07B72E529DA1FCC8E57C1C2BC30685D12635B3A136755A70224D79FA7AB1124A69701DFF4AB135508014FB4BCF044218D4918790455923039AF9591087A5ACAC37363097C41B4153D375C933C488C216C5CC1AC56134F9B3567519CA21496A4CA06AFB84C0DC2743673AA94B15867EEC0945398376DC6981C6A9BFBA78D9950E27E16D3852A63CB08BDCE1C99172B4181654BF5A90496C764B6B96A25331E84162F902009BB4B76D8BC41C08AB7FA8B1C4657AB51CAD6FCC324E4BC70979AEE6125F2BF916FE8C3F4F5A72A695A6F8E34084728B0FF59CE1FB5161D8AF07CAB498D23475869F746563DAFB49B64103EAE0CE8A17BFDF1853E743262593C327608B27614F32C1ADCCC9B638029F7F9377B302248017747AB5553833ADE94A3846D309D5BB9872C89AC4E7831D9A3A3FDA26A42747E96AA6EE375FD407585E964CC4D6821323C7874986A1192FC0C62099A764A4554B8D89B9D9585A339072E9D677ED3475181197EA28BF6D84A3DE367D7529AE481133D1618007D5832E0A13B7028BCF5CAA36F4861DD22DAA497167E171CAF912B9FC8056016520ACCE1F68397246097A5755F8462FAE3413408264BDD915BB253A6229C26B14426F439D9AB79C39B11A7F51B9376A300C7530744B754713A50D71BDC299B9C0C7B266CC41F31AB512D0BCF5AC9BEE85BEA109734E7861646A7160BC3A27AA5CA3F87128468F3266B2B156210AF79D03890386A9AC0CB71BA3B41937960E575494F60B0704960518399199CA227D48B99ABC8E85C1795DA67C0D331B40CA8E448A934A38CB24D0730E181A7B30366335958D5993385871DE69C97B22A1DDC6BE8C5242BFD93073893D2B498627B76B6D39ACD7405B64C16E60E190CF45B5EB12735572AEF8F99E37CC3C1492979D3718BD363EABD56E1E416ADF9CB106F3540ECB4ABB052D57C728A558AB52FC4FB9C078374919F29558481C3ACB782959E2C41AC05B8701217E7BBF945B970298A694FCB0E12490A6C5665E267A8AA1A5F060CC0A08093E816EF9644720024FD0ABC5C30C39EA095FC5426E732C2490B288FB38AA6A3517D16BAE8F38BFB091BD70260BE1D80B2694B3651316484C1E97B714A67A0416179F2C582E25F770EDE422453607ACA79C1EF217C2418840609FEDF914D083595C10CC4CA70D40A8BAC5470DFE4638DD86A03DD428CC305569963CF620931B40245FF3098DB6C6A1870D5D7B838C976D0D0B462F441B2D79BED3A488697A191C20C0A8281CA8A39D61E69A0767CE753A02EE8987414AA3BB99BAB032CF451BAC1075162CD1097B00AF6A4A82F8112F28861BF0A6AA22733DB462BD15F95A211161ABC0C5B5330FE4D63854F3C0F074C077D06AC2839F06913FBAF33F7F91A948A19D01D6110AE54025CA068D1B0D7CC66A6EE0BA83E377FD2313EF44C87A58354D841B0158C8010B6EEC2898A9A0778072149452C2B6A628256C257FC224C0B767DCB3710071A71B43015D994ADCACCBF7B3A234C11FB2B56E75E4154DBB473978BC25758EEDB5319AECCEEF44AD82C3584F8378437763C3055C4A84AB71815EE5E360AE0A363286936486C69976AF602885769C1CBE21229B9C350562AAD4A91BE145AB3B090B9031175EF96CD275CDC68444BF890CAC56241159C55A474647A4257A978470BC97D28549F21590EAEC25D9603ECB5909D375CAA56B076DE917B8C7251C92B34563BB56AA6C3749113A837B5F6B5496259F5EB94195E2AADEDA453309F91EC2AACB59E01FBAB4B8F8"""), + xeh("BD990171C3252230BE21FA7F186A121686187B77C234C37CA5122A7AC77E318B") + ), + new EncapsulateTestCase( + xeh(""" +1909B5ED6C0D8D3C301F144373956424139AFF46757A070167BAA70BE7BC375A6D43E18FB0EB4A69B49A2D951E9265BC159A282B724F3477A2DFC89378CB9FE6CA8CBF55BE9976CEC668402D7A3D2E4CA2AF6A1E479621DB16A3187461036513C84ABE5BB228484023760266DE5CA11F1A8C63EA77F6E45F35D4CAB24443B51B851DD2C58EAAB9D426C90064AF14F8BD8984CDBB84C7E2208C5AA2C7E3A222249943985CC1F199BBAC9B8719849E5D539986D8B063A363B76953D22A508CEB03C46A04F19769E327A774A063B1D412B7B43D5651051E547487F2293EE2B78849BD36D2A54E966F8B386BC735152DC34E1A12772F67506B6474A2C57AC0A8CF53122949D52828D69E8A7A326F18599BDCA23C8C8E3B28624F26609DA18044411A9866C3A7D7083F09707A70192CEA40B936BCE696112AC92582428F30A800876BA7BB40560561AC5996A4B11639BDF00DD67A52F85C6BAB54055C2352121591260B656C43B2C2E89A891C97F39B7921794CB5A552C05A2D8E8BAEC89250666734C2DB73EAE68484DA254969918B10914CF4274C2C27319412360433ED27C810712F4E3145B5265D1EDA7B6917CFFCA61CC087926CB116020C7C49D1A8A723C197CB44118B3861A0773D52C6CE25A9E2C66BCFB6C5BEB43185EAC855D1A99C0A2FD5A348BB0C579DC23C7E777AA57249008497C7332EAD85C491A89B76427835983E00F5856B1443A60C83C714B122369A97C356C0755FE1F249C8D56F0D9897680CAC247A7EFA8386744B607BD7C195B52C07001384C17EE70AA04393C081EB43C7F912F3D786C7E63DF043A277329AE2C90A0E721C5713A47417A9ED1370C2761C1C029630C26DD215028EBA6CEF5239C25383F6370863F622BC055517946EC0D2C4CD909182CB51C817A04C53B4309B14507069303245B4B55B47226970D269D87340DD5A864A85A62CE3115AB7A972C813FD18C9AA0B582E79C228468292A8A133CA5C53A4C842233FFFDA7DD0002444C51B2009654067C7AA34BA17B7368745C1719572A2C66D6D894B92049EBDF629C7C5A2D1EA82C7791B7840729DFC7975C2C18F3B319B45AFD1E0BB0C527D3FE8BB7E95A7DF958EF9268ACDCA208053ABEA894928DA891788177185B362EC3364F93D4B602167942603412CCB595DA8910B748A2EC022C3EDA8437781BEC4A913D2C56043A1BD6A5B2A858A8F7742A82986509891A9EDA7859D3A99FD78A11335910D830FBA1B13823154ADF8984DB9066B6735704196D49C8771B870C05504EA110E252B4DEC2743F1F39142B6BC5B635110CB37925A3CB0AA83858A54294B29054805B969A6352925CC53017235CD75DB70C86198EAE30AE8F933412C0504DAAFE7516BC9D7A780E04290891E5594819F08C2ECF083711A85E1A679235441976B03E37B0B0DAC6BC8456497220F2D4B927688021FF90F2E00A64DA33D3C878462529B98CB709B01BDA6D27FCAF7899BE90853BC6C8652137851C3C7FB40CB3647AD8B7B081B46C8A2587086426D48819AC1AE43C429954BB5F7F2227FD8058C18AD81203462C055ADD5045BF48CE22271C5A67E20ACC0EC93B182684E2B230C0E44C0688A2BA0A6BFB7D10C476B24719700C70A7EDEC0C6879345AA781B6B415FCFE4373F78BB33CC62A659B8286154073193894B6D8AE85284033082186478FC763231154518B1A8A59B1CBBB56A50A8F9C38223C5BFDA5C310A1C30F2569C4E179D4039331293CC18870E1D1B90E0008B29008FECF00152748FA9248B7D64491455044D86C6C3565AB4618233A2154BD277DD5067B2E6784DA94876D1BEC361869493542C470D7E58A7B6F9236E200D66CB16D70A6273E40C8C69C033CA8EBD7A2E5ACA69A5E0CAD2C352D0F36BC8A0B90A29B604EA0DD6A77FE9505E717A721849A0B435C08C66AA44E202015CAC90D364D1D83F21E5177A100A9E7855A5C5C0A4B46B388C58D256088E455D59016A4DF337C8A69827A399E2E9BCAAA7B11CE6440A7536D0BC544CDA12392340504088B8EC6CB737C3B1C0A11F9B83C049759D74BA44507C6881B1F98167720C0B35A095DB1A7659B52E38803935241766237E073B1D2C52BB5F4152AD80625E7C52352AA4EBD89820F4AD1DDC3944784A239A9F71B243AB50C1700BA6FE82A501B275DC3391EE30C022997F00F09D0F5FC8A9F5B02358F99511C32A582B24C0"""), + xeh("135056EAAD8A28DEB1BE77EEA30CDEBC7B3DD89D1444DBAE145F39898256ADB3") + ), + new EncapsulateTestCase( + xeh(""" +11068DF3FB0ED1514D8B2B8F424C03B75995406482FC8AA24BA003886711E921832222367CB2C2EE87617A30A270B447D4A1BAA3377B83FAC80A7C8D779669C49C461B311DDA442FF10C9F2B9057225423BD119C68E34FA7A92DA2D36C58014A9076C391A451EBA75B5C92A2F14853845838D0DB502629B796703523C29575B4A5094C1BE329066BFB7AB6E17FD0163BE4E60E9D676FB970C68AE416897174D4577E0AA8BE0D234FBC80279FD724AD5925FAE2B478816CB07C165A335F1B27B030E7BA5CA40F610B0E07C82FA134812D9A4E083836B158231DEB7568B73A9B3C60780266BB550A36C7288A9387D1E4C904D79296088047F34F4E72A23A1720B7543FADC3821C6442F4B501E6894A6E25231437AAA7A04329A8CC6AC729B185781B8BC4D9142063E55A0F053FFF57CF93C5851C86714E872840A264E316C37CF90CE60960EC2B0F4D18418AC96E202C07EA61B2B1E6A430DC5DD1A18926E0BD88351B56434E26CB10268468D67B2D04FB2AE7C43C032675A2C88A3E704A7D110B4A544975616D694C9E6E243E3D546217471B14711505B945E87C0D39170E3AA71A0663062CF07FFD0C3952D526B662CAFCE429A35839D667C7F0090965CB1F87642D2A8C28A0A57B4FF539CBC3195A0B063F3966CDF41FB4D9451A84970B6B93E006342247BF5DF06B041A6A2B019C3FF93DFD39502E198F5587B358B39B640C7A71C43A31D711E9E5434B75AABC436531542F90730EC7FA6B72A3613BAA4C0579A245B06B979B22623C93D5CB6437D17A7E3302BA1CA5EA0533F02B1D481573C1C3AB05424900F1613B379707433D7089A316F52012B646B9A24A90F87584C36C1F58B891F5482B757F758A03E53B38F282C2700502984ABE9F1C2BA00376091021DB8A1ED27B01AB11B7F404B2C5FC9E0F8943BE434FA4135A4714507FA628F4027D0DBA912E0B3B096C057BE77506FB8BCF5A8EE6DA96CF335BE8C0555EE446DCB96DC2567348433E98D46C83319E3FE1624AF07AD838241C5CBC3C78C8493214447C8AD0D40DBF319057531FC456CFDEF999F9F280234A03C7437786B1469D705655D01EDE1A72BD0981978815086A0DE74B059BE879199A67C67BBCAAAA87201A1910F39B5D35670A9790DB3B5EFC798BD9EC46F2FA1E993110F180203BD1A7D3506B87325DDDD695211440F60CC1C5B7A947F42DB94ABF0C8C3B203A7038682DA9840BC8B50C4343A4D49AB89DE916CE72835AD4C7298B68BDB417EE999EFE7B20C6C99A0B36BACE2C35D7388DCECA369768463051B377CB57BC0B155B969EFAD615BF7B3AA1189702A7494CCBADB0266224FB5BA75189766771BD1B54FE1139E6C607C95A2DCC2462515C4C1981C931C6628202A1BAD941AB7667F89BBE94118568F0C5CC59914AB113AA4C9DC2787F92BA2E9DD7363D99CB7EF6AD2EB5C1B992670B5541B1BA9368E7986D4628AE96836018934FD100670260ED931BF9A47652B85C44F988B559A48B2007361A3E4FA88AB8CCCF94939D5F419861FCC617250C38DCBA082CA50035A196880540E50A0E1BB363E81B1FD158DCA79DFFFACEB2494712F28A52249A103C5FCF888D275A8BA3768BA0599F5FE1CF632B07F4120570EC5A3EF96CD3031A3425A0CF3A7E408337412288575C1A414A271149A2B115825D409A1C478980CCBB4B4B1C2AF675DB141A3CD12B0860318EC340B7D3C2C0521C57D5675864243AA55C517BAFDA7187A174C109CC1C65BA42AB5288EA23CBA8C286EF98479BBA0396106999C220CFD043C60C4B9610ACF0086AE9D883A0A89BDA5AB9993C1DDF82610B0A1C6D75093B207A72037E77E76CCB282F2A0C7A9149941F3A149EA18CA519C1800B392F48C3DB358EF1179498CC2DA8EB48180A99F1BA280012A324AC8DF3FC8B3D6859A0B4334980157994502C80C0AAD301F6E9311AE9C132889A3C26501678CFED55427F94B05B57404B4BACC7607E19E873D1902163B25C06BB3CEBBA5D403456C2CA26CBE27240ABC8B6A85E50762FFBCA34FF96C1525B2A35435A7CCA663B37C202931CC16039EBAB2D6E45BE1002023BE959F2568D4FDCADD8A1B6EDE529AB088D79DAB407D4791AB43FE5087E4A9CCEBFE02C0C44C3FA925B7294A92E928C29663D2854210D405ECA2C2E5032A3058C6FB2B381F5597FE98855CD09B73DDFB831B56551306BA4591ECF403545BA"""), + xeh("54E7B2E3305950EA570F823FE36A7999E419BB36181B5514860BED41F418EE77") + ), + new EncapsulateTestCase( + xeh(""" +4F4504922C38F9871EEABAB438D03555F272E9F9493F005F5F8CAF8A620F362A1D1B90A66289111D03929118CAF31B0AD9ECBB203017A02711BAD26B02310379C117F6F58257F6C6ED5A14BB32760D5A9EA062A9C106064D703BC9E378DF498B347075A7F6515787C500472BFACA0729A4590D39C291DCAB327C10BDCC6B1837883BC90B379B3C32F56C30F78C2A347EE0452FFE4878E2280608265931CC7E123768B0F93EB0081D642B4DC756210952541BB3BE08352CB983911F3B944671B759A16FB28C3883020892865E903045C84BA1E5E54159604AC058056C6153F738745140CB8B5ABE3318809651790EDC20CA5380CC76568DA5915C5AB8272748B42446EFAB58852C619332A08F537C28E93EC676345E0A2666708CB5D5281F981D3B8A19180565704808963B4015DC9B8C06905DA43680402E6B5888F2EC7448AA6578787EBF42329D060998E74B09C13D1C432A17F56D18BC624F02AC7ECB6235C42A24B42639FC490D07A635360932C71E25720EF59340F21836B74AB8F31C2CAC035AEFEA846210AD665A5D64616861F1CA3B963A2C10C662F7AC66298751AB3CE6A64C59770568B4B234129550702375D722AE4BBA5FD0899C84A834E7B7938627C9285912D346099423BA37B25364B67258A121650E895660C8E014A5B08D38B7AEC29175B424C234D2B87C791B60159AE753CB61D240DDD2814F1A7EB69A79AC37634850CBFBE2CCE6E918D1CCC70E13707732A6AB11329A3336D8E221531335BED560A468092CF690D1B8791F58993BEA001186AF5E48A2BE0B3D17656A3ED98BC3628C9F863A2C88C90AF25A11AB41FE7CADBB3C1013B59A115AB83F9003BE28759A3148706B891D9770961AC53D4C8B6CE5788ECA3F4A4A47D7F5165DC7B94B358591348BAD7B8CDA482B26F650DA1765A0911527260703E2CCC703A69F10331095BD3AB167DB52A3EC16B69F233862EA11AA9118FF539071A05066388A6DFA10BA4819D31A03B3980677CC6B888263D74007057C6C3C272464497A58681816C3C59E05064D147F62D5C848B8919C97C3BAC20A43CB58F8CA98EAB48B221851F634459B7AC514161A1C490B8B576A0FB2497A65006EA78F9ED50763A19F8D2C99D546642A68B6C2A49FFF919687E67EF0ECBCE23266114982FDF15F572A9519EC12CB90BDB3516E85E01106B9BA456738F4206F5F0C314156307F4CADC8983A91F730219C322A1602714849CD1B7DF5D02C24758DA6DA8FC8600CA2C1CF7294B1F6598D9E844625C29F589006C0875F3FB33EB357B7AAF0607BB31743153B98D64A8FC56DE56714D71303E9F6A3ED228961E607D6D6C0D4776828B7574A8CA28D837D24470E56F3A6CB6A4A90F5A9BA8A3F60576857E1C7AA52A16E1A84F7421EDF46C312BC83EE0776A9819DFA8B66FF2BB907A96F4D6228FF34ABC68248C1990C2484CBBC70745B045C602C1552B952FE8B4D24D027E1C65B3704945E507D09A9A6AA7000C1607A27591F606AC1D2C5CB55BBA149A15C4B261894EC9A9AB9C3DE446C1832744CF6BBBF949D54498319504BABACB8DFB15F90F66DA9E0B7F8B7A42A7B09C5E19DF58CAD8641C2DFAC77412B49D17A0C02341C6FB78DF00809903835518392D0288907184F126A69BA77863C84C1813835926311EA705433298D77AACA4DFC30CA218DAE405732841605840625E57D7CC3AEFCBA637CF8077ACBB9CBA0744E462D02F406ACB24E9A3C5CC5048337390E4EAA295F6831161CC7FED8938EC6287C8C08DCB0AAE66340C4A380B5B816B8110F3D190EB97C8457DCCB410739C48B8132A32C0CF59028962A8BD1B03F0229C908BE9D22C9AE65880E110977508595F6754776B4203AB1633870C4EACF7B3689A8D43F4C213FA839B7C0281D242452455A31F396BBBDC41D9C4C5F99960ECA0537DCDA3FC6405B139241EFFB20CFA05A739A43EBD39E2A516A6D136F78F43CC5E24C2335CBBBD7335DB820A235129F10C62D13C5013732214012B00C1383E670D5D37484850D2EA49E9E835A750C63BFCB2357E472A4406C6DD2990349987707CAAA1030D4206460848F3C988179E31A4334AEE89511AE4297A668A154270D963C7EB930CD3C35290C9585F428690F88721443757D793D9DF912680C21923138D119B777530A3FBB406E110F408199CFAE822AF8B67807B0181714C1EB366D2750DBA3CEE603"""), + xeh("F2C864FFBDC366EB96BC5F5FDE0D4B3348A07E861D9EBA90E70896F7FFCBD55E") + ), + new EncapsulateTestCase( + xeh(""" +44DB8BD3C4B5FE45CD408B054B878343261AB8F812BC75A953C8617582B10D789F7114A00E0166EBEBA0BA149370639BCF020197F82080BCBB9BDB49D15493114698079B7021C55CC275612D843FBFEB0F2B86CB659C6EED1CC5661B711621320A85B307C96F66C4C35C3081410045AF4B898C2C14B645AF9E0C9CFC03BE42DA4DB3A759E77B7D6894BF380991C3D4CB0D5B2CFFAAA08DF0085B8555228CA8E18672880C4F96E555F879C2CD6740960B94B6A60BE7557D2E230083D757DF76506311BEBF28C5496C00F338594AF41AA15566B24B004E60956AD09CCDB034B7C35BC5D550F52828007C1F85503AD86A9C811C440E6600B16CCD51EC098AE298042C128494A203D20BDB4789C4314C8D14543C9553954C9FC34C40912862500B2F3A5929471382D3531FC9767CAE6937D6E37D6AE18FE5B858BA968927201912782C6D436851C80E7AB0782FC5AC1D9C2F8CAC0D6C29148E220EB30909B2A43A4322B90E741C90C19AD52CBC1527CCC883209952A5A7C68E3E580BD987338BDC75FA84CDCAC3A0990246A7050E1022AF89C7165E45B32ED995A8C4B7FB28999E4CC2C79250DAB67119AC2C6B5B195526439E17A913F3BE3BE896E8023AE6A78AC00244B8EB2891CB5634955F908424C4B77BFDDA017D3B71909320CC53C4D4196E0C39701F8839711BCAE59BAB4B4908F5121B931777E17B331AFA5E955B5CD5840A734A41E35CC016C01407B02039B5064E97C24F4B9197091DE6AB22D0FC0459033EF7816D12596CCEDA120F534CE74571A4E668F5C1488C1503BC0354161BB651F673DA9019C9A83D9D97381E72CCBB1628F8F9A42039CFA07B1D67A1AC37407319360883539E7E060D32469CB9D87DE784439D2B453B77C158045F4BE5A96F090603963A18574FC027C0A0597D6A30B9235ACF5FD49619F47F7E8833D5D719B9F95825571B32C17B0B4AAE2DDB7EC0B14413E73EFA105EA308AAAAC76C2A257DD4A36407468802703787C4AF27D21EDD08108534AE994A1805AB5E6235B88AE7C6997374E50C1077F7702F809B092368F43A9CB2AB539FA104F5B23A4E69B9D46C4452208E3DCA58CC1045955784C82099EFB01ADB86CFEEFBA1EF3A43F16B7CDAE28A3E74C24B6648B8F20AB88088974B75BCC79E692C57501783F57434B7C2BCDE20B2E7129857EC9FC95452BACC9D96D89CB892C78CA07E790906A6FAB62CE170B63443CBC9BAD6F48B383050FB788270392F396C8CB8A73D4912115C41869D54AE1AE6173A34B6C3C91A5F6C39DA659268456E0B51389D7B05D4367C9F5C6CBD371E84EA9BEEB4C09DF9205296B9E947BD4E086A97760CCCDBA94A2108D02CC6544028E05A2FED297F32491042241EFC36A24F634DF3626A217ABA75882A050B7569318E8E00AE8A267EC0207CE9E8A524E1CE8F8CA117B0C77A680231F773B756152878363A9C38D93423C0378A60C8AAF8063BBD1484A3F37D055215A4403AB3C80DC9223D91165BC2D077C71A49093548D4A32922633258844193759D4DF26E1CE367C3229FECA492A9E7669ED4158CC08D9FF0C24027AE9759A517DACA6CD58090D5673C753101987B8914BD8B71C552D96DD093257A9313CBB757AE42860790AC70A593ED65A492078B6043B7B2AC4CC7D85A7145C6EE210C26D60906A5571AAC3EE71333155055381281A584A66C090252A3CA70D9AF09063F3DCC9BBF020715126122602AC9F9930D59669647CE64F356DA97A5C1740BB283781C2A10CB161BAB6B709CF9AC7C7911A23A9F4D6507537C497F3BA5CFE52AE9E34B1D9922669520DA2662BAA0282B33C5029145CC34B0FA9CCF201C6491E12646DB1D1548C0FBF6C7925C9670F4ABC84AB289958A26A9310ABA90CF8C41B39B7DC96673724CBF4BCC7754A71E3158B35214A8706652E11621635C5B6AEBAF64365497518D5D1B6635178E318569D23C50C3683CEEF593498037457C4494F03C7E92C055BABEB96C70EBBA20658787C1B27D6CBAB485741712F9169E3265E376A0241A36C0B2303F8865E6AA9D89213CA1F874E758A569E4055D70BB1B512C0845B933E470B1D9730B5024F520C8F2221B9D49836405525EC3864065BCA04A6AFDA11CC59A9BC28479D9D0B42B1B733E186D50B603CEDA34E8D283AB0939005B06815FD3531BAD6AA926F931C478F71A699A17741447FAAF6CF360D4C64098E9F1"""), + xeh("EF29D988D373C381541AC8723EB67C68CEDFB9DEC0FF2B40CDC763378B380C12") + ), + new EncapsulateTestCase( + xeh(""" +E2C18353FB0F024A0E05FC7F0F14B49A9A36CB49CE7EB963A2C20A5228B0B6ECA4AF63A1F7B1B8260B64D2F2C0718397F4F402A0946C9DE5B0F083B57903418C30BD7CC321574531B2163DDDF23A69B04B1D393C5916280DC11485FAC369D0AD1C85656D4A6A7BA480FA5ACC1788AC37C9706C26A357D7821D636078FC2204530C3D3358DA002F3136CF033443C519B6C505D00FE92B04A305A890267B238882EA9010554A1671862BE8097B67B8E8A37E8F0A5C96F94FBE296162AB1FA456785550AEE6B05A80554606B76714AA91C5E7B747A2005900077874CBD91970111C800C49CF05A4332570863929497AD6617D1B5614F2670390574F554C7D337417C792FF8953143638F60A7BF9517890D56D02039AD30392DEB045D8CC4994274E5CF83B702784637C6D53284F4F14C15335A86A642427E589AA454C6FB9707155BE23745FEAD04EC1CB07DA341F7FF1B6D17C315BC3282634A39C9104392B1D12222E8D091AAC69CD5A72276B01BE22FC3C634B41AB613DDC602EAAA00A72478D713C7A0F895880224CA8489E6860868A7B72CF876FDDB230C55C0523342C5F42B0A533A8FEB798D3104145E27D29CC96D54301D5B07274F700B9201555430D8EB961AA7C3307B0B56B479BCB6147D9035D786A58E7199F6BC9335918204A345826446A50801603EAC992E93FB104B834D7220B1494FAA2CB1A59650B00AAB00AA15F6909DFA969DED0B540648830360ED052661557280683084B93B746E27D916A05C96CB73964A4AE15CEBF4C84A1528506A69D2FC27A2A16CF270A09654A8B566651D097C61079A859171BDFD35262116479742DF74C0845D596FB83984F27811FF81CEEE0C37D618B93321A7DF0C0D22124CF521D92715EA7DBA1DD6112E9152CE2E15FED4769805A5857896EDAE13854648AC9DC26B770109372929FA511B573685D7951ACF21BDEBBC97D384D454B5625059A7EB8034FB4533F55B897B77930F3911F2808F54944CFB96BC0CC5AEDB8960A9C024984CDE756441C6381B3E38909DB3E85A36408C5414B471A68093B188134B3F54C751061093C4DEEF54891039AD71A74134806C7F102CDE67432D37DDDB4ABF33987A2AA47634C80260B5A246758102C864B2B40613C42425313855897FCC835C7C587B007C94760AF26A1531CEC874B9C492F4AA4C97567D6A61C21EB00FC52B1E0F24E9D680F8FE38B82243FD0B562C0DC86E2024593562B4AF4A682ACBE720813859B92A9C20DEEE4B4FFA1A1B17A24C394455077450B4C2CCE67A0E5C4016C746FF508A1DF89A5BE2A2A7B866ACA0A72A603843949909CD16DA542068604A380741C32E986366749CDD461A4362401CB8243613A2C442983B52C681A3CFC362FEDB337910668C5732906C41637778BFA619D502640545715F709C31B506534C0216790779EFC053B4A7789662B989A75C6580754A92588A30617E960C714171C8310A2802092261A85A5C882D407AE263A119B3E68E3BE158BB0325C30026BAB21D30B09637A54FA0A4B980DF807048F139223D33CCF206FC68672113A55E2084B6700B396F68873636DD8E5479BC0CA3E47B52329BD7F20681D5C2208AC0DE2123D50F6023A4472B0300CB3F8865BF7B49374AF01B002C4087BDAF4CAAE4336AA3A78E3856DC408B04E9AAAE77C464351C97938CAE829171BF724A8779C7FE20E5FC254D0BC283B773C2DFC83D28C3E854140A81267C2D2C67F361DFAF623D817B1655CA8A626A8A91BB088F539576C8795CC8A53044FF547B328377F4D17273AC323E6481CBFA058CCC456741057F1F668CAC51F34D666AEDCC176382037C674B4793104A4BF6B336E3D59A1C43958FD827493CB956C046025737B7FC0A3C2098BAB916E397191BEF5CC13F3BA0FD98F7A25BE0CCB113EE081B9AC808E2C728801C70CFBB2BD9A34469C064EA07952BA0D579380F7E782D0D5C6E1C26F3E17619CD47D4BA88C61600721BC2AB3C50F591988CCD77AFD3C43655272565401AD0778671939636C8BC24C794FB73EFFB99232503A0B50030A672CC8C2C0FDD5CD43B131DF0C9B9F867039E2A2B41B3CFB1A82C983AC54E002388692AD885C676AC2D7D0C5645B06A2684E9463AAAFEBC6C07709DC68078F7BCA36F5584579C3E3261D319A58392518ED507ED54ABFCA95CCDDB6C74949DCA48D01DBE3525A0BD91AC78428D5A930A5"""), + xeh("3D6441A62F1998E2B5B9B1E73A9A5022FD005778204977F66F7A5FCEAF17E30E") + ), + new EncapsulateTestCase( + xeh(""" +53EA0623859BC606082104996B5CC3FF292846658A17D60CEFF78B4EE37FD693876084A46A9A8337B61079705D2269BFE7486161E3370FC7492B92C666A889962B7450B15993C027051B8F0ABBAC66EB2024F6CBB63868D6389F39E580E05A357E5179367A48D5E00F03503C0E4C11EF5758B05C8B61AA51B3019C5CB017DEE224685035651703D0C5877414846C30A20DFC25B6E8AA76D98AC95534D1CA8A7E9177C57B2B46A0237B8B678BF889221C64C1882B7196AEFCB8056E0CAB1AFB0E50D467F09A9733960C4BDB5AEA3C9F0447B8A7198AF5D6A9DFA6785ADA30456B843F84CEDFC6761CE507B85A3715C3CC53409972D28E8F2A1E9EDC9DC3A368E2257A57373C967CCCF8002B5AC3C762E8C3B9B607C7451A9DD28F06472F3B4503C1A31A276727958210810716F53A8578FC76CFDAA35CB757BF069CC8429A9DB9C4F5B1602315882F11C83C260720A11FD6D01FB94171588539C5328E951B1E7F5605B4557F5A476430456A33572B60161A43A18A3780516D232F8B87B5E821081B109A39DAA7D74396B8213B37D314DE258B3FF0934FB27C276A913A337051E038EEE78542D78C8A04051A76A3BCA319BBDB99D3FA87FC9A03AADB8D0561B77C394D2F60A84B096D873BAAE7342378D8513E8B8B13DC6AC9E285966CB2E53521E4928465841ED7CA8F76B56BAC958E011C6CB751A4F7D788DC73CDE1F67A24EA9CAC41A0676C11B3D618386465C7557FB0BBB7A3441497764C9D898313A2ADF59983E0B2031BF7364EF0C25E347D2EF1111F29B8509085264C9D366970FE8CC19293AE8407602A21001391A51C609C7184C8FC0267E683C6FB83B0EE66B6EC1C930B1A5D60C108EDB646841415EDC5CCAE32CD8581BC48E58E8598285A4B31F805A56E395556B120B2DA591D3985B4D7C50ACB1D5DD12617343F9FBC9854250500C03725B010D45361C3DC745648CF337774AFE704EECAB4DEB9746104566C8CB0DC512A06E198CF04A8DF13AB6966AF12D552F3B6BA72A266625749D6AA30D1DC9DE8DC26870C317C9C26324A265787635E2CAC1922057916A425872C48E29C39AA4C06E24A462161C20ACFA6B458F56012B3A828300570F9EB92ABB3400691C8E76BBC1D3B36E6254E771130B555A68CA05A3A8112051CB10A2A3B0F547A11E53D803970E671B0E85C146BE1AB47F63AC46439F1C7AF41326DAAC72AB1274CC6D0AA3291C0C2843229B820E3C7B0B3B600EE72AF71671FA875CBA59782221781F3338F45B1466D60C31F6189F2D29C1F427D440B3560C11CEBBA7B0E298D2B270FB6D21DDEB30990271F15A3947B464802062851984AF1DCCC5A7083FE7C81A454A03AA9674D98CCDE10A76B3C696802347E519156F977CDA5923D73656A0081A26320C6CA7E1AD7A12362176D9A18AA75356E147FE3278C911070D2D61111B87FBBCCA67B991E5915196994034CC83246C024F27C1C62353E79290C26552DD52A57F19ACE5C006BF7774CD6C07BAED7696D61C51C8108C42237D8F4846BD4891AC44605D93F8EC03DE607456555365212C35D59B7FB267BE713CA43502BF3045CC2400C11A571C8468093F499C7E46D34C9A75602782BA606AE67A5D3C50D31CA5FD6E3B963FB7650DC5BB312BC35F67650E4B12B780D4B6680F640372A99C90433A7AA388AE8043DC5E9AB6105CC6FD91E61F35CBA99CA39E979256A1700AA9373AC14F282B71ECC419417984AC34677F0A83386B91028B4B7ACAC22C57908AA9F04F878E7B6420132A47AB5A1BF5A30116A6E59B6157E4228BFF499CEB59A09276B5D398B6A8677E725725D5C54809097833CA7E6136EC994AEFFE00C87F6845F20BF76C2A348E08C3895277AA082B84202229B7698924B4D5684E8C8AB81B34B87CA28D3E95FFF82B5DDA9BA9172076D937B6D02745DB7C1F77B3B3C795872CA728EC36029DA80353310D4A50CDDAB29E1381FC20AC97F48920A445F566C390206C6183666B2523B6A43BFC3E077CC0C422C1C91176C50B34C419AB4C97D640F1FB913B760685B64126725C7527A313A454D5F683B23828965067943E12BF633411B7B8C71F648E4FCCBD2A1262FD350A66CCAF2FB1D9CD66515C52E1BDB1478726426C84022F60A6DC61F7CA2B33A60957BC50B4E248DA86071FDF8080E7801F81199A9FB0C5888643D8192ABA9DA4D73869D884AA2A7E0727231D4FD"""), + xeh("637B7A1B57EB76C50417601EB71269E050008F415DF974C07BEF46CEFD08368E") + ), + new EncapsulateTestCase( + xeh(""" +51F74568AA5F4A54B2F4C9CFBC7666B7075A9D65A016416A49F16EC0CA716B75A3D80609FAAB06DFE69661706013A0C5FB7AB0340CC1BA72C2D7E1635B33B0EC3B29FEB369CEF671BFB907B3A2219B1554151A62B43638C635219F86B792B18527D8CFF00BB24853A5A6B81C9BB77790B25BA8A71A7CF7231A9007EB8B50F586139279CACCACCA4C7C64EDEAA194768D6A33BDFC42218EB279FD111E1C9633307AA30830B161D93F13973BDBB3772FA57309E36880816F97DB8E7E6411CC569A578A5C6F62AA33C2354CDC15D2065451E1ACC212ADBDE104F094378ED8882BFA416B1C55BBBC20C1E5AC89892B0CBA2B54516937E781F7A4A9B1802876598FF95832F6478ABEA33362A40EE28AA957E74540129D6FF3BCC0114A4AC8A40AD30BBDDA2BFD2BC5A6CB4DE5978F9AAB64CC8659A5765AB11AC3A654A247165253C81065359E070921188A312805417FA149D335ABE8404293329C73DA1E2E43CBF9B22B0D84339F792C9FC97006345FE6DB931AD71F897878B4318073B9A64400B5B4D0C4D6FB57E8B511743859D8E873B9C5052578282F9A6362172014089F2993BA7FCC2444FB185EF055D9D6A0EB564D5E4667E537AC9B49AD1241950140B188F4C88CD6A241BC42122A3DD7720E6E6B214D2721BDFB9358E7026F1A024132CBD0BB0EDFD83552F271B151099CE55D783C88B29A578B2943E3809A68D268DF746557435B5EE1597CCB58446403B98C88DF38399CE58BCDA1CD00462B9D933A83546526BB9E5C887050F5109090600CE84072DBAFAED20D137A7D129ACCDF1712C94098267148C0B1A301DC618D684152C817F27B3E8AF83F91951347C633C7921804D853A2E66C948143DF1B3C15B201EEA56E764273CF50AA58B45E71950FFD32C69B079564C48B08A43857E09FC33B8222A3852A055E3E4CA7B72B190E6C8B557AAB84D7BD138CA148330B75AB5FEAB8419A55938771053A5B09261CB0D4A42575E72F8F505D77F0896780CCF589376D5A651E4008CF600972008540A0896F80C17BFC78E16B64956677CBF864683735A279B966A4A906B1972AE4875BFC81EEFB75248B72E3A3768EB56D2DC3C04921011F4A92FDCC8EC9347353FA0055CAB83B7465D221B877A70B59715A6075799C19C8818595E6D478D659C7F9155A841B28EC751866CA3C2A829D43467E12563F5A4154947581D4B4ACD827B3315B44B3E31BEE0C04E9C03D1A186AAA7438EA9AA15FCA83D26B79A2093CC4505051B31F3D563832F397C8671516648AE92108A8E149392209A04816EFA1207CF854FA655538C161F6561274E5154D89A223665FC285B6D3A45A2F38278DA7B5055BAF8B1A052196C2547C3BACE09CFBA1299071635510ADDE3898C4C20E4F8034B454BFCD0CA262812D43C4A8660A5B2CA42E2FFA7AAB513DFCBC437077609596A45FE8BF330741A88A5FFD20AE19B58C3B19774A047F563AC6CF0A205A2A4C1D6641F93AB4C0F39E6BB51032F0A12B8A45E900954BB3A4379129E44918998A50454050607101BDE2975E66C0AE2436664B15850294FBC985B638C8303767DB7A10A8A74D5AEA0EE2B6105112525890C6D5A8CD1712A2913B73C386C450F7286F4A8ED7284AD9F36A22494E51D43950526B19766E388AAD84A39391399628F9C251D4C784AC2AD0424FC57BBEC391A549D59E5638A8056929203BB8F9A44A27117B28BA2670508680D55B82B4CA8E523BEF1AC4CFE83511B920309A735C62CDD5151338C50D104950C9273263E8250488135240A949958090F06BD46B5AAA3035CF9B7308C09952B66AB5999EC6E6BE7A027964249D63D1817F430737C96F54B391EB44640959277B56B495C49F482B829F97B94FF8B4F0E347A9B6BB83E9AC6617000694AF0C7AA13A273BE2981286ABC62444AA16FC043CE4B1B4F50437C9503F815772A8BFBF6B229D48B75D94BC02219E0F71BA020C37169B42CDC1A88081B7846C3636F3598630B314D809AAD1B7F3D335B41468C019C2C061240BE39325D34DDE9C24FD29CB3ED62F815C248F4B6E8D3908FA3B9C8AB1534AE49176652DB909059402128F18C0C9E52DED217C7CA864E378CB59711B0C764B96F13EC5E3766297C9B303806C685F4A861878CA8415D60B057814E554B04F49C3DF9AAC26A5CDCEC91B59F32BED063E299ACD431F8B781FBC1AB90AE6AD004FFA864E0E16AB57"""), + xeh("B5C84B4535CC622A5D6B93229BCE68789D3014D500D3263B6E0F54359D20ECE8") + ), + new EncapsulateTestCase( + xeh(""" +10971ED51709D256CAD9B57F0E48850C4B803642732C89A84439CD31C6B0F045915090168F8952B3382BF1186A56D2CBC102898F112FD91A2BE5AB0391A67C3C5255CEC88FACF3B6ABD427E3A410ED22C2C6C173F4894E9BF20CA3713CF0E8506846507BC762047715A7A37DA3A5730D8A1556560609E4CCB61298C4B2BEC374B534D0B266C427088816E843B118FA9CB27B9D1F549480F98F7F4B5AE71BA376B0B9180A157D8128D2286C4B5BC54F8590852B5CDDC5C11E6B4B36EC7CD6081D45A9C50272643CF0569A9A237581AD36D0705C004091F7C46D9073739226EFBCBAD5B551680C86E4290C3CA1AA756851A380ACFC033FBDAAC5B82C364DB075633A9A10B8137A05B29863AD1DA1CAEF5ACD2D75A9643B495EBBC184038B58B9A95998AA95B672A2D15CB78B0A00E386F433425C469A7677B8569CAC8F5A3A035C777B4570BAE1898FD379ABA62C960024E55645CA6625327457A37A92FBD68C76E79528D3B9E3E8917F93B5774B9A7DC44AE416006D8955895B6C611814C99432F683C67C09C354B97DA3CB0DB93841991B764C9A08EB26B9BFA96EBB39027D6399AD2688AC047360A7989BAC587FBA7DA76153360298A3D67FE73C983E4563F67207E1B835B7DC7CC9CC3372E12DB6EC759B86A684702D2B6CC805726DCB04AEFBDA224C02405635040EF60FD799A906116410A6C5EFD587BF1778CEDA4CB0152A272B89E43017B40C9B974600F03908EC397556E8AA7271828C049F895753E7BA96569A280CA15F5A82CC1F6121B6F7AEB214C726B1C64F7A958DB7459D4A30E4599A71FAB28D5196288A443D6C35C4AA27DF674EF6B4B72FC6485A31410457C182304538424A7501A7D62086910ABE0C54CC752B5E8E87039E64233EF5B837C3B50286172DE5C9CEB92C9A0BBDE4E7B14A0419DC6AA03F655592D25DF4A6191EDB8545351B2D89A7FA89826988657763A93EB71F8832B159E690B95C04DF37A2C9024451A18088A1C801B40A601AAAA6EB692E229817D8A390BB2474A95A7131C84D1745272A289C84BC2742CA1097A610D8A90F2C609651AAF5D0414C3C3FB3D37AD8CA382C9980A52539BFF73FCDE029FEAB0F184A7EDE4C7142478253C84EA5D7B6DB963ABC39A6B5BC29D43BAA24B4B26C7C53DE096E85E945310A484F591AAEAB48BEF98353C17EEB457E7D0719247A62EA85400B23491CB65932200F74EAAD3DF7184A54654C7B6DC931B574A2A55C7679F15C5944191A58D2A5B24674FD80452B22ABB7305501D9A156D0C48C656A35540FCBD43F14F531557BB9E8A3A710C000AF227FC6878AD28A708A34320191A236B38E64F3C4E705555DFC1FA3A144D8E6A122F7C5F557462579765A017AAF4A814E6B1201CC4E8D0757C378198A5798D3A59186A54FF158A451C42564B4659E0A35BE734600210A68F8A64E3951E849CB1062BCD6335970005B1B69C3A4845226A2C0834C1A467C6A799609CB870C7370C39265C0015BCE968419EC7C58464CB518550338B6807A97528FB34D1011A67F15B06C1BCD7B5909047136702C9AE604B927F28B8918CDC6F07A5D60B38BF7CFF2EAAE3C075D1579A30A76093B7A6DB44AB21A722F818861480129ED03B1FEFCC2607B5A1D5BA6ECB91B75B9810F991DC55823333A927AC13C3C297EBE02A27B949F47CC70A2266FDC76B5B55468A6B98D33955BAB3418F2D3C1D206C29EBB05E97811EC140307F9347255381AE152113C2ED2A7C1812A93FBC67ABFC1C1233B864AFC4B34B9CD30358990F51477911D6C68338A9857335B9152C5302F32BD5602A9ED97892F14951F111CA2B607DC46CFE6297D0A41BEE369CB3EB941FC2701104713A1784D6DE88948032AC78251328A8C58311848EA02008669B4BC811D6232A859756B306F24607DFD812DE89A0A6A00304FE795DD1C4A55366E615957855ABE11D97C7BE95A43A757948C5F4C046E9DF6A70674541B20010837307443444C27AD36C431F1F372EA659EB0693447FA5C40E8A38A7472D4A1BB0180433585B0CEF74650733CD90094199ABDFC1392E24C6D1C74408D00AE27F05D1729433A90AD9BD22F1B6C8155F68BAD1307811770A749A85F060E74625893462CCD946E2C1B79B6CB3CEF971899AB29F4328CE29313E4794C3463AEA46106D9CB82B5EC39D83D27C4CB3B69DAFA2E955D002E61C3E7BB247A76042FFEEE7E"""), + xeh("FCB46FB66E388182DF6149F60DBD0FCA88D1BB1A9866A2C97B84848531230B48") + ), + new EncapsulateTestCase( + xeh(""" +54B452960A93BBC12032E0507F7B83F112BA14CAC4A733700AF288D6DC0918C2B3D1625F475083E7967ED8A708B2B147D50658E1881DA6501D6AC6B7EF5AA4EAA5A7AB85844E3994E44A5431145A873834EB88A177400E95ABA99FCBA079914074209E06E17CED04636AB4ABD7824B98DB2A35215D5FEC091D5428B2928B809AA94C57694B2B65DE050817D6AD7326687E9A68695151F60A9B1502789AB8017760A6F3E7029B5074CBA929765B5C1DA8217C1105535699FC59195ED3A0E8799C66E3264F692C8DA198082860793446FD0536EA0301F5104AA689CC0263633F7A436621864099AF9C108D882043467B4888922D2254CFE8F937DCE040AC5B8641102959A90539F5177E21AF7AEBAEA2D9731AC87150A52068A71C183B8F4BE312A033719EA12E2CB8A197C1BA28B093E50437FF9779F0377BF5698557B9A45BBB7C8ED1AED0D982D71993F80CC5E7F16330D142BD0AC602F42DF89391156CCF1621AEAEB95701933A3CA82487E057FD186199BB5F4E2341D91A1D5B753B53E3719F65CBF0B3AE33153461459708B6B6E1131C9573C7B0CBCDF3A1C8ADA919D09C020FE6648221CE7AD35AB37C16010A3CAB1251B5930EC69C1728CA45E6639E97626A09469A6E204386E6A458D35E58ABCBE5C279BF79BA85021DEA6B6DE6E9A802198B969560F2C8C99328C5427207623C03E68181851401BDD615E2263761DAA3D0D16324FCAC9FF98E85ECA88FE668526501AF4C135F259277202E96D56F91C07D86692C91FC14187B99F1847EF11AB06CC019EA89AA88E114C034608C03A77280BC1B96307F81531009278193BBD1F5ADD812B278796309102CC2CAA9CF8C127472C4C63B47015CB852798379C73D0C4517E985ADC6F60E49053CB2B5BEDE0230A9E9A138C44178489EC5D5C2F069B737A143D6802454647C1B8C0837B43A89C879A0656CF087C733B7A1A7D153E092AAF193B6334A729B2B9F64D311090B29BDBBC5F1CA5E054461EEF72CAB14580B505BED3543ED15B02E33AD2A63B6EF980C407998AA5C357705B047D1848B4CB551845D3FE9A2BD491AD8E60308D880D6C56607F4AD24616845F092FCAC559CDCAA6FB16F2BB19475B700BC16C8FA8526055333EF389F6983C105E879FB4738166A1705BB625412B847553C462145A13175C60820783998150C40A2F673A3117FE1778A0A4A75F37BAC7D8A6C9690870D6874D2650182FC51C003698FD164BF5314FE3A4FA291BDD9EC3920F5A656000BA05A8F6CB020EE4701E8D8AB8BFC8DBA31887E65C7E403BFB036BCCF3C281ECABDAEC3984FB87D1C97C1F1112F8252C31A986941A50107D40EC6CC67E6E20F446C598832061BA21212E37943359B6B005621BB275235AAD581985168C468E15BF6C56C9AB65C7574B44FD83A32ABA5CA9831A6769135FA9916E3729361CF0D1142610C9A98363ED6642B853461C062C7D0B9B5F70694C8D4C2F073AE788A9CCA13446CD6BE40C82478E338C5DC34CCFB538451B6F94877A4B56B5AE6B3136B9BAFA1CCCC4902585907331C1F4811602716A5EAC209953B75A3B30EFD1B4E42F716B37A2F79E2C8ED062B1F79976C010EDFE4838929589A90B0A0ABB3E41CC8AA974C4C1308C4E12FE2D24162738A3811070D796701929C12E9A94FA96A823B6903498C4862732D48122D0265B0E571F0B4C43C62015F422753B2A562A80D68F19E2637581AD77592B67AC785B923AACD631A0B53D375E911797C0B76C79C53161015DFA7A67D1485C21A5B039A609F7386F8AC339B962472907D48F753314155C78A3DCF2010B1880C48196C0CD3B38B79BA9243CCB4AB5DF9D4569EC11F2F88525082B1C2224573C94FE3D24927B7AFF7E44B27755A0DA4C8053A7B8876AF4F809C22205B710B43C4D8B046CBB562B2BEED1C27CE736BDEA5317B658139509E4737C52A77186666947F7796D4261FAA8B9767814B7D096856A272BF6572B4998D2F6128D3FC6AA0FB2B66486A578B984C8835D1223D9E446AE6752D355A0FA09379F108ADD50683AD57AE731942C4F9C938464EB95C4D08264456F565E5981625FC75260496D05610CEBA5A751560059C38A8E2809609BAC2C853B819A781F61A7AF0C6FD728D9DB2C5623521D762440568272DD8831A4AA1B2F4CC8016BC53964CD7D3262D93710C56033B0F515A7B9E0AD3D6CBF0049DF4E55FD931257F"""), + xeh("4CED177C0A454052BCBD682B39BEA31D0D219A73184BC00C100964C25BD106D3") + ), + new EncapsulateTestCase( + xeh(""" +C701BA88063589288E73E4BE1AB28C6E3ABB70AAA03F656AE87B38A9EC947786A41D722EC63C0E9E8C1DDA078E28608D11E84219E35239D8030C212F34CC284EEC748D34C6CAB04A7F3C15A5DBA8C74C8666167CA4508EB47774A7C3BCD6589306FC6365D74018D2082DE1753A854EC6FA7813431D31C6A3FA711E03F042E6251E2E27787BEC65AA8CA47FEB5662599083E6944F442716342DF25AA551C36643EC3B9598184431405C8C8EB4AC8360E1789A06B2D13232E831C39A005881273B0086591760AE8A20913D942314F45BA5094AAAA05444469D12C20566B0C008CB2C5FB90257929DCB648E0D616001095309E00FE19235DD29B1EFC2A80E1402E851CD19D2BE9B4001ED214E418C156BB6BB85C0744C3B81AFEA59BBF055C8046386B576BDD009CB412D13B3918B19A658C690726BC93D4928F1B2A7C386320D41BE98C1AECFB75288B94511113B902489FFF157DEF97D762A5302B89AD18546F5C9262C06C98F62632681859D132F756A7008B76CD92C760BB12EB276BC5611B5A1F20A22982AB7616F8802136F54815D66BDF87859C7A79F29769AB4CA735181557AEB9D76468D8855302D4A5E9CC171DC6000C7363789C3A76E59905EF5686C31C765541131E62120399B16CAB27A4677C8E36150E728CE747D2C2B305CB780250CBB1282044B5443DB128695F4A6637102ED3469E3548592D3BE83FB30FDCAB034C1499F69ABDD174E82041FA4CB9B25773BAFCB071BAC2394B6B9E3D5446289A8E08339D91BC12E84ABEE2BA51A563E1DD154E075CC33409609835A8345C86EF96B31F28E3B42ACEAB464380413F475B00CA904E958CB260B186E3C5CFC6068914638AE831D8AA78BEE7B65B9233F8950783973C4971AB0C3BC9F7A7A5176083B4B9B1C045157738C460F77A6D9311A3591789DB0BDE85C3A863594DE182D789A7244E05FA05965A4294FDEB2AF843CAB9F273687E3487C4756B0D441303C9C8B6284733652F074B087288F6BB08AEFA990517C08E9E984A4029FA1C420FCB19FAA78B61C35B4DBA021889826108A1A95A6816DCAA08D535C77959C7EB20209307996592E94DA842A52C329E3625CECC6A8624EDDF7B77C2264933B7B263499AD0930F539C0F24A14A157A56AA469891403BEA0A3531CCFF5A217282652B027513C05D03FE142DD14BD85755507473AC91767C69CBDDDA71CAF8A12A611C0F7F50CEBE87BE9D88514611A9516A6433B8FCBA54527FA10532A808E57979E73C8EB444DB3404D4888370A419E1AB04760617AA0E66BB2E715FB17036D300D9F3480D691450BF0571F875EDFA668D68B16D426668A68BE91F1337AD15577375477045633984AEE80824A08C486F25443E61B47658D03A21A51B085C656664B8345C1149CF690A9B99543B9E98CD090CC4B57C5A1D7BDE6E256E2059B20752E44331486515083DA5A99697A47A342BCD9679C77C6A243896B05CDED231919D0448994ACEC094E082A7434C9A3F6B97F21056CD827AB2648613B3B95CA065E1B3CC3740BC7F4F156650A722FF26D70E5276F53267CCCA11513A719624A2F1BB99677B845A436C9AA3A2D1202F1094F9040813B26BA6DA05E904206DC33A665959228B62BD9391133AB21B79967AF31CA0C727B464A8737535973042831FB06A0B89CA65B6DF8F3983037957DC838CFE0C65D7791D3148A3FB59656472BFBBC8AFC7C6EBBCB6BD83B6760643425FA72FE343DEE61187A73C98B9000E2577990F9109A8B1DAF30BF384227D45BB8BD4CABFA4A9CB20B0B81152BB46281A68445F7F78AA56545B59C75E9852912870373B1CCBB14396EDC70C2C00896762A129B775B4B9168C97F9A259FC22219DDB0CAD614C4F06030140A1F335B033AA2A1753CA5E2A2ACBBA83A3CD65978686FDB8959B4F39CF41B98EFD2048241B69B27AFBD142FD5046AF69AA3EBF67ED1632C4683B88C6BB7B388B4A4D7178A8ABEDF1523A6816F10C40065056DC9393D21F76A48EB7C122331900406D960A4D46C9EF12429B8E4C45C4032F089458818C759584947F6415D1468A6436E764CC86E725A936000B242155CA0A9B884B69490CBD223C76FBA954319161748706CE5A31FB067C20663F443B885E4C5C1A421D589777AA4C13555432AF00B27571D8217B09AD4BC9732C8ED10BB8841315539DA5DD99F9A7FACC71557853FA10547CF7B89E98345"""), + xeh("F594FE1E810814496BC73A1523FA1E0FF207AD5F5F0FD4B232C25EB9F6EB5B1C") + ), + new EncapsulateTestCase( + xeh(""" +24155F435909068A815A6853C9F17BD928B0B7891B83F4447C2C5213760678D74FDA8C793C071002040EF4D81BCF676483B85D2AC796F964C9B4F8B7EF77656FA2976BFA65B9E6AFB7811903E114D3060A1A967A1465C512D2C1513863A548A787279E81674FFD45BCBD7C398D567F22D7291F50324D45C9A2FB26DE3A7A7CB875058979FCF4BF19A03A8A721F17E514773A83FA0A939393ADE55CC7176AC984CB43C7092DC2D0A55DEA11F3E41B879B5B52984BE72158B08BC0EDF25866563A56D4B98DF9528FFB28BF345C4D136EA84791DAE11ED324AB279C6C8983AF725818829CCE05770AC3837A2C92AE2B1812D143032C72A32C94C2A06882ECE2CB73C0C41EDA64B607BDBFD9258E03A013B9CB3BBC5C40FB10CE413B11897E81D32585240851E487877C4D5274C6CCD45CDE88978994CF463111A20BBA9905A6114899BDBAAB1053541BB3502D9779DCB48FC8E523FA260F8582B6B8F30232342848492DAB73197EC492407ACDB52844033C9ACBC79C366A4583D98585942B05281328659506D714FF856A9C2B5F370B5136F896BCB87A23331AD0A7610FB69515E84A0A302407FB9949ECCFD91550A8618049A48BA2F4096567A0D383BDEDC705645C4025E0B139C22E6A16023062901B8A2B6B515DC8E06A4D5514489229D926521942BE150B96F2486CB34B09D7E7237A440588C357CE061DFDE1362DF1C2E58C1E1D72235E922B61EB2163D906B5E051BC58497C7CAAF5363724985D0FB3BAE964A86AB36EC46AA3D7AA290B428744623A3DF900DE975E3AFCCCA539837BD897F12CC555D684E34BBB3CD7041FCB2004A687B5E6A3E801CFE9C8C2815C2AC4783042A23736137447337D9221116A62C0E1D8C191B53E22C92A71A15D9D22505FA5BE17221A7236392C0348562216BCB037D4880A6D1236D3626E1B354142B5C897C646BD62CE000C27C53991A1C69176D03A16A61FCA51067C596CF01B89933A258B43C22F489AC70C1D8658B2C0FB2D3A6924A704302F33C25BDB556E97780747CF652C80E87B23479AB2C8119DFCEC47265A4F7D524E50294C826AC4C7B39C3C0782763A1A6ABABB9E14903720A9380939FDC9A99C6766C9D8B2828881BAFA555A35022A23A6F57CCA446319E71780AFB3767E9311D5C990F1E4ABDFF51A0E7238AA98AC412C05356583B05C170BF793CE770F79F81E99F78FD46310EEE27F614226F42367319C81C98A1FE2B2C09F886ED827610C8621B079A5A51863BB69ABC01C4A75051B50D83D1AF85B89F6918313AE5AB0999035088813102BEA06CBCB14656928DCD53A30255B4931017BBC4682CBA54378CB7E118A275728B83A4BD2586D271A8F64C06562248CCAD9A1FFB8265512712D0B707424B015157788318C7086BD964490A11A35FA43BED6ECC533E07D2A6ACC806990072A7DC0322573D6B88E29A7B47CC42508C7CCE64AD436AAE0160309E6922B655FD3B96FEC22CFC7349A746A0012D60A88C17D7934246EA0290369B3F7783FB177534F300BBED06EDCA87786D5175B93239B115254D676C921C1E5C3BA42737AD51B4BA30B1E65A8B59EB6A45C34950E9AABB7E5CD2F556485036BEF93CEAFBA97E83408D61C6FEEB908873B7FCBE93D7E386F2563CB4A80A671A1155762A02968622CE9163284777A3B4AF4B8858392BDEB9446BF59CEDEB689C609859C9B47561A8B39A19F7B36896DE82AF89BC41CE6C54791A78D6258534AB7090C502CE0A6F70CB3DB442A9DCA58E766A2E72286B42BB431B4740B125C73D43F49C1994761A57E3291CE95A2F4B88B3DA31CA994685A75B71CC622B3C2BEF60C222696C031789EFA1A3DBDA576EC1B802C261D1F44A5E4B973AB73946E41159D622BD8A0833396517DD2C51904AB67F05BF5FCBF9B47BF05A18DA600C1AA411B60901096838A5CBB8EA236A0D4C7109BF65EF8E6B2507651F2FAA61ACA225744A1B56354CB945065D6ACFD3697B8D331C0929A59AAA06570B0FD3B02135006DD198A92D4037301BEC0B328725533FC385B2E03033ABC4E1CD4975E438B19D902C3E3435019A42F664C063A5A5E31932ABAC10420A10A89B54582138CE812A473945952460F541B9CE51C9A23C5CC6BA0896249F097218210A329956057E6BE66DB1BD139A791FCB95B3603F12BC19E2876617520522AE31D827CAE8422FAE85C30AF33DBAA77967001910F"""), + xeh("ACDF91D5B4F2047AB9C7A8C2F4809FF69B9D480334C501E6BC66D535D309B100") + ), + new EncapsulateTestCase( + xeh(""" +FE456F478002570478BED88055B4567135B19DB8CF52A56E41824984A8BEDB64467D7A0A45654153C8645C5054C0E35C2C75877633BA83AB25857CBE5EA998FC6C79D983B5B1A984FCBB14CBEB483587BC5D952A4BF422344A70C4BB8E9162CB31D2411637526514920CBBACA6A911FB80662096B85194B308B881189813D171CDF6463893CC58EC512DDBFA31920CB1F33AC72C15BE64A3BBD114B27185455DBCCE9BC67AFDF6C8A393CD8A427A73E052FAC64AC22B5DAA7481E7D017B8E14BD84690D9054BCF2557E942BC7248AFAE57911FC64732C450EC3C1CCA599B96DB685EB704764CA7EED07F9BAC7103F38356F86FB9639665C35A576B8627CA6DF0F138FD198405B6371AB1BBB7EC4175F739B408B281D28BCA369AC0F1971A374A97E9097FEC3A5ADA6C2C7714B5CA0958E4848C9CCCB5172F1A6B7F2BDBB37EA346D1C9AC0C31A5822218F9D3544DB6464E605029073DF5F030939C8B7CF84A714904DDF56E63F04B2240376820417FF320BED27D8C385841C54222097742E23B972A6B7491524B88538A07988FFB9861D0B693CC80BDF6BE9B645193C06EF8132813E715A2D72C55140A1A9C54163B2780414A5996489326CF52112640B08166FB9F9461BA19661F1F47B8270396A0A6C8218B636E8496CDAB3639338D50D0919BB7610AD1BF9FF76D7D0B1F0E241E61A6377CD83D430118DC222452426A9259709D91BB46444793741AEC8998F876553B7770E9CC1E3FC749DF81AA4461BF5E6CC1622980968878ABF113CA67B7646A0463604D90353C635C2F2E330F71949E2E21806091319B328731B298E99127777808153652C9C763AB386ED7F6CFEFF10034090D134A642A218D277B6B00511F35A25BB3DA1F299C22B4A3889D10B3754C52D3F1B1373840A973793EC4A5DBE76D2C29626F1BB469722BBB99B003ECAA85545CBC313AEFFA6006F0AB7A857AEA991F9BDBB92E3B75DC300D1C656B2324CCE8DA2FD95C9F510676A8D6AAE77535BE3A9ADF8B1C974293FCCA05DDB31AE1CC81768CA90D00A4A7F8191C127F6B8CA010B46F3C05A808D9911A626B80365E6AE6BCB428BF3EC8710557485DDAC34583B43BF55D257089EC997F857B94752B8BFE7942689A5397F71944343088D6A9A2BA4936B2AAB663857B87278C3293491A75C861987C187655F13FC2A28749E3891E8C236B1B675E250639E5461BFC94F6B7CAB6D8077E4CB8719420DFD4951F76CC6288229EF49C8B8821C3D497CD860C58A619C9294689B5029F5B2D0BC95C370A8C7FA3C521A695C829A9A1F8012D479E38DB4CFE650550664CC9E0B631E2682AABC81A601A62EA16548584A571CE417508AABC4F1970407ACC47B449890598621EA7623530409EC49AEEDA8AED0336DE4BC4D4F9163A3C82C12A2C5D86B24FE56235CCCD26F5AE517367523AC739C6B69E977E3FF2A854F8040DC4B97FB3A29967005D373E0D91166A679A517822F7AA59BD4B00185AA25E0929091ACEA1FA4ED7F7BF7E463005D59403010539465D5D918C1CE22C55A50C749C6B02A360345A0A0790970717986AE9A020564D82DC851AE815D5FC76FDEC1411D01C56166773D7067FB29CF842BA9E8136F755631ECA53D49B7B2B296D65E63D29F96931C02E2AC013C016BB05EA6817F19E1286C3C2B9A803276FB58A916C838E923932895C9961BB3A4BA6ABD52880B86B391035764C4B953684AD13C5918ADA13AFBC42D4B6B1D523B39C380AB8390E6984179A5863AD488897258CBEF615D53281AF99239D4A59AEE6ABD6EA9F72B88E34D544F25A18FB9A45B0BA7906367ADBFBBE3BC467EE7BA3520360DF56040E730C2ADB162F78BA49EA4E2D1969839BA16B2AC991CA439D337CED7153A6E80877B73F6A16A22FE196F5F833ED7C0133505EF9E323C00355D2405B8CA01FAB6B780385121DAB8544C2C609C708193B969701728BE36F5F972C0C402D2E230370175971A601C0560A22789262E539AFB55B4EDA9F8DAC1C63FB77B91B2E77F17D98C0297FB17919CB23E4D45BA538523047A17690C245E009B031469F6CCB30980649A14211997A823C092C98452517A2BFBCBAA0B43478AC399FA9B58FB96687CBBEF715AC3855C493665735192A718965D3825325F151D3A325318A667492B7F6324FB28DE4A16F77BBA3884809A3445D53289ABBBA26997E95B89029457749E9B70D"""), + xeh("696EF6079C573B67BA3531CC69730216A3A8136EB6F647481382A5CD93C6B7AF") + ), + new EncapsulateTestCase( + xeh(""" +FD1B79ACFC0D6D79464A3A59A5E18DA6D54C7E272B77703A22610C75FAC3675B89E350047C80C6F5B6023A455C88A44B0327BBB6F40E1D502861F77E7F2732742C88DCFBB539464E3189A5B21ACA30474E3758AA8BD2259987B8390698FD52378DD505D964350AA30B26AA925D83B6C3CB069113A2A3133FC2C19714A042C3056C774805262595CD2504FDE7A82D19878AE208E8173D9A855D39173D027B05CBAC4DE7408A4C0A4427109D60571D98D1738FA09B1D80BE859B34F3268F31A6CC472846C6E5C50F2A3E22CC8E81C78DA627CB2F474CE1EA0B6C02C7F9135129056D05F62D9B36BA466B9806F4ACF09302B135906AF7BFB43020A68444D22168388C8944BA60E7E803458B10D3B061F0652E08607CC2214CFCD2BC0B1B2148BA14691635C40492A4464230F7B6C9AC0366D813249B37FF57AD8533C752C0CE2B765D0319B84F204B9960B8C553721E5C1B93178621D4A16B8C5D2BEC6A91018F80861BC92CB44B25AC1B8C937793892A989D8FF465623666B1E467340984F45A1A591453D894C0E27876F851C664E19C3DBB3F62D7C7B9AC5C4D201FD3C0B3F7597D56A34CABC65F5E62898B0358A803B8A8651E8526C010184EDC0A1008F047E082BC63F0236FB93A9E70750255A28065A32B582CBADB3178F4B146A47893C62AF7CC63DF404715182013F13A11249CE5513D242A2E8B33C4B1B730B59A1B121181BB39449CC021C97C7B6F187966522C4DABA78BF231B945806B590C5638B1767280C29A070C0619A74A6D3D65C704DA99018418266A2AB1D2861B80700F67C6C845744A51220C4743E2A6639F188C95871B44D586F05A1EDEEAB382D123FF731042C29D50096155EB59906A7BDD2881D94081BC330CC3A71D3C1391485109CBD8026744AB57632D0EB35087B11EBDDC24222B4ECB435586C7226B11644AB9A243291CAC62CF3EF90B7991014CB7906D9B455A023FC94C7DC935221C4B2A58398F803801BD2A1BD5B40C17B529FABBC5F3219419DCC911E70FA0397AB407BD73258002594EEBECB45218154196A07A53AEA0ECC56F25AC5184CC39DAB2399B555851B933B45971C85CD3299819A27F756848C33C4E67B6449796B99A914AC8083719D752F06580D328087510AF7A5122F95A02A30190CE72482BF04FA37306A28836AB7A6AB11A2A311C1D9591630FD827431A54C2C738C5AC9CFC67BAC2480763E2CAA1C81E52C9455E305438BAC378D8A4A05168D72C39FEA242DBC794BD11B504E4630487142AE867903C4872F0B9A8F1572403A51940CCEF99618958A71569A8E32992F881B6084354548046F1E4186E11707CA72103DC7292A7858EC77D24BA225819B9574470C467033E35C3FC8A8CF955CD82565576EA576F5C43E0682C50D0260A30043CD40010B2B70C60A86F242EF193C4D3B837F33771DCA999253278D2CA2B9B88473DFC7565F282EED3739967345F90AB34A902F393A2389A557C815591665D63652F43C321ABF0712A012DFA6C04EF86A67F95A16B784E3BA18CB13215EA09CC2B5238F9391BB6A5C6DDA2C6F670A1E58329A8544C1E2C3E5D2A478057A5E46A26982911CC599D83A5A18D918FAECC86217A165C052344A38ECD885AA0E4CBC7D4742C99B1700578D454ABD5C83F587CA48A3A219D72B55F1934BAF1249ED25110177B6B126E0E1379111BCAFFF719D65B5570681164A80AE5E71D677586625020F605103513A0CC94A6632220A5687D89EC887956CC3F6575DF735C738222FF7AC70D468860420D0E53C192FBB31C8B834FD10EBB4B38C1517BC6E60BCC7A5831741DE067274B637060D4CFB3A82624B4207D94355EA3BB562AA9C5B9C04E2182C45955A06C5C7DEC5AD78BC9FAC6A87637BCB14AAC3CA76D5695196937CA34A36F183C599645CD67F33E060C6BB784227C735773534B4D501D25584C0F412A1A697C041C59EB85472ECC1B780C509E3417C9890722E57003A1B5AEEB11A764A6248C724F8770400747F04675C2F54BB1A983C59573EB8C64B39A3F552B79F5D365FC461A0414CA2BCA1DAC961C2E3A0A72109D79E26A59C1B659C4A45E9C8C2882CF6E26B67764244E3BC739349EFA0B9DB47B2152634240CB7A44A0A2B9CC70D557B6849A9976118DD8E74CB7896915368BFD120E31C4A261683DE548D0D6BF829F1E94FCF9E53757DC7EC8255975E848CD84360CBEF3FD"""), + xeh("B2180DB6D5A468155A4C45C90495F8875538F05B8B8587644B4A668CC8936447") + ), + new EncapsulateTestCase( + xeh(""" +5AE08BEC33AF8C2967C72B389BF868211B80B3F3621279CB84739860479BE408929695B043BBC623B13B7313494111C07EACCBAEDA248DF4BFD4E480526958FB9811FF98CCC755231045C744D29A6A3103012A3C61613C3305C0A424C8F483362B5150A045888AB09E39F08FCC81B79005C1B3B0BA5FAC23BF438048C675122ACE4CA672D4D6540F9064AA9766937017B147CB05111C0706A5B549498899423B1000A27B648F0BAB03307F8E492D582723BB20B044E91CE259C611F71B7BB57E90D4A249D02A7892B4589A63EB591CC559A3477766776505689820601B9CBD75AFC344C43FD9C9FF55AA4C791DC0188B17177032796E07368CEA357874882F32948EE0B63D589C808F833AD2566E22FB02C77AA78767B194731EBF5728F1A858C6C85102B70C56B96D32428364EA7A904A7EC4F2517AFB2AAC817AED1A53D701CF16168AC2E45730D57F93C12B9CDB38D602025B1C53E4A1CEB4EBBDC9403DAAA368BBDC9BD9858BB0B53945948CC3DBBD7B2B41A97B847447402C5624D30CA0738912BA19780BC5C81A7B9E26C3C2E155CF5C1A58D26413988267738B848F20681B823E9828BE7A6A8799A1360C2298F448BFCB5C422ADB3D6CE32D8FFC1A2E52244DB9C994416F15C3B5433319C04559E3C3B895B1B322232A69029AFEF53500AC5C87A4606F5268BFAA26FD99B45C456D96E1B248BC8D2D79CBC9435D3A8B962E91A81FC76B1670ADFD12B3FF044078A72BC36C8A435B966DBA5C0CC97B71635206CCCCE2972B80C818DC43325830A02C6482CB5B2079B5AB6AC50C24E95D16C8259945AAE9D45CC66B1F125B70915C5F222670E54A5B8CCBA4F973BFCBD763BF2BCACFF5AD51A9255481925C893C630B38678A355EF40A39F56570D961846A2E6CD827CC1BA4B3813B6B956CF4AA26D7E9CCE1721E04B9A5B8D4910CDC484134730B639B57B39CB5F69663EC7490B339C61B4EE4AA83393ABEBC60868B945CFDE98933296793F74466320615F03DC4222F69461DBEA4458E2B6E1573CFF4F610F78C3AB609036641007EE369BBE382ECDC888EF97C1E1812B87964EC19B04DF5194B4049DFD2A87B63034F7A02C3BB731CB67F7282B8DCB131146570AFB993661B059797799CEB7D081CA13421BE41B32ADE2404B0519A00B88A0E088E29F846F5B738113B31C680BB96AA736CEC1138CC5F5D9C67CBAC9B29E1C1226812E1BAA39F151BDFF15037E30E1D3B9CF86423131A4FBAD95FA0585015485B5DB755E0F45D129841EB7614D6C7AFF6194061DB727B299A30238E8B716C72400828B377D46B3F2AE9119EF72AB410C97CD4B31EF77A610242D3ACB17CC2B335C5B2DCB3759A4255921096087CA0ED428AE6703CB15A9D9D8A5E0D64B85534AEB4F2076130848CB450EE55954AE61F40CC25932851A2D80FA3601C74906F1A5360A69120A5FCB4793326F0C8222969A40FC16D46F1CDB318BA511C72AB516A4F31CE67204938E68EB4F16202F42D9E095F1714BF2719C7E571498CE304DA997FEF45549B5BB9F3834209096ABB39C686E4B2C9C796BA69B368417A45970178E9801221944EAB90656B623B53903554AF1F0C7644D79B2BC186C0EA5C791795F99A0B9C29346CF9639EA892935878E6F2AAB73CCEC7201D38A26305A286BB1970BCE86033A14D3677AFEFC81757A69C07299164790473055F10A8279357BBEB31C173B87B62293BF963C453988B390B3697A3CDE4EBBA5CF1B08F78CAC7498DFBB6407D6220C376A4799AA3A8871D0270870B9495499C88C98A5762F7CCB6FB0CA10046F06C06864345CF4C5B40B11181A973E473ABB9786FF307C65CB7048FEA4885041E65E0013422BCCFB65BE8CC9CFBB4448A645FD3F81779AAB29ACA1648708F249C8B3F9CBF55C736F5746854D89A923C1CFFA781D26C241616CD01D7B372F568B50BCA58D88D01FCBB23931DE6DA2D688A6751158971A5B19C6B46C3B761D8385238F8B9831266B09B16B5559B5EB82F64B7133AD36C5497C9BBA4AC9DCC094C3673691207D3587C97197F5CF7C1DDAB6A9F1383211639F3C57BFFF3B01709974C79C9C51B2E29E91770911A52281F030531239CB049BBCD841B1D764C49E0E8492AD383A093925AA818FC0CCEA049271F307C51F3C97A7AB5A81B43B52A6BCE2CEDB2D0E706D280DDE4A0991FCAF55CD36AC05F3593F3C797A9DCFD0FD0E0"""), + xeh("ACA147DD83685FDC5BE522178384DDB0C8714D0F818A5A20CD1AAA71730D8E36") + ), + new EncapsulateTestCase( + xeh(""" +9EBAA37C34B6F0C92BC7E98A0C56689C989E33E9126DAA3D94C95C6D60639DDCC008E4220F8C6348E44738C1AC50521A926B9BCD42511A33C1A704871C11A962E062B9625169A842F8D15CF3F3A0A2411017860C88A22D01262666F6895390AF652204ED9CB0F7589A63C23ECA851C25B527D242AC8D310B3199AF5EF7C54472739E17A6986ACAEE76B0B262C5BFB051343580E60150250865397B4C498B465B6C62E1C3A4B89B756871313AC1C4034509803C59103AA4B9A50CFC7C7EE0A34EAA417009538570C197D04C60CFB41578E274AF9ABED10B4BB7B71A4B925DDCF5432940934B222A36BC80E96C1094E5C264364660012514444ADE22A6121C30C4F037FAD29C2819350700A10C9861FEA471BD05C3D31A2EEA2A9CEFABCCF0B4AB9C33C19FF126B017370073561857084A83ABFA5B3550C2A93B785A4223AC57F4B6FCA0B4D12422B509CA45B63775FBCA4E785972E775E2989D844A4308B786F230CE990010541868C2C21B3D311E6AB14C4D417B37D10DEEBBA6309686896017F08C224DC806AE87658A0B00ECABC2A9F66029873C6C3446914C5A967441BB4AC6900575FA52238636707C69097E19C30ED66A9F28762056585C5738A6F51ADE3603B963476213B78EF65AB6CA7F612134E82A6BECF48D4DB4AD7958787A377483F0A8BAA76B06243DA4F61CF803807C17837A6293D144637BD3A92039282DA86485B005767519C9C0A0B513CA5325866DB3AA67638A2C0117FC80C4845ABADCA92C529C539431363A9A58E6A25CE6A42AB8E5CAD3865AC1B69E77B2B48DD5CFEDABAC79257D15269D72B1CE90265556DA687D894D15F11B1268692E22AD8313877FA8629F3BA224F8C5A98AA31FA58FDD05101C3705496516970B200F984B67EB497DB9AACBD6922EC84C73DB42EC0BA4D1D11859DC356765C82947B4953ACFAECB5969D34A4A8A44BA53346023517C2474A301AE7177A0253904186A5527772CD7845A4129A90B292051765772C09EF585A5BBC976F1F9B24C7AA4478B04B47398491785D9B9B9376B89D6C90320831117949A72406BE6076B4268A356E615A2168C9EEA37B2165B143304B9C51B3CC97AE3A6B0DDB185825C8B7AB073B5086B7D215D4C953F7BC9863339A045DBA784F5489FA51096234DD08B7C457B1C326B8F73672881562310E90B43FA7A37B7550696422A1B32A2615D4E8C5B3C3C61C4479A15D94F210A165311BB4C95060FB8287BC526C212B1EE0470C5497480DA396B2C39B9BB413E267583C249911029DF9B7822327764C16FA67307EFA499F0A7CADCE8B1732C91D284B505D59A444B41ED738C09A40F335C7F7050B80DAC9E5609C000473E440840D1799A86705276761E8CAC3474C1836AA9C6B4D732118AC515EC2A4DFCACB7929776501EF02415A0638819582F6AA2853DD189CF7900F834671718221933C2962B3FE598BC2EB0245C229B2ECA5B1A1A2F94BC6E278875570BCB92C043493267F7DB06C887BD66E38CDEECBCD0A998FFC094376119E4A961020C8BA05B15FE06062FD4892DC0C023AC6B2806BF863ACD85A120A0701435305A65E91D5D908B0BDBBCCBD518BC9481A5920BB4900468A893589128845BC95294A0DC5918274C4FDE2A0B18467699D637AF4CB62DBA3735E33DFE25AE1493501A590DFD0342506B748EFA5590BB689D18A50B2151C9E9B559B346E8E530A14A1CBE5AA2843431CA32AEDEEC4E9081B50A3BA764B1B0EDCC99B17B3FCB3046E6C2C1B1966F2F481E4E1CBFA4E7546E0A9E6ADB649D59151209942B92B019E8394416C19004CEF1E9235BE0228E6B2CE3603A37966BBF51CA366A3F2D18B931E4B3A827887FB3147331A746E713F60040F3277CEBC2BDB7251E84EBA5012A10CCE965E4A9963151698AF1492CF51372C37AD0D78F817B466A26372F3213873802EE26558C9ACD0F511B3F9138EDCA56FCCB36392ACE11411EB2936CCE03A0F2F347E2332E14E85B8652984D09CCEFEB8963E2A5EF845888576EE1B36EF362274D292F10355163BCBD51A7AD7B284BC4A10C3370A1391003289016F22310FD3C4CFB31CF88A42685103F3813393C1A12915981C11A616FBB8DD6905712F387D279C24B17230D32B018E14902CA1BB0561CCB73A0E2F4C8DAD9969745A1D238250B76FAA9FE97E3E08E3BCBB6E860DC8EC5EF30B92C5648EDF353871C148883FC"""), + xeh("B974689F6F36C7AB262C8B97D5469ACD3BCAA3A3454F611FF0B304FE1DF6C66E") + ), + new EncapsulateTestCase( + xeh(""" +A6902B0559182B341E3A6ABE0B646DCC84B39881948CA396CA782A65D6221589333E98A88A9C320D83A10422948B64A0DA1C4ED165B0144B22190656F1DAAE36A5641A4863A3985AE9D08456629C153A596289C01BD2912FC3603EF7ADD1EBAE1A745675F316ED0A6D4CB5C5A431C2871B939B5648D1018911D752BF08B40CC571D863B33C9043E3B2C73C67CB9A4C8087F28D7D37B9B66B638CC66796C146135C2A743AB94FC693473089E6D32492842D8D114C9A92C6721818CD0530C91A09FD7C3A124B7E98DB056C77049008A112AB61D03A8C38738B96F64D4E530E5345958EA38F19517B7293B6D2DA11BAD668988820CE8479C3B5A832C708FE09481CAA7ABDAC2E8658544067810AA31D88A52F66459B3E0A5AA8EBCBA1B5C9B8776FAAF59CFCAC69A1CC8EF166615998AE88968FABC67D67C7675B94CEF447667FF53D2B3890943303BC88C5B3DB08BA75187B6CBC97503E9A563745824A533C59A71B66D5CC21972B843BE0C0768970571796AB992B39F43F2CD8017B5517A91235474A821C541B526B0404212C194238B18AA5B8A175E4A59417D119EF8A385B7458980335842BB318214E55794C635692736B6708863A066462EEF41ED66771EAC578E029642954111C0B20F9BA3B8646456DA39873B89F6449324CBAB5ED017CC1C72E1ED4322D55B2030A8E0B390E54384449096A2DE676BEA01F03A458160341B7C743719B89A158120B790AE8E1AB4468467C4507F7CB659EB8C16A77315E553AB287836C4472EA1075C7A1C84DB4CABDD5CEB2CB5638D75FE3567659443B38B2B21C422DF97A14A8A633C2279DDB056302AB0FA83905C846AB57D2120EA1CC92195320B5B873B406CB44B73FB02160200460431581979967FC16233333A8EB7D48A120F451B3FAE9BAF6318E384B6D42B36D5B38188D849652935494C4BBBDFA22A562A27BFAB60B3455E775912D27698AA30F76CC291107629E3627EB443D0F00AA3F220877010876B485F57495C9E80DC4F3AFD6118E1849ABA06919968163CC9CB358DA03B3550198A2C43F476954F1557058C05EF828D8EB982340C9BC6A5AC1A27977402B2242A40D89072C1270DD8772008A505D4604831C1924B97C980B01788107472800EFD807FAFA1ED3466548D698CAB76B820667D630C7D03447820BB8815BBCB8DCC11752788782CA3BFC51DB9BA0D16198132A0ACDA7BD7A6531A8AAB9C8AC2770030C512740CE62CB60F79F8087CC9177B56E6A4B8155B854993E2BCB78AA849E72398590B24E87A31097AA54ACA80A9CEB29BBC5B24CBB7DA084B76B5C522F73185A05A8024629F8A6AE304CC7FE88258C94A396912A16B491DD0843D8A82BBA86843F458E91261588D7AFE89A1D7EA9786DD13C4111CF89EAB9118A7EA39A72408C8F1EA2C77765C12881192A33C552D61A76424783E5C48C881E9A541B8F6157EC138AD5E93AA925194FA37644F397A98C60DBE786983C8B2CB6C76C73CCD0371CF0CA85998C65D1F76DD5E545991A00567A48EE69A537921379923D7676401A06A81D68BD9FC4C2A28B4B72C966576BC6DA870BE8C415F94174F8137B3EE4793786652EAC97D6C91DBA4749CE4B69DB82209B24C5FAA0C4A0CAA71A39BA51E7A6F19381219900E6F8AF06F0B224326EFC2C8560A95AF8296D2B87353360A5AD3B6DCDD95377B0B201EA7A6E475D5D563A373554E83982A35503E1C179324276F6147B698C32AD24AAEFE0B2B1FA911444808C6A25CBA21B4BB008F49C0CA8D209E2BA02E3B164DA41793C212F9C5B2E0EB00CE7146284C0B26FF940268318EB330C6F0100ADD43FBF0615D2EBC27B0819CDEB6A327C590DC83D678AA4BA910E509B4EBCDCBF3B74CA581A2B55F46154D17F9AEB3A09D5C30356A75AA2859BC11DFE866E3C463C96826613880470A1CE8276B033C1810BD645B5278C25F81B678228F4D20FA3726C5715311DA4BE1F1C0752DB6D16D889D27313C4046E05FC161E889DFDE2255F434C8008AB12167F3B6A15D74B4791B293C902CCC6F4C98A75344864C35E6B189C8C116735C7636A6F0AF653DB17CBE0E3CA7C677CF9604CFADA8031611321DBC90308BCF7F93AFE1B02B0C9826A4139C4B2097CD061BCCCC5B3C562BB13A30CDBB318CB9457C1B9A69236B820AC0717EB65554D8CBB46EC883E0392B79C92DB8D07FCD393633C020FE2C469A32D"""), + xeh("7B93EBA796CAD98FDBCEAF0B8F3BFF196C1F89125B2AA88F623A91DC6AEE3771") + ) + }; + + static DecapsulateTestCase[] decap512TestCases = new DecapsulateTestCase[] { + new DecapsulateTestCase( + xeh(""" +69F9CBFD1237BA161CF6E6C18F488FC6E39AB4A5C9E6C22EA4E3AD8F267A9C442010D32E61F83E6BFA5C58706145376DBB849528F68007C822B33A95B84904DCD2708D0340C8B808BCD3AAD0E48B85849583A1B4E5945DD9514A7F6461E057B7ECF61957E97CF62815F9C32294B326E1A1C4E360B9498BA80F8CA91532B171D0AEFC4849FA53BC617932E208A677C6044A6600B8D8B83F26A747B18CFB78BEAFC551AD52B7CA6CB88F3B5D9CE2AF6C67956C478CEF491F59E0191B3BBE929B94B666C176138B00F49724341EE2E164B94C053C185A51F93E00F36861613A7FD72FEBD23A8B96A260234239C9628F995DC13807B43A69468167CB1A8F9DD07EE3B33238F63096EBC49D5051C4B65963D74A4766C226F0B94F1862C2124C8C749748C0BC4DC14CB34906B81C5524FB8100798542DC6CC2AA0A708575EABCC11F96A9E61C017A96A7CE93C42091737113AE783C0AE8755E594111EDFABFD86C3212C612A7B62AFD3C7A5C78B2F07344B789C2B2DBB5F4448BE97BBA4233C0039C0FE84300F9B03AC99497E6D46B6E95308FF84790F612CF186EC16811E80C179316A63B25703F60B842B61907E62894E736647B3C09DA6FEC5932782B36E0635085A3949E694D7E17CBA3D9064330438C071B5836A770C55F6213CC1425845DE5A334D75D3E5058C7809FDA4BCD78191DA9797325E6236C2650FC604EE43A83CEB34980084403A33259857907799A9D2A713A633B5C904727F61E42520991D655705CB6BC1B74AF60713EF8712F14086869BE8EB297D228B325A0609FD615EAB7081540A61A82ABF43B7DF98A595BE11F416B41E1EB75BB57977C25C64E97437D88CA5FDA6159D668F6BAB8157555B5D54C0F47CBCD16843B1A0A0F0210EE310313967F3D516499018FDF3114772470A1889CC06CB6B6690AC31ABCFAF4BC707684545B000B580CCBFCBCE9FA70AAEA0BBD9110992A7C6C06CB368527FD229090757E6FE75705FA592A7608F050C6F88703CC28CB000C1D7E77B897B72C62BCC7AEA21A57729483D2211832BED612430C983103C69E8C072C0EA7898F2283BEC48C5AC81984D4A5A83619735A842BD172C0D1B39F43588AF170458BA9EE7492EAAA94EA53A4D38498ECBB98A5F407E7C97B4E166E397192C216033014B878E938075C6C1F10A0065ABC3163722F1A2EFFEC8D6E3A0C4F7174FC16B79FB5186A75168F81A56AA48A20A04BDDF182C6E179C3F69061555EF7396DD0B7499601A6EB3A96A9A22D04F1168DB56355B07600A20370637B645976BBD97B6D6288A0D3036360472E3AC71D566DB8FBB1B1D76CB755CD0D68BDBFC048EBA2525EEA9DD5B144FB3B60FBC34239320CBC069B35AB16B8756536FB33E8A6AF1DD42C79F48AD120AE4B159D3D8C319060CCE569C3F6035365585D34413795A6A18EC5136AB13C90E3AF14C0B8A464C86B9073222B56B3F7328AEA798155325911250EF016D72802E3878AA50540CC983956971D6EFA352C02554DC760A5A91358EA56370884FD5B3F85B70E83E4697DEB1705169E9C60A74528CF15281CB1B1C457D467B5F93A60373D10E0CF6A837AA3C9596A72BEC29B2D7E58653D533061D381D51759752217EB46CAC7807C4AD38B611644ACF0A3F26B6B084AB47A83BF0D696F8A4768FC35BCA6BC7903B2A237C27749F5510C863869E6AE56BB2AFE4771C9221874F50F5B14BAAD5993B49238FD0A0C9F79B7B4584E41301F7A885C9F91819BEA00D512581730539FB37E59E86A6D19CA25F0A811C9B428BA8614AA4F94807BC031CBCC183F3BF07FE2C1A6EBA80D5A706EE0DAB27E231458025D84A7A9B0230501116C290A6BB50626D97B939850942828390B0A2001B7853AD1AE9B011B2DB36CAEEA73A2328E3C56485B491C299115A017C907AB54317260A593A0D7BA6D06615D6E2CA84B860EFF3CCB597211BFE36BDEF8069AFA36C5A73392722650E4957DCA597ACBA5605B63C163CFA94B64DDD62301A4332083361972589DB0599A694DD4547A5EE9196577C22ED427AC89BB8BA3753EB76C41F2C1129C8A77D6805FA719B1B6CA11B740A78A3D41B5330526AB87D58D5925315A1485EDC647C1604EB38138DE637AD2C6CA5BE44E1008B2C0867B229CCC36619E2758C4C2029EAEB26E7A803FCA305A59CD585E117D698ECE011CC3FCE54D2E114545A21AC5BE6771AB8F13122FAD295E745A503B142F91AEF7BDE99998845FDA043555C9C1EE535BE125E5DCE5D266667E723E67B6BA891C16CBA174098A3F351778B0888C9590A9090CD404"""), + xeh(""" +161CD259FEAA7EC6B286498A9A6F69F8B262A2E2093D0FBD76D5DC1C9FDE0DEDB36581004CB48112F852E7F87F649E8A42CD9E0349E7DABDF0A9AC1B521C37EA5241370A8AB2911CC79902C95D28224FA8896AD715209ECDD5D784E91DD9D0BE916B4565F4D5669AEE0DEF931E9768294EEC5258DE8391ECE271E7E4CFD9D23A79FAC3A8E0DB5DDD6E0107235688BBDF7BC5D5632F206C63A0C9564F30965CA58C69FF92D25A4F93A09EAB9B9085947E078A23E4D9C13B8A56E73E18DF42D6949FAF5921F2E373D450C8C09D07B152A97C245447429481D498BEB7256BC47F68F9922B0B1C62D9C23F9F733DD73792CFC7B43CBCEA277D51B2B8AD4A4F522F642CAD5C5DEB21F3627F8AF4D3E5BC9E91D4CB2F124B5BD7C2F4A050CA755BDB8056609663FB9511C9AD83B5039088CC01F0DD54353B0DD7433F0C6CEE0D075959810DEC5416522BB1F1F65547A0C2E9CC9BC17F8D39D29309EBE79F21331B75E12AF2E93F03F74F7F87D360F1DAF86CED736092A211A8158859C42E223CFE2E6E553437D80576CFD1944E97EEFF9B49E5ECCFC678EE165268DFE3D3596B4B86204A81C6063B0CDCE619FDBB96DF7DE6E0BD5270B4D59C4DC508476E7F0708F98C7A4F6645C49D06100C760C599528D1B8BBFE628191CC083C8D225A093F9F17E35574986F86BAA46898B589F3CB7DB46A45F3EDD4FAC20808F4CD0249DA693F8FABFBD4E10C02C65BA8C8610FA8C6DF3DBAEB6763DD482AF41558B1E15CC9C7A72E071685AC19A051F19245B9F77C3038A54E2958623EB8105955609E27D67CF72EC5C4A8E9B9C2924A9E2298508BABA13CF111FDFB062C9607AC1AAA6C637310A8894BF0B96F0C19136186B618DFFB275528BED1CC2715DEF412F77A3CF96645733B048A78474320D1A380F5EEDBDA21FA0125C91D3C37C54BF3752A1F8471C81FCAE2D3EDA966E14E66F223B054D79848FF9411D634024A098970ADE6A88B5F9069F760584DC4CFFFCEA8ECE11BB5566BD2360AB707DF2D21B67488D931F020069176423E6944490CB385E70B358A25346BAFCDD06D402FF24D6C1E5F61A85D""") + ), + new DecapsulateTestCase( + xeh(""" +69F9CBFD1237BA161CF6E6C18F488FC6E39AB4A5C9E6C22EA4E3AD8F267A9C442010D32E61F83E6BFA5C58706145376DBB849528F68007C822B33A95B84904DCD2708D0340C8B808BCD3AAD0E48B85849583A1B4E5945DD9514A7F6461E057B7ECF61957E97CF62815F9C32294B326E1A1C4E360B9498BA80F8CA91532B171D0AEFC4849FA53BC617932E208A677C6044A6600B8D8B83F26A747B18CFB78BEAFC551AD52B7CA6CB88F3B5D9CE2AF6C67956C478CEF491F59E0191B3BBE929B94B666C176138B00F49724341EE2E164B94C053C185A51F93E00F36861613A7FD72FEBD23A8B96A260234239C9628F995DC13807B43A69468167CB1A8F9DD07EE3B33238F63096EBC49D5051C4B65963D74A4766C226F0B94F1862C2124C8C749748C0BC4DC14CB34906B81C5524FB8100798542DC6CC2AA0A708575EABCC11F96A9E61C017A96A7CE93C42091737113AE783C0AE8755E594111EDFABFD86C3212C612A7B62AFD3C7A5C78B2F07344B789C2B2DBB5F4448BE97BBA4233C0039C0FE84300F9B03AC99497E6D46B6E95308FF84790F612CF186EC16811E80C179316A63B25703F60B842B61907E62894E736647B3C09DA6FEC5932782B36E0635085A3949E694D7E17CBA3D9064330438C071B5836A770C55F6213CC1425845DE5A334D75D3E5058C7809FDA4BCD78191DA9797325E6236C2650FC604EE43A83CEB34980084403A33259857907799A9D2A713A633B5C904727F61E42520991D655705CB6BC1B74AF60713EF8712F14086869BE8EB297D228B325A0609FD615EAB7081540A61A82ABF43B7DF98A595BE11F416B41E1EB75BB57977C25C64E97437D88CA5FDA6159D668F6BAB8157555B5D54C0F47CBCD16843B1A0A0F0210EE310313967F3D516499018FDF3114772470A1889CC06CB6B6690AC31ABCFAF4BC707684545B000B580CCBFCBCE9FA70AAEA0BBD9110992A7C6C06CB368527FD229090757E6FE75705FA592A7608F050C6F88703CC28CB000C1D7E77B897B72C62BCC7AEA21A57729483D2211832BED612430C983103C69E8C072C0EA7898F2283BEC48C5AC81984D4A5A83619735A842BD172C0D1B39F43588AF170458BA9EE7492EAAA94EA53A4D38498ECBB98A5F407E7C97B4E166E397192C216033014B878E938075C6C1F10A0065ABC3163722F1A2EFFEC8D6E3A0C4F7174FC16B79FB5186A75168F81A56AA48A20A04BDDF182C6E179C3F69061555EF7396DD0B7499601A6EB3A96A9A22D04F1168DB56355B07600A20370637B645976BBD97B6D6288A0D3036360472E3AC71D566DB8FBB1B1D76CB755CD0D68BDBFC048EBA2525EEA9DD5B144FB3B60FBC34239320CBC069B35AB16B8756536FB33E8A6AF1DD42C79F48AD120AE4B159D3D8C319060CCE569C3F6035365585D34413795A6A18EC5136AB13C90E3AF14C0B8A464C86B9073222B56B3F7328AEA798155325911250EF016D72802E3878AA50540CC983956971D6EFA352C02554DC760A5A91358EA56370884FD5B3F85B70E83E4697DEB1705169E9C60A74528CF15281CB1B1C457D467B5F93A60373D10E0CF6A837AA3C9596A72BEC29B2D7E58653D533061D381D51759752217EB46CAC7807C4AD38B611644ACF0A3F26B6B084AB47A83BF0D696F8A4768FC35BCA6BC7903B2A237C27749F5510C863869E6AE56BB2AFE4771C9221874F50F5B14BAAD5993B49238FD0A0C9F79B7B4584E41301F7A885C9F91819BEA00D512581730539FB37E59E86A6D19CA25F0A811C9B428BA8614AA4F94807BC031CBCC183F3BF07FE2C1A6EBA80D5A706EE0DAB27E231458025D84A7A9B0230501116C290A6BB50626D97B939850942828390B0A2001B7853AD1AE9B011B2DB36CAEEA73A2328E3C56485B491C299115A017C907AB54317260A593A0D7BA6D06615D6E2CA84B860EFF3CCB597211BFE36BDEF8069AFA36C5A73392722650E4957DCA597ACBA5605B63C163CFA94B64DDD62301A4332083361972589DB0599A694DD4547A5EE9196577C22ED427AC89BB8BA3753EB76C41F2C1129C8A77D6805FA719B1B6CA11B740A78A3D41B5330526AB87D58D5925315A1485EDC647C1604EB38138DE637AD2C6CA5BE44E1008B2C0867B229CCC36619E2758C4C2029EAEB26E7A803FCA305A59CD585E117D698ECE011CC3FCE54D2E114545A21AC5BE6771AB8F13122FAD295E745A503B142F91AEF7BDE99998845FDA043555C9C1EE535BE125E5DCE5D266667E723E67B6BA891C16CBA174098A3F351778B0888C9590A9090CD404"""), + xeh(""" +5C26D456C6C7B0E8DF0B125E5D5428FE393655127A5E05BDD1BCAC14C47493783097B6185058FA700555DD8AF10F0F979A39A603826FFEB0B44E9487539F3F1A07C673E96640DDF754C8B98CD83473568B49D095F682C1ACF0E160AB93EB41A16A57D53B419620D351C837315080D530845CF8D63CFCCDB6E9DFBE220A2C14221AA392E6337FA364DF0D2E0398F15AC3DC822B5DD7217081107A45C8CB8EACA51E034117962AEE7EC0EE212FA67A5D4B07D355A0981E4285116ECF5CA9FAB6E3105E4DE4AEC5E32938A1EB91E65CE7B39C3B9829AA1E72B8092C3622E519EE092FAC8106D6597CEB941C763288723CB55044A36D4181052A78B424B0DE1B0260F624A8D3B317095371EE9BEEA9272250D598AC63C2138D23F99087777A902EBA2163171A07546B72FCE7F86EE3B1DC1B8EAC85440B8D241742C3771F91BF981909E4F3E2505C594761259ED3AADA6AA09181B99037A395D66E6EE4BBEF97DE6BA36C53A1808CBA50938038C151603105BD6A4199EA44BF4B08961672598CB708F896E03CD9B8F8AD89DECFBE6BE0EF0006B7BD2F4AA6EB21C0218EDE601D46924CF391AE3A44E43D96EBE84A630937C3409EF0710970C27E3ADD4E64DC64E83942ABEA9CCF498EF1FE72B254043D2775A37E0B5DDD3F596EA131E0734AFA9D0223F4CD9D1AB7304CA979AD37F717BEDC3A9526F8FC94433FE4614F82E709456F39BEE7BACC84E5A70114AF1C2AC8B9B3FAA81C8F35F5A5D24189E1A457F58166473F5F1DF0170AAB5E4AC8FC719F945CCBE6F2FED24B23321D95C4C850B278B8C4EA02E3098D5A599AA3D842CF889B7F284AC5E6E66386D63F2C860B997966B4DF2C32288A50045012B7362727B856AF4F8258509B563758752FFBB1040F3C2AD8B0DED64FC15C95C1A16DE0DAE6625A9EFFCE190FC7F3261D844C114913C6B1152A258A37761B81879B59C37A1DFAC07C3E934510B45DA44C2581A79DAFBF00FABB207306269D9B74B93F4367B3BA22CCC51B362DE16E49D9FDBF8CFF84F6CE6892CA2245D34CEB9C8759E702832B66A572DE9F3016A38F7328700F96B2E947""") + ), + new DecapsulateTestCase( + xeh(""" +69F9CBFD1237BA161CF6E6C18F488FC6E39AB4A5C9E6C22EA4E3AD8F267A9C442010D32E61F83E6BFA5C58706145376DBB849528F68007C822B33A95B84904DCD2708D0340C8B808BCD3AAD0E48B85849583A1B4E5945DD9514A7F6461E057B7ECF61957E97CF62815F9C32294B326E1A1C4E360B9498BA80F8CA91532B171D0AEFC4849FA53BC617932E208A677C6044A6600B8D8B83F26A747B18CFB78BEAFC551AD52B7CA6CB88F3B5D9CE2AF6C67956C478CEF491F59E0191B3BBE929B94B666C176138B00F49724341EE2E164B94C053C185A51F93E00F36861613A7FD72FEBD23A8B96A260234239C9628F995DC13807B43A69468167CB1A8F9DD07EE3B33238F63096EBC49D5051C4B65963D74A4766C226F0B94F1862C2124C8C749748C0BC4DC14CB34906B81C5524FB8100798542DC6CC2AA0A708575EABCC11F96A9E61C017A96A7CE93C42091737113AE783C0AE8755E594111EDFABFD86C3212C612A7B62AFD3C7A5C78B2F07344B789C2B2DBB5F4448BE97BBA4233C0039C0FE84300F9B03AC99497E6D46B6E95308FF84790F612CF186EC16811E80C179316A63B25703F60B842B61907E62894E736647B3C09DA6FEC5932782B36E0635085A3949E694D7E17CBA3D9064330438C071B5836A770C55F6213CC1425845DE5A334D75D3E5058C7809FDA4BCD78191DA9797325E6236C2650FC604EE43A83CEB34980084403A33259857907799A9D2A713A633B5C904727F61E42520991D655705CB6BC1B74AF60713EF8712F14086869BE8EB297D228B325A0609FD615EAB7081540A61A82ABF43B7DF98A595BE11F416B41E1EB75BB57977C25C64E97437D88CA5FDA6159D668F6BAB8157555B5D54C0F47CBCD16843B1A0A0F0210EE310313967F3D516499018FDF3114772470A1889CC06CB6B6690AC31ABCFAF4BC707684545B000B580CCBFCBCE9FA70AAEA0BBD9110992A7C6C06CB368527FD229090757E6FE75705FA592A7608F050C6F88703CC28CB000C1D7E77B897B72C62BCC7AEA21A57729483D2211832BED612430C983103C69E8C072C0EA7898F2283BEC48C5AC81984D4A5A83619735A842BD172C0D1B39F43588AF170458BA9EE7492EAAA94EA53A4D38498ECBB98A5F407E7C97B4E166E397192C216033014B878E938075C6C1F10A0065ABC3163722F1A2EFFEC8D6E3A0C4F7174FC16B79FB5186A75168F81A56AA48A20A04BDDF182C6E179C3F69061555EF7396DD0B7499601A6EB3A96A9A22D04F1168DB56355B07600A20370637B645976BBD97B6D6288A0D3036360472E3AC71D566DB8FBB1B1D76CB755CD0D68BDBFC048EBA2525EEA9DD5B144FB3B60FBC34239320CBC069B35AB16B8756536FB33E8A6AF1DD42C79F48AD120AE4B159D3D8C319060CCE569C3F6035365585D34413795A6A18EC5136AB13C90E3AF14C0B8A464C86B9073222B56B3F7328AEA798155325911250EF016D72802E3878AA50540CC983956971D6EFA352C02554DC760A5A91358EA56370884FD5B3F85B70E83E4697DEB1705169E9C60A74528CF15281CB1B1C457D467B5F93A60373D10E0CF6A837AA3C9596A72BEC29B2D7E58653D533061D381D51759752217EB46CAC7807C4AD38B611644ACF0A3F26B6B084AB47A83BF0D696F8A4768FC35BCA6BC7903B2A237C27749F5510C863869E6AE56BB2AFE4771C9221874F50F5B14BAAD5993B49238FD0A0C9F79B7B4584E41301F7A885C9F91819BEA00D512581730539FB37E59E86A6D19CA25F0A811C9B428BA8614AA4F94807BC031CBCC183F3BF07FE2C1A6EBA80D5A706EE0DAB27E231458025D84A7A9B0230501116C290A6BB50626D97B939850942828390B0A2001B7853AD1AE9B011B2DB36CAEEA73A2328E3C56485B491C299115A017C907AB54317260A593A0D7BA6D06615D6E2CA84B860EFF3CCB597211BFE36BDEF8069AFA36C5A73392722650E4957DCA597ACBA5605B63C163CFA94B64DDD62301A4332083361972589DB0599A694DD4547A5EE9196577C22ED427AC89BB8BA3753EB76C41F2C1129C8A77D6805FA719B1B6CA11B740A78A3D41B5330526AB87D58D5925315A1485EDC647C1604EB38138DE637AD2C6CA5BE44E1008B2C0867B229CCC36619E2758C4C2029EAEB26E7A803FCA305A59CD585E117D698ECE011CC3FCE54D2E114545A21AC5BE6771AB8F13122FAD295E745A503B142F91AEF7BDE99998845FDA043555C9C1EE535BE125E5DCE5D266667E723E67B6BA891C16CBA174098A3F351778B0888C9590A9090CD404"""), + xeh(""" +79E255908B83DAD198AA6EA7219D5C170DA8548B172A2C28D53EB890914E16A6CE4405E8867112D35228DAC037743E25D26D720742C95935218ABBD93B4EB1C145794697EE761EA567BD561C6F5C076A48A34485539C49D23784606432B4913640644CDEE799961E5332E9502E683FEE98C9E1D071D8976E7F652EEE92E736D598F3B4D7217C0ED30FFA7DE590BBADCC0574A7280E502694A13A4E1D5D8837633A2EABDC97F36722D772A380595859134B9ACE346360860F8E60EACAB4AA3F9CF1DA73B5813F773008E0153B1BA0A5940DBC5C9E71E9A46BB4EA04AA9757E8E1AD0209C86334D05FCB611F3A00C7D983C7B9C160B7807CED18E5BC64A52462F4F9438199C2E4C6E9E70EDE2614913BE6D0C28894319B7B646444B5C86FCE61297EC11B21D216AC79159801ED3181667B15A7F30873BFD5727802E7B6588BDD04A5F7CFCD47043E600B4B3A0227E924E2CB92E514547BE4C1236C7AB2139F986AB956C704485DE570841F5857108D2AA57C535B3D44D0535208D501A9B56FFCBE8FDE32B375B90A5578EE44940E1E1888C21A4045D0338149D4C80CEF47BA25558E1842116E1E25499714163C0EE9A95A87A27CA2A61C4BD8D28BB04DE34EFB6E44FA7026B158883019B89AC4A5B5CA8F347A3FE892EE3949BD40D0614B9923052ED174FFBA720F516B6FD1317754A95520C66E3907B32A1648B344C34B3FA2ACEA2C8410DEEB40483529AC7D83351D888E968E457644CD76B8CAA55FC25BA1359F4A50119B1E69242DCE30E93983E50285DC0592537C6202F2E3C9878067A1777EA6A4E5ACC31614AE52787454FEEF503B82492828A736BF22E3278CF2ECAC1D0E11EC67815046CB4A66A8F48D04D4FB3C91CE7C251B37A8F3FB62A37489FFE63BDE22BAA18D4AA5BCCC0D8C709786B6C94D268382B649598A7A6785582CB2C02A2E9BECE29AC919785CCD026ADB6C9D8E85C3332DA956DC20B8470F8DD78B47E19B49BA5B27326D4937E93CC3453BB67EAFE42CAB03A70960DF236C04C344CA7177FD1E72E7E0A2C10D14F0C054337BD14152D4AFE9BB6243260E696EEE1327""") + ), + new DecapsulateTestCase( + xeh(""" +69F9CBFD1237BA161CF6E6C18F488FC6E39AB4A5C9E6C22EA4E3AD8F267A9C442010D32E61F83E6BFA5C58706145376DBB849528F68007C822B33A95B84904DCD2708D0340C8B808BCD3AAD0E48B85849583A1B4E5945DD9514A7F6461E057B7ECF61957E97CF62815F9C32294B326E1A1C4E360B9498BA80F8CA91532B171D0AEFC4849FA53BC617932E208A677C6044A6600B8D8B83F26A747B18CFB78BEAFC551AD52B7CA6CB88F3B5D9CE2AF6C67956C478CEF491F59E0191B3BBE929B94B666C176138B00F49724341EE2E164B94C053C185A51F93E00F36861613A7FD72FEBD23A8B96A260234239C9628F995DC13807B43A69468167CB1A8F9DD07EE3B33238F63096EBC49D5051C4B65963D74A4766C226F0B94F1862C2124C8C749748C0BC4DC14CB34906B81C5524FB8100798542DC6CC2AA0A708575EABCC11F96A9E61C017A96A7CE93C42091737113AE783C0AE8755E594111EDFABFD86C3212C612A7B62AFD3C7A5C78B2F07344B789C2B2DBB5F4448BE97BBA4233C0039C0FE84300F9B03AC99497E6D46B6E95308FF84790F612CF186EC16811E80C179316A63B25703F60B842B61907E62894E736647B3C09DA6FEC5932782B36E0635085A3949E694D7E17CBA3D9064330438C071B5836A770C55F6213CC1425845DE5A334D75D3E5058C7809FDA4BCD78191DA9797325E6236C2650FC604EE43A83CEB34980084403A33259857907799A9D2A713A633B5C904727F61E42520991D655705CB6BC1B74AF60713EF8712F14086869BE8EB297D228B325A0609FD615EAB7081540A61A82ABF43B7DF98A595BE11F416B41E1EB75BB57977C25C64E97437D88CA5FDA6159D668F6BAB8157555B5D54C0F47CBCD16843B1A0A0F0210EE310313967F3D516499018FDF3114772470A1889CC06CB6B6690AC31ABCFAF4BC707684545B000B580CCBFCBCE9FA70AAEA0BBD9110992A7C6C06CB368527FD229090757E6FE75705FA592A7608F050C6F88703CC28CB000C1D7E77B897B72C62BCC7AEA21A57729483D2211832BED612430C983103C69E8C072C0EA7898F2283BEC48C5AC81984D4A5A83619735A842BD172C0D1B39F43588AF170458BA9EE7492EAAA94EA53A4D38498ECBB98A5F407E7C97B4E166E397192C216033014B878E938075C6C1F10A0065ABC3163722F1A2EFFEC8D6E3A0C4F7174FC16B79FB5186A75168F81A56AA48A20A04BDDF182C6E179C3F69061555EF7396DD0B7499601A6EB3A96A9A22D04F1168DB56355B07600A20370637B645976BBD97B6D6288A0D3036360472E3AC71D566DB8FBB1B1D76CB755CD0D68BDBFC048EBA2525EEA9DD5B144FB3B60FBC34239320CBC069B35AB16B8756536FB33E8A6AF1DD42C79F48AD120AE4B159D3D8C319060CCE569C3F6035365585D34413795A6A18EC5136AB13C90E3AF14C0B8A464C86B9073222B56B3F7328AEA798155325911250EF016D72802E3878AA50540CC983956971D6EFA352C02554DC760A5A91358EA56370884FD5B3F85B70E83E4697DEB1705169E9C60A74528CF15281CB1B1C457D467B5F93A60373D10E0CF6A837AA3C9596A72BEC29B2D7E58653D533061D381D51759752217EB46CAC7807C4AD38B611644ACF0A3F26B6B084AB47A83BF0D696F8A4768FC35BCA6BC7903B2A237C27749F5510C863869E6AE56BB2AFE4771C9221874F50F5B14BAAD5993B49238FD0A0C9F79B7B4584E41301F7A885C9F91819BEA00D512581730539FB37E59E86A6D19CA25F0A811C9B428BA8614AA4F94807BC031CBCC183F3BF07FE2C1A6EBA80D5A706EE0DAB27E231458025D84A7A9B0230501116C290A6BB50626D97B939850942828390B0A2001B7853AD1AE9B011B2DB36CAEEA73A2328E3C56485B491C299115A017C907AB54317260A593A0D7BA6D06615D6E2CA84B860EFF3CCB597211BFE36BDEF8069AFA36C5A73392722650E4957DCA597ACBA5605B63C163CFA94B64DDD62301A4332083361972589DB0599A694DD4547A5EE9196577C22ED427AC89BB8BA3753EB76C41F2C1129C8A77D6805FA719B1B6CA11B740A78A3D41B5330526AB87D58D5925315A1485EDC647C1604EB38138DE637AD2C6CA5BE44E1008B2C0867B229CCC36619E2758C4C2029EAEB26E7A803FCA305A59CD585E117D698ECE011CC3FCE54D2E114545A21AC5BE6771AB8F13122FAD295E745A503B142F91AEF7BDE99998845FDA043555C9C1EE535BE125E5DCE5D266667E723E67B6BA891C16CBA174098A3F351778B0888C9590A9090CD404"""), + xeh(""" +D980E3002A28401678E1641E9E7A34D12CB2B4C9D986C7DB0FAB941AA83E43F42C44368138ED65B7A917B22ABA2DB0FBE44E5E9E7A3DAC3301379F7152585C8C7195031774CBEC61D8E1E093D694970B5377DC94CEDC53B6D3802BAF1C6F9152E05DCF66C1643528155C78118DFB00646B90726C75131DC934DCBB706ADBEC64E07F0D113BF71D4205D8E47DE67B9E01B224B82CA24405AE5591BBB1307D44E405E3866B1BB51ECE5985EE95D54568A81E7F285596DCAEBDC807EE6C8322EF2100EB38D10327DF92BC10A74A2D44842AA02AE9101A24736949D116CEC81F30C3092AAD941FC7F4BA10670CC0894A2F81E3155B9081004B4ADFB6532A1458F727F418D3F8F228E7425ACB7A4E4A3653529D1B9F72E57B8AB5852E35D0093B548FCC354A590C256B50BCADC30B55B5E05A3231611C93D5E34775741374F3E703B6E6362B35A68E33D859918D93EC03633220C61E1B81ED7AB1A5E46D4E640A9DE4E5A19FD11F0C24C556FE8D91F2358E7E78033A3C9FBF68C99DBA351F8F866CFF14E990C29E4A47579376606EB85A9D07D0BFD835C7670A5F4F2D4EA62B2BB13528A27BA3420095B852E3B73AB38E3CD068E276D8BD7A0B85BEFA48FEB72EBFC5240408B069FBC28F48B3A8E6556D7C601ADF98F0E9D64108F0BFE3C3B56C800D76E6DB14736809CEC22FA811EE92EA7950421B22F613E1349D259CF877075D476798C66FF58DBED013675BF6C5D3704528FBBE91486D7E956F785F73EDB6EB42861694F5C27E318C7B481377770125D99F236875D5B26CC8ED9859393BA2D8531E25FD6E2B3560BBC13176EBA638C72626C32D0250AB7F7EFFE661B18A641F75AE279C39771C7F23EAD50CD3AE461BB0EAACDDAD4F9C6436EDA5F2348F0ED4CD9514310AAE609B539368F53EA787ACD630080B832221B1CEF67FEB63CD2DDBA25282B020A3CB418130AD96D66EBAC09F09CB35BE0539B44924CEE15C6DBEAEE04C5BE5B9C43535FCA64B32BB204497AF175513375971B15F107F88980F0C0EB15D34762C98198A94EDCA385F32FD82CE7F6FB36F12B742C1755417A8D3F7D8A9""") + ), + new DecapsulateTestCase( + xeh(""" +69F9CBFD1237BA161CF6E6C18F488FC6E39AB4A5C9E6C22EA4E3AD8F267A9C442010D32E61F83E6BFA5C58706145376DBB849528F68007C822B33A95B84904DCD2708D0340C8B808BCD3AAD0E48B85849583A1B4E5945DD9514A7F6461E057B7ECF61957E97CF62815F9C32294B326E1A1C4E360B9498BA80F8CA91532B171D0AEFC4849FA53BC617932E208A677C6044A6600B8D8B83F26A747B18CFB78BEAFC551AD52B7CA6CB88F3B5D9CE2AF6C67956C478CEF491F59E0191B3BBE929B94B666C176138B00F49724341EE2E164B94C053C185A51F93E00F36861613A7FD72FEBD23A8B96A260234239C9628F995DC13807B43A69468167CB1A8F9DD07EE3B33238F63096EBC49D5051C4B65963D74A4766C226F0B94F1862C2124C8C749748C0BC4DC14CB34906B81C5524FB8100798542DC6CC2AA0A708575EABCC11F96A9E61C017A96A7CE93C42091737113AE783C0AE8755E594111EDFABFD86C3212C612A7B62AFD3C7A5C78B2F07344B789C2B2DBB5F4448BE97BBA4233C0039C0FE84300F9B03AC99497E6D46B6E95308FF84790F612CF186EC16811E80C179316A63B25703F60B842B61907E62894E736647B3C09DA6FEC5932782B36E0635085A3949E694D7E17CBA3D9064330438C071B5836A770C55F6213CC1425845DE5A334D75D3E5058C7809FDA4BCD78191DA9797325E6236C2650FC604EE43A83CEB34980084403A33259857907799A9D2A713A633B5C904727F61E42520991D655705CB6BC1B74AF60713EF8712F14086869BE8EB297D228B325A0609FD615EAB7081540A61A82ABF43B7DF98A595BE11F416B41E1EB75BB57977C25C64E97437D88CA5FDA6159D668F6BAB8157555B5D54C0F47CBCD16843B1A0A0F0210EE310313967F3D516499018FDF3114772470A1889CC06CB6B6690AC31ABCFAF4BC707684545B000B580CCBFCBCE9FA70AAEA0BBD9110992A7C6C06CB368527FD229090757E6FE75705FA592A7608F050C6F88703CC28CB000C1D7E77B897B72C62BCC7AEA21A57729483D2211832BED612430C983103C69E8C072C0EA7898F2283BEC48C5AC81984D4A5A83619735A842BD172C0D1B39F43588AF170458BA9EE7492EAAA94EA53A4D38498ECBB98A5F407E7C97B4E166E397192C216033014B878E938075C6C1F10A0065ABC3163722F1A2EFFEC8D6E3A0C4F7174FC16B79FB5186A75168F81A56AA48A20A04BDDF182C6E179C3F69061555EF7396DD0B7499601A6EB3A96A9A22D04F1168DB56355B07600A20370637B645976BBD97B6D6288A0D3036360472E3AC71D566DB8FBB1B1D76CB755CD0D68BDBFC048EBA2525EEA9DD5B144FB3B60FBC34239320CBC069B35AB16B8756536FB33E8A6AF1DD42C79F48AD120AE4B159D3D8C319060CCE569C3F6035365585D34413795A6A18EC5136AB13C90E3AF14C0B8A464C86B9073222B56B3F7328AEA798155325911250EF016D72802E3878AA50540CC983956971D6EFA352C02554DC760A5A91358EA56370884FD5B3F85B70E83E4697DEB1705169E9C60A74528CF15281CB1B1C457D467B5F93A60373D10E0CF6A837AA3C9596A72BEC29B2D7E58653D533061D381D51759752217EB46CAC7807C4AD38B611644ACF0A3F26B6B084AB47A83BF0D696F8A4768FC35BCA6BC7903B2A237C27749F5510C863869E6AE56BB2AFE4771C9221874F50F5B14BAAD5993B49238FD0A0C9F79B7B4584E41301F7A885C9F91819BEA00D512581730539FB37E59E86A6D19CA25F0A811C9B428BA8614AA4F94807BC031CBCC183F3BF07FE2C1A6EBA80D5A706EE0DAB27E231458025D84A7A9B0230501116C290A6BB50626D97B939850942828390B0A2001B7853AD1AE9B011B2DB36CAEEA73A2328E3C56485B491C299115A017C907AB54317260A593A0D7BA6D06615D6E2CA84B860EFF3CCB597211BFE36BDEF8069AFA36C5A73392722650E4957DCA597ACBA5605B63C163CFA94B64DDD62301A4332083361972589DB0599A694DD4547A5EE9196577C22ED427AC89BB8BA3753EB76C41F2C1129C8A77D6805FA719B1B6CA11B740A78A3D41B5330526AB87D58D5925315A1485EDC647C1604EB38138DE637AD2C6CA5BE44E1008B2C0867B229CCC36619E2758C4C2029EAEB26E7A803FCA305A59CD585E117D698ECE011CC3FCE54D2E114545A21AC5BE6771AB8F13122FAD295E745A503B142F91AEF7BDE99998845FDA043555C9C1EE535BE125E5DCE5D266667E723E67B6BA891C16CBA174098A3F351778B0888C9590A9090CD404"""), + xeh(""" +E1E906D018CCDE68680DF762DE4612106E918C29FF5D576D8FEF01D5241B666C26CB7B2F80793146AEEB9308511D9BA264A9A05D6621425730A50479B889F8C6E5AF66CFC9A3123D3B7335C06C8CD2F867484240E8B6C19EFBD3C15C33CFD10EA482D1897A516D07E39C3C1AA866C10655736F18689ECE7359D91E6EF5CEE957930258CD890C09EE1714150347A18DC97AD955B60750624755135AC81AFF8352B701EC5FF50AD925ADA003A617AE64DBFD305038E1E40108C6F12CCDD7738A83C9F7A76164F670ED4756097426700E51BA02EE36BF12FF22A316790F2C2FE7216C12F03023D87E2ADB99683229E77D6B1938EACF10D8686CEE46127CD7652A33FC05414FE370A159C516D250F7D345BAE5E1C9628A65FA9F5ED9E39FA10A316620A2D760C5DC128A5C6137F193226D18B5E013E300A41B1F2D1B47D90E3DF8B4FD71A794FAE0404570261477B32DC80CEA32F2DE743ACF7EBDD41EDBB0119EAF7F872A50A5F4C92A8B85DF792DBAC764C3A9A5A5C12D9E3913356C7F5463BEE9BD2A739FD485493B1C0DEEF716E129ED1E085F146E0D70A7E58D924F576F948BEBEF7842ED831FFD58B4656F91686B4D0F832DD3A4E6FA9F11A4870E9602E0DF0EF4FE9312EC4C7EC216D3EEDCA2076D0F0B5C9FE139145222347E816EBDC1AA70CBEB5D65954427A3DF6A78BEA86C410462596950AB8798F9BACE51A46A544C1BD17A86C2995E3BC82A7F965401A599103B0896E1B9EBA540614CE8F218DC7290103A6044E87069286E5BB18CBD89EF562B6AE1C7353F64D8CED183FA8D05D6B6A6633751EF342D839562733CDC1977684317EBC71378EC02B298671F76EEDCC3041E943A76ED9E0C496B798E10B59BAE17A195544C05CD1FA6A161358EA1D4DC7DF454220D79B235C24720021174C1BF47859CA30BCB57FC19CAD92ABF24C051D48B3D9D46779F910D26AAB4543DB2A0044BEDD491E1D72D8FDF361B50F1FD10AF4668D78F56FDC7E96CA16DCCD9BE8C1819DECAEBBECE41C09093DD508191562D6510307FA4685144D9679E84F58929D79E693DA041B12B76F629912B1E49""") + ), + new DecapsulateTestCase( + xeh(""" +69F9CBFD1237BA161CF6E6C18F488FC6E39AB4A5C9E6C22EA4E3AD8F267A9C442010D32E61F83E6BFA5C58706145376DBB849528F68007C822B33A95B84904DCD2708D0340C8B808BCD3AAD0E48B85849583A1B4E5945DD9514A7F6461E057B7ECF61957E97CF62815F9C32294B326E1A1C4E360B9498BA80F8CA91532B171D0AEFC4849FA53BC617932E208A677C6044A6600B8D8B83F26A747B18CFB78BEAFC551AD52B7CA6CB88F3B5D9CE2AF6C67956C478CEF491F59E0191B3BBE929B94B666C176138B00F49724341EE2E164B94C053C185A51F93E00F36861613A7FD72FEBD23A8B96A260234239C9628F995DC13807B43A69468167CB1A8F9DD07EE3B33238F63096EBC49D5051C4B65963D74A4766C226F0B94F1862C2124C8C749748C0BC4DC14CB34906B81C5524FB8100798542DC6CC2AA0A708575EABCC11F96A9E61C017A96A7CE93C42091737113AE783C0AE8755E594111EDFABFD86C3212C612A7B62AFD3C7A5C78B2F07344B789C2B2DBB5F4448BE97BBA4233C0039C0FE84300F9B03AC99497E6D46B6E95308FF84790F612CF186EC16811E80C179316A63B25703F60B842B61907E62894E736647B3C09DA6FEC5932782B36E0635085A3949E694D7E17CBA3D9064330438C071B5836A770C55F6213CC1425845DE5A334D75D3E5058C7809FDA4BCD78191DA9797325E6236C2650FC604EE43A83CEB34980084403A33259857907799A9D2A713A633B5C904727F61E42520991D655705CB6BC1B74AF60713EF8712F14086869BE8EB297D228B325A0609FD615EAB7081540A61A82ABF43B7DF98A595BE11F416B41E1EB75BB57977C25C64E97437D88CA5FDA6159D668F6BAB8157555B5D54C0F47CBCD16843B1A0A0F0210EE310313967F3D516499018FDF3114772470A1889CC06CB6B6690AC31ABCFAF4BC707684545B000B580CCBFCBCE9FA70AAEA0BBD9110992A7C6C06CB368527FD229090757E6FE75705FA592A7608F050C6F88703CC28CB000C1D7E77B897B72C62BCC7AEA21A57729483D2211832BED612430C983103C69E8C072C0EA7898F2283BEC48C5AC81984D4A5A83619735A842BD172C0D1B39F43588AF170458BA9EE7492EAAA94EA53A4D38498ECBB98A5F407E7C97B4E166E397192C216033014B878E938075C6C1F10A0065ABC3163722F1A2EFFEC8D6E3A0C4F7174FC16B79FB5186A75168F81A56AA48A20A04BDDF182C6E179C3F69061555EF7396DD0B7499601A6EB3A96A9A22D04F1168DB56355B07600A20370637B645976BBD97B6D6288A0D3036360472E3AC71D566DB8FBB1B1D76CB755CD0D68BDBFC048EBA2525EEA9DD5B144FB3B60FBC34239320CBC069B35AB16B8756536FB33E8A6AF1DD42C79F48AD120AE4B159D3D8C319060CCE569C3F6035365585D34413795A6A18EC5136AB13C90E3AF14C0B8A464C86B9073222B56B3F7328AEA798155325911250EF016D72802E3878AA50540CC983956971D6EFA352C02554DC760A5A91358EA56370884FD5B3F85B70E83E4697DEB1705169E9C60A74528CF15281CB1B1C457D467B5F93A60373D10E0CF6A837AA3C9596A72BEC29B2D7E58653D533061D381D51759752217EB46CAC7807C4AD38B611644ACF0A3F26B6B084AB47A83BF0D696F8A4768FC35BCA6BC7903B2A237C27749F5510C863869E6AE56BB2AFE4771C9221874F50F5B14BAAD5993B49238FD0A0C9F79B7B4584E41301F7A885C9F91819BEA00D512581730539FB37E59E86A6D19CA25F0A811C9B428BA8614AA4F94807BC031CBCC183F3BF07FE2C1A6EBA80D5A706EE0DAB27E231458025D84A7A9B0230501116C290A6BB50626D97B939850942828390B0A2001B7853AD1AE9B011B2DB36CAEEA73A2328E3C56485B491C299115A017C907AB54317260A593A0D7BA6D06615D6E2CA84B860EFF3CCB597211BFE36BDEF8069AFA36C5A73392722650E4957DCA597ACBA5605B63C163CFA94B64DDD62301A4332083361972589DB0599A694DD4547A5EE9196577C22ED427AC89BB8BA3753EB76C41F2C1129C8A77D6805FA719B1B6CA11B740A78A3D41B5330526AB87D58D5925315A1485EDC647C1604EB38138DE637AD2C6CA5BE44E1008B2C0867B229CCC36619E2758C4C2029EAEB26E7A803FCA305A59CD585E117D698ECE011CC3FCE54D2E114545A21AC5BE6771AB8F13122FAD295E745A503B142F91AEF7BDE99998845FDA043555C9C1EE535BE125E5DCE5D266667E723E67B6BA891C16CBA174098A3F351778B0888C9590A9090CD404"""), + xeh(""" +3EAE23CC5F424EDC10108FCAE8EA3AC2BE8E90EB6AFC438B5A7DCD8E149AEBA25F0D5B25052C030F8157CC5BFB876A62F6A85B6C1C954F7C0F99EF4E3AE4B48C1CA9AF035543ECA1069B067057FEFB1E50FE0374F4162F0628F1D383A8B111EA9DE854EF33FB79488AA81E75712E5B9B6485290F0956B0574A6A9E1B4D677A832A85717CF7FF5A9E23B205C4FBD4ED7C2F7C5D91F46CD6A1EDB692750A4C1B11DB15C5643C7572FF9B765713C5C97C05BC2B861997CC6CC2C4D82CC62A32EA361630454756138C015D5501E362BC4E2B03A7AD679293658E45CF155B1C4F165954D594871CBF556CFAD2C3E6EB238DA3FF3A8140C5FCB74A278ED495DD14849D4C874C3E1F6E56EE657238F4E927FAE4588F1628DECE45C625AE0A6137868B9E86CFE29CCB4483CCA6FEE905F084B2B03A84DA421417CA5087B19654C803CF072B3C9E37A70B24E30E2F52B1DFCB6817ED05D38BB6FC7558B9B96AFA0CDBE708025D8D0454B90767753524CEEF8372150480BD104F1B7E659AD28EB155842CA81A55E81B707DAAF2F42A0B1CCE0B3BFF23F5ACF984ED20B0970ECF973DD0D5E33D34FBFD1672BFFF6725B5F1F869945FC67C5D01F3ED1CD8CD43A2008181AF7F65B0922D4BC634670AAD8A23A698AC3675EB3452DCE23D7E1A130964CCF4E26A9CD3D424A54ED7861E2D807F9C98E434A78695EFAC8BC86C69CD5911A2F52B5DAF50866151C5D00FAFCAB6219A9BA675413B4BB28619CFFACA38B9ABD1C3647BCE412336C02044EAA752B79248EBA1A7AED403801DAE5377CD55F517432B677A75DE4D4B504EBBF6453E319BB6EDACE30EE44810332CC84CBFFEE2B20548EEEEE1CA131AD87CCC284B3677E7F632D69F776060005439DE5648E466AF68C6616C63144451126D10311798A9B311064301BFAC1E4641830B1FAF4963F14A740529C360A73A351B6D330364BCCD2B012CD2B571ED243BF63F2FC1F1963604923B397A57680290D413FE7413B2C6C01D5BD6A0E314A644ECB10C69418251F48D3C3941211CEDB083F6FCDE24C5F5832034780B539D3FB1493C631F0C10F2F50262FA""") + ), + new DecapsulateTestCase( + xeh(""" +69F9CBFD1237BA161CF6E6C18F488FC6E39AB4A5C9E6C22EA4E3AD8F267A9C442010D32E61F83E6BFA5C58706145376DBB849528F68007C822B33A95B84904DCD2708D0340C8B808BCD3AAD0E48B85849583A1B4E5945DD9514A7F6461E057B7ECF61957E97CF62815F9C32294B326E1A1C4E360B9498BA80F8CA91532B171D0AEFC4849FA53BC617932E208A677C6044A6600B8D8B83F26A747B18CFB78BEAFC551AD52B7CA6CB88F3B5D9CE2AF6C67956C478CEF491F59E0191B3BBE929B94B666C176138B00F49724341EE2E164B94C053C185A51F93E00F36861613A7FD72FEBD23A8B96A260234239C9628F995DC13807B43A69468167CB1A8F9DD07EE3B33238F63096EBC49D5051C4B65963D74A4766C226F0B94F1862C2124C8C749748C0BC4DC14CB34906B81C5524FB8100798542DC6CC2AA0A708575EABCC11F96A9E61C017A96A7CE93C42091737113AE783C0AE8755E594111EDFABFD86C3212C612A7B62AFD3C7A5C78B2F07344B789C2B2DBB5F4448BE97BBA4233C0039C0FE84300F9B03AC99497E6D46B6E95308FF84790F612CF186EC16811E80C179316A63B25703F60B842B61907E62894E736647B3C09DA6FEC5932782B36E0635085A3949E694D7E17CBA3D9064330438C071B5836A770C55F6213CC1425845DE5A334D75D3E5058C7809FDA4BCD78191DA9797325E6236C2650FC604EE43A83CEB34980084403A33259857907799A9D2A713A633B5C904727F61E42520991D655705CB6BC1B74AF60713EF8712F14086869BE8EB297D228B325A0609FD615EAB7081540A61A82ABF43B7DF98A595BE11F416B41E1EB75BB57977C25C64E97437D88CA5FDA6159D668F6BAB8157555B5D54C0F47CBCD16843B1A0A0F0210EE310313967F3D516499018FDF3114772470A1889CC06CB6B6690AC31ABCFAF4BC707684545B000B580CCBFCBCE9FA70AAEA0BBD9110992A7C6C06CB368527FD229090757E6FE75705FA592A7608F050C6F88703CC28CB000C1D7E77B897B72C62BCC7AEA21A57729483D2211832BED612430C983103C69E8C072C0EA7898F2283BEC48C5AC81984D4A5A83619735A842BD172C0D1B39F43588AF170458BA9EE7492EAAA94EA53A4D38498ECBB98A5F407E7C97B4E166E397192C216033014B878E938075C6C1F10A0065ABC3163722F1A2EFFEC8D6E3A0C4F7174FC16B79FB5186A75168F81A56AA48A20A04BDDF182C6E179C3F69061555EF7396DD0B7499601A6EB3A96A9A22D04F1168DB56355B07600A20370637B645976BBD97B6D6288A0D3036360472E3AC71D566DB8FBB1B1D76CB755CD0D68BDBFC048EBA2525EEA9DD5B144FB3B60FBC34239320CBC069B35AB16B8756536FB33E8A6AF1DD42C79F48AD120AE4B159D3D8C319060CCE569C3F6035365585D34413795A6A18EC5136AB13C90E3AF14C0B8A464C86B9073222B56B3F7328AEA798155325911250EF016D72802E3878AA50540CC983956971D6EFA352C02554DC760A5A91358EA56370884FD5B3F85B70E83E4697DEB1705169E9C60A74528CF15281CB1B1C457D467B5F93A60373D10E0CF6A837AA3C9596A72BEC29B2D7E58653D533061D381D51759752217EB46CAC7807C4AD38B611644ACF0A3F26B6B084AB47A83BF0D696F8A4768FC35BCA6BC7903B2A237C27749F5510C863869E6AE56BB2AFE4771C9221874F50F5B14BAAD5993B49238FD0A0C9F79B7B4584E41301F7A885C9F91819BEA00D512581730539FB37E59E86A6D19CA25F0A811C9B428BA8614AA4F94807BC031CBCC183F3BF07FE2C1A6EBA80D5A706EE0DAB27E231458025D84A7A9B0230501116C290A6BB50626D97B939850942828390B0A2001B7853AD1AE9B011B2DB36CAEEA73A2328E3C56485B491C299115A017C907AB54317260A593A0D7BA6D06615D6E2CA84B860EFF3CCB597211BFE36BDEF8069AFA36C5A73392722650E4957DCA597ACBA5605B63C163CFA94B64DDD62301A4332083361972589DB0599A694DD4547A5EE9196577C22ED427AC89BB8BA3753EB76C41F2C1129C8A77D6805FA719B1B6CA11B740A78A3D41B5330526AB87D58D5925315A1485EDC647C1604EB38138DE637AD2C6CA5BE44E1008B2C0867B229CCC36619E2758C4C2029EAEB26E7A803FCA305A59CD585E117D698ECE011CC3FCE54D2E114545A21AC5BE6771AB8F13122FAD295E745A503B142F91AEF7BDE99998845FDA043555C9C1EE535BE125E5DCE5D266667E723E67B6BA891C16CBA174098A3F351778B0888C9590A9090CD404"""), + xeh(""" +B3B6B84D9A33C59758CBEEF8EA26540D4E3D4A45BDC623CA1D0AC05D8E780D2DA1FAB26A0E250527FB0B9BD56B2A0686BD0FD310164A17244374B82FC9A93FC0AC6067929C4718B2054C7AA4AF1FDBC9EBCC55A787F7C0B98A8E6181E5604E8F7108B181AD1385422EB747286FF72BD1EF650AB88865BFC37EA5536A220C29ACE17F8AA82A77F92E0A031E526171C44BD5FA1E7946CD063B1A7E113FAEAF92015CB3CCFBDD9C5E0329CD3DBD1B8CA90EC226ACC27716615B5998E0F5A5BFBA347FDD3DD851682B8968858F4A73FE5FD952CE7FF597185855E4B7F76F44BC1B24DB7C8C3A37217DBDF0BA7168D91B59DE9EA219195D29A5C67327D51D4E05131119C81722794D825B9F01DDA93C74B176545E32E638243891EE09E2AC1A9693C83D4BEFACCF25C81554802FC422C75812E18BCCF4D3CF208BE6EB16FB4E82C4ECE33C838A0B3D3EA4C027F41B4027643D9E4B6A7EFBD8D42A65B29786F4A00C16ED4492F4E945469C6E03A9A297AD9763333A2B9725DB5C6F8DF1CA7B0E77F5E6364FB6E8E528578350A04E4E4617E72E5FD67FE029AE2D738D8DFE24730D9D737D8E30ADCB602102FE2D99B915C9B04CDA463D444ED9C6E6A71BCAAFE503BF1D15270DEF8B9D7AA5557177EDEAD75E2FB01A4635A46D2F95DEA6314DE4965EBA8358210F79E64933AB4B6600856124363A47C6063433BB670266AA8FB968D947AD96D97C4003A50B0D1119E3A73E00363AE5EE85B5815A5BD944280031F0DC9B98F1F5C589F259A486BFE26EE1446D937EEDAE41275AB72E0CD15EAA6368F59686DE08E147CE2F5978B366D0A4F98ACD7D4004D1D0A4897A0DF5B1AF9F811BBAC64952D10E36A3EF78D379EF0E95DCD2D804C07AD8D1A8882FE1F2FF188F31B886BB597FF16F4D597EB337319AB4E81565EE4AC0A9BB3B6C3184C9C66511D7313555EF703194A747D0857DD27F92A6DE12DB311828B684FF3F1D848D5E92E0EFD7BC6B3EA7039296D587A075781880039A7C0DD6DB66EDEE3A22F7F2EF02B267429F6BEE16F214A59EB96CA79EC5065784445ED2FB631BADF6645991736BE7ED""") + ), + new DecapsulateTestCase( + xeh(""" +69F9CBFD1237BA161CF6E6C18F488FC6E39AB4A5C9E6C22EA4E3AD8F267A9C442010D32E61F83E6BFA5C58706145376DBB849528F68007C822B33A95B84904DCD2708D0340C8B808BCD3AAD0E48B85849583A1B4E5945DD9514A7F6461E057B7ECF61957E97CF62815F9C32294B326E1A1C4E360B9498BA80F8CA91532B171D0AEFC4849FA53BC617932E208A677C6044A6600B8D8B83F26A747B18CFB78BEAFC551AD52B7CA6CB88F3B5D9CE2AF6C67956C478CEF491F59E0191B3BBE929B94B666C176138B00F49724341EE2E164B94C053C185A51F93E00F36861613A7FD72FEBD23A8B96A260234239C9628F995DC13807B43A69468167CB1A8F9DD07EE3B33238F63096EBC49D5051C4B65963D74A4766C226F0B94F1862C2124C8C749748C0BC4DC14CB34906B81C5524FB8100798542DC6CC2AA0A708575EABCC11F96A9E61C017A96A7CE93C42091737113AE783C0AE8755E594111EDFABFD86C3212C612A7B62AFD3C7A5C78B2F07344B789C2B2DBB5F4448BE97BBA4233C0039C0FE84300F9B03AC99497E6D46B6E95308FF84790F612CF186EC16811E80C179316A63B25703F60B842B61907E62894E736647B3C09DA6FEC5932782B36E0635085A3949E694D7E17CBA3D9064330438C071B5836A770C55F6213CC1425845DE5A334D75D3E5058C7809FDA4BCD78191DA9797325E6236C2650FC604EE43A83CEB34980084403A33259857907799A9D2A713A633B5C904727F61E42520991D655705CB6BC1B74AF60713EF8712F14086869BE8EB297D228B325A0609FD615EAB7081540A61A82ABF43B7DF98A595BE11F416B41E1EB75BB57977C25C64E97437D88CA5FDA6159D668F6BAB8157555B5D54C0F47CBCD16843B1A0A0F0210EE310313967F3D516499018FDF3114772470A1889CC06CB6B6690AC31ABCFAF4BC707684545B000B580CCBFCBCE9FA70AAEA0BBD9110992A7C6C06CB368527FD229090757E6FE75705FA592A7608F050C6F88703CC28CB000C1D7E77B897B72C62BCC7AEA21A57729483D2211832BED612430C983103C69E8C072C0EA7898F2283BEC48C5AC81984D4A5A83619735A842BD172C0D1B39F43588AF170458BA9EE7492EAAA94EA53A4D38498ECBB98A5F407E7C97B4E166E397192C216033014B878E938075C6C1F10A0065ABC3163722F1A2EFFEC8D6E3A0C4F7174FC16B79FB5186A75168F81A56AA48A20A04BDDF182C6E179C3F69061555EF7396DD0B7499601A6EB3A96A9A22D04F1168DB56355B07600A20370637B645976BBD97B6D6288A0D3036360472E3AC71D566DB8FBB1B1D76CB755CD0D68BDBFC048EBA2525EEA9DD5B144FB3B60FBC34239320CBC069B35AB16B8756536FB33E8A6AF1DD42C79F48AD120AE4B159D3D8C319060CCE569C3F6035365585D34413795A6A18EC5136AB13C90E3AF14C0B8A464C86B9073222B56B3F7328AEA798155325911250EF016D72802E3878AA50540CC983956971D6EFA352C02554DC760A5A91358EA56370884FD5B3F85B70E83E4697DEB1705169E9C60A74528CF15281CB1B1C457D467B5F93A60373D10E0CF6A837AA3C9596A72BEC29B2D7E58653D533061D381D51759752217EB46CAC7807C4AD38B611644ACF0A3F26B6B084AB47A83BF0D696F8A4768FC35BCA6BC7903B2A237C27749F5510C863869E6AE56BB2AFE4771C9221874F50F5B14BAAD5993B49238FD0A0C9F79B7B4584E41301F7A885C9F91819BEA00D512581730539FB37E59E86A6D19CA25F0A811C9B428BA8614AA4F94807BC031CBCC183F3BF07FE2C1A6EBA80D5A706EE0DAB27E231458025D84A7A9B0230501116C290A6BB50626D97B939850942828390B0A2001B7853AD1AE9B011B2DB36CAEEA73A2328E3C56485B491C299115A017C907AB54317260A593A0D7BA6D06615D6E2CA84B860EFF3CCB597211BFE36BDEF8069AFA36C5A73392722650E4957DCA597ACBA5605B63C163CFA94B64DDD62301A4332083361972589DB0599A694DD4547A5EE9196577C22ED427AC89BB8BA3753EB76C41F2C1129C8A77D6805FA719B1B6CA11B740A78A3D41B5330526AB87D58D5925315A1485EDC647C1604EB38138DE637AD2C6CA5BE44E1008B2C0867B229CCC36619E2758C4C2029EAEB26E7A803FCA305A59CD585E117D698ECE011CC3FCE54D2E114545A21AC5BE6771AB8F13122FAD295E745A503B142F91AEF7BDE99998845FDA043555C9C1EE535BE125E5DCE5D266667E723E67B6BA891C16CBA174098A3F351778B0888C9590A9090CD404"""), + xeh(""" +FA42A8B407B527A8CD9351560BA4DA60756B27FEF326BC549B3A4429B2E58EAF22B3A36AE554B416DCE209E8CC708846312992DCDD43AB177347363F81578B94F451F1D046233BEEC6B42C9E0D55F3D741A55F7C564C4A9D5ECF6B067723E4403A17CBCFAA00E2F8D2EDFE1E236AE861011A5DB659042AA23BEB01A0471D178DB91039EEE5FC7EE85AC6FF3845959E5001C61CD1756EC681C97F4A70887884157D664A505ED7E4E1F4598EBF8BCDC0BEDE7FC0A89B3E14237187CED97BB0C0E54D21F4DF47BC8FC3F863978DBB673835D17931B7819535C1ACCD8706F8726BB0A0DE20BB824560AE5BAAE2F0BF0E3E676FF74C681474534C857837E7040C33B7F031AD9900A29DCB71BC305DB0ABF92CEB5DD2EB8E644F23AC0BFD8DCD2B44101FD7CB8A287318979BAE754661FFB13097B2A52B50236094693A754DC97CFAB550877A4D8C6CBA8B4A2E3D719ABF0EB13D40976B9E3F6C433DB1E16D794466D2C023988528AD0336CE43636DD50FA6A5E899578EACEFACA5FFC5B6FCC8C53E21503B83ABEDF2174FE08B4B960476934C5D6021829AB7AA7767492FAFBEE492A08524FBED46E8D0451C6BE1BE02B55653326735B0D8CCE951A5CF534E3547731EE36EB9BA38E0AE253B8CEC35001EECE0058E634A11F59FD6F21C1A3882E291F59B1FE3EC7F55315E0A65F9D011210462A8CAFC9779208452FD4F3B64FF456EA8588D2CB394A9169F1392646880A1C63721A2277FDA432FC6EBB61FF87AD473FF41D831DD95111CF0A1D69F001A008C3FD00B46F5342EDB8DADC818E6470D21C915F3E91992806E5B18DB314F9592E0EC8B8F0DEAF92DC89C194449A2539BE7C6A1B01B6F3DC496CF33CA25825B66971880652BC6E4FBD901A286C50D625F0F682B0B4CC769EB00940C45ADE947844175A3BBE8DB92BA6DAE5BE456CEA41384BB29A8C9D4E08F1375D4865A69A59619724900DDFAE48A2D12975C789E76104AE114F30ED4F836E46BCD8CA7520F4838651225894595C4F7BEFD7ED41EAF6F395EDE40F988CBDA7E08122A61E552801C7F3E84039FFF17E3534610D3434B996312""") + ), + new DecapsulateTestCase( + xeh(""" +69F9CBFD1237BA161CF6E6C18F488FC6E39AB4A5C9E6C22EA4E3AD8F267A9C442010D32E61F83E6BFA5C58706145376DBB849528F68007C822B33A95B84904DCD2708D0340C8B808BCD3AAD0E48B85849583A1B4E5945DD9514A7F6461E057B7ECF61957E97CF62815F9C32294B326E1A1C4E360B9498BA80F8CA91532B171D0AEFC4849FA53BC617932E208A677C6044A6600B8D8B83F26A747B18CFB78BEAFC551AD52B7CA6CB88F3B5D9CE2AF6C67956C478CEF491F59E0191B3BBE929B94B666C176138B00F49724341EE2E164B94C053C185A51F93E00F36861613A7FD72FEBD23A8B96A260234239C9628F995DC13807B43A69468167CB1A8F9DD07EE3B33238F63096EBC49D5051C4B65963D74A4766C226F0B94F1862C2124C8C749748C0BC4DC14CB34906B81C5524FB8100798542DC6CC2AA0A708575EABCC11F96A9E61C017A96A7CE93C42091737113AE783C0AE8755E594111EDFABFD86C3212C612A7B62AFD3C7A5C78B2F07344B789C2B2DBB5F4448BE97BBA4233C0039C0FE84300F9B03AC99497E6D46B6E95308FF84790F612CF186EC16811E80C179316A63B25703F60B842B61907E62894E736647B3C09DA6FEC5932782B36E0635085A3949E694D7E17CBA3D9064330438C071B5836A770C55F6213CC1425845DE5A334D75D3E5058C7809FDA4BCD78191DA9797325E6236C2650FC604EE43A83CEB34980084403A33259857907799A9D2A713A633B5C904727F61E42520991D655705CB6BC1B74AF60713EF8712F14086869BE8EB297D228B325A0609FD615EAB7081540A61A82ABF43B7DF98A595BE11F416B41E1EB75BB57977C25C64E97437D88CA5FDA6159D668F6BAB8157555B5D54C0F47CBCD16843B1A0A0F0210EE310313967F3D516499018FDF3114772470A1889CC06CB6B6690AC31ABCFAF4BC707684545B000B580CCBFCBCE9FA70AAEA0BBD9110992A7C6C06CB368527FD229090757E6FE75705FA592A7608F050C6F88703CC28CB000C1D7E77B897B72C62BCC7AEA21A57729483D2211832BED612430C983103C69E8C072C0EA7898F2283BEC48C5AC81984D4A5A83619735A842BD172C0D1B39F43588AF170458BA9EE7492EAAA94EA53A4D38498ECBB98A5F407E7C97B4E166E397192C216033014B878E938075C6C1F10A0065ABC3163722F1A2EFFEC8D6E3A0C4F7174FC16B79FB5186A75168F81A56AA48A20A04BDDF182C6E179C3F69061555EF7396DD0B7499601A6EB3A96A9A22D04F1168DB56355B07600A20370637B645976BBD97B6D6288A0D3036360472E3AC71D566DB8FBB1B1D76CB755CD0D68BDBFC048EBA2525EEA9DD5B144FB3B60FBC34239320CBC069B35AB16B8756536FB33E8A6AF1DD42C79F48AD120AE4B159D3D8C319060CCE569C3F6035365585D34413795A6A18EC5136AB13C90E3AF14C0B8A464C86B9073222B56B3F7328AEA798155325911250EF016D72802E3878AA50540CC983956971D6EFA352C02554DC760A5A91358EA56370884FD5B3F85B70E83E4697DEB1705169E9C60A74528CF15281CB1B1C457D467B5F93A60373D10E0CF6A837AA3C9596A72BEC29B2D7E58653D533061D381D51759752217EB46CAC7807C4AD38B611644ACF0A3F26B6B084AB47A83BF0D696F8A4768FC35BCA6BC7903B2A237C27749F5510C863869E6AE56BB2AFE4771C9221874F50F5B14BAAD5993B49238FD0A0C9F79B7B4584E41301F7A885C9F91819BEA00D512581730539FB37E59E86A6D19CA25F0A811C9B428BA8614AA4F94807BC031CBCC183F3BF07FE2C1A6EBA80D5A706EE0DAB27E231458025D84A7A9B0230501116C290A6BB50626D97B939850942828390B0A2001B7853AD1AE9B011B2DB36CAEEA73A2328E3C56485B491C299115A017C907AB54317260A593A0D7BA6D06615D6E2CA84B860EFF3CCB597211BFE36BDEF8069AFA36C5A73392722650E4957DCA597ACBA5605B63C163CFA94B64DDD62301A4332083361972589DB0599A694DD4547A5EE9196577C22ED427AC89BB8BA3753EB76C41F2C1129C8A77D6805FA719B1B6CA11B740A78A3D41B5330526AB87D58D5925315A1485EDC647C1604EB38138DE637AD2C6CA5BE44E1008B2C0867B229CCC36619E2758C4C2029EAEB26E7A803FCA305A59CD585E117D698ECE011CC3FCE54D2E114545A21AC5BE6771AB8F13122FAD295E745A503B142F91AEF7BDE99998845FDA043555C9C1EE535BE125E5DCE5D266667E723E67B6BA891C16CBA174098A3F351778B0888C9590A9090CD404"""), + xeh(""" +9F972164967C0CD03A3DD68714FE0B4EE0EDF9ACF63AA068C10FA947F8A03264B4309EE61C8C9B0C03C5FEDFC7B77AA862DDEFEFE394FB09A2396097452585ACD0CE510324A03F36904AF07B765575DCB3B1A84131C352EF14C2572E39DDBC8118875ECFD7EF7D2E41D9C9BE858FF08DBFABF8A80BCF18FDA8735F440D9B8FCAE0E67C5BF0171B99800BBF0F3EADF76F9FD69BB0734F1356C53EA9CD64E86C14C084BC3B1FEF040E5FA939F8F0D5171AD02628AFD8B02DB7D7B5C3B32F1A8EF3AD4116ADD4502414163C14D49EC73E5F4B25C5BAAB82C73401975F2119C569E1F2873DA202F32BDFB76F9AF49F22604D1B1BB173DDF6ED70D82B360C13822F5F9BC4C4D5F2391E4FB6BCB723A56666087A55E033E50202EFBBE7DAAF96AC541C855AA4154E37CDA55B1BEAB005554947F781512E2873B5CD8B118EE0932DB2FF427A15BD114D7DA79C7D899FD820A0222DF90D8E85CEAD8A1BD96A88D6D58C0A4FBDE3AA55DFA1E4B12AE6964DEDE20FE337E4BA5EE8B67CE1ADAE9851D021A56B999DED62D0E4471CD928E9AA4AEEC5C878199149D82C3CF4FCB68F63DF27842C37E52182A7E3B332F24948F3646874326B4FDF215524A1095A224F6EB02355974A6DE9746824A3954B700903292DA43D5DD51DD9D8E98E63DD01C357E4913855190049E0F1A8D9725B095ADAC4885FE832E0BEE82BF3DC355668093B475FFCF7D92228FDEDF0451C441B345372D6EE58408462E2C3BF22A095E5E23A159397FC959C126CAF936A3E64552003FEB2B963AF7F915885445EB25B934D659900DD0506A5FCB7168392824945AABFCCD01D9EA8A2256FC8E7AAF0C4243025A9F47F295F9D2713D5257D626057E904E34B8C0530A11DF2D15AE6BF1ADA6971B233B5DFB59EF8B9EB813E7E52794883BD6D676119B5B86333CBE6427F97ED719C432127805A9790837A1EB04B82907A59CED1286164A9F02716CDAAEE48799599CB09F5CA8BDE83CE8278382776CC3246EB2C0EA91C1A9D0CD7406B419A22CD6115018B9641405F9F44E13D2CD6AB457825326FC5CDE85C94DF86097BFB5204530FE8""") + ), + new DecapsulateTestCase( + xeh(""" +69F9CBFD1237BA161CF6E6C18F488FC6E39AB4A5C9E6C22EA4E3AD8F267A9C442010D32E61F83E6BFA5C58706145376DBB849528F68007C822B33A95B84904DCD2708D0340C8B808BCD3AAD0E48B85849583A1B4E5945DD9514A7F6461E057B7ECF61957E97CF62815F9C32294B326E1A1C4E360B9498BA80F8CA91532B171D0AEFC4849FA53BC617932E208A677C6044A6600B8D8B83F26A747B18CFB78BEAFC551AD52B7CA6CB88F3B5D9CE2AF6C67956C478CEF491F59E0191B3BBE929B94B666C176138B00F49724341EE2E164B94C053C185A51F93E00F36861613A7FD72FEBD23A8B96A260234239C9628F995DC13807B43A69468167CB1A8F9DD07EE3B33238F63096EBC49D5051C4B65963D74A4766C226F0B94F1862C2124C8C749748C0BC4DC14CB34906B81C5524FB8100798542DC6CC2AA0A708575EABCC11F96A9E61C017A96A7CE93C42091737113AE783C0AE8755E594111EDFABFD86C3212C612A7B62AFD3C7A5C78B2F07344B789C2B2DBB5F4448BE97BBA4233C0039C0FE84300F9B03AC99497E6D46B6E95308FF84790F612CF186EC16811E80C179316A63B25703F60B842B61907E62894E736647B3C09DA6FEC5932782B36E0635085A3949E694D7E17CBA3D9064330438C071B5836A770C55F6213CC1425845DE5A334D75D3E5058C7809FDA4BCD78191DA9797325E6236C2650FC604EE43A83CEB34980084403A33259857907799A9D2A713A633B5C904727F61E42520991D655705CB6BC1B74AF60713EF8712F14086869BE8EB297D228B325A0609FD615EAB7081540A61A82ABF43B7DF98A595BE11F416B41E1EB75BB57977C25C64E97437D88CA5FDA6159D668F6BAB8157555B5D54C0F47CBCD16843B1A0A0F0210EE310313967F3D516499018FDF3114772470A1889CC06CB6B6690AC31ABCFAF4BC707684545B000B580CCBFCBCE9FA70AAEA0BBD9110992A7C6C06CB368527FD229090757E6FE75705FA592A7608F050C6F88703CC28CB000C1D7E77B897B72C62BCC7AEA21A57729483D2211832BED612430C983103C69E8C072C0EA7898F2283BEC48C5AC81984D4A5A83619735A842BD172C0D1B39F43588AF170458BA9EE7492EAAA94EA53A4D38498ECBB98A5F407E7C97B4E166E397192C216033014B878E938075C6C1F10A0065ABC3163722F1A2EFFEC8D6E3A0C4F7174FC16B79FB5186A75168F81A56AA48A20A04BDDF182C6E179C3F69061555EF7396DD0B7499601A6EB3A96A9A22D04F1168DB56355B07600A20370637B645976BBD97B6D6288A0D3036360472E3AC71D566DB8FBB1B1D76CB755CD0D68BDBFC048EBA2525EEA9DD5B144FB3B60FBC34239320CBC069B35AB16B8756536FB33E8A6AF1DD42C79F48AD120AE4B159D3D8C319060CCE569C3F6035365585D34413795A6A18EC5136AB13C90E3AF14C0B8A464C86B9073222B56B3F7328AEA798155325911250EF016D72802E3878AA50540CC983956971D6EFA352C02554DC760A5A91358EA56370884FD5B3F85B70E83E4697DEB1705169E9C60A74528CF15281CB1B1C457D467B5F93A60373D10E0CF6A837AA3C9596A72BEC29B2D7E58653D533061D381D51759752217EB46CAC7807C4AD38B611644ACF0A3F26B6B084AB47A83BF0D696F8A4768FC35BCA6BC7903B2A237C27749F5510C863869E6AE56BB2AFE4771C9221874F50F5B14BAAD5993B49238FD0A0C9F79B7B4584E41301F7A885C9F91819BEA00D512581730539FB37E59E86A6D19CA25F0A811C9B428BA8614AA4F94807BC031CBCC183F3BF07FE2C1A6EBA80D5A706EE0DAB27E231458025D84A7A9B0230501116C290A6BB50626D97B939850942828390B0A2001B7853AD1AE9B011B2DB36CAEEA73A2328E3C56485B491C299115A017C907AB54317260A593A0D7BA6D06615D6E2CA84B860EFF3CCB597211BFE36BDEF8069AFA36C5A73392722650E4957DCA597ACBA5605B63C163CFA94B64DDD62301A4332083361972589DB0599A694DD4547A5EE9196577C22ED427AC89BB8BA3753EB76C41F2C1129C8A77D6805FA719B1B6CA11B740A78A3D41B5330526AB87D58D5925315A1485EDC647C1604EB38138DE637AD2C6CA5BE44E1008B2C0867B229CCC36619E2758C4C2029EAEB26E7A803FCA305A59CD585E117D698ECE011CC3FCE54D2E114545A21AC5BE6771AB8F13122FAD295E745A503B142F91AEF7BDE99998845FDA043555C9C1EE535BE125E5DCE5D266667E723E67B6BA891C16CBA174098A3F351778B0888C9590A9090CD404"""), + xeh(""" +082411FFADCEE22B6C33277C32130E4C77CCB1849A2E7BDCE47EB519CAAACAAAA8DF129C5D876EAA7495ADED159D27F525EDD5F1F86B7A4FD50AC0B1F7B07C23F726D96F82D17818EEE6F032D0AEAD04D0F56EC244218905FD779268B259E29BAEF8BC66B42F47DC5BBFEA06620F38E0F373BA3F598CA7244A9F5B6823CA293BDACDD6D7B2E49BB2D00D1811C0F7FB2736876699D3F115C1D5AC58EBCFF10F514D863A56901F3DEE1328ACEF5D37DFEF841392BB29A88324CB51820A0CB30A4C222F7450F321B6617EEE7E722004AEBB5A52ABC3A984B8A142F0193EB90654FF86B8799EF7BDC01BBCD7C151587557334E01B833E950260C5E126C2BBF35EC030BBACFEF2812819A20960A9CA4E8D4836A7282F8F99AAC18BC02F6275582C7D1E6197938F67A80FB2363BF77A96355FA9E0AB19883CEA65A3010795E4A48A8B22FD04EC4578DA4452DC1B851C03A93AB147F3A34981515B75AB80D10A96570C2BF9ACB2E1662CF86E077EA455ED1B130D59CCA1F603A3471C408A342C42BE1AF6BA3E096E78CCF36CFCF6705078800E4E968FF372CE836AF5090E2442CF73E565146C69CBC0F55DB89BE1179CDF24DB6DD2C73371B00BD8CEC89FBBFAB3537DD0F50156FFA2D604BD135B91728DC93AAF31EBB51BCA15C02270D93051FBC0CF006C57F6BDDF5B8E60866E7A051358C4D0363ECB9A5EC3B6C745C41A3EFA2887B6B5AD8DC68E3C3FA17291D3D044D7085C6E2D3EB12FC3536CA8A6BEAC7B55BC2DD77B6F102C577B988E03AD963FF34CE4DFAF5194A05F12606D8E62FA7E20329E6630177BD60BCE780E014A856207A2745E5A22801A680CDBF0653EFC71F263E795AD7C495A90B7A5BECE0CC3F879B411A39A4346C677F53094298C0B2596DA1B136A32415E68A249161217414CC0F5F4D40614E162A3A757BDA41A80FCD17202AE062832D971FFD0A2F66D5EE94A26B1B78582E9F79F65A20D94EAC98DCC54D62B191DA89108126143E810AF6F8345723C69C009C481837FCED2408A8E37C96A248D7DDEFC7BBF73A5A91BFC10163813D22B0B26D5C6E380CCFCD6598844913""") + ) + }; + + static DecapsulateTestCase[] decap768TestCases = new DecapsulateTestCase[] { + new DecapsulateTestCase( + xeh(""" +1E4AC87B1A692A529FDBBAB93374C57D110B10F2B1DDEBAC0D196B7BA631B8E9293028A8F379888C422DC8D32BBF226010C2C1EC73189080456B0564B258B0F23131BC79C8E8C11CEF3938B243C5CE9C0EDD37C8F9D29877DBBB615B9B5AC3C948487E467196A9143EFBC7CEDB64B45D4ACDA2666CBC2804F2C8662E128F6A9969EC15BC0B9351F6F96346AA7ABC743A14FA030E37A2E7597BDDFC5A22F9CEDAF8614832527210B26F024C7F6C0DCF551E97A4858764C321D1834AD51D75BB246D277237B7BD41DC4362D063F4298292272D01011780B79856B296C4E946658B79603197C9B2A99EC66ACB06CE2F69B5A5A61E9BD06AD443CEB0C74ED65345A903B614E81368AAC2B3D2A79CA8CCAA1C3B88FB82A36632860B3F7950833FD0212EC96EDE4AB6F5A0BDA3EC6060A658F9457F6CC87C6B620C1A1451987486E496612A101D0E9C20577C571EDB5282608BF4E1AC926C0DB1C82A504A799D89885CA6252BD5B1C183AF701392A407C05B848C2A3016C40613F02A449B3C7926DA067A533116506840097510460BBFD36073DCB0BFA009B36A9123EAA68F835F74A01B00D2097835964DF521CE9210789C30B7F06E5844B444C53322396E4799BAF6A88AF7315860D0192D48C2C0DA6B5BA64325543ACDF5900E8BC477AB05820072D463AFFED097E062BD78C99D12B385131A241B708865B4190AF69EA0A64DB71448A60829369C7555198E438C9ABC310BC70101913BB12FAA5BEEF975841617C847CD6B336F877987753822020B92C4CC97055C9B1E0B128BF11F505005B6AB0E627795A20609EFA991E598B80F37B1C6A1C3A1E9AEE7028F77570AB2139128A00108C50EB305CDB8F9A603A6B078413F6F9B14C6D82B5199CE59D887902A281A027B717495FE12672A127BBF9B256C43720D7C160B281C12757DA135B1933352BE4AB67E40248AFC318E2370C3B8208E695BDF337459B9ACBFE5B487F76E9B4B4001D6CF90CA8C699A174D42972DC733F33389FDF59A1DABA81D834955027334185AD02C76CF294846CA9294BA0ED66741DDEC791CAB34196AC5657C5A78321B56C33306B5102397A5C09C3508F76B48282459F81D0C72A43F737BC2F12F45422628B67DB51AC1424276A6C08C3F7615665BBB8E928148A270F991BCF365A90F87C30687B68809C91F231813B866BEA82E30374D80AA0C02973437498A53B14BF6B6CA1ED76AB8A20D54A083F4A26B7C038D81967640C20BF4431E71DACCE8577B21240E494C31F2D877DAF4924FD39D82D6167FBCC1F9C5A259F843E30987CCC4BCE7493A2404B5E44387F707425781B743FB555685584E2557CC038B1A9B3F4043121F5472EB2B96E5941FEC011CEEA50791636C6ABC26C1377EE3B5146FC7C85CB335B1E795EEC2033EE44B9AA90685245EF7B4436C000E66BC8BCBF1CDB803AC1421B1FDB266D5291C8310373A8A3CE9562AB197953871AB99F382CC5AA9C0F273D1DCA55D2712853871E1A83CB3B85450F76D3F3C42BAB5505F7212FDB6B8B7F6029972A8F3751E4C94C1108B02D6AC79F8D938F05A1B2C229B14B42B31B01A364017E59578C6B033833774CB9B570F9086B722903B375446B495D8A29BF80751877A80FB724A0210C3E1692F397C2F1DDC2E6BA17AF81B92ACFABEF5F7573CB493D184027B718238C89A3549B8905B28A83362867C082D3019D3CA70700731CEB73E8472C1A3A093361C5FEA6A7D40955D07A41B64E50081A361B604CC518447C8E25765AB7D68B243275207AF8CA6564A4CB1E94199DBA1878C59BEC809AB48B2F211BADC6A1998D9C7227C1303F469D46A9C7E5303F98ABA67569AE8227C16BA1FB3244466A25E7F823671810CC26206FEB29C7E2A1A91959EEB03A98252A4F7412674EB9A4B277E1F2595FCA64033B41B40330812E9735B7C607501CD8183A22AFC3392553744F33C4D202526945C6D78A60E201A16987A6FA59D94464B56506556784824A07058F57320E76C825B9347F2936F4A0E5CDAA18CF8833945AE312A36B5F5A3810AAC82381FDAE4CB9C6831D8EB8ABAB850416443D739086B1C326FC2A3975704E396A59680C3B5F360F5480D2B62169CD94CA71B37BC5878BA2985E068BA050B2CE50726D4B4451B77AAA8676EAE094982210192197B1E92A27F59868B78867887B9A70C32AF84630AA908814379E6519150BA16439B5E2B0603D06AA6674557F5B0983E5CB6A97596069B01BB3128C416680657204FD07640392E16B19F337A99A304844E1AA474E9C799062971F672268960F5A82F950070BBE9C2A71950A3785BDF0B8440255ED63928D257845168B1ECCC4191325AA76645719B28EBD89302DC6723C786DF5217B243099CA78238E57E64692F206B177ABC259660395CD7860FB35A16F6B2FE6548C85AB66330C517FA74CDF3CB49D26B1181901AF775A1E180813B6A24C456829B5C38104ECE43C76A437A6A33B6FC6C5E65C8A89466C1425485B29B9E1854368AFCA353E143D0A90A6C6C9E7FDB62A606856B5614F12B64B796020C3534C3605CFDC73B86714F411850228A28B8F4B49E663416C84F7E381F6AF1071343BF9D39B45439240CC03897295FEA080B14BB2D8119A880E164495C61BEBC7139C11857C85E1750338D6343913706A507C9566464CD2837CF914D1A3C35E89B235C6AB7ED078BED234757C02EF6993D4A273CB8150528DA4D76708177E9425546C83E147039766603B30DA6268F4598A53194240A2832A3D67533B5056F9AAAC61B4B17B9A2693AA0D58891E6CC56CDD772410900C405AF20B903797C64876915C37B8487A1449CE924CD345C29A36E08238F7A157CC7E516AB5BA73C8063F726BB5A0A0319E57127438C7FC601C99CCAAE4C1A83726FDCB5045ED1A82A985EA995396D77272C66CE493289F6110910F37C2741CE47026A6F8261999C6482572B1693912EF12EEBEA7ACF9234FB409F2A6090E6B0BFD895469D0B2A921BB723F87A33EA5465AB90F514B67698C0768B6CA498B022C512FA0875F054AA2265867E31C0E522651E024A07D60DD9F633166921F4126BC2B6AA01CC15A09B85BFF8218C5AAE95BC1FFB26AE5A137670F04910CA9D7241B6660C394C5455917746A26682FB71A432EA9530E839BDEB07433004F45A0DDAA0B24E3A566A540815F281E3FC259AC6CBC0ACB8D62268B603BC676AB415C474BB94873E4487AE31A4E3845C79901550890EE8784EEF904FEE62BA8C5F952C68413052E0A7E3388BB8FF0AD602AE3EA14D9DF6DD5E4CC6A381A41DA5C137ECC49DF587E178EAF47702EC623780691A3233F69F12BD9C9B9637C51378AD71A831055277254CC63C5AD4CB76B4AB82E5FCA135E8D26A6B3A89FA5B6F"""), + xeh(""" +74A26C7D27146A22C7EAB420134E973799CEC1DA2DF61AE0FA7905A3A47485A063076BFA22D6E4FE5059DE0A32E38F11ABD63F990E91BD0E3A5BC6E710DFE5DC0F6D4A18147EBC2E2D9B179374D83692C53EFBD45F28A2A928C2494F903576C410EB1773895EBEADB119960EEBDA9C3C710795A6D9B781FC58B30D08107F4E20944A382AFB079F31D21724F2C26E6A53412F0A908BE7586F2B3D6D7C1DEA0270E98AA209244BD88ED68AAE01432342BA5F49E015CB476B5B78D15EA77A354CC9E9FD07137D8760BE42FD4746C62C02028E7B405DDC95DF3D021921CFEDDB3D961B957ECA302A263DAB2DC117BEB3E79EFACFCF936DFC09FC0D19C358D724FA381EA06CA067C384E944302C3907AB15A1DA4B41352692ADD59B061541F07EFF25EC42F46E1A0E370CAD06FF3FD997D4D2C5648AF762231B382D0593401936CBA21551A2AE30D8E8EFFCF43916B83138BB5E610364429879FA9CDD5B7D3CF2FEABAA1DC8D50CE69402E21103E795DF7074D1FCF65F8A4E18986D5417780602C63BE5A044863384BD3D8FFB685EAC567ED8349DCF2CEB702B7375B145729998049D13E2CD466CF2231B9D3A20018EE908F8514A6C6A89DF7232F91FCD84B81EBC8BC539E9A37A4324755564BE1BF4FA1FB4571E0ABBC9B52F9D090C33BE599DE6C8532C7CB7EC8B4E2D3C07505280E99923865903FFD18BC13B9C8164AA1EAE84E38D3F57FDB8801785F105A6A8574BD2FE9BF305848E525330BC2D24F0257E47A4950F433A9233E8CDEBA81DBAE7D8C1A06D01F70DE6EF663207D84952827BAB3D451CBEA0990007FBDB4240FE899A706F7C1563E05C70BE9D575189EF83E0CF76195F6652491CCE04F1CE2092170A92E0DD7301246A4C44FC0B4EE6AAA63FC7027840ABD2EC25F654589738CD38B9E10B975CFB6C1D2EB4DA97736998F84FDDDD810D72DA3C5AB13507420DDBFAA4F7750C1FAE9C7DFB30F40A12AEA689FC78DA900020E3ABB32A364D5C6B3C7544A1B5734A41E95C8314B448CD0B738D829AF772A8F81C51ADBA2D85F326C8F5D6961CF12D44A9BEDEA00D1DF5B48F429B1CE0C15EA5F5BC10B017247BA2C6BE922B0563B8E9698677CB6C45CCF2081BF84219D2904C11FF92199F8AEFAD62D8608E200802C5A07202CC820E9E520E31BF36A83002ECA4018B0B3A398801562AA86C77AB0D50A8FBC3768B0A643B97E7F9072168DE29B8175999C9AA48D301A3F0303172E9C7D4F16329D5CA9D42397C3982E10C9DA42DE88BD6C2AB91C1E71E778E58BB8F801F207A88A9B47F9C687AFBBA34EDA6D2899E4FA0008AA2B539711753DC7C07F614E814F683D6C037562AE1FBBE6D7D5FA54B7A6D9451E11B01AACCC3BF2ED64742DD100E0EAB2DF6CCCF937B6D5981ECA0E01F3245CF26A72AD1ADF066C8F5430D72F509963A657D85E554C14E26E8BEC5D5F3AB998C9B29F16B04747D80749B30E51FD2A7F690C22F9986AAF6358D6FAB8DED54971B32641DE2B258590EEAA6BF1F32324A7C4C983F49466D86""") + ), + new DecapsulateTestCase( + xeh(""" +1E4AC87B1A692A529FDBBAB93374C57D110B10F2B1DDEBAC0D196B7BA631B8E9293028A8F379888C422DC8D32BBF226010C2C1EC73189080456B0564B258B0F23131BC79C8E8C11CEF3938B243C5CE9C0EDD37C8F9D29877DBBB615B9B5AC3C948487E467196A9143EFBC7CEDB64B45D4ACDA2666CBC2804F2C8662E128F6A9969EC15BC0B9351F6F96346AA7ABC743A14FA030E37A2E7597BDDFC5A22F9CEDAF8614832527210B26F024C7F6C0DCF551E97A4858764C321D1834AD51D75BB246D277237B7BD41DC4362D063F4298292272D01011780B79856B296C4E946658B79603197C9B2A99EC66ACB06CE2F69B5A5A61E9BD06AD443CEB0C74ED65345A903B614E81368AAC2B3D2A79CA8CCAA1C3B88FB82A36632860B3F7950833FD0212EC96EDE4AB6F5A0BDA3EC6060A658F9457F6CC87C6B620C1A1451987486E496612A101D0E9C20577C571EDB5282608BF4E1AC926C0DB1C82A504A799D89885CA6252BD5B1C183AF701392A407C05B848C2A3016C40613F02A449B3C7926DA067A533116506840097510460BBFD36073DCB0BFA009B36A9123EAA68F835F74A01B00D2097835964DF521CE9210789C30B7F06E5844B444C53322396E4799BAF6A88AF7315860D0192D48C2C0DA6B5BA64325543ACDF5900E8BC477AB05820072D463AFFED097E062BD78C99D12B385131A241B708865B4190AF69EA0A64DB71448A60829369C7555198E438C9ABC310BC70101913BB12FAA5BEEF975841617C847CD6B336F877987753822020B92C4CC97055C9B1E0B128BF11F505005B6AB0E627795A20609EFA991E598B80F37B1C6A1C3A1E9AEE7028F77570AB2139128A00108C50EB305CDB8F9A603A6B078413F6F9B14C6D82B5199CE59D887902A281A027B717495FE12672A127BBF9B256C43720D7C160B281C12757DA135B1933352BE4AB67E40248AFC318E2370C3B8208E695BDF337459B9ACBFE5B487F76E9B4B4001D6CF90CA8C699A174D42972DC733F33389FDF59A1DABA81D834955027334185AD02C76CF294846CA9294BA0ED66741DDEC791CAB34196AC5657C5A78321B56C33306B5102397A5C09C3508F76B48282459F81D0C72A43F737BC2F12F45422628B67DB51AC1424276A6C08C3F7615665BBB8E928148A270F991BCF365A90F87C30687B68809C91F231813B866BEA82E30374D80AA0C02973437498A53B14BF6B6CA1ED76AB8A20D54A083F4A26B7C038D81967640C20BF4431E71DACCE8577B21240E494C31F2D877DAF4924FD39D82D6167FBCC1F9C5A259F843E30987CCC4BCE7493A2404B5E44387F707425781B743FB555685584E2557CC038B1A9B3F4043121F5472EB2B96E5941FEC011CEEA50791636C6ABC26C1377EE3B5146FC7C85CB335B1E795EEC2033EE44B9AA90685245EF7B4436C000E66BC8BCBF1CDB803AC1421B1FDB266D5291C8310373A8A3CE9562AB197953871AB99F382CC5AA9C0F273D1DCA55D2712853871E1A83CB3B85450F76D3F3C42BAB5505F7212FDB6B8B7F6029972A8F3751E4C94C1108B02D6AC79F8D938F05A1B2C229B14B42B31B01A364017E59578C6B033833774CB9B570F9086B722903B375446B495D8A29BF80751877A80FB724A0210C3E1692F397C2F1DDC2E6BA17AF81B92ACFABEF5F7573CB493D184027B718238C89A3549B8905B28A83362867C082D3019D3CA70700731CEB73E8472C1A3A093361C5FEA6A7D40955D07A41B64E50081A361B604CC518447C8E25765AB7D68B243275207AF8CA6564A4CB1E94199DBA1878C59BEC809AB48B2F211BADC6A1998D9C7227C1303F469D46A9C7E5303F98ABA67569AE8227C16BA1FB3244466A25E7F823671810CC26206FEB29C7E2A1A91959EEB03A98252A4F7412674EB9A4B277E1F2595FCA64033B41B40330812E9735B7C607501CD8183A22AFC3392553744F33C4D202526945C6D78A60E201A16987A6FA59D94464B56506556784824A07058F57320E76C825B9347F2936F4A0E5CDAA18CF8833945AE312A36B5F5A3810AAC82381FDAE4CB9C6831D8EB8ABAB850416443D739086B1C326FC2A3975704E396A59680C3B5F360F5480D2B62169CD94CA71B37BC5878BA2985E068BA050B2CE50726D4B4451B77AAA8676EAE094982210192197B1E92A27F59868B78867887B9A70C32AF84630AA908814379E6519150BA16439B5E2B0603D06AA6674557F5B0983E5CB6A97596069B01BB3128C416680657204FD07640392E16B19F337A99A304844E1AA474E9C799062971F672268960F5A82F950070BBE9C2A71950A3785BDF0B8440255ED63928D257845168B1ECCC4191325AA76645719B28EBD89302DC6723C786DF5217B243099CA78238E57E64692F206B177ABC259660395CD7860FB35A16F6B2FE6548C85AB66330C517FA74CDF3CB49D26B1181901AF775A1E180813B6A24C456829B5C38104ECE43C76A437A6A33B6FC6C5E65C8A89466C1425485B29B9E1854368AFCA353E143D0A90A6C6C9E7FDB62A606856B5614F12B64B796020C3534C3605CFDC73B86714F411850228A28B8F4B49E663416C84F7E381F6AF1071343BF9D39B45439240CC03897295FEA080B14BB2D8119A880E164495C61BEBC7139C11857C85E1750338D6343913706A507C9566464CD2837CF914D1A3C35E89B235C6AB7ED078BED234757C02EF6993D4A273CB8150528DA4D76708177E9425546C83E147039766603B30DA6268F4598A53194240A2832A3D67533B5056F9AAAC61B4B17B9A2693AA0D58891E6CC56CDD772410900C405AF20B903797C64876915C37B8487A1449CE924CD345C29A36E08238F7A157CC7E516AB5BA73C8063F726BB5A0A0319E57127438C7FC601C99CCAAE4C1A83726FDCB5045ED1A82A985EA995396D77272C66CE493289F6110910F37C2741CE47026A6F8261999C6482572B1693912EF12EEBEA7ACF9234FB409F2A6090E6B0BFD895469D0B2A921BB723F87A33EA5465AB90F514B67698C0768B6CA498B022C512FA0875F054AA2265867E31C0E522651E024A07D60DD9F633166921F4126BC2B6AA01CC15A09B85BFF8218C5AAE95BC1FFB26AE5A137670F04910CA9D7241B6660C394C5455917746A26682FB71A432EA9530E839BDEB07433004F45A0DDAA0B24E3A566A540815F281E3FC259AC6CBC0ACB8D62268B603BC676AB415C474BB94873E4487AE31A4E3845C79901550890EE8784EEF904FEE62BA8C5F952C68413052E0A7E3388BB8FF0AD602AE3EA14D9DF6DD5E4CC6A381A41DA5C137ECC49DF587E178EAF47702EC623780691A3233F69F12BD9C9B9637C51378AD71A831055277254CC63C5AD4CB76B4AB82E5FCA135E8D26A6B3A89FA5B6F"""), + xeh(""" +39EFB90089F1DC32A54370B3EEDF2B12880DC7D657F0404E41F7DAAA73E7F06CB90BBEEC7544160768EC3B56681D057AE1DB58F0123286D3A8CDD0B414CF9894FDA1CFF3A37CF67B82C5C7AD3427F2F2B393978B94E524F33334E4A98AFFEA8D7514D6E12E85086E58A0C078EBA64435441F3E3702EA27EEA984E46893BB886572491F22AE09F8D50774B4DDD5CF478CB0B2D070437E86645EF62AA83599093732F81A75D1D5DE15C31EC81AC4D67852FDE089D580B71E3DB07C71394424E0936BF74D0C9405BD3DFB60B920E7EFA38C72D5912BBD301BD3F3709CBEEEB7BFD0767B77A8639913E8C228FBB7E3E13C423BF05AC65B7E75F29C9048F161AF1B4B41C495ADB53FECC57FED0DCF792050A2A586C33AA4A7F6BCDA9068EA295FB692BDCA756FCC47CA0A8C84DB5DCB6A616605F3D3A34C4D23EC14942492C07EF123C8D084DF21F3B2141D277FA16E3CF4D5A3AB8D78CE8370F411DF737647A2D6123120AEE1CCF7DEFC35A5408FA6013E94703E8E04C50BADCBBF2E1FF0FB82DB4AAC595B9EAA9E370C9C6175CEF20B1D0B8A4309AB91918451E6C8A6DF04AE468D446FD9E83F9252F145A2B44A19E7B27DA56044717DB5A6ED5F6E5CDD90208ABC324290292B1F2E84FB69F5989D9921DCB4F058DCAF7B99DF71B26BD1090E457767954B8ACC84FDDFD663D64027528077B3C9E370600942E4C1175B487FBF25E267474B5238576010CCCE3315CEDD5634658B2028F3FB9959D77FA23756DB4878697C9BC491DBD68986B9073D187F2A9E72C943D94C97DA865CFD9C23508105637FED62E56E745555909A49D23B86E620D48FD55A92CC2266C38B857F5DF9BB683D60B084819CF04F5BB8CBED05AC6F48C518EDB5B222F5E6DCBB438182A7BA3B2279E5856828CBE9BDA6009A70D20DA082D2FFBD092EDAD4B272E46D215B8ECC26222499F024327A391CEB007789757FF8FA8267429F0534F305F75709DCC4229803EA8E612F55890C5FDF8252794D5C9C4058C2258A5599BA858A02F89A6FDB35C4F2364A4C6B326A31F7D04F62C2FAFE51D280CD7A4CAB66404FDFD033EADD07974BCAA7F0CB7401B9484DAF9F325B6BA53FBF41219384B264F24AA8D65281693295E6F71FCA885F808026829A3FC32DC9603F0CED36F0B58A296B44ADDA3AAF10638C31F354D1A5AC34E77D4D0154C9546709E920258F73E039FBC223EE74A270840165F64E3051B10B5E63F9ACCF5D1EF40E43F5823B15F8C25CAFCE698A64F9AE316D3905B8E510C56CF7544CA94719735A640F2B8C3A2B828A04E0568863937595E5B9DADA33533D9D676AA657FE69152E93159A00C5962F4DFF9C901A9AB32DB28B93F4BA780E44A2F73878AA76E112E3490205AF83000EFD889FCEEA5E87AE9AE01EE1CCF6BA0461A8D8654B7702C09BB41C4F61A00D05F031B244EDED8D1CAC7916BEB9AA67A3880F4C3516A8D8204932EA00EFB3AA20369FB6BE404843C7411E88428568AB9A39124EAD115298D49C998651E5EF613A6819336683""") + ), + new DecapsulateTestCase( + xeh(""" +1E4AC87B1A692A529FDBBAB93374C57D110B10F2B1DDEBAC0D196B7BA631B8E9293028A8F379888C422DC8D32BBF226010C2C1EC73189080456B0564B258B0F23131BC79C8E8C11CEF3938B243C5CE9C0EDD37C8F9D29877DBBB615B9B5AC3C948487E467196A9143EFBC7CEDB64B45D4ACDA2666CBC2804F2C8662E128F6A9969EC15BC0B9351F6F96346AA7ABC743A14FA030E37A2E7597BDDFC5A22F9CEDAF8614832527210B26F024C7F6C0DCF551E97A4858764C321D1834AD51D75BB246D277237B7BD41DC4362D063F4298292272D01011780B79856B296C4E946658B79603197C9B2A99EC66ACB06CE2F69B5A5A61E9BD06AD443CEB0C74ED65345A903B614E81368AAC2B3D2A79CA8CCAA1C3B88FB82A36632860B3F7950833FD0212EC96EDE4AB6F5A0BDA3EC6060A658F9457F6CC87C6B620C1A1451987486E496612A101D0E9C20577C571EDB5282608BF4E1AC926C0DB1C82A504A799D89885CA6252BD5B1C183AF701392A407C05B848C2A3016C40613F02A449B3C7926DA067A533116506840097510460BBFD36073DCB0BFA009B36A9123EAA68F835F74A01B00D2097835964DF521CE9210789C30B7F06E5844B444C53322396E4799BAF6A88AF7315860D0192D48C2C0DA6B5BA64325543ACDF5900E8BC477AB05820072D463AFFED097E062BD78C99D12B385131A241B708865B4190AF69EA0A64DB71448A60829369C7555198E438C9ABC310BC70101913BB12FAA5BEEF975841617C847CD6B336F877987753822020B92C4CC97055C9B1E0B128BF11F505005B6AB0E627795A20609EFA991E598B80F37B1C6A1C3A1E9AEE7028F77570AB2139128A00108C50EB305CDB8F9A603A6B078413F6F9B14C6D82B5199CE59D887902A281A027B717495FE12672A127BBF9B256C43720D7C160B281C12757DA135B1933352BE4AB67E40248AFC318E2370C3B8208E695BDF337459B9ACBFE5B487F76E9B4B4001D6CF90CA8C699A174D42972DC733F33389FDF59A1DABA81D834955027334185AD02C76CF294846CA9294BA0ED66741DDEC791CAB34196AC5657C5A78321B56C33306B5102397A5C09C3508F76B48282459F81D0C72A43F737BC2F12F45422628B67DB51AC1424276A6C08C3F7615665BBB8E928148A270F991BCF365A90F87C30687B68809C91F231813B866BEA82E30374D80AA0C02973437498A53B14BF6B6CA1ED76AB8A20D54A083F4A26B7C038D81967640C20BF4431E71DACCE8577B21240E494C31F2D877DAF4924FD39D82D6167FBCC1F9C5A259F843E30987CCC4BCE7493A2404B5E44387F707425781B743FB555685584E2557CC038B1A9B3F4043121F5472EB2B96E5941FEC011CEEA50791636C6ABC26C1377EE3B5146FC7C85CB335B1E795EEC2033EE44B9AA90685245EF7B4436C000E66BC8BCBF1CDB803AC1421B1FDB266D5291C8310373A8A3CE9562AB197953871AB99F382CC5AA9C0F273D1DCA55D2712853871E1A83CB3B85450F76D3F3C42BAB5505F7212FDB6B8B7F6029972A8F3751E4C94C1108B02D6AC79F8D938F05A1B2C229B14B42B31B01A364017E59578C6B033833774CB9B570F9086B722903B375446B495D8A29BF80751877A80FB724A0210C3E1692F397C2F1DDC2E6BA17AF81B92ACFABEF5F7573CB493D184027B718238C89A3549B8905B28A83362867C082D3019D3CA70700731CEB73E8472C1A3A093361C5FEA6A7D40955D07A41B64E50081A361B604CC518447C8E25765AB7D68B243275207AF8CA6564A4CB1E94199DBA1878C59BEC809AB48B2F211BADC6A1998D9C7227C1303F469D46A9C7E5303F98ABA67569AE8227C16BA1FB3244466A25E7F823671810CC26206FEB29C7E2A1A91959EEB03A98252A4F7412674EB9A4B277E1F2595FCA64033B41B40330812E9735B7C607501CD8183A22AFC3392553744F33C4D202526945C6D78A60E201A16987A6FA59D94464B56506556784824A07058F57320E76C825B9347F2936F4A0E5CDAA18CF8833945AE312A36B5F5A3810AAC82381FDAE4CB9C6831D8EB8ABAB850416443D739086B1C326FC2A3975704E396A59680C3B5F360F5480D2B62169CD94CA71B37BC5878BA2985E068BA050B2CE50726D4B4451B77AAA8676EAE094982210192197B1E92A27F59868B78867887B9A70C32AF84630AA908814379E6519150BA16439B5E2B0603D06AA6674557F5B0983E5CB6A97596069B01BB3128C416680657204FD07640392E16B19F337A99A304844E1AA474E9C799062971F672268960F5A82F950070BBE9C2A71950A3785BDF0B8440255ED63928D257845168B1ECCC4191325AA76645719B28EBD89302DC6723C786DF5217B243099CA78238E57E64692F206B177ABC259660395CD7860FB35A16F6B2FE6548C85AB66330C517FA74CDF3CB49D26B1181901AF775A1E180813B6A24C456829B5C38104ECE43C76A437A6A33B6FC6C5E65C8A89466C1425485B29B9E1854368AFCA353E143D0A90A6C6C9E7FDB62A606856B5614F12B64B796020C3534C3605CFDC73B86714F411850228A28B8F4B49E663416C84F7E381F6AF1071343BF9D39B45439240CC03897295FEA080B14BB2D8119A880E164495C61BEBC7139C11857C85E1750338D6343913706A507C9566464CD2837CF914D1A3C35E89B235C6AB7ED078BED234757C02EF6993D4A273CB8150528DA4D76708177E9425546C83E147039766603B30DA6268F4598A53194240A2832A3D67533B5056F9AAAC61B4B17B9A2693AA0D58891E6CC56CDD772410900C405AF20B903797C64876915C37B8487A1449CE924CD345C29A36E08238F7A157CC7E516AB5BA73C8063F726BB5A0A0319E57127438C7FC601C99CCAAE4C1A83726FDCB5045ED1A82A985EA995396D77272C66CE493289F6110910F37C2741CE47026A6F8261999C6482572B1693912EF12EEBEA7ACF9234FB409F2A6090E6B0BFD895469D0B2A921BB723F87A33EA5465AB90F514B67698C0768B6CA498B022C512FA0875F054AA2265867E31C0E522651E024A07D60DD9F633166921F4126BC2B6AA01CC15A09B85BFF8218C5AAE95BC1FFB26AE5A137670F04910CA9D7241B6660C394C5455917746A26682FB71A432EA9530E839BDEB07433004F45A0DDAA0B24E3A566A540815F281E3FC259AC6CBC0ACB8D62268B603BC676AB415C474BB94873E4487AE31A4E3845C79901550890EE8784EEF904FEE62BA8C5F952C68413052E0A7E3388BB8FF0AD602AE3EA14D9DF6DD5E4CC6A381A41DA5C137ECC49DF587E178EAF47702EC623780691A3233F69F12BD9C9B9637C51378AD71A831055277254CC63C5AD4CB76B4AB82E5FCA135E8D26A6B3A89FA5B6F"""), + xeh(""" +A5C81C76C24305E1CE5D8135D41523682E9EE6D7B40AD41DF1F37C9B17DCE78076019A6B0B7C95C9BE7AF29507B2D5A6987C8EE3259190855243E6E56F5620608C52D96FAB103A8700FBA1A87DCA6078118A0871762C9534C0C0C3978C91C3A01F0F608DCF757815438FE8957C8A859183B1B6721A0865BEBC799D4E5C0E7BD3EAE4858E6AB6A2E7658ED80D4ED158B036B93FA03AFA6AE3136CF3D693C911BCC75905E5B0CB2865B9E9884522A77777613E53111D5A1C7D3DAB734CEB03657AE0C89763E99471054776BAE7D51B0E73A5BB35AEC30FF6BC93684916FEF1162586452F426653E2CA844D5744307FF9AEB287A6447783B21A0E939C81421D631F5DCB452E51ED34E3DAD1CF504E0A3B0F4711A8DC6499D1691D109569336CE1558A4C0A464E2087EA8F9E3B18F747EF61F4576AEB42B17CADB7F0FD84DA8E3A6F471D95EDFA65BE9E6C9F6AE756A22A4F1A5C543C26BA7BAD88E16D5F5B7E12E2D4CA34B3A64D17F87CCFC4FF8C5E4F53752A077C68721E8CC817F9FF24876170FF2AF89FA95855A5B1DE347C07FDDBCFE7264AA5ED6401491561D831538F852B0ED7B9E8EBAFFC060284F22D2BAEE56FA9F6D01432A115A2D6A64C38AE0A50BA362FB57B53E3E855B83CE8C42274045599F65FA6A8921D85F94ED230B516712DB6FD2FF28B3A3371D9BE058AE75C2FA591B7EC3C3DAA1F7642BC26C324C08090607E6662154DB37CF747967A1F9FC29089F570EBE60EEEF89FD24481028C85AEF1DC3B09F22CD3691BBBB821C7A8A0F35AD12BE1DD199B977048F3D48C16BB2CA94CECB8928770D5BB329A0327E0B286FAA1C65281031A31C84F2EDC9C04D475ED4E128E51EFA97D0148CBA6C95F674C589F301C265BED708E9AD8DA3C5CECBDEEED35EF1E253132BA89920D786B88230B013BCF2DC92D6B157AFA8DA8592CD0743D4982BE60D7C2D5C472AB9FA7F4CC3D12B0EBAF0ABE555C75805426844DD9428643F84406A1B8D6FAEDFD8AE6E73A72772A2159ACABD972AEB6F7DE091AC5FDD7F49A3DC6641CDF62446B4B04A31F73B80A62F80A404A8CB18CE3E65480EF7B52BF0091117E5D08EAE1B0AABB72E6DFFFF76F6E44BBD7EA570D6604BC2E74318BAFA315A38861AA1B21AFB2A53F2614F1D640075984AE62E2FCA1D1B4DB369F15705CE7D4DF8AE98264501051C0DEF21D645D49625AF02CA428D9F0C2CD9FBAEEAB97E8E9151662B6992B4C99AB1B925D08920363373F76D3FDF0828CAA69C8B1BDC6F521DF641CF1C8A4E7EF0C23289A4E2CF18ACEBBE4C1E68369BD5235120142ECDD1A73811E2E533A647D7AEE16DAA03B683639DCF1E1F1E71CFAED48F69AEC3E831733DA19CEBEC1DDBF71CBAE0800F2F6D64A096EC495D62F4344F7AA5621B322353A795AA099EA3A070272D053D4653A20CF210EAAF12CAE6023D8E5118DF04B384A44D1EDB91C44989EF7EE57F2BF81A24BDC76807DA967EE6525410C5C485067EFC3D39A9AD42CC753BAA59A1FD28AF35C00D18A406A28FC79BA""") + ), + new DecapsulateTestCase( + xeh(""" +1E4AC87B1A692A529FDBBAB93374C57D110B10F2B1DDEBAC0D196B7BA631B8E9293028A8F379888C422DC8D32BBF226010C2C1EC73189080456B0564B258B0F23131BC79C8E8C11CEF3938B243C5CE9C0EDD37C8F9D29877DBBB615B9B5AC3C948487E467196A9143EFBC7CEDB64B45D4ACDA2666CBC2804F2C8662E128F6A9969EC15BC0B9351F6F96346AA7ABC743A14FA030E37A2E7597BDDFC5A22F9CEDAF8614832527210B26F024C7F6C0DCF551E97A4858764C321D1834AD51D75BB246D277237B7BD41DC4362D063F4298292272D01011780B79856B296C4E946658B79603197C9B2A99EC66ACB06CE2F69B5A5A61E9BD06AD443CEB0C74ED65345A903B614E81368AAC2B3D2A79CA8CCAA1C3B88FB82A36632860B3F7950833FD0212EC96EDE4AB6F5A0BDA3EC6060A658F9457F6CC87C6B620C1A1451987486E496612A101D0E9C20577C571EDB5282608BF4E1AC926C0DB1C82A504A799D89885CA6252BD5B1C183AF701392A407C05B848C2A3016C40613F02A449B3C7926DA067A533116506840097510460BBFD36073DCB0BFA009B36A9123EAA68F835F74A01B00D2097835964DF521CE9210789C30B7F06E5844B444C53322396E4799BAF6A88AF7315860D0192D48C2C0DA6B5BA64325543ACDF5900E8BC477AB05820072D463AFFED097E062BD78C99D12B385131A241B708865B4190AF69EA0A64DB71448A60829369C7555198E438C9ABC310BC70101913BB12FAA5BEEF975841617C847CD6B336F877987753822020B92C4CC97055C9B1E0B128BF11F505005B6AB0E627795A20609EFA991E598B80F37B1C6A1C3A1E9AEE7028F77570AB2139128A00108C50EB305CDB8F9A603A6B078413F6F9B14C6D82B5199CE59D887902A281A027B717495FE12672A127BBF9B256C43720D7C160B281C12757DA135B1933352BE4AB67E40248AFC318E2370C3B8208E695BDF337459B9ACBFE5B487F76E9B4B4001D6CF90CA8C699A174D42972DC733F33389FDF59A1DABA81D834955027334185AD02C76CF294846CA9294BA0ED66741DDEC791CAB34196AC5657C5A78321B56C33306B5102397A5C09C3508F76B48282459F81D0C72A43F737BC2F12F45422628B67DB51AC1424276A6C08C3F7615665BBB8E928148A270F991BCF365A90F87C30687B68809C91F231813B866BEA82E30374D80AA0C02973437498A53B14BF6B6CA1ED76AB8A20D54A083F4A26B7C038D81967640C20BF4431E71DACCE8577B21240E494C31F2D877DAF4924FD39D82D6167FBCC1F9C5A259F843E30987CCC4BCE7493A2404B5E44387F707425781B743FB555685584E2557CC038B1A9B3F4043121F5472EB2B96E5941FEC011CEEA50791636C6ABC26C1377EE3B5146FC7C85CB335B1E795EEC2033EE44B9AA90685245EF7B4436C000E66BC8BCBF1CDB803AC1421B1FDB266D5291C8310373A8A3CE9562AB197953871AB99F382CC5AA9C0F273D1DCA55D2712853871E1A83CB3B85450F76D3F3C42BAB5505F7212FDB6B8B7F6029972A8F3751E4C94C1108B02D6AC79F8D938F05A1B2C229B14B42B31B01A364017E59578C6B033833774CB9B570F9086B722903B375446B495D8A29BF80751877A80FB724A0210C3E1692F397C2F1DDC2E6BA17AF81B92ACFABEF5F7573CB493D184027B718238C89A3549B8905B28A83362867C082D3019D3CA70700731CEB73E8472C1A3A093361C5FEA6A7D40955D07A41B64E50081A361B604CC518447C8E25765AB7D68B243275207AF8CA6564A4CB1E94199DBA1878C59BEC809AB48B2F211BADC6A1998D9C7227C1303F469D46A9C7E5303F98ABA67569AE8227C16BA1FB3244466A25E7F823671810CC26206FEB29C7E2A1A91959EEB03A98252A4F7412674EB9A4B277E1F2595FCA64033B41B40330812E9735B7C607501CD8183A22AFC3392553744F33C4D202526945C6D78A60E201A16987A6FA59D94464B56506556784824A07058F57320E76C825B9347F2936F4A0E5CDAA18CF8833945AE312A36B5F5A3810AAC82381FDAE4CB9C6831D8EB8ABAB850416443D739086B1C326FC2A3975704E396A59680C3B5F360F5480D2B62169CD94CA71B37BC5878BA2985E068BA050B2CE50726D4B4451B77AAA8676EAE094982210192197B1E92A27F59868B78867887B9A70C32AF84630AA908814379E6519150BA16439B5E2B0603D06AA6674557F5B0983E5CB6A97596069B01BB3128C416680657204FD07640392E16B19F337A99A304844E1AA474E9C799062971F672268960F5A82F950070BBE9C2A71950A3785BDF0B8440255ED63928D257845168B1ECCC4191325AA76645719B28EBD89302DC6723C786DF5217B243099CA78238E57E64692F206B177ABC259660395CD7860FB35A16F6B2FE6548C85AB66330C517FA74CDF3CB49D26B1181901AF775A1E180813B6A24C456829B5C38104ECE43C76A437A6A33B6FC6C5E65C8A89466C1425485B29B9E1854368AFCA353E143D0A90A6C6C9E7FDB62A606856B5614F12B64B796020C3534C3605CFDC73B86714F411850228A28B8F4B49E663416C84F7E381F6AF1071343BF9D39B45439240CC03897295FEA080B14BB2D8119A880E164495C61BEBC7139C11857C85E1750338D6343913706A507C9566464CD2837CF914D1A3C35E89B235C6AB7ED078BED234757C02EF6993D4A273CB8150528DA4D76708177E9425546C83E147039766603B30DA6268F4598A53194240A2832A3D67533B5056F9AAAC61B4B17B9A2693AA0D58891E6CC56CDD772410900C405AF20B903797C64876915C37B8487A1449CE924CD345C29A36E08238F7A157CC7E516AB5BA73C8063F726BB5A0A0319E57127438C7FC601C99CCAAE4C1A83726FDCB5045ED1A82A985EA995396D77272C66CE493289F6110910F37C2741CE47026A6F8261999C6482572B1693912EF12EEBEA7ACF9234FB409F2A6090E6B0BFD895469D0B2A921BB723F87A33EA5465AB90F514B67698C0768B6CA498B022C512FA0875F054AA2265867E31C0E522651E024A07D60DD9F633166921F4126BC2B6AA01CC15A09B85BFF8218C5AAE95BC1FFB26AE5A137670F04910CA9D7241B6660C394C5455917746A26682FB71A432EA9530E839BDEB07433004F45A0DDAA0B24E3A566A540815F281E3FC259AC6CBC0ACB8D62268B603BC676AB415C474BB94873E4487AE31A4E3845C79901550890EE8784EEF904FEE62BA8C5F952C68413052E0A7E3388BB8FF0AD602AE3EA14D9DF6DD5E4CC6A381A41DA5C137ECC49DF587E178EAF47702EC623780691A3233F69F12BD9C9B9637C51378AD71A831055277254CC63C5AD4CB76B4AB82E5FCA135E8D26A6B3A89FA5B6F"""), + xeh(""" +0BAF0F6E91ECAE3199F4921631891A14C13B418B53384992DA3A8DADA7DEFFB9E1E5F559D27344B60BE81ECD01CAB1E316573D571ED46F59248F4023DB0282207E730549CDB60E793E4CD17AC6F2800E2D1FFB83477A6FE1D73992682123EA730C63269DB13088D6DA46D086CCEA2176398EAC663270B8B2F337A55E19F4C500DE066B5441794C2D0CCADFE5ABDE7D93FD7D6468BC4F925633366D9316788B90B110A4D99485E7E578537A267744FB266A4F243FA02E3A81DA67ED477923B36B37BE21DDA21EB51DCA1F0CE41652145F4C542B2E5C922617033608246BBE2B5250A368804ABDB2EF6C31C491CE3DD852AEABF6EEF1530F4C99286B4B595D57CF3A99580B59AAA2C55E080B5230EA19CF2701D21A37FEFD6F9709657A21ADD063ECBC197B5AD068BE502A2E090D83F4156B671E46617BE6D6A17D0425FAC565C4A0E48966E9D900CB2C2B0D296E0BAA9D6C5E0514CD78834053058A97D3DDF81529079858737440812670E818C9891681D350ECEC93DAE389D534A5C78F01811917061CAC0003D2BEA390EB63FA0FE9BABCD7FF302D4B66567B2BFA67B20F962847D010AA4193CBE9F8CC1B14F8B237C22675B298A8376DFB6037BF7CEA36BDEAD5B505111F67730824B4964815D00F63EE98B9BEA0F2F47CC007D5606ED7F967CB15CCD4AFBC99881CFD297BDC2A509ED3CB320DF58DC4A5BCD1CB100B9D6418CB8E0F40DEF293DA2370CA729B0FAB071FA6AEB0F3F5D1925AB2DF732F98DDBFF23D5411E4921A1C506F2F93251E822C4CF83998B000FE65ED386F5745B1D4D91AD9F98B45E713C8D944409E9D354F42FDB9749A5107C8831562E683498C55E1475E552AC10858AB9867BF8003FB88B3B09F6E8AD8E94CE82E342B1780D68EC8565FC0684AB6C798BF09FA65BE62C37A0862ABFE99D7DBE1431B4CFE007B7EC7930B14F6D161BDCAAE2217D69D9FDBB4F882B9F464F8642ACD9BA018B93A8E3A965194ACCD96E661CF0CF4A2662076E20E8BC319693F1953DAB93FEB9BCAD666832DF42F250FADBCFAF742D68642021BD6FFD97720C3E5AB86D82CE8B14C0289DBF51B50C13CFCEC12A3922DCD2DE8473329AEB23580B22F9C36B4F06D6579751BE0593120F808F0E145D94D1DDBBE1D489B744CF6C35964C3DD96D95FB693543C69766877DA80BDE8ACDF62C366D0A4A553187461F671376F7E70F554965D57760CDF5C6F6366E33B3BFB550CC1F93D98D250F90D7D36BC01581C49417546BF6BBA9D10D41C0A008855F321547BDD5A6CFA2A2516F71415B5BC2D5FA1B9B79FDC7F2B78AA113375EC1717F0F273BD8CBEF59139518A4E8A67DB4D071257000336BB07497F72FAAC2C1FC0F553B2EBA53475F466A2B36AFE0B72B4342E995C544E6E14FF7D327F80E7AC6F65190045F380B5978F50E33272484626266125A39DA08B46256624CE34223BB17299B8B8162753812F2644C9A13C51430B02ABD188DD1A4547C920BA27CDAF145BDEBC6F45EEE3F2F55553010F7B35AC63A3C7C61C""") + ), + new DecapsulateTestCase( + xeh(""" +1E4AC87B1A692A529FDBBAB93374C57D110B10F2B1DDEBAC0D196B7BA631B8E9293028A8F379888C422DC8D32BBF226010C2C1EC73189080456B0564B258B0F23131BC79C8E8C11CEF3938B243C5CE9C0EDD37C8F9D29877DBBB615B9B5AC3C948487E467196A9143EFBC7CEDB64B45D4ACDA2666CBC2804F2C8662E128F6A9969EC15BC0B9351F6F96346AA7ABC743A14FA030E37A2E7597BDDFC5A22F9CEDAF8614832527210B26F024C7F6C0DCF551E97A4858764C321D1834AD51D75BB246D277237B7BD41DC4362D063F4298292272D01011780B79856B296C4E946658B79603197C9B2A99EC66ACB06CE2F69B5A5A61E9BD06AD443CEB0C74ED65345A903B614E81368AAC2B3D2A79CA8CCAA1C3B88FB82A36632860B3F7950833FD0212EC96EDE4AB6F5A0BDA3EC6060A658F9457F6CC87C6B620C1A1451987486E496612A101D0E9C20577C571EDB5282608BF4E1AC926C0DB1C82A504A799D89885CA6252BD5B1C183AF701392A407C05B848C2A3016C40613F02A449B3C7926DA067A533116506840097510460BBFD36073DCB0BFA009B36A9123EAA68F835F74A01B00D2097835964DF521CE9210789C30B7F06E5844B444C53322396E4799BAF6A88AF7315860D0192D48C2C0DA6B5BA64325543ACDF5900E8BC477AB05820072D463AFFED097E062BD78C99D12B385131A241B708865B4190AF69EA0A64DB71448A60829369C7555198E438C9ABC310BC70101913BB12FAA5BEEF975841617C847CD6B336F877987753822020B92C4CC97055C9B1E0B128BF11F505005B6AB0E627795A20609EFA991E598B80F37B1C6A1C3A1E9AEE7028F77570AB2139128A00108C50EB305CDB8F9A603A6B078413F6F9B14C6D82B5199CE59D887902A281A027B717495FE12672A127BBF9B256C43720D7C160B281C12757DA135B1933352BE4AB67E40248AFC318E2370C3B8208E695BDF337459B9ACBFE5B487F76E9B4B4001D6CF90CA8C699A174D42972DC733F33389FDF59A1DABA81D834955027334185AD02C76CF294846CA9294BA0ED66741DDEC791CAB34196AC5657C5A78321B56C33306B5102397A5C09C3508F76B48282459F81D0C72A43F737BC2F12F45422628B67DB51AC1424276A6C08C3F7615665BBB8E928148A270F991BCF365A90F87C30687B68809C91F231813B866BEA82E30374D80AA0C02973437498A53B14BF6B6CA1ED76AB8A20D54A083F4A26B7C038D81967640C20BF4431E71DACCE8577B21240E494C31F2D877DAF4924FD39D82D6167FBCC1F9C5A259F843E30987CCC4BCE7493A2404B5E44387F707425781B743FB555685584E2557CC038B1A9B3F4043121F5472EB2B96E5941FEC011CEEA50791636C6ABC26C1377EE3B5146FC7C85CB335B1E795EEC2033EE44B9AA90685245EF7B4436C000E66BC8BCBF1CDB803AC1421B1FDB266D5291C8310373A8A3CE9562AB197953871AB99F382CC5AA9C0F273D1DCA55D2712853871E1A83CB3B85450F76D3F3C42BAB5505F7212FDB6B8B7F6029972A8F3751E4C94C1108B02D6AC79F8D938F05A1B2C229B14B42B31B01A364017E59578C6B033833774CB9B570F9086B722903B375446B495D8A29BF80751877A80FB724A0210C3E1692F397C2F1DDC2E6BA17AF81B92ACFABEF5F7573CB493D184027B718238C89A3549B8905B28A83362867C082D3019D3CA70700731CEB73E8472C1A3A093361C5FEA6A7D40955D07A41B64E50081A361B604CC518447C8E25765AB7D68B243275207AF8CA6564A4CB1E94199DBA1878C59BEC809AB48B2F211BADC6A1998D9C7227C1303F469D46A9C7E5303F98ABA67569AE8227C16BA1FB3244466A25E7F823671810CC26206FEB29C7E2A1A91959EEB03A98252A4F7412674EB9A4B277E1F2595FCA64033B41B40330812E9735B7C607501CD8183A22AFC3392553744F33C4D202526945C6D78A60E201A16987A6FA59D94464B56506556784824A07058F57320E76C825B9347F2936F4A0E5CDAA18CF8833945AE312A36B5F5A3810AAC82381FDAE4CB9C6831D8EB8ABAB850416443D739086B1C326FC2A3975704E396A59680C3B5F360F5480D2B62169CD94CA71B37BC5878BA2985E068BA050B2CE50726D4B4451B77AAA8676EAE094982210192197B1E92A27F59868B78867887B9A70C32AF84630AA908814379E6519150BA16439B5E2B0603D06AA6674557F5B0983E5CB6A97596069B01BB3128C416680657204FD07640392E16B19F337A99A304844E1AA474E9C799062971F672268960F5A82F950070BBE9C2A71950A3785BDF0B8440255ED63928D257845168B1ECCC4191325AA76645719B28EBD89302DC6723C786DF5217B243099CA78238E57E64692F206B177ABC259660395CD7860FB35A16F6B2FE6548C85AB66330C517FA74CDF3CB49D26B1181901AF775A1E180813B6A24C456829B5C38104ECE43C76A437A6A33B6FC6C5E65C8A89466C1425485B29B9E1854368AFCA353E143D0A90A6C6C9E7FDB62A606856B5614F12B64B796020C3534C3605CFDC73B86714F411850228A28B8F4B49E663416C84F7E381F6AF1071343BF9D39B45439240CC03897295FEA080B14BB2D8119A880E164495C61BEBC7139C11857C85E1750338D6343913706A507C9566464CD2837CF914D1A3C35E89B235C6AB7ED078BED234757C02EF6993D4A273CB8150528DA4D76708177E9425546C83E147039766603B30DA6268F4598A53194240A2832A3D67533B5056F9AAAC61B4B17B9A2693AA0D58891E6CC56CDD772410900C405AF20B903797C64876915C37B8487A1449CE924CD345C29A36E08238F7A157CC7E516AB5BA73C8063F726BB5A0A0319E57127438C7FC601C99CCAAE4C1A83726FDCB5045ED1A82A985EA995396D77272C66CE493289F6110910F37C2741CE47026A6F8261999C6482572B1693912EF12EEBEA7ACF9234FB409F2A6090E6B0BFD895469D0B2A921BB723F87A33EA5465AB90F514B67698C0768B6CA498B022C512FA0875F054AA2265867E31C0E522651E024A07D60DD9F633166921F4126BC2B6AA01CC15A09B85BFF8218C5AAE95BC1FFB26AE5A137670F04910CA9D7241B6660C394C5455917746A26682FB71A432EA9530E839BDEB07433004F45A0DDAA0B24E3A566A540815F281E3FC259AC6CBC0ACB8D62268B603BC676AB415C474BB94873E4487AE31A4E3845C79901550890EE8784EEF904FEE62BA8C5F952C68413052E0A7E3388BB8FF0AD602AE3EA14D9DF6DD5E4CC6A381A41DA5C137ECC49DF587E178EAF47702EC623780691A3233F69F12BD9C9B9637C51378AD71A831055277254CC63C5AD4CB76B4AB82E5FCA135E8D26A6B3A89FA5B6F"""), + xeh(""" +2513DE1E55ED0E862614587FE47F308C90A1F426470CA1293BDDF7B9DDD6C368DC152F45C71354904ED48E15A1CB449B4C45D0F201ED5C7D3A047A72F080265D66C47D39469097EEEABBAA3B07ED1F1AEAB80C7D24552FA8889C674A5D4840289DE6B0FA9A222E693708D1F252DFE8B993956883C07067C1C0844EF0BEB49F63534D21D471D6B727FFC59477F9E89E5BEB2AF0CBEB052F003414DA4070008753CFC0C6D0FA9D1C15388FE5886EADD3474F28E4682C0E01784A037DC3799330EA380767B0D0B6EDFC9730E04D1039548A6F83889098522EBAB684DA6FE26A4A6891D86D40FCD9A24F743D74B23B1596810727C81BB3F9F3BADFAE9997949EE0E24987FA182A00D73DCEADF667E90E5AE76A1F83A91FCEA78C96269F0C9501F1D4CE682506A7EA89302A1480E18CDC1F6D57B5312EAF808895B20897E9A782F916CD75B4981DA1381F14EB1EC248B27F0E6966A0CD75414A735928B2120615D88FA57AF5C40E61750F0A0F8E605747E7C32D5A23F14124969C072E949C8475E3108D689D2D20797FE14618811E9A497FD26B9E71355852D4B36340B61695E3745F8D07644AC6E2C18B3FC276D4D19DB69A7CF26086F172E2BCE1618A740A0C739FD504F72C2A72ADB5564BC85DAB4C9CE790D78D14D3BD242DF04106D96CE7C3B392CCED9B99DF359FD51F306CBCBD5B46B8487CD7B7EDD3C5C02965C84630DA1B6B8B317FE55F7C79E05CDAC9E863023DAF470E9C3FB8C01FDF3AEDF2193BFA69A806E2E70151ABCF96D31CF6A317C059CA8C7D456A8E5EBAA6C1283A319F188AAA80D8301E321754E5FB4E0B25594B01BC5F82FF25B064C766424D658459EFD7A20B65DB181811E6D5A4BD153F7066BD7757D2D417D21F83D7C4CB6A0703A42032F0FD198D9D8B0F91B359FBE908432C3286E1EF9D601702157EFBAB68E0E7136BFC90D26BD8A9A7018DE4C4BF05CE465F917D20A4F221A4EE78813A1E8A117C8470929701CCC201A85E7F18B6BC96FE80B1E074661525D3FD0CE2565AB11155DAFE4D3410328D6DBB4DD99A84FE96283D32322522B88B3AA2A11C0324B1D5556EF408D37B0DF802D163FE38D7C38916A26810BD175D22762353C3175DC6040C899E07A339CD4DDBD4D5549E02C0D691263936A9F63111412B60AA9F57486334E40B2BC1B8EAA487A094E45C3F77F72EA741CE225ECBE2B5E4A1FC080070A658FDF9E2B388722855267B30D94B63C3ED35D475B7EB22E3D2462ABA9CF2A86B738EBB270AB29708A2614A557E33A620B507286E5D4CA57E2CEEDB9965FF1C3E1777F980CDFB1445BBE0B6ACBA0216980F962FBFABE265B3ADFE8641088287468827AE601B6A165DEED39C0E8773BF2046BBF63634BDBCAF98358D25FDE475781733DDE8C6D6383D13B6D48FF1B65E2FF13AAA9CCCFC3C626935C5270F9E23A71A87CF2BD793CB175D23EA5FBD82C18A1822428C32DB9E31B94BE3144ABB00F5ACAAA431C17386719C3FF47C38720B1AB01889DAD877BADC9FC716F648FC8B551F""") + ), + new DecapsulateTestCase( + xeh(""" +1E4AC87B1A692A529FDBBAB93374C57D110B10F2B1DDEBAC0D196B7BA631B8E9293028A8F379888C422DC8D32BBF226010C2C1EC73189080456B0564B258B0F23131BC79C8E8C11CEF3938B243C5CE9C0EDD37C8F9D29877DBBB615B9B5AC3C948487E467196A9143EFBC7CEDB64B45D4ACDA2666CBC2804F2C8662E128F6A9969EC15BC0B9351F6F96346AA7ABC743A14FA030E37A2E7597BDDFC5A22F9CEDAF8614832527210B26F024C7F6C0DCF551E97A4858764C321D1834AD51D75BB246D277237B7BD41DC4362D063F4298292272D01011780B79856B296C4E946658B79603197C9B2A99EC66ACB06CE2F69B5A5A61E9BD06AD443CEB0C74ED65345A903B614E81368AAC2B3D2A79CA8CCAA1C3B88FB82A36632860B3F7950833FD0212EC96EDE4AB6F5A0BDA3EC6060A658F9457F6CC87C6B620C1A1451987486E496612A101D0E9C20577C571EDB5282608BF4E1AC926C0DB1C82A504A799D89885CA6252BD5B1C183AF701392A407C05B848C2A3016C40613F02A449B3C7926DA067A533116506840097510460BBFD36073DCB0BFA009B36A9123EAA68F835F74A01B00D2097835964DF521CE9210789C30B7F06E5844B444C53322396E4799BAF6A88AF7315860D0192D48C2C0DA6B5BA64325543ACDF5900E8BC477AB05820072D463AFFED097E062BD78C99D12B385131A241B708865B4190AF69EA0A64DB71448A60829369C7555198E438C9ABC310BC70101913BB12FAA5BEEF975841617C847CD6B336F877987753822020B92C4CC97055C9B1E0B128BF11F505005B6AB0E627795A20609EFA991E598B80F37B1C6A1C3A1E9AEE7028F77570AB2139128A00108C50EB305CDB8F9A603A6B078413F6F9B14C6D82B5199CE59D887902A281A027B717495FE12672A127BBF9B256C43720D7C160B281C12757DA135B1933352BE4AB67E40248AFC318E2370C3B8208E695BDF337459B9ACBFE5B487F76E9B4B4001D6CF90CA8C699A174D42972DC733F33389FDF59A1DABA81D834955027334185AD02C76CF294846CA9294BA0ED66741DDEC791CAB34196AC5657C5A78321B56C33306B5102397A5C09C3508F76B48282459F81D0C72A43F737BC2F12F45422628B67DB51AC1424276A6C08C3F7615665BBB8E928148A270F991BCF365A90F87C30687B68809C91F231813B866BEA82E30374D80AA0C02973437498A53B14BF6B6CA1ED76AB8A20D54A083F4A26B7C038D81967640C20BF4431E71DACCE8577B21240E494C31F2D877DAF4924FD39D82D6167FBCC1F9C5A259F843E30987CCC4BCE7493A2404B5E44387F707425781B743FB555685584E2557CC038B1A9B3F4043121F5472EB2B96E5941FEC011CEEA50791636C6ABC26C1377EE3B5146FC7C85CB335B1E795EEC2033EE44B9AA90685245EF7B4436C000E66BC8BCBF1CDB803AC1421B1FDB266D5291C8310373A8A3CE9562AB197953871AB99F382CC5AA9C0F273D1DCA55D2712853871E1A83CB3B85450F76D3F3C42BAB5505F7212FDB6B8B7F6029972A8F3751E4C94C1108B02D6AC79F8D938F05A1B2C229B14B42B31B01A364017E59578C6B033833774CB9B570F9086B722903B375446B495D8A29BF80751877A80FB724A0210C3E1692F397C2F1DDC2E6BA17AF81B92ACFABEF5F7573CB493D184027B718238C89A3549B8905B28A83362867C082D3019D3CA70700731CEB73E8472C1A3A093361C5FEA6A7D40955D07A41B64E50081A361B604CC518447C8E25765AB7D68B243275207AF8CA6564A4CB1E94199DBA1878C59BEC809AB48B2F211BADC6A1998D9C7227C1303F469D46A9C7E5303F98ABA67569AE8227C16BA1FB3244466A25E7F823671810CC26206FEB29C7E2A1A91959EEB03A98252A4F7412674EB9A4B277E1F2595FCA64033B41B40330812E9735B7C607501CD8183A22AFC3392553744F33C4D202526945C6D78A60E201A16987A6FA59D94464B56506556784824A07058F57320E76C825B9347F2936F4A0E5CDAA18CF8833945AE312A36B5F5A3810AAC82381FDAE4CB9C6831D8EB8ABAB850416443D739086B1C326FC2A3975704E396A59680C3B5F360F5480D2B62169CD94CA71B37BC5878BA2985E068BA050B2CE50726D4B4451B77AAA8676EAE094982210192197B1E92A27F59868B78867887B9A70C32AF84630AA908814379E6519150BA16439B5E2B0603D06AA6674557F5B0983E5CB6A97596069B01BB3128C416680657204FD07640392E16B19F337A99A304844E1AA474E9C799062971F672268960F5A82F950070BBE9C2A71950A3785BDF0B8440255ED63928D257845168B1ECCC4191325AA76645719B28EBD89302DC6723C786DF5217B243099CA78238E57E64692F206B177ABC259660395CD7860FB35A16F6B2FE6548C85AB66330C517FA74CDF3CB49D26B1181901AF775A1E180813B6A24C456829B5C38104ECE43C76A437A6A33B6FC6C5E65C8A89466C1425485B29B9E1854368AFCA353E143D0A90A6C6C9E7FDB62A606856B5614F12B64B796020C3534C3605CFDC73B86714F411850228A28B8F4B49E663416C84F7E381F6AF1071343BF9D39B45439240CC03897295FEA080B14BB2D8119A880E164495C61BEBC7139C11857C85E1750338D6343913706A507C9566464CD2837CF914D1A3C35E89B235C6AB7ED078BED234757C02EF6993D4A273CB8150528DA4D76708177E9425546C83E147039766603B30DA6268F4598A53194240A2832A3D67533B5056F9AAAC61B4B17B9A2693AA0D58891E6CC56CDD772410900C405AF20B903797C64876915C37B8487A1449CE924CD345C29A36E08238F7A157CC7E516AB5BA73C8063F726BB5A0A0319E57127438C7FC601C99CCAAE4C1A83726FDCB5045ED1A82A985EA995396D77272C66CE493289F6110910F37C2741CE47026A6F8261999C6482572B1693912EF12EEBEA7ACF9234FB409F2A6090E6B0BFD895469D0B2A921BB723F87A33EA5465AB90F514B67698C0768B6CA498B022C512FA0875F054AA2265867E31C0E522651E024A07D60DD9F633166921F4126BC2B6AA01CC15A09B85BFF8218C5AAE95BC1FFB26AE5A137670F04910CA9D7241B6660C394C5455917746A26682FB71A432EA9530E839BDEB07433004F45A0DDAA0B24E3A566A540815F281E3FC259AC6CBC0ACB8D62268B603BC676AB415C474BB94873E4487AE31A4E3845C79901550890EE8784EEF904FEE62BA8C5F952C68413052E0A7E3388BB8FF0AD602AE3EA14D9DF6DD5E4CC6A381A41DA5C137ECC49DF587E178EAF47702EC623780691A3233F69F12BD9C9B9637C51378AD71A831055277254CC63C5AD4CB76B4AB82E5FCA135E8D26A6B3A89FA5B6F"""), + xeh(""" +8A4336FDDB3F55D16ADBBE54C6EF0DB27F20679393D86EA4590CB6F5F09BC4EB76181A13C9826FBD2A7174BE8A11F13759EE23DA15337A4C5612480E0A843CC6D04F3A902E144EFDC0AC118BF8553B984E758E6D7ED1373B20A5726271C5F4B542FCCD6379671CE37A5D0128F55539B9A855172CA2DA3BB6823484A87DC2333F56CBADF4A694A5DAE341A0E3FBB3D852929FBAFBF4A5C12CD3494CDF910010A0FAFBC09B375BABFFDEACCD12E6E7BD347CBFBD0C84CDABB5004CA11DDC6D14C1BD700FE3EB2371E3293F7185E2A065532C3B6529E60240E7AB6456139D66745F17B94FDF2C54B13EE4DEBF1B77099718804BAEAAACD2BC60A190487CDC76AF2EEB906E4C9F2664A30FAFB65013B8CA393793B650CAC4A93377A6511D739C2136CEC59E1BD14584989A591E1F3B7F6D7237AEDB556880810FABDB1D7F8250B61A2D16A3337DA65AEA644D7E2226BE5F24CBE01C8A33A4CCA06F6F646A3F5453FE2D9FDEA8D8613F491BCF2AEA950DB1D9B43C7C3F86FA2F4A51CB44EB9761363C38723852925247D92E37FC694D2CB00248023D5448CDE2867125250B17388440C188F7E500CEF7747A101E0BF2521E2C8A2D04F42D834C0274ECBC73E94612CCDB1C4B908BAF63C09C945AD4645912A0666E9844A1614B7F34415C1842F9B1C7DAF7EE4459A8724B7050F6B5833341691019149F351A7F11AE2416DCD5B36F18B1A4B82CC3E924114CFC126CA309E319D497A594B0AB2AFB58C19DEF3BC3AD885B29AEAC81F346A19683B8577F4A1E0F30BDC85A3814CD1196E6B29E55E5C0E4E028872477CB675B2408E136D15E54C85E8A468423CB795D9348BFCC975B4EC20A23991E6E9EF91D676983AC26B66C71548FB46C4BF06E280D7C55E7B8DB90743A8F893F95AEB4DED1DC65C5E0B61FBAD9DA0DDAC274591AA6CF23C79C09414356584F0BE02CE9B500A3EE6BD4FA0119783F50E800ED36D3A4445934DCFD87A31AF3ABC02CAC39C4B28068EECC6D16B6FA187A073BA143209C0F38AFE100BC700D461B1B364ED298AAFDFC716FA6E3870E6258B66645091FCF9413EDF6BC79B75132A46D1DFBBCE3CE9B0558EF003929CC6E3D57BC4FD3092EEAC4ED71B7B7FC70D0E65901DC9196928C5B8CF4A63C62797727C192CF1CE4315120A57D4C8CFD03143AF8754432EEBADCADBCD26C2E3A14BB43A951AFDC19EE67AAEC5DE0722E9D11E3627AD1B624ADF0FB6FD2A6733B2B1B1411DD14EE87AD3BCBBCAD2EB4A38EA00575BFA99332400083FC519C3733F6EDCCAAF71D09A7164E18A9E9587A8D9B9A46563FD3F14BFA2F2B8EBD9FDEAAEF466E591F502151E43A7E1123273E5E0574814B20253A17917D7BDF8370BC50461AC8D86127DC527B8290FE386F1AC1E6E9D7B493BB7FEDEC9E5A82DC1402DEAE71B18AB4B658E43F707259039EB9978D4FB0D62839A0DD8E3A1183CE330D57BC7927F7CCF06BA10A0478B7E2EC818195171AFF75C29B283E759F4D2F5D55F0FFC35E0581D98E582107BF64A6D80603""") + ), + new DecapsulateTestCase( + xeh(""" +1E4AC87B1A692A529FDBBAB93374C57D110B10F2B1DDEBAC0D196B7BA631B8E9293028A8F379888C422DC8D32BBF226010C2C1EC73189080456B0564B258B0F23131BC79C8E8C11CEF3938B243C5CE9C0EDD37C8F9D29877DBBB615B9B5AC3C948487E467196A9143EFBC7CEDB64B45D4ACDA2666CBC2804F2C8662E128F6A9969EC15BC0B9351F6F96346AA7ABC743A14FA030E37A2E7597BDDFC5A22F9CEDAF8614832527210B26F024C7F6C0DCF551E97A4858764C321D1834AD51D75BB246D277237B7BD41DC4362D063F4298292272D01011780B79856B296C4E946658B79603197C9B2A99EC66ACB06CE2F69B5A5A61E9BD06AD443CEB0C74ED65345A903B614E81368AAC2B3D2A79CA8CCAA1C3B88FB82A36632860B3F7950833FD0212EC96EDE4AB6F5A0BDA3EC6060A658F9457F6CC87C6B620C1A1451987486E496612A101D0E9C20577C571EDB5282608BF4E1AC926C0DB1C82A504A799D89885CA6252BD5B1C183AF701392A407C05B848C2A3016C40613F02A449B3C7926DA067A533116506840097510460BBFD36073DCB0BFA009B36A9123EAA68F835F74A01B00D2097835964DF521CE9210789C30B7F06E5844B444C53322396E4799BAF6A88AF7315860D0192D48C2C0DA6B5BA64325543ACDF5900E8BC477AB05820072D463AFFED097E062BD78C99D12B385131A241B708865B4190AF69EA0A64DB71448A60829369C7555198E438C9ABC310BC70101913BB12FAA5BEEF975841617C847CD6B336F877987753822020B92C4CC97055C9B1E0B128BF11F505005B6AB0E627795A20609EFA991E598B80F37B1C6A1C3A1E9AEE7028F77570AB2139128A00108C50EB305CDB8F9A603A6B078413F6F9B14C6D82B5199CE59D887902A281A027B717495FE12672A127BBF9B256C43720D7C160B281C12757DA135B1933352BE4AB67E40248AFC318E2370C3B8208E695BDF337459B9ACBFE5B487F76E9B4B4001D6CF90CA8C699A174D42972DC733F33389FDF59A1DABA81D834955027334185AD02C76CF294846CA9294BA0ED66741DDEC791CAB34196AC5657C5A78321B56C33306B5102397A5C09C3508F76B48282459F81D0C72A43F737BC2F12F45422628B67DB51AC1424276A6C08C3F7615665BBB8E928148A270F991BCF365A90F87C30687B68809C91F231813B866BEA82E30374D80AA0C02973437498A53B14BF6B6CA1ED76AB8A20D54A083F4A26B7C038D81967640C20BF4431E71DACCE8577B21240E494C31F2D877DAF4924FD39D82D6167FBCC1F9C5A259F843E30987CCC4BCE7493A2404B5E44387F707425781B743FB555685584E2557CC038B1A9B3F4043121F5472EB2B96E5941FEC011CEEA50791636C6ABC26C1377EE3B5146FC7C85CB335B1E795EEC2033EE44B9AA90685245EF7B4436C000E66BC8BCBF1CDB803AC1421B1FDB266D5291C8310373A8A3CE9562AB197953871AB99F382CC5AA9C0F273D1DCA55D2712853871E1A83CB3B85450F76D3F3C42BAB5505F7212FDB6B8B7F6029972A8F3751E4C94C1108B02D6AC79F8D938F05A1B2C229B14B42B31B01A364017E59578C6B033833774CB9B570F9086B722903B375446B495D8A29BF80751877A80FB724A0210C3E1692F397C2F1DDC2E6BA17AF81B92ACFABEF5F7573CB493D184027B718238C89A3549B8905B28A83362867C082D3019D3CA70700731CEB73E8472C1A3A093361C5FEA6A7D40955D07A41B64E50081A361B604CC518447C8E25765AB7D68B243275207AF8CA6564A4CB1E94199DBA1878C59BEC809AB48B2F211BADC6A1998D9C7227C1303F469D46A9C7E5303F98ABA67569AE8227C16BA1FB3244466A25E7F823671810CC26206FEB29C7E2A1A91959EEB03A98252A4F7412674EB9A4B277E1F2595FCA64033B41B40330812E9735B7C607501CD8183A22AFC3392553744F33C4D202526945C6D78A60E201A16987A6FA59D94464B56506556784824A07058F57320E76C825B9347F2936F4A0E5CDAA18CF8833945AE312A36B5F5A3810AAC82381FDAE4CB9C6831D8EB8ABAB850416443D739086B1C326FC2A3975704E396A59680C3B5F360F5480D2B62169CD94CA71B37BC5878BA2985E068BA050B2CE50726D4B4451B77AAA8676EAE094982210192197B1E92A27F59868B78867887B9A70C32AF84630AA908814379E6519150BA16439B5E2B0603D06AA6674557F5B0983E5CB6A97596069B01BB3128C416680657204FD07640392E16B19F337A99A304844E1AA474E9C799062971F672268960F5A82F950070BBE9C2A71950A3785BDF0B8440255ED63928D257845168B1ECCC4191325AA76645719B28EBD89302DC6723C786DF5217B243099CA78238E57E64692F206B177ABC259660395CD7860FB35A16F6B2FE6548C85AB66330C517FA74CDF3CB49D26B1181901AF775A1E180813B6A24C456829B5C38104ECE43C76A437A6A33B6FC6C5E65C8A89466C1425485B29B9E1854368AFCA353E143D0A90A6C6C9E7FDB62A606856B5614F12B64B796020C3534C3605CFDC73B86714F411850228A28B8F4B49E663416C84F7E381F6AF1071343BF9D39B45439240CC03897295FEA080B14BB2D8119A880E164495C61BEBC7139C11857C85E1750338D6343913706A507C9566464CD2837CF914D1A3C35E89B235C6AB7ED078BED234757C02EF6993D4A273CB8150528DA4D76708177E9425546C83E147039766603B30DA6268F4598A53194240A2832A3D67533B5056F9AAAC61B4B17B9A2693AA0D58891E6CC56CDD772410900C405AF20B903797C64876915C37B8487A1449CE924CD345C29A36E08238F7A157CC7E516AB5BA73C8063F726BB5A0A0319E57127438C7FC601C99CCAAE4C1A83726FDCB5045ED1A82A985EA995396D77272C66CE493289F6110910F37C2741CE47026A6F8261999C6482572B1693912EF12EEBEA7ACF9234FB409F2A6090E6B0BFD895469D0B2A921BB723F87A33EA5465AB90F514B67698C0768B6CA498B022C512FA0875F054AA2265867E31C0E522651E024A07D60DD9F633166921F4126BC2B6AA01CC15A09B85BFF8218C5AAE95BC1FFB26AE5A137670F04910CA9D7241B6660C394C5455917746A26682FB71A432EA9530E839BDEB07433004F45A0DDAA0B24E3A566A540815F281E3FC259AC6CBC0ACB8D62268B603BC676AB415C474BB94873E4487AE31A4E3845C79901550890EE8784EEF904FEE62BA8C5F952C68413052E0A7E3388BB8FF0AD602AE3EA14D9DF6DD5E4CC6A381A41DA5C137ECC49DF587E178EAF47702EC623780691A3233F69F12BD9C9B9637C51378AD71A831055277254CC63C5AD4CB76B4AB82E5FCA135E8D26A6B3A89FA5B6F"""), + xeh(""" +6095A951753A644DD898D69138B4E521A704DCFAAD44EB53E284F836A469349C5B9279248AFC57AC93FA34A643DE02B724615CF5865927FED60A6B41E4AB15B4DA3599F13D2C1996C6D6989443BE6FB81F5BA03BDD53462BE5812A3E177876A102B0EBDFCB16DE7B29B5123A79DD82E5CD47ABA02759FAF5401E3BF03144A90AE957EC04DB9864ADE1C5A700CEC7872CCB64FF931984DDC3FB8D4971D761E5544130278C75A1B04E641E070A747789A71E09409C155C7D341D5F828A575EE74439155930DF22FD7716185BDF917472432A30A6762C9FE1A254442F755804D295B1698B47A67BBFDE178200F9CC3D4C705F4AC1B00C372D468E16ED3CBAAA862A2574A9574A7280878BB82DA7BD1B2A58943456838F2E6AA9F6EF1827C5B24FA09DE07E9B3153B0F44A4F2AEA7610F9CCA92565740E7295BA3AC5764A20A44D4E1862E55B1DF7913B279F438B3B34E0C22FD90E06497F7DCF8D62352447C2B8C51C214796194CDF66D5001278D0D55F82FA31DAA72BA6CDA34E60D696ED79C7056BFE97265F3D1BC07719B745ADD4A83404D91A184E629FC24AE236CF6AFAE46295D24B431D819E366F51E1BB2B44B1FB7A3060091DEA1D416268CA550EE4E41FCA1F387E941DBE4EBAE222D3CF625632D1A61414038FD437BFA20005EBC404ADCDE2DC10DB741A3B7534C40822520C4703FDFB6B380F7DB72B725B330D0C20DF256BBDDC31E0EA20E636A9FAE310185A5081923BAFE041AC6FCD4E73F5F7237142B74681F637996D28C3FDE6052243269D19316C56993722EADF19A985E579ED559F971E69EB5125937EBC80ECD15A4F80D7067905A4D39C6220EFE43883CF22E9A366F8911E21D0491B8FF61FD07B733E707A08DB400E438DAA00D481C5AC62064CF47AFE3AB08027B3890E8C8835CEAF8128F9D887A6CB7FDE879D9611C01281A0F02DE0E969C9131F8512138036EC1967DCA45AA30BE8C5B1008113E17A91D9F8E9995C07C0B13A45668C96356F09C3E08FE4C7DF5F7230E0C93EEF08E8958B55E213718C516E624B57765257D21696A3458FFBA11DE708C4EE9AF2EDC5F37458DEC8B985076882D3F4DEB00BFD8E7EA4D57BAEAEC6BABC0E28C15419CCD785CF6ACEC96D1111CDD1DA9A151F59A7366B64A53F0497D3B5A8ECB60D7C220E99126CDE82938C7E131BD841300AE461A1817703ED5B0510B47F2C2980F1E11CFBECB524B295C42187F15B0C9F6B0EB1E70B3EC43ED955528B1E42E2BCB31F3A1CFB5E9C807E8D366E9227A87784748B277D6C885B1385C6C691B3DBD7841DD89721B3A8BF96EBA99C53D4BB3B41DB9409B992BCC2D8FC53E70723CA1FDC1341A3E608D7F62F2322C6A9BA1316639690A22AECEE364B4F13949A0310FBA1A0E35DDA5FF840DABAC55041B0931D9EBEC89B78DD930512340B4B5D0877AF546FF0F342FB76B647D604EE2E20207924F39907D6E72DD4A9A1ED0B6D7364CCE69981F56CBDEDD51CBAF6FDDB36E327AD65D4FE283D253E6BF3C7969FFF1F34DCC742""") + ), + new DecapsulateTestCase( + xeh(""" +1E4AC87B1A692A529FDBBAB93374C57D110B10F2B1DDEBAC0D196B7BA631B8E9293028A8F379888C422DC8D32BBF226010C2C1EC73189080456B0564B258B0F23131BC79C8E8C11CEF3938B243C5CE9C0EDD37C8F9D29877DBBB615B9B5AC3C948487E467196A9143EFBC7CEDB64B45D4ACDA2666CBC2804F2C8662E128F6A9969EC15BC0B9351F6F96346AA7ABC743A14FA030E37A2E7597BDDFC5A22F9CEDAF8614832527210B26F024C7F6C0DCF551E97A4858764C321D1834AD51D75BB246D277237B7BD41DC4362D063F4298292272D01011780B79856B296C4E946658B79603197C9B2A99EC66ACB06CE2F69B5A5A61E9BD06AD443CEB0C74ED65345A903B614E81368AAC2B3D2A79CA8CCAA1C3B88FB82A36632860B3F7950833FD0212EC96EDE4AB6F5A0BDA3EC6060A658F9457F6CC87C6B620C1A1451987486E496612A101D0E9C20577C571EDB5282608BF4E1AC926C0DB1C82A504A799D89885CA6252BD5B1C183AF701392A407C05B848C2A3016C40613F02A449B3C7926DA067A533116506840097510460BBFD36073DCB0BFA009B36A9123EAA68F835F74A01B00D2097835964DF521CE9210789C30B7F06E5844B444C53322396E4799BAF6A88AF7315860D0192D48C2C0DA6B5BA64325543ACDF5900E8BC477AB05820072D463AFFED097E062BD78C99D12B385131A241B708865B4190AF69EA0A64DB71448A60829369C7555198E438C9ABC310BC70101913BB12FAA5BEEF975841617C847CD6B336F877987753822020B92C4CC97055C9B1E0B128BF11F505005B6AB0E627795A20609EFA991E598B80F37B1C6A1C3A1E9AEE7028F77570AB2139128A00108C50EB305CDB8F9A603A6B078413F6F9B14C6D82B5199CE59D887902A281A027B717495FE12672A127BBF9B256C43720D7C160B281C12757DA135B1933352BE4AB67E40248AFC318E2370C3B8208E695BDF337459B9ACBFE5B487F76E9B4B4001D6CF90CA8C699A174D42972DC733F33389FDF59A1DABA81D834955027334185AD02C76CF294846CA9294BA0ED66741DDEC791CAB34196AC5657C5A78321B56C33306B5102397A5C09C3508F76B48282459F81D0C72A43F737BC2F12F45422628B67DB51AC1424276A6C08C3F7615665BBB8E928148A270F991BCF365A90F87C30687B68809C91F231813B866BEA82E30374D80AA0C02973437498A53B14BF6B6CA1ED76AB8A20D54A083F4A26B7C038D81967640C20BF4431E71DACCE8577B21240E494C31F2D877DAF4924FD39D82D6167FBCC1F9C5A259F843E30987CCC4BCE7493A2404B5E44387F707425781B743FB555685584E2557CC038B1A9B3F4043121F5472EB2B96E5941FEC011CEEA50791636C6ABC26C1377EE3B5146FC7C85CB335B1E795EEC2033EE44B9AA90685245EF7B4436C000E66BC8BCBF1CDB803AC1421B1FDB266D5291C8310373A8A3CE9562AB197953871AB99F382CC5AA9C0F273D1DCA55D2712853871E1A83CB3B85450F76D3F3C42BAB5505F7212FDB6B8B7F6029972A8F3751E4C94C1108B02D6AC79F8D938F05A1B2C229B14B42B31B01A364017E59578C6B033833774CB9B570F9086B722903B375446B495D8A29BF80751877A80FB724A0210C3E1692F397C2F1DDC2E6BA17AF81B92ACFABEF5F7573CB493D184027B718238C89A3549B8905B28A83362867C082D3019D3CA70700731CEB73E8472C1A3A093361C5FEA6A7D40955D07A41B64E50081A361B604CC518447C8E25765AB7D68B243275207AF8CA6564A4CB1E94199DBA1878C59BEC809AB48B2F211BADC6A1998D9C7227C1303F469D46A9C7E5303F98ABA67569AE8227C16BA1FB3244466A25E7F823671810CC26206FEB29C7E2A1A91959EEB03A98252A4F7412674EB9A4B277E1F2595FCA64033B41B40330812E9735B7C607501CD8183A22AFC3392553744F33C4D202526945C6D78A60E201A16987A6FA59D94464B56506556784824A07058F57320E76C825B9347F2936F4A0E5CDAA18CF8833945AE312A36B5F5A3810AAC82381FDAE4CB9C6831D8EB8ABAB850416443D739086B1C326FC2A3975704E396A59680C3B5F360F5480D2B62169CD94CA71B37BC5878BA2985E068BA050B2CE50726D4B4451B77AAA8676EAE094982210192197B1E92A27F59868B78867887B9A70C32AF84630AA908814379E6519150BA16439B5E2B0603D06AA6674557F5B0983E5CB6A97596069B01BB3128C416680657204FD07640392E16B19F337A99A304844E1AA474E9C799062971F672268960F5A82F950070BBE9C2A71950A3785BDF0B8440255ED63928D257845168B1ECCC4191325AA76645719B28EBD89302DC6723C786DF5217B243099CA78238E57E64692F206B177ABC259660395CD7860FB35A16F6B2FE6548C85AB66330C517FA74CDF3CB49D26B1181901AF775A1E180813B6A24C456829B5C38104ECE43C76A437A6A33B6FC6C5E65C8A89466C1425485B29B9E1854368AFCA353E143D0A90A6C6C9E7FDB62A606856B5614F12B64B796020C3534C3605CFDC73B86714F411850228A28B8F4B49E663416C84F7E381F6AF1071343BF9D39B45439240CC03897295FEA080B14BB2D8119A880E164495C61BEBC7139C11857C85E1750338D6343913706A507C9566464CD2837CF914D1A3C35E89B235C6AB7ED078BED234757C02EF6993D4A273CB8150528DA4D76708177E9425546C83E147039766603B30DA6268F4598A53194240A2832A3D67533B5056F9AAAC61B4B17B9A2693AA0D58891E6CC56CDD772410900C405AF20B903797C64876915C37B8487A1449CE924CD345C29A36E08238F7A157CC7E516AB5BA73C8063F726BB5A0A0319E57127438C7FC601C99CCAAE4C1A83726FDCB5045ED1A82A985EA995396D77272C66CE493289F6110910F37C2741CE47026A6F8261999C6482572B1693912EF12EEBEA7ACF9234FB409F2A6090E6B0BFD895469D0B2A921BB723F87A33EA5465AB90F514B67698C0768B6CA498B022C512FA0875F054AA2265867E31C0E522651E024A07D60DD9F633166921F4126BC2B6AA01CC15A09B85BFF8218C5AAE95BC1FFB26AE5A137670F04910CA9D7241B6660C394C5455917746A26682FB71A432EA9530E839BDEB07433004F45A0DDAA0B24E3A566A540815F281E3FC259AC6CBC0ACB8D62268B603BC676AB415C474BB94873E4487AE31A4E3845C79901550890EE8784EEF904FEE62BA8C5F952C68413052E0A7E3388BB8FF0AD602AE3EA14D9DF6DD5E4CC6A381A41DA5C137ECC49DF587E178EAF47702EC623780691A3233F69F12BD9C9B9637C51378AD71A831055277254CC63C5AD4CB76B4AB82E5FCA135E8D26A6B3A89FA5B6F"""), + xeh(""" +2AACD2E6B884BE6A3DDD80155BDCA80EBAF0E2BF714312BBA30D5B367F2D95AC7BEC3965AB05AFA370A42A512B5EFE4B0DEFF3E163AF186B725BCAFD2AFB2BD2A0DBAB74C2BF9362E27D69B6B4B5AA6500EBC9316EA4112745F1C6E98F2DEF9132C7C0BFFEAAFAF994C89B96D3F436B875178963FBC18D2E06ECAF3871787C1AE93B3210896837EC1DA87F0FD8F14AB7C5CB2531E90F415FEBDA378E5492E1DEC8243FE2E8A7BAA6FB6A034D9C524E99D848A804F150915BFD66067C8603B5DB0FE29E27D3F6CA629E96BF3E9C77A5919701EC19646C69A73DFAAB0ABA28FE3E9EAAEB475A441B9B0D62B259DC6B77DEC964AB57D5D776988D54E6246C526F1E8EFDF454E7F0DDAED5363CE02B279CD3B554C251793C3A616C07A7BABA8062919A2B46C64C152BC887A27E382254EA6D50CCC0702B7BC0994BAC09B7891FA64A773AE0B4FBF8204C13A4950FC2C4DF60CEFED7582FD9FBB8C83442517BA0E3B60D9A04FBB24ABCECB303E3FDD37F1037741FD2489F632192A6B9C122A7344CB781A0F61D5011EB0251A842AD4838F9B8D52E21A783F0D839E8BA221CCDD6B968A2B5FD21B8458BF53C9C8076AC0C52C0F53097ED1C25C9F6F12407772D6743EB8E0CE8B1A926F0FDD0DB00482D9590675E56D4509CB5E5F32FC3B4A2DAB2BA080F9A7CDD0B611742A8F83CEE1B091E629D2A0371FDB5A64412B5FA63716961527640D02885C4A09B04A3A6F5EC01A9E0DBB8FC4DDD9E05BDB240AC4878F0D41461C4661777417D6150422FEAB6A39F156CADB5F5D3BEBE417BABCEFF5AAD1B7A624FC23ABE28B2AB2E8273E8F44636A60CDAD9236DCB02FCF87722C899AA321C564B25BC33B4976BC9603BB8B8AB18B5B04625981FB38B2A42722CE2358FC0BA99EF4B122C7B70BB347D0D482DA30638EF8B9C1D9121D83BCDBBEB2A608617054F4B3FDD33E9A08F8DF999A98E715DBF04F8EFACF123BBEB37B9038E9AD906E3C570BB398C10E6D36647A2B0B2731FD39F726171EFC7321BC67D936F7989EA58336E549A34B73F097E3EA2C25887EC6A2E9FED5D2CFF475E99F392162D959DE1C4A4DAD3C96542756AEC3367F7B2515F2225BF7B704B780A6D0B279B8B4EE4879A9BBB2F3303216CBADEA00D229C03E3E2843892FA8E5B0A600D0E3EBDD14FA229819CE9C10B8D5F393DE0119A5B509B80D56B06783447F931177123824910C9BFDE9A29FBA0252E69A90B3E717832866115C06EA73B033EC3B0D45DFDB69A76B484DB0BE7A81215B3817E1C02F9A5DEE8967B147DF9F63C93A6E396DE4251A5A706DFDE9670B8B2F6C4C3E2509142256FDDA905C125FBBB294EB29A3B4D9BE3B67762AFC049B96B3F41B8C31BC5D7B522DCD1AD12B252370A8A57E42F6A9AC26FF784B374DA4B86FFDB65CC753CD049F1A21CF832447E1DF7BA7D0D11E403FC18BC545501E16568595AEB6BD7811C214CF2FB1CDFB07BB32321F536E3896B6EF4D16130ADD71B271CD1027E35538D9E475A3A53DFEA430C151DF7D516CD0D9B""") + ), + new DecapsulateTestCase( + xeh(""" +1E4AC87B1A692A529FDBBAB93374C57D110B10F2B1DDEBAC0D196B7BA631B8E9293028A8F379888C422DC8D32BBF226010C2C1EC73189080456B0564B258B0F23131BC79C8E8C11CEF3938B243C5CE9C0EDD37C8F9D29877DBBB615B9B5AC3C948487E467196A9143EFBC7CEDB64B45D4ACDA2666CBC2804F2C8662E128F6A9969EC15BC0B9351F6F96346AA7ABC743A14FA030E37A2E7597BDDFC5A22F9CEDAF8614832527210B26F024C7F6C0DCF551E97A4858764C321D1834AD51D75BB246D277237B7BD41DC4362D063F4298292272D01011780B79856B296C4E946658B79603197C9B2A99EC66ACB06CE2F69B5A5A61E9BD06AD443CEB0C74ED65345A903B614E81368AAC2B3D2A79CA8CCAA1C3B88FB82A36632860B3F7950833FD0212EC96EDE4AB6F5A0BDA3EC6060A658F9457F6CC87C6B620C1A1451987486E496612A101D0E9C20577C571EDB5282608BF4E1AC926C0DB1C82A504A799D89885CA6252BD5B1C183AF701392A407C05B848C2A3016C40613F02A449B3C7926DA067A533116506840097510460BBFD36073DCB0BFA009B36A9123EAA68F835F74A01B00D2097835964DF521CE9210789C30B7F06E5844B444C53322396E4799BAF6A88AF7315860D0192D48C2C0DA6B5BA64325543ACDF5900E8BC477AB05820072D463AFFED097E062BD78C99D12B385131A241B708865B4190AF69EA0A64DB71448A60829369C7555198E438C9ABC310BC70101913BB12FAA5BEEF975841617C847CD6B336F877987753822020B92C4CC97055C9B1E0B128BF11F505005B6AB0E627795A20609EFA991E598B80F37B1C6A1C3A1E9AEE7028F77570AB2139128A00108C50EB305CDB8F9A603A6B078413F6F9B14C6D82B5199CE59D887902A281A027B717495FE12672A127BBF9B256C43720D7C160B281C12757DA135B1933352BE4AB67E40248AFC318E2370C3B8208E695BDF337459B9ACBFE5B487F76E9B4B4001D6CF90CA8C699A174D42972DC733F33389FDF59A1DABA81D834955027334185AD02C76CF294846CA9294BA0ED66741DDEC791CAB34196AC5657C5A78321B56C33306B5102397A5C09C3508F76B48282459F81D0C72A43F737BC2F12F45422628B67DB51AC1424276A6C08C3F7615665BBB8E928148A270F991BCF365A90F87C30687B68809C91F231813B866BEA82E30374D80AA0C02973437498A53B14BF6B6CA1ED76AB8A20D54A083F4A26B7C038D81967640C20BF4431E71DACCE8577B21240E494C31F2D877DAF4924FD39D82D6167FBCC1F9C5A259F843E30987CCC4BCE7493A2404B5E44387F707425781B743FB555685584E2557CC038B1A9B3F4043121F5472EB2B96E5941FEC011CEEA50791636C6ABC26C1377EE3B5146FC7C85CB335B1E795EEC2033EE44B9AA90685245EF7B4436C000E66BC8BCBF1CDB803AC1421B1FDB266D5291C8310373A8A3CE9562AB197953871AB99F382CC5AA9C0F273D1DCA55D2712853871E1A83CB3B85450F76D3F3C42BAB5505F7212FDB6B8B7F6029972A8F3751E4C94C1108B02D6AC79F8D938F05A1B2C229B14B42B31B01A364017E59578C6B033833774CB9B570F9086B722903B375446B495D8A29BF80751877A80FB724A0210C3E1692F397C2F1DDC2E6BA17AF81B92ACFABEF5F7573CB493D184027B718238C89A3549B8905B28A83362867C082D3019D3CA70700731CEB73E8472C1A3A093361C5FEA6A7D40955D07A41B64E50081A361B604CC518447C8E25765AB7D68B243275207AF8CA6564A4CB1E94199DBA1878C59BEC809AB48B2F211BADC6A1998D9C7227C1303F469D46A9C7E5303F98ABA67569AE8227C16BA1FB3244466A25E7F823671810CC26206FEB29C7E2A1A91959EEB03A98252A4F7412674EB9A4B277E1F2595FCA64033B41B40330812E9735B7C607501CD8183A22AFC3392553744F33C4D202526945C6D78A60E201A16987A6FA59D94464B56506556784824A07058F57320E76C825B9347F2936F4A0E5CDAA18CF8833945AE312A36B5F5A3810AAC82381FDAE4CB9C6831D8EB8ABAB850416443D739086B1C326FC2A3975704E396A59680C3B5F360F5480D2B62169CD94CA71B37BC5878BA2985E068BA050B2CE50726D4B4451B77AAA8676EAE094982210192197B1E92A27F59868B78867887B9A70C32AF84630AA908814379E6519150BA16439B5E2B0603D06AA6674557F5B0983E5CB6A97596069B01BB3128C416680657204FD07640392E16B19F337A99A304844E1AA474E9C799062971F672268960F5A82F950070BBE9C2A71950A3785BDF0B8440255ED63928D257845168B1ECCC4191325AA76645719B28EBD89302DC6723C786DF5217B243099CA78238E57E64692F206B177ABC259660395CD7860FB35A16F6B2FE6548C85AB66330C517FA74CDF3CB49D26B1181901AF775A1E180813B6A24C456829B5C38104ECE43C76A437A6A33B6FC6C5E65C8A89466C1425485B29B9E1854368AFCA353E143D0A90A6C6C9E7FDB62A606856B5614F12B64B796020C3534C3605CFDC73B86714F411850228A28B8F4B49E663416C84F7E381F6AF1071343BF9D39B45439240CC03897295FEA080B14BB2D8119A880E164495C61BEBC7139C11857C85E1750338D6343913706A507C9566464CD2837CF914D1A3C35E89B235C6AB7ED078BED234757C02EF6993D4A273CB8150528DA4D76708177E9425546C83E147039766603B30DA6268F4598A53194240A2832A3D67533B5056F9AAAC61B4B17B9A2693AA0D58891E6CC56CDD772410900C405AF20B903797C64876915C37B8487A1449CE924CD345C29A36E08238F7A157CC7E516AB5BA73C8063F726BB5A0A0319E57127438C7FC601C99CCAAE4C1A83726FDCB5045ED1A82A985EA995396D77272C66CE493289F6110910F37C2741CE47026A6F8261999C6482572B1693912EF12EEBEA7ACF9234FB409F2A6090E6B0BFD895469D0B2A921BB723F87A33EA5465AB90F514B67698C0768B6CA498B022C512FA0875F054AA2265867E31C0E522651E024A07D60DD9F633166921F4126BC2B6AA01CC15A09B85BFF8218C5AAE95BC1FFB26AE5A137670F04910CA9D7241B6660C394C5455917746A26682FB71A432EA9530E839BDEB07433004F45A0DDAA0B24E3A566A540815F281E3FC259AC6CBC0ACB8D62268B603BC676AB415C474BB94873E4487AE31A4E3845C79901550890EE8784EEF904FEE62BA8C5F952C68413052E0A7E3388BB8FF0AD602AE3EA14D9DF6DD5E4CC6A381A41DA5C137ECC49DF587E178EAF47702EC623780691A3233F69F12BD9C9B9637C51378AD71A831055277254CC63C5AD4CB76B4AB82E5FCA135E8D26A6B3A89FA5B6F"""), + xeh(""" +8FFBC80E4662864D6F373DC8837AA91B3CC26B68124ABD73DAD025A1D1C18829DCF077D303579E5F39F4BE101BB9E355DFB5323882EACB3D184E6812C03A7BEBE25166D55F821A00F80B8D2BAB1A7EEC83D384AFDF30F6BBC9960C4662067EF7E200E37268B9F5348FF484642799258B45E541101A21FDD6FBFAA2374A28FAA97204953B95BBD1BB519785210DA7C8A09D071D8AFC9B29F2C3C2909A4C53671408B8083BCF5AE03D45C0CFBA399F44D24A06321BB74F6863B7D4BF0BFE73C8AF8EE1DDA45212E3F9C853D4D0E16F8EBDB8581C4ADEEE833D81A9E0A9E8587E9C19E689E6DF715564BCE27CFA73BA16226A77CE44DC496992F41AB918643C6D86A8B26ABA6F94F3502D22DD94FE55483F67C635B307745D33F17133293639118E70CE42C6DB7332D4862C73D5B84415454AD51F89B5559B5C85D6B6ED47B6958F21FBC2ADF8C8A9D43FD2E1B0C02418D227B83F85CBC3A81C719E8602781AE71E15E6D714919E52FCCCFD9A68B4751825BFBB53B7940B15B546158DBBC612E602F660B9E0FF439E0156C4C8792346014BA1B4838C7425AB34744DE51D854CBBA58B7E67E014122518036CE1541A1675AFEAE4F29A5318602ABBD0A1540F33176C984E306098DBD08E822ABB55F9FF38D9E31EA4695150F2CB60BC2EB5F4780CBEBB210CF48662C454C7A42360F306FB03617C998AD8A9297D6B71A71285F7AE8DFB336FA922540C92DC71F777D3B4D11D87B8D082FA8A00DF647CF7FEB27403D3CF50D829EEE3575A01E2CCA57849B11B14F001BE180DD5FA13C03B98EDEA6358C5AB30A526027CB45E33E646B37988CC84B979CC5CFC3BFDA05BD2C7B8CB1B11AFEE007E20FCCF8D0F764F4A6D2F6A8B74281800CBDCBBCF0DF1EC9D27E6A94968604D9EFD37928B6856C48F0108155595D03231DFC22DC0C8EE614090F37E0828B48A4DD371C677B5DBA95E417F12C9A396875FB05623F7A544AEAE41A0AA536FB8D767BA2E14752C84E147149F655AE7B903CAA591AE00267ADD3EA816612AB0B9A5FB263C70C4367062F7794274C75AC66F706AE93699859D55B2E4960E9D538F38A2FAEE366B80DC78BB673A9E1B057D711F9DDB3770947E6DD7BCFB425B96670506758AEA39A5ECB33A1B76B822AF903787DA3B61A7B9263C0FAE1B729B1A2E16FEB50C32A8728181D4E8A9F8376C39F6AABC2C022306B05E494CF9B6ADEEEC95887440508981D6A74707FCEFA24B9F0DC3AABC984E9C44174E6DFB51FCF4588C57F9659A8E7A6FAEAFBAE7ABE4600444936B3763463D4AE411DDC1C98585E0DE58867251079BE72075973275141801B98F7B9397C096A56B8CD83CFBD374E182F7DCC9A7C764DBBF4D7576A1CC9239848E7295D29CF034A1A7AE33A386C3DDC24A535168ED23D7ADE9433B50DC5694C969F4C546EF2293CD842F4B62B6B7435F597CF5C1733884E0A6AA47FA31887DEDC6C402D8ED013E49E5CAD7718CCEFEE0E6A041715CC9ADD79965413049ABCE88636AA7543EE2601F162838EF6B""") + ), + new DecapsulateTestCase( + xeh(""" +1E4AC87B1A692A529FDBBAB93374C57D110B10F2B1DDEBAC0D196B7BA631B8E9293028A8F379888C422DC8D32BBF226010C2C1EC73189080456B0564B258B0F23131BC79C8E8C11CEF3938B243C5CE9C0EDD37C8F9D29877DBBB615B9B5AC3C948487E467196A9143EFBC7CEDB64B45D4ACDA2666CBC2804F2C8662E128F6A9969EC15BC0B9351F6F96346AA7ABC743A14FA030E37A2E7597BDDFC5A22F9CEDAF8614832527210B26F024C7F6C0DCF551E97A4858764C321D1834AD51D75BB246D277237B7BD41DC4362D063F4298292272D01011780B79856B296C4E946658B79603197C9B2A99EC66ACB06CE2F69B5A5A61E9BD06AD443CEB0C74ED65345A903B614E81368AAC2B3D2A79CA8CCAA1C3B88FB82A36632860B3F7950833FD0212EC96EDE4AB6F5A0BDA3EC6060A658F9457F6CC87C6B620C1A1451987486E496612A101D0E9C20577C571EDB5282608BF4E1AC926C0DB1C82A504A799D89885CA6252BD5B1C183AF701392A407C05B848C2A3016C40613F02A449B3C7926DA067A533116506840097510460BBFD36073DCB0BFA009B36A9123EAA68F835F74A01B00D2097835964DF521CE9210789C30B7F06E5844B444C53322396E4799BAF6A88AF7315860D0192D48C2C0DA6B5BA64325543ACDF5900E8BC477AB05820072D463AFFED097E062BD78C99D12B385131A241B708865B4190AF69EA0A64DB71448A60829369C7555198E438C9ABC310BC70101913BB12FAA5BEEF975841617C847CD6B336F877987753822020B92C4CC97055C9B1E0B128BF11F505005B6AB0E627795A20609EFA991E598B80F37B1C6A1C3A1E9AEE7028F77570AB2139128A00108C50EB305CDB8F9A603A6B078413F6F9B14C6D82B5199CE59D887902A281A027B717495FE12672A127BBF9B256C43720D7C160B281C12757DA135B1933352BE4AB67E40248AFC318E2370C3B8208E695BDF337459B9ACBFE5B487F76E9B4B4001D6CF90CA8C699A174D42972DC733F33389FDF59A1DABA81D834955027334185AD02C76CF294846CA9294BA0ED66741DDEC791CAB34196AC5657C5A78321B56C33306B5102397A5C09C3508F76B48282459F81D0C72A43F737BC2F12F45422628B67DB51AC1424276A6C08C3F7615665BBB8E928148A270F991BCF365A90F87C30687B68809C91F231813B866BEA82E30374D80AA0C02973437498A53B14BF6B6CA1ED76AB8A20D54A083F4A26B7C038D81967640C20BF4431E71DACCE8577B21240E494C31F2D877DAF4924FD39D82D6167FBCC1F9C5A259F843E30987CCC4BCE7493A2404B5E44387F707425781B743FB555685584E2557CC038B1A9B3F4043121F5472EB2B96E5941FEC011CEEA50791636C6ABC26C1377EE3B5146FC7C85CB335B1E795EEC2033EE44B9AA90685245EF7B4436C000E66BC8BCBF1CDB803AC1421B1FDB266D5291C8310373A8A3CE9562AB197953871AB99F382CC5AA9C0F273D1DCA55D2712853871E1A83CB3B85450F76D3F3C42BAB5505F7212FDB6B8B7F6029972A8F3751E4C94C1108B02D6AC79F8D938F05A1B2C229B14B42B31B01A364017E59578C6B033833774CB9B570F9086B722903B375446B495D8A29BF80751877A80FB724A0210C3E1692F397C2F1DDC2E6BA17AF81B92ACFABEF5F7573CB493D184027B718238C89A3549B8905B28A83362867C082D3019D3CA70700731CEB73E8472C1A3A093361C5FEA6A7D40955D07A41B64E50081A361B604CC518447C8E25765AB7D68B243275207AF8CA6564A4CB1E94199DBA1878C59BEC809AB48B2F211BADC6A1998D9C7227C1303F469D46A9C7E5303F98ABA67569AE8227C16BA1FB3244466A25E7F823671810CC26206FEB29C7E2A1A91959EEB03A98252A4F7412674EB9A4B277E1F2595FCA64033B41B40330812E9735B7C607501CD8183A22AFC3392553744F33C4D202526945C6D78A60E201A16987A6FA59D94464B56506556784824A07058F57320E76C825B9347F2936F4A0E5CDAA18CF8833945AE312A36B5F5A3810AAC82381FDAE4CB9C6831D8EB8ABAB850416443D739086B1C326FC2A3975704E396A59680C3B5F360F5480D2B62169CD94CA71B37BC5878BA2985E068BA050B2CE50726D4B4451B77AAA8676EAE094982210192197B1E92A27F59868B78867887B9A70C32AF84630AA908814379E6519150BA16439B5E2B0603D06AA6674557F5B0983E5CB6A97596069B01BB3128C416680657204FD07640392E16B19F337A99A304844E1AA474E9C799062971F672268960F5A82F950070BBE9C2A71950A3785BDF0B8440255ED63928D257845168B1ECCC4191325AA76645719B28EBD89302DC6723C786DF5217B243099CA78238E57E64692F206B177ABC259660395CD7860FB35A16F6B2FE6548C85AB66330C517FA74CDF3CB49D26B1181901AF775A1E180813B6A24C456829B5C38104ECE43C76A437A6A33B6FC6C5E65C8A89466C1425485B29B9E1854368AFCA353E143D0A90A6C6C9E7FDB62A606856B5614F12B64B796020C3534C3605CFDC73B86714F411850228A28B8F4B49E663416C84F7E381F6AF1071343BF9D39B45439240CC03897295FEA080B14BB2D8119A880E164495C61BEBC7139C11857C85E1750338D6343913706A507C9566464CD2837CF914D1A3C35E89B235C6AB7ED078BED234757C02EF6993D4A273CB8150528DA4D76708177E9425546C83E147039766603B30DA6268F4598A53194240A2832A3D67533B5056F9AAAC61B4B17B9A2693AA0D58891E6CC56CDD772410900C405AF20B903797C64876915C37B8487A1449CE924CD345C29A36E08238F7A157CC7E516AB5BA73C8063F726BB5A0A0319E57127438C7FC601C99CCAAE4C1A83726FDCB5045ED1A82A985EA995396D77272C66CE493289F6110910F37C2741CE47026A6F8261999C6482572B1693912EF12EEBEA7ACF9234FB409F2A6090E6B0BFD895469D0B2A921BB723F87A33EA5465AB90F514B67698C0768B6CA498B022C512FA0875F054AA2265867E31C0E522651E024A07D60DD9F633166921F4126BC2B6AA01CC15A09B85BFF8218C5AAE95BC1FFB26AE5A137670F04910CA9D7241B6660C394C5455917746A26682FB71A432EA9530E839BDEB07433004F45A0DDAA0B24E3A566A540815F281E3FC259AC6CBC0ACB8D62268B603BC676AB415C474BB94873E4487AE31A4E3845C79901550890EE8784EEF904FEE62BA8C5F952C68413052E0A7E3388BB8FF0AD602AE3EA14D9DF6DD5E4CC6A381A41DA5C137ECC49DF587E178EAF47702EC623780691A3233F69F12BD9C9B9637C51378AD71A831055277254CC63C5AD4CB76B4AB82E5FCA135E8D26A6B3A89FA5B6F"""), + xeh(""" +17976BAC62F66CEF2B6F947C121079B6F2E9350C137E738BFD884FF2BA6E211640A30FBF2695EDF7046E1F5234AB1C8A9B0E8A3FF88EF18C1E5512D5F69E4A36CC9362F00920481E5460B1FB0C2B9FF0CD0D95718966AF7EC1F76B8DA93F6AB179A5DE70DEE34C579E284AE8504ED96E1A85898076F69AAFEC1357533EBB636FBA2372204DAB87C47AF27D4D9EB1B4FF4286D6A9FA7FD506C9FEBA596D2047DB765C1EBF1F7921867D394487F6BE926E6B0323058CB591195436ECC805C8B88615C7A03833AABF490337063DFEED698F7DA8DD589A794C956C2BF8D8CA4AE18B0A7767693802BD6DD53F543E105EC526C1D1D00AC9C0B606BD9B3A1D52CB8C56F8535ECADD8239308F2FE7E1D7BFAC5848B547B4579AFC13A0B2BEDEFA46322F92E2B73980695369C5F48D37F9345F20C7820DB6DE09D5E8313B73ED705B33646FB14CC4D40D65290A4C27360FBBD080E61A16BB15E9560A097E4AEC16F8B8030FAE1D47E024F10C33E6A1C56AEB8EC2F6AD6EF4B8FF04C67307B23E470FB3E5BCB6F533F955C36FDB46516A07DFF2956130AD0924158CC2A083378FB9AE32DE89CF774D82C2FC70DA48536372299C61927A5AE67E55E792B64FE61F06EFFC1F216CC9D739ADBF3B2190E1D080E00F169F145FE32AF7EC7CBA1D76FA6839D5FD2068E1DFFF557755FF2F4271204A5468C79C7BB8D00FAD63938F12D53B243B3FF866556913EB57AD2AE034F8B62B1A1B9DA2B1D45800B4CEF1E1943A0C92F0EF2EE924F80CF67EBD3D0199D45ED4DCC00140829A0992DB43616CC468508B852EB822066A05CC91D6BC2B47E5622B774F8128ECBBB94CADD15588B36A71E9FD97B05D69E8BAF00D30A3D3C00E663E00AFC9F5E1BAC8534ED5F6E5AB47D7EFDF6537753408299A9E8D5F5AE0FE36A9EC41C6DC9F78A891BFA9C8E90AA1A457A0C01AF70CBC9E55B68A5D8CC5CD3BD6886AE11FF510C6ED0EB2F5C081B25989518BA217BC1C153864E5BB312EF0D43D6DA4A0FDE44F1157CD238E8D70BEB420BD310F8E5DB9D74EF4EC9980CBA74358FC77C5D4FAE3036E176647D78C73900C79BFBF0BC545ABF7CBB4DC7F6041D4FA3B66E4D4655E24B11DC30B0061C452A605CE73362F2A3F052370D873FC68DFFCD3999FDEDB45DD9F2A02B4699BCF1FC5F888B019B5028465F30AEFAD946D481285D1122EA78F3BD8B1982558C38FA3DF0F058B12EEBB11F4C7809F6334EA1D7FE0B529C0BC9C67044648178D2AE9232E4E88DD6D0016D8A590B7703F1A017A4A2671BBB24FA97ADE1B61C489AFE9B3E63CF4CCC42168C98880921C2C0EA7D24DB6DD676B77F7B6C0525C8D0578C7F5A20DBF2F82873904D7CF2522CE6360397B254B18C3059A4BEA169A44D9BA17CFDA1827EABECD269FD391CBC0D49D71FA81AC16F9A0DED9E72A58D1BC2262979D8D7E531D1C46A8F107BDA18A1D2CCD17334183DD3E79D905ACA7DAD348BC6D5CE124A1397EB3B89BE7580720B5DD00BD3A63DAD813E0E967EFEDF17F3D960E70A4F83F""") + ) + }; + + static DecapsulateTestCase[] decap1024TestCases = new DecapsulateTestCase[] { + new DecapsulateTestCase( + xeh(""" +8445C336F3518B298163DCBB6357597983CA2E873DCB49610CF52F14DBCB947C1F3EE9266967276B0C576CF7C30EE6B93DEA5118676CBEE1B1D4794206FB369ABA41167B4393855C84EBA8F32373C05BAE7631C802744AADB6C2DE41250C494315230B52826C34587CB21B183B49B2A5AC04921AC6BFAC1B24A4B37A93A4B168CCE7591BE6111F476260F2762959F5C1640118C2423772E2AD03DC7168A38C6DD39F5F7254264280C8BC10B914168070472FA880ACB8601A8A0837F25FE194687CD68B7DE2340F036DAD891D38D1B0CE9C2633355CF57B50B896036FCA260D2669F85BAC79714FDAFB41EF80B8C30264C31386AE60B05FAA542A26B41EB85F67068F088034FF67AA2E815AAB8BCA6BF71F70ECC3CBCBC45EF701FCD542BD21C7B09568F369C669F396473844FBA14957F51974D852B978014603A210C019036287008994F21255B25099AD82AA132438963B2C0A47CDF5F32BA46B76C7A6559F18BFD555B762E487B6AC992FE20E283CA0B3F6164496955995C3B28A57BBC29826F06FB38B253470AF631BC46C3A8F9CE824321985DD01C05F69B824F916633B40654C75AAEB9385576FFDE2990A6B0A3BE829D6D84E34F1780589C79204C63C798F55D23187E461D48C21E5C047E535B19F458BBA1345B9E41E0CB4A9C2D8C40B490A3BABC553B3026B1672D28CBC8B498A3A99579A832FEAE74610F0B6250CC333E9493EB1621ED34AA4AB175F2CA231152509ACB6AC86B20F6B39108439E5EC12D465A0FEF35003E14277A21812146B2544716D6AB82D1B0726C27A98D589EBDACC4C54BA77B2498F217E14E34E66025A2A143A992520A61C0672CC9CCED7C9450C683E90A3E4651DB623A6DB39AC26125B7FC1986D7B0493B8B72DE7707DC20BBDD43713156AF7D9430EF45399663C2202739168692DD657545B056D9C92385A7F414B34B90C7960D57B35BA7DDE7B81FCA0119D741B12780926018FE4C8030BF038E18B4FA33743D0D3C846417E9D5915C246315938B1E233614501D026959551258B233230D428B181B132F1D0B026067BA816999BC0CD6B547E548B63C9EAA091BAC493DC598DBC2B0E146A2591C2A8C009DD5170AAE027C541A1B5E66E45C65612984C46770493EC896EF25AA9305E9F06692CD0B2F06962E205BEBE113A34EBB1A4830A9B3749641BB935007B23B24BFE576956254D7A35AA496AC446C67A7FEC85A60057E8580617BCB3FAD15C76440FED54CC789394FEA24452CC6B0585B7EB0A88BBA9500D9800E6241AFEB523B55A96A535151D1049573206E59C7FEB070966823634F77D5F1291755A243119621AF8084AB7AC1E22A0568C6201417CBE3655D8A08DD5B513884C98D5A493FD49382EA41860F133CCD601E885966426A2B1F23D42D82E24582D99725192C21777467B1457B1DD429A0C41A5C3D704CEA06278C59941B438C62727097809B4530DBE837EA396B6D31077FAD3733053989A8442AAC4255CB163B8CA2F27501EA967305695ABD659AA02C83EE60BB574203E9937AE1C621C8ECB5CC1D21D556960B5B9161EA96FFFEBAC72E1B8A6154FC4D88B56C04741F090CBB156A737C9E6A22BA8AC704BC304F8E17E5EA845FDE59FBF788CCE0B97C8761F89A242F3052583C6844A632031C964A6C4A85A128A28619BA1BB3D1BEA4B49841FC847614A066841F52ED0EB8AE0B8B096E92B8195405815B231266F36B18C1A53333DAB95D2A9A374B5478A4A41FB8759957C9AB22CAE545AB544BA8DD05B83F3A613A2437ADB073A9635CB4BBC965FB454CF27B298A40CD0DA3B8F9CA99D8CB4286C5EB476416796070BA535AAA58CDB451CD6DB5CBB0CA20F0C71DE97C30DA97EC7906D06B4B939396028C46BA0E7A865BC8308A3810F1212006339F7BC169B1666FDF475911BBC8AAAB41755C9A8AABFA23C0E37F84FE46999E030494B9298EF9934E8A649C0A5CCE2B22F31809AFED23955D87881D99FC1D352896CAC9055BEA0D016CCBA7805A3A50E221630379BD01135221CAD5D9517C8CC42637B9FC0718E9A9BB4945C72D8D11D3D659D83A3C419509AF5B470DD89B7F3ACCF5F35CFC322115FD66A5CD2875651326F9B3168913BE5B9C87AE0B025EC7A2F4A072750946AC61170A7826D9704C5A23A1C0A2325146C3BC1858826C6B39279C2DA7438A370ED8A0AA5169E3BEC29ED88478732758D454143E227F8595883297842E6AF133B17E4811B0F5713AC73B7E347423EB92822D2306FA14500A7207A0672672046544ACC4EA9C16ED7421A069E0D737A98628519C6A29A424A868B46D9A0CC7C6C9DDD8B8BCBF422C8F48A73143D5ABB66BC55499418430802BAC544463CC7319D17998F29411365766D04C847F3129D9077B7D8339BFB96A6739C3F6B74A8F05F9138AB2FE37ACB57634D1820B50176F5A0B6BC2940F1D5938F1936B5F95828B92EB72973C1590AEB7A552CECA10B00C303B7C75D402071A79E2C810AF7C745E3336712492A42043F2903A37C6434CEE20B1D159B057699FF9C1D3BD68029839A08F43E6C1C819913532F911DD370C7021488E11CB504CB9C70570FFF35B4B4601191DC1AD9E6ADC5FA9618798D7CC860C87A939E4CCF8533632268CF1A51AFF0CB811C5545CB1656E65269477430699CCDEA3800630B78CD5810334CCF02E013F3B80244E70ACDB060BBE7A553B063456B2EA807473413165CE57DD563473CFBC90618ADE1F0B888AA48E722BB2751858FE19687442A48E7CA0D2A29CD51BFD8F78C17B9660BFB54A470B2AE9A955C6AB8D6E5CC92AC8ED3C185DAA8BC29F0578EBB812B97C9E5A848A6384DE4E75A31470B53066A8D027BA44B21749C0492465F9072B28376C4E290B30C1863F9E5B79996083422BD8C272C10ECC6EB9A0A8225B31AA0A66E35B9C0B9A79582BA20A3C04CD29914F083A0158288BA4D6EB62D87264B912BCA39732FBDE536A377AD02B8C835D4A2F4E7B1CE115D0C860BEAA7955A49AD689586A89A2B9F9B10D1595D2FC065AD018A7D56C614471F8E946FE8AB49E8226591119FCADB4F9A861631378736B6688B782D58E97E4572753A9664B6B8536812B25911AA76A242375433192738EEE762F6B84315BB3436231E0A9B277ED28AE0050728346457E13405062DB2804B8DA60BB5C793D4CC0E101CBA2D9182FD7124FF52BF4CA28292AC26D678088953971DBA0B6FEC2C9659353291C70C5B9245A0CA253304AFD3C95102BEA66875C6201680B4BDA38687B648C28EB37478E3BC00CA8A3CC27204642B42B68FCBE7B21A366D0668A5029A7DEEF94CDD6A95D7EA8931673BF7112D4042107B1B8B9700C974F9C4E83A8FACD89BFE0CA3CC4C2FCE80A03D3576C222A792B72B1F070AB7F6B6F2B5CA2AF5054AFA70A896990159B45D1003E2A05648675E596016F1B71DD0F7BDA7E2097FC73B3A143D12C726020AC34958AD7062B92B9ABF3CA6BE5AE29F57135E625A367971837E6363D1532094E022A23467CF932E1F89B5B0803C1EC99B585A78B5865096746F32258214ECB38065C97F455E155ACC2DD005A9C76BED59CDA73837D303504E6C976A606A2BE7BBEC5948B91A349E8936688CC0279754B743ABC58666B19B6C3260051F19206BB962BB6633EB0048E32BAACC5B020D02C86CA9770AD469DB54A106AC73A35B8057422B3DB202C5A5B4E3D535F0FC99326C4B8B7B16F1CB5AF96803FA8C195FC0BCEDDAAF012A51728B76489082373C91E92C87ACCA795160782E3B0DD643544BB96ABC2708D49B759CF057AA223BAFD96A330BAF39810FE8671B4343C297DA1E1969C996216AB5106DA668941B160D4477017136CBCA5B5A8D44C4A8B1CF3EF79785E5AA25C3A1AD6C24FD140F79207DE5A499F8A1534FFA804AA7B3889CBE25C0414704AA57897F17862364ECA56258007248813912B836497F0359C2F7238A05D305A0EA152E72B44417A868134E91B3CA7931232FD4C25F8C2A492A339CDC0A138967211451F2562678FA14080A34436C42B07865AC036A81E97A7787A938025CAF813450368BED0C94B1857604526405D27A1C1ABC81B5B6EC13C71930A97D9232CF7021EF87A4D155328E62B583A83B4AF21F9F5750F8575150424F63B899D71CAD267C09E4467146E16E9B6C653F008C311375E2E006D4076A546B82F5314222F7C654317E79EC6035B73FAF491757E61C828326D53044541C4D4537ABD3EA1E67998C3382974CA78AE1B1960E4A9226B0219AB070F0D7AA66D76F9316ADB80C54D6499771B471E8168D47BCAA08324AB6BA92C3A70275F24FA4DC10E251633FB98D162BB5537202C6A553CE7841C4D40B873B85CA03A0A1E1CFADE6BA5180AB1323CCBA9A3E9C53D37575AB1FD9E7316C6FEECB0A14DF6F2DA56C2F56F55A89635CFCFDA47927AF1F0A47B2D4E4E61634B1B51D37A3A307A972420DE1B7A481B83E583B6AF16F63CB00C6"""), + xeh(""" +0C681B4AA81F26ADFB645EC24B3752F6B32C68645AA5E7A999B62036A53DC5CB060A473C08E5DA5C0F5AF0E5170C6597E50EC08060F99B0C00EE9BDDAD7E7D25A22B226F90149B4CE887C72FB60AFF2144EA2A72383B3118F922D032A16F554289902A14CF7755512BB1186BAFAFFE794D2B6CDE90109E6582D39CE0C96197484B3FA07FC91D394FC8D88E7FC4BE002E2DB56F0C4D9D3FBDA274536A0B86ABC6E39BDA52931AEBB8F1084C5C1F7CB3177788B7F331B7074361163491D428E78BCBB57B630841AA987333377CF09569CFD14CC2A11C501BDF82C93DE05BEA20060DE89C686B824571CEF94AB3FDAFA8512619813669D4F53637FEFA4D028CB233E56930E2235F7E6034CA94B143B77AD4A68756E8A9184DBA61A89F91EDFB51A39211402473A5F89145736B2BF8569C705B0CDB8980A447E4E1EAAD3E7E0578F5F86B8D03C9DAFE875E339B4423845616799EDCE05F31B92664C5A59253A60E9D89548A300C1ADB6D190A775C5EE6E8A89B6E779B034C3400A625F4BBEDBF919C45B2BCD14C669248FC43C3EF47E100758942E75E8ED6075A96D70D4EBD2B61358224DDA1EC4C19C2A92898176FEB3C02EDCB9908BAE49BD94AF028EDF8CFC2E5F2E0BD375006986AD49E717548E746FEF49C868BCEA2790AA97E04061B75605CB39EFD463D7B3D68BA574434FF7BE8E2B84BFC47E67E9CD15F3ED450C61AFBA79A20B0B6F287777C72F4AD248174F1959477AA7A7C97F122C50447C7484F382BC47D81FCC9C7E892C8839D37B35394B53E6B2B1895ABB0DE8C98F2633DC4413A8D5735DFC9A64026B6F34779D6AC8AD99CC31AA898C2E7057F3DB8A1A8A98527A79E43552F28D1023E1F6A6B84855CF5E6DF889BA269F048946E84021C65C5A93B007B07741C1EE176C73949110F548EF4332DCDD491D2CEFD0248883F5E9525BC91F30AF17CF5A98DD44EF9A71F99BB732985BA10A723EF476FCF966DA9456B24978E33050D0EC90D3CE46378851C9ECFCFD36C895D44E9E506993082523D26185766B23568CB95E64108F89D1014747C67B6F3C8767BE5FC341227DE9488861C5FE811409F80957D07522A72CF6AB0378D0F2F28AF548185C3936777994466A019D33B18A54F380A33892AB4D4BD507B5A61D0D358341AC92F07B43B8F6AFC6991BB6A1EAC23CA6F73E91F2464BD119098D7E768E77ECE53FB899BEB42265ECF7B271F66546282D472C36239006BB0ABABCCA24550BAA0A601348C810FF5F9EE504BF7155DEE4141A11605A4F3509AC9CAEF6624D21DE332D5D50828B52E92885D3B90553B14463AFB1EDCCD3B569B5A7F00BB66769DADAC23AD8BB5D73A6F390E6FC2F6F8EE3CF4009A5C3E1EF60E8F040672D262E6490379BBC70495DFF237BECD9952CD7EDEB6D1DFC360B3FC8B0AF480FFE024AEEFCD4E9CE95D9B469C9A70E5110DA0BAC124FC3741DCF49116261796504D5F490B433C33C40EDCE2B75151DA256A868A5E35F86226B8151C91934CCC3DACA391DECCA745375660B6EC41AE5D810838CBEEFFA12557884412357B1008363D32B237AA1DD8E2D9C6367ADA09B2C95060206CEC3EED391FDC5DBEF6F08BDF0408E585AE5EBC8E9745D44FECA975ABBC140BB37B8ADD16FCC2956910DC72BB3F02E9A130C9A84F9CCB74D134CDF40AFCBA2009C8F0040239BC99220EF64C4DCCDE2E2E5C9B68602FBE8EF4C98B3468C79DF4E078511BFB8AA3DA09597A02511E7C21A7CF66A93843A94868F19E8552552E3ACDF6CB810634DB97CBC4BB569709DAD4845645446FA8D289FC59307B801E60CE2A91E06E9C22C16E2E59BDE38A416BB1B4AC5457438FDC5D64450A89ECB832C1BB279DBF59334681776AC00409846D09D6F687772E340850AB8673384215E12C8D0F531C451E58493E0EE415AD594DF38C34408C7ED9F0C392F1534604EAC3D9C15465A9A46632214B536990D78078E5BD7EAE2013FFF8FDD8B275C89D97C9353DF3C42A28E814D8468E2B48DB0976D88F5EECEFEAFB8F7F4AF291A728F6249ECF5622339269AA945329E919F8B441C83D5507F30DF0FD2B13FF806F522DAA11AF676A513C149C70F0D6E99A880450A54E0417FE3C1E513E9D920E30A8B42891267A2DC50AD81F98044920C099DF22C73998A25C581A5178C72B17AC875BC68548A0FB0CBEE38F05017B12433343A658F1980C8124EA6DD81F""") + ), + new DecapsulateTestCase( + xeh(""" +8445C336F3518B298163DCBB6357597983CA2E873DCB49610CF52F14DBCB947C1F3EE9266967276B0C576CF7C30EE6B93DEA5118676CBEE1B1D4794206FB369ABA41167B4393855C84EBA8F32373C05BAE7631C802744AADB6C2DE41250C494315230B52826C34587CB21B183B49B2A5AC04921AC6BFAC1B24A4B37A93A4B168CCE7591BE6111F476260F2762959F5C1640118C2423772E2AD03DC7168A38C6DD39F5F7254264280C8BC10B914168070472FA880ACB8601A8A0837F25FE194687CD68B7DE2340F036DAD891D38D1B0CE9C2633355CF57B50B896036FCA260D2669F85BAC79714FDAFB41EF80B8C30264C31386AE60B05FAA542A26B41EB85F67068F088034FF67AA2E815AAB8BCA6BF71F70ECC3CBCBC45EF701FCD542BD21C7B09568F369C669F396473844FBA14957F51974D852B978014603A210C019036287008994F21255B25099AD82AA132438963B2C0A47CDF5F32BA46B76C7A6559F18BFD555B762E487B6AC992FE20E283CA0B3F6164496955995C3B28A57BBC29826F06FB38B253470AF631BC46C3A8F9CE824321985DD01C05F69B824F916633B40654C75AAEB9385576FFDE2990A6B0A3BE829D6D84E34F1780589C79204C63C798F55D23187E461D48C21E5C047E535B19F458BBA1345B9E41E0CB4A9C2D8C40B490A3BABC553B3026B1672D28CBC8B498A3A99579A832FEAE74610F0B6250CC333E9493EB1621ED34AA4AB175F2CA231152509ACB6AC86B20F6B39108439E5EC12D465A0FEF35003E14277A21812146B2544716D6AB82D1B0726C27A98D589EBDACC4C54BA77B2498F217E14E34E66025A2A143A992520A61C0672CC9CCED7C9450C683E90A3E4651DB623A6DB39AC26125B7FC1986D7B0493B8B72DE7707DC20BBDD43713156AF7D9430EF45399663C2202739168692DD657545B056D9C92385A7F414B34B90C7960D57B35BA7DDE7B81FCA0119D741B12780926018FE4C8030BF038E18B4FA33743D0D3C846417E9D5915C246315938B1E233614501D026959551258B233230D428B181B132F1D0B026067BA816999BC0CD6B547E548B63C9EAA091BAC493DC598DBC2B0E146A2591C2A8C009DD5170AAE027C541A1B5E66E45C65612984C46770493EC896EF25AA9305E9F06692CD0B2F06962E205BEBE113A34EBB1A4830A9B3749641BB935007B23B24BFE576956254D7A35AA496AC446C67A7FEC85A60057E8580617BCB3FAD15C76440FED54CC789394FEA24452CC6B0585B7EB0A88BBA9500D9800E6241AFEB523B55A96A535151D1049573206E59C7FEB070966823634F77D5F1291755A243119621AF8084AB7AC1E22A0568C6201417CBE3655D8A08DD5B513884C98D5A493FD49382EA41860F133CCD601E885966426A2B1F23D42D82E24582D99725192C21777467B1457B1DD429A0C41A5C3D704CEA06278C59941B438C62727097809B4530DBE837EA396B6D31077FAD3733053989A8442AAC4255CB163B8CA2F27501EA967305695ABD659AA02C83EE60BB574203E9937AE1C621C8ECB5CC1D21D556960B5B9161EA96FFFEBAC72E1B8A6154FC4D88B56C04741F090CBB156A737C9E6A22BA8AC704BC304F8E17E5EA845FDE59FBF788CCE0B97C8761F89A242F3052583C6844A632031C964A6C4A85A128A28619BA1BB3D1BEA4B49841FC847614A066841F52ED0EB8AE0B8B096E92B8195405815B231266F36B18C1A53333DAB95D2A9A374B5478A4A41FB8759957C9AB22CAE545AB544BA8DD05B83F3A613A2437ADB073A9635CB4BBC965FB454CF27B298A40CD0DA3B8F9CA99D8CB4286C5EB476416796070BA535AAA58CDB451CD6DB5CBB0CA20F0C71DE97C30DA97EC7906D06B4B939396028C46BA0E7A865BC8308A3810F1212006339F7BC169B1666FDF475911BBC8AAAB41755C9A8AABFA23C0E37F84FE46999E030494B9298EF9934E8A649C0A5CCE2B22F31809AFED23955D87881D99FC1D352896CAC9055BEA0D016CCBA7805A3A50E221630379BD01135221CAD5D9517C8CC42637B9FC0718E9A9BB4945C72D8D11D3D659D83A3C419509AF5B470DD89B7F3ACCF5F35CFC322115FD66A5CD2875651326F9B3168913BE5B9C87AE0B025EC7A2F4A072750946AC61170A7826D9704C5A23A1C0A2325146C3BC1858826C6B39279C2DA7438A370ED8A0AA5169E3BEC29ED88478732758D454143E227F8595883297842E6AF133B17E4811B0F5713AC73B7E347423EB92822D2306FA14500A7207A0672672046544ACC4EA9C16ED7421A069E0D737A98628519C6A29A424A868B46D9A0CC7C6C9DDD8B8BCBF422C8F48A73143D5ABB66BC55499418430802BAC544463CC7319D17998F29411365766D04C847F3129D9077B7D8339BFB96A6739C3F6B74A8F05F9138AB2FE37ACB57634D1820B50176F5A0B6BC2940F1D5938F1936B5F95828B92EB72973C1590AEB7A552CECA10B00C303B7C75D402071A79E2C810AF7C745E3336712492A42043F2903A37C6434CEE20B1D159B057699FF9C1D3BD68029839A08F43E6C1C819913532F911DD370C7021488E11CB504CB9C70570FFF35B4B4601191DC1AD9E6ADC5FA9618798D7CC860C87A939E4CCF8533632268CF1A51AFF0CB811C5545CB1656E65269477430699CCDEA3800630B78CD5810334CCF02E013F3B80244E70ACDB060BBE7A553B063456B2EA807473413165CE57DD563473CFBC90618ADE1F0B888AA48E722BB2751858FE19687442A48E7CA0D2A29CD51BFD8F78C17B9660BFB54A470B2AE9A955C6AB8D6E5CC92AC8ED3C185DAA8BC29F0578EBB812B97C9E5A848A6384DE4E75A31470B53066A8D027BA44B21749C0492465F9072B28376C4E290B30C1863F9E5B79996083422BD8C272C10ECC6EB9A0A8225B31AA0A66E35B9C0B9A79582BA20A3C04CD29914F083A0158288BA4D6EB62D87264B912BCA39732FBDE536A377AD02B8C835D4A2F4E7B1CE115D0C860BEAA7955A49AD689586A89A2B9F9B10D1595D2FC065AD018A7D56C614471F8E946FE8AB49E8226591119FCADB4F9A861631378736B6688B782D58E97E4572753A9664B6B8536812B25911AA76A242375433192738EEE762F6B84315BB3436231E0A9B277ED28AE0050728346457E13405062DB2804B8DA60BB5C793D4CC0E101CBA2D9182FD7124FF52BF4CA28292AC26D678088953971DBA0B6FEC2C9659353291C70C5B9245A0CA253304AFD3C95102BEA66875C6201680B4BDA38687B648C28EB37478E3BC00CA8A3CC27204642B42B68FCBE7B21A366D0668A5029A7DEEF94CDD6A95D7EA8931673BF7112D4042107B1B8B9700C974F9C4E83A8FACD89BFE0CA3CC4C2FCE80A03D3576C222A792B72B1F070AB7F6B6F2B5CA2AF5054AFA70A896990159B45D1003E2A05648675E596016F1B71DD0F7BDA7E2097FC73B3A143D12C726020AC34958AD7062B92B9ABF3CA6BE5AE29F57135E625A367971837E6363D1532094E022A23467CF932E1F89B5B0803C1EC99B585A78B5865096746F32258214ECB38065C97F455E155ACC2DD005A9C76BED59CDA73837D303504E6C976A606A2BE7BBEC5948B91A349E8936688CC0279754B743ABC58666B19B6C3260051F19206BB962BB6633EB0048E32BAACC5B020D02C86CA9770AD469DB54A106AC73A35B8057422B3DB202C5A5B4E3D535F0FC99326C4B8B7B16F1CB5AF96803FA8C195FC0BCEDDAAF012A51728B76489082373C91E92C87ACCA795160782E3B0DD643544BB96ABC2708D49B759CF057AA223BAFD96A330BAF39810FE8671B4343C297DA1E1969C996216AB5106DA668941B160D4477017136CBCA5B5A8D44C4A8B1CF3EF79785E5AA25C3A1AD6C24FD140F79207DE5A499F8A1534FFA804AA7B3889CBE25C0414704AA57897F17862364ECA56258007248813912B836497F0359C2F7238A05D305A0EA152E72B44417A868134E91B3CA7931232FD4C25F8C2A492A339CDC0A138967211451F2562678FA14080A34436C42B07865AC036A81E97A7787A938025CAF813450368BED0C94B1857604526405D27A1C1ABC81B5B6EC13C71930A97D9232CF7021EF87A4D155328E62B583A83B4AF21F9F5750F8575150424F63B899D71CAD267C09E4467146E16E9B6C653F008C311375E2E006D4076A546B82F5314222F7C654317E79EC6035B73FAF491757E61C828326D53044541C4D4537ABD3EA1E67998C3382974CA78AE1B1960E4A9226B0219AB070F0D7AA66D76F9316ADB80C54D6499771B471E8168D47BCAA08324AB6BA92C3A70275F24FA4DC10E251633FB98D162BB5537202C6A553CE7841C4D40B873B85CA03A0A1E1CFADE6BA5180AB1323CCBA9A3E9C53D37575AB1FD9E7316C6FEECB0A14DF6F2DA56C2F56F55A89635CFCFDA47927AF1F0A47B2D4E4E61634B1B51D37A3A307A972420DE1B7A481B83E583B6AF16F63CB00C6"""), + xeh(""" +4F90106FF7C3DC4E47417F31AB56B1C5E426C1ECD5878AAD2B705E75062DA5FA6F4D18B704C941C6C6D941FD21191A69210BC39E24950D9F851B6DE8CE30023DC7536439104D42245F3E04E6AA6763F8AC97ADBD04CC69547BCE0BF290FFB5D12946301174AF1B0868C14D4293FA9DCC5B23F809B02CC78DEFE7F27935B9B681E531FC21CCB2AF8EF6144D8498E63E0EE48AF8D4CEF7AC1F669AC740B06F79DDB58E794F2FC2CA832E05A0374C18A4F2CC78343EEA064ABC5F468F4DD11E0B6E8FA1D18A221D8241450C05EB9EDF90D9D7F666AC82E7FD44AF9328E0BC6004D5B114E80E9B980D18E081D771DFCB2ACFD40142A2EB33234F75733EAB7D8EE8A5A6F796681A4A8AF85CCE86971B821D4AD8371049E94E280B77B15D111A42AEADFC08D4F804BD78885443E81A393DF7C8754C460915846E09A0596587460038F55D06EC21434A1C2DF44D0C16706E8D2B83F0E7833976EF05BF1D9F0DDC9A37597E401B817C2BEC8E02EB9DF7591E239F25F8648E7F2F4F673093BD9CB703DA32B353F58514C6AB55748B194E52F153D52F5F33FE95C5F9F65EA97BA721E8DDF333B64D233A867A12701E00C5D8A9B5AE344F3D847C27C079DCC9C3B40EC4604A9F041E7987E8B930C658B9A132DE4E422C0E27553A2A0EAB8C859EB0E5677E83272725C5C1652E61B9BBF5C9C59BC2357A4D1DB9C607F34DC1BA074B84DFC69E4097A7AD2BA9A58000027296AD39FC1CE218A5EEC7ADFA8AA3B9100B0B603CFC83C152589E12E6BD9EE10C49131A701D315DFEC38E018328916F9FFAA7305CFB66781707D2D1020EB782F9F003DB4E46B87D693F62E8BDE170141FF71F26DDF5310C00C9163655F5217DD2C8B0466AC89DB55BD7FB3B0964BC9009E9686185117DCB50D6D0297753CF7F1217E819EE60E3F0FAEC4A5AF0C2EA83CCDE15CF045C6961DE8FF6235C9D93BA4C89B7A82A7471FCFB0B8EAD54D56E8A1DE21B3933AC5B4A0689EEF3598926E17BBB16AEC61EC30A2CCC0E0323EC282887C108C3A4E83E3666493D8653D0E92443808C79D770BFF48A49E65AE089FEC790BBA4C66354EF67A334C1EA5C6C5707B6928EBD1BDB6A940FA242C6EBD7F3E71272421C9082841A6CAD2894BB8AC85F105D8BBC9E6F0A3DF0D7C46F6E2F4CAB904ED157AFA85D4A852220A9636E1E8821643A9E4028D87A430432F09354B3973182385CF5ABFC8F84982BEE0BCBF5D18637399163A09EB45711E07C4458498C76979107CF91B3FC590EA4AD715D656D5E56DC32146580101C952E02ED7017960D54CAACCC70607196980ADBDAEA420A52C0559ED23C9514F8CA7AB7F3BAAFD2FAB58960A64128D5A50E9AD8DB7D23A90CE64C1BC349D118D3603358377F84FF5A64457FA1CF41B27094BCA72360BD429415B9EF9ACCB7A5D7B9E5F5FDCA8FCFA4592E91D7E5120DF7E3C6675AF2211BB94D856A5D2285FBBB36984A1345590930B13232565D54812A9345324C232653190323CC67C840E478D09E6DDBCF999F7AA3B556F80332E67ACA41EC0661088D7696BB64E9A98A0749FAA9854D9B48754023BACAF3C8081A46157C6453BDC89341D3092F3B5337874CE5DE559A56A2FFB7F401F6E28EECAF4FDE5B60DEA73D6B2182EF68E07A8297F3C959E17139B5DEDC72C7A0E103AFF866E89D1F62A1F6B97B61BC059BDE5A2A06087EF783A441F23DD191C692D03C097FF9EE831F7715C6E508BF475E79A8353E84B06A9356045C8FD09FBA35879069B9A3F478FBD051143C13D753BC45F3040E85985EFD6B149EFA9455A18E2894E6EA0BE58F451FF1156F93CC7117B5D091E9DD50D41BFCCD44F2C4EB7812AEFD13C8B68D7F0103BB6CA38D233B6AADD01845B7E44D13C1CB1577D6C4354B063991344787F8C0BE667A7440B98917AD64CC2EF2BC82EFC3398B3B1B238540756CE9FC5EDD26CC20E761D592A1A0530AA8BEFCFE8DADBAC99A417CA0827F4983FF5BE656669F2B5F985FF6B16C44BBEA131D1FCC70FC53BF31EF225D1F5D41863B51B57EA65C6164F7531AE492EFA64161B7DABA3EF4586F3459BE8A962367DC276597B98E91FF594EFE8849BAD4CF91B9E5F244CF03CA9615BE128E96958533544A56E735994B92E4EF0D5FAB54B78EC66641C7463F225D261C144F00A0270741D7A511994833635A8A9B670CBFBEF239BF83327E247943B205DA68DB94E3F3""") + ), + new DecapsulateTestCase( + xeh(""" +8445C336F3518B298163DCBB6357597983CA2E873DCB49610CF52F14DBCB947C1F3EE9266967276B0C576CF7C30EE6B93DEA5118676CBEE1B1D4794206FB369ABA41167B4393855C84EBA8F32373C05BAE7631C802744AADB6C2DE41250C494315230B52826C34587CB21B183B49B2A5AC04921AC6BFAC1B24A4B37A93A4B168CCE7591BE6111F476260F2762959F5C1640118C2423772E2AD03DC7168A38C6DD39F5F7254264280C8BC10B914168070472FA880ACB8601A8A0837F25FE194687CD68B7DE2340F036DAD891D38D1B0CE9C2633355CF57B50B896036FCA260D2669F85BAC79714FDAFB41EF80B8C30264C31386AE60B05FAA542A26B41EB85F67068F088034FF67AA2E815AAB8BCA6BF71F70ECC3CBCBC45EF701FCD542BD21C7B09568F369C669F396473844FBA14957F51974D852B978014603A210C019036287008994F21255B25099AD82AA132438963B2C0A47CDF5F32BA46B76C7A6559F18BFD555B762E487B6AC992FE20E283CA0B3F6164496955995C3B28A57BBC29826F06FB38B253470AF631BC46C3A8F9CE824321985DD01C05F69B824F916633B40654C75AAEB9385576FFDE2990A6B0A3BE829D6D84E34F1780589C79204C63C798F55D23187E461D48C21E5C047E535B19F458BBA1345B9E41E0CB4A9C2D8C40B490A3BABC553B3026B1672D28CBC8B498A3A99579A832FEAE74610F0B6250CC333E9493EB1621ED34AA4AB175F2CA231152509ACB6AC86B20F6B39108439E5EC12D465A0FEF35003E14277A21812146B2544716D6AB82D1B0726C27A98D589EBDACC4C54BA77B2498F217E14E34E66025A2A143A992520A61C0672CC9CCED7C9450C683E90A3E4651DB623A6DB39AC26125B7FC1986D7B0493B8B72DE7707DC20BBDD43713156AF7D9430EF45399663C2202739168692DD657545B056D9C92385A7F414B34B90C7960D57B35BA7DDE7B81FCA0119D741B12780926018FE4C8030BF038E18B4FA33743D0D3C846417E9D5915C246315938B1E233614501D026959551258B233230D428B181B132F1D0B026067BA816999BC0CD6B547E548B63C9EAA091BAC493DC598DBC2B0E146A2591C2A8C009DD5170AAE027C541A1B5E66E45C65612984C46770493EC896EF25AA9305E9F06692CD0B2F06962E205BEBE113A34EBB1A4830A9B3749641BB935007B23B24BFE576956254D7A35AA496AC446C67A7FEC85A60057E8580617BCB3FAD15C76440FED54CC789394FEA24452CC6B0585B7EB0A88BBA9500D9800E6241AFEB523B55A96A535151D1049573206E59C7FEB070966823634F77D5F1291755A243119621AF8084AB7AC1E22A0568C6201417CBE3655D8A08DD5B513884C98D5A493FD49382EA41860F133CCD601E885966426A2B1F23D42D82E24582D99725192C21777467B1457B1DD429A0C41A5C3D704CEA06278C59941B438C62727097809B4530DBE837EA396B6D31077FAD3733053989A8442AAC4255CB163B8CA2F27501EA967305695ABD659AA02C83EE60BB574203E9937AE1C621C8ECB5CC1D21D556960B5B9161EA96FFFEBAC72E1B8A6154FC4D88B56C04741F090CBB156A737C9E6A22BA8AC704BC304F8E17E5EA845FDE59FBF788CCE0B97C8761F89A242F3052583C6844A632031C964A6C4A85A128A28619BA1BB3D1BEA4B49841FC847614A066841F52ED0EB8AE0B8B096E92B8195405815B231266F36B18C1A53333DAB95D2A9A374B5478A4A41FB8759957C9AB22CAE545AB544BA8DD05B83F3A613A2437ADB073A9635CB4BBC965FB454CF27B298A40CD0DA3B8F9CA99D8CB4286C5EB476416796070BA535AAA58CDB451CD6DB5CBB0CA20F0C71DE97C30DA97EC7906D06B4B939396028C46BA0E7A865BC8308A3810F1212006339F7BC169B1666FDF475911BBC8AAAB41755C9A8AABFA23C0E37F84FE46999E030494B9298EF9934E8A649C0A5CCE2B22F31809AFED23955D87881D99FC1D352896CAC9055BEA0D016CCBA7805A3A50E221630379BD01135221CAD5D9517C8CC42637B9FC0718E9A9BB4945C72D8D11D3D659D83A3C419509AF5B470DD89B7F3ACCF5F35CFC322115FD66A5CD2875651326F9B3168913BE5B9C87AE0B025EC7A2F4A072750946AC61170A7826D9704C5A23A1C0A2325146C3BC1858826C6B39279C2DA7438A370ED8A0AA5169E3BEC29ED88478732758D454143E227F8595883297842E6AF133B17E4811B0F5713AC73B7E347423EB92822D2306FA14500A7207A0672672046544ACC4EA9C16ED7421A069E0D737A98628519C6A29A424A868B46D9A0CC7C6C9DDD8B8BCBF422C8F48A73143D5ABB66BC55499418430802BAC544463CC7319D17998F29411365766D04C847F3129D9077B7D8339BFB96A6739C3F6B74A8F05F9138AB2FE37ACB57634D1820B50176F5A0B6BC2940F1D5938F1936B5F95828B92EB72973C1590AEB7A552CECA10B00C303B7C75D402071A79E2C810AF7C745E3336712492A42043F2903A37C6434CEE20B1D159B057699FF9C1D3BD68029839A08F43E6C1C819913532F911DD370C7021488E11CB504CB9C70570FFF35B4B4601191DC1AD9E6ADC5FA9618798D7CC860C87A939E4CCF8533632268CF1A51AFF0CB811C5545CB1656E65269477430699CCDEA3800630B78CD5810334CCF02E013F3B80244E70ACDB060BBE7A553B063456B2EA807473413165CE57DD563473CFBC90618ADE1F0B888AA48E722BB2751858FE19687442A48E7CA0D2A29CD51BFD8F78C17B9660BFB54A470B2AE9A955C6AB8D6E5CC92AC8ED3C185DAA8BC29F0578EBB812B97C9E5A848A6384DE4E75A31470B53066A8D027BA44B21749C0492465F9072B28376C4E290B30C1863F9E5B79996083422BD8C272C10ECC6EB9A0A8225B31AA0A66E35B9C0B9A79582BA20A3C04CD29914F083A0158288BA4D6EB62D87264B912BCA39732FBDE536A377AD02B8C835D4A2F4E7B1CE115D0C860BEAA7955A49AD689586A89A2B9F9B10D1595D2FC065AD018A7D56C614471F8E946FE8AB49E8226591119FCADB4F9A861631378736B6688B782D58E97E4572753A9664B6B8536812B25911AA76A242375433192738EEE762F6B84315BB3436231E0A9B277ED28AE0050728346457E13405062DB2804B8DA60BB5C793D4CC0E101CBA2D9182FD7124FF52BF4CA28292AC26D678088953971DBA0B6FEC2C9659353291C70C5B9245A0CA253304AFD3C95102BEA66875C6201680B4BDA38687B648C28EB37478E3BC00CA8A3CC27204642B42B68FCBE7B21A366D0668A5029A7DEEF94CDD6A95D7EA8931673BF7112D4042107B1B8B9700C974F9C4E83A8FACD89BFE0CA3CC4C2FCE80A03D3576C222A792B72B1F070AB7F6B6F2B5CA2AF5054AFA70A896990159B45D1003E2A05648675E596016F1B71DD0F7BDA7E2097FC73B3A143D12C726020AC34958AD7062B92B9ABF3CA6BE5AE29F57135E625A367971837E6363D1532094E022A23467CF932E1F89B5B0803C1EC99B585A78B5865096746F32258214ECB38065C97F455E155ACC2DD005A9C76BED59CDA73837D303504E6C976A606A2BE7BBEC5948B91A349E8936688CC0279754B743ABC58666B19B6C3260051F19206BB962BB6633EB0048E32BAACC5B020D02C86CA9770AD469DB54A106AC73A35B8057422B3DB202C5A5B4E3D535F0FC99326C4B8B7B16F1CB5AF96803FA8C195FC0BCEDDAAF012A51728B76489082373C91E92C87ACCA795160782E3B0DD643544BB96ABC2708D49B759CF057AA223BAFD96A330BAF39810FE8671B4343C297DA1E1969C996216AB5106DA668941B160D4477017136CBCA5B5A8D44C4A8B1CF3EF79785E5AA25C3A1AD6C24FD140F79207DE5A499F8A1534FFA804AA7B3889CBE25C0414704AA57897F17862364ECA56258007248813912B836497F0359C2F7238A05D305A0EA152E72B44417A868134E91B3CA7931232FD4C25F8C2A492A339CDC0A138967211451F2562678FA14080A34436C42B07865AC036A81E97A7787A938025CAF813450368BED0C94B1857604526405D27A1C1ABC81B5B6EC13C71930A97D9232CF7021EF87A4D155328E62B583A83B4AF21F9F5750F8575150424F63B899D71CAD267C09E4467146E16E9B6C653F008C311375E2E006D4076A546B82F5314222F7C654317E79EC6035B73FAF491757E61C828326D53044541C4D4537ABD3EA1E67998C3382974CA78AE1B1960E4A9226B0219AB070F0D7AA66D76F9316ADB80C54D6499771B471E8168D47BCAA08324AB6BA92C3A70275F24FA4DC10E251633FB98D162BB5537202C6A553CE7841C4D40B873B85CA03A0A1E1CFADE6BA5180AB1323CCBA9A3E9C53D37575AB1FD9E7316C6FEECB0A14DF6F2DA56C2F56F55A89635CFCFDA47927AF1F0A47B2D4E4E61634B1B51D37A3A307A972420DE1B7A481B83E583B6AF16F63CB00C6"""), + xeh(""" +26CC4F22E035BC00687D557655C46B6E1C447ACB824204FEF7582EB8DBC704D7CE72B0A5FFE54FB89BD7B779B5B1DD1573010B227473FDEFFFB74DF7DCC1E6B48B554563C6C23004AE2CB1996943821F480E91081F1A6765E08A8AAB7F203E95DEEA49A1129A676DCB21540D2AAE1B21223DDDF1453150483176F3EA3580CE631FC85508690D8DDCBC9513A4A5951A440232223FB2ED9E0E5A8ACFEE113D22548B8E98131EE1F45A33656F079870A146F12819BFDDF8792C3C9AC3BBEA3A92B8606FF2B7296DB9D9782C8E788AF4C961840041735DE456A35E5536D861CA118D67408E84D8BB9128B65F2C11C7147EAC928599979EF195A7979CFC48277CF1FDF4B0CAAEB3F8A172A3CA25A3A8C39AAB4495A70E0AFD3861C41A8C01FAD1E9D81281CAE1C33572BA4BCA9A5294000FFD040545B021AF583F56434ACCD4CB7B788517243B09737D355ECE53273FC0C492F251FA02E47EA846121DFF00CBF2767D4DEB25F705591D26FB1B6F839A58EBA4572745A618CB2EBE02CC0CB1C62AA9F0EFB794C385BC47E440BEB38BA742C7357A97CF33098E2EA4D823BD0B9699FB1EBFA806D64FAB18E106D4A97B23A889355C7A2635A9D3BB330A1B8EE5E707DC32C20CACFED68C8DE783562488A64400A4528EF568D833D73E456A9AC22431B2C22441EF5BCE3E77CCEC99D2D1C092ED8A28D686214313F683D4A020FA714459C36A257DDFF7B19B7ED05A16FCACA2570279A11E1439D07F2F23B88411404749C37836585182F31AD65CFEADCFEC3FA905CD4BFE2B6ECAE99D469F3EFC55615D45D19360EBB7C68C73ABD4562EEDA283776C887E70A971176DDC10FC399EAD6B9E247353C25289C0836C626E5376326FE5630C3098436556D61F5C75DA6057008A6E1D50B4F270FCB86F868D5F235428B4D7E13010D20175D4CF0759F56422CF955A721792DEB8EC887E5225F6E52CDFF40B8BD3FEE4DEBC7B363574FD1F3CC113A3B4281F4E8DC3AEBE4B67500ACB50B5DB1BB64F0634B19D4612F597DE2B4CAEEE8A3258DDF8436ACADF3677B46E7E5CF41071DEAD3FBCE2A73388E19AC0C7748E10E3F586E2EB844ADFC079EC0A2CD8C9BAC8E859460DCDAB688AAAA179882B91111A604F75198F55B17C79AD4BE3FDB493B59775ED449BF938B594D87A1C9F721D1C39868591496E62BDBF5CC2947DD81B65ED8CA0BAF0A64E924B5F4FFA88BE86C3594EA7472B822D2D84CDBFC7A2C5039FEC6EBB14FAE2D5D7E9CAF1C2B8788E7354BB6A12C4EA1ABDF0811417586F01553AFD9D8B1EA233066023BC45FA4BC064E7D289AE9DDAF1F985E4BAA86C55BA1F1866E010C55E166C3AA29A682A81195819B7165DF6CC72045D143135EDABA08ACF9DD9FCB8CE732F9CDF1A99C772A2EDAB78647132C33B80E7F03C84A044491B311BC6F3571E7935C6EDFB283BC59F29DD5CCFF9DD6A9640139B173E64F2755F6BBD977F15AF1524827DCE4C2FDF1EBB7C35F0F34800E5A07FC83821FA6CD41695B322F0909D55251372DB8B3CB147FBBF6264BF764B1A20BFA41EFB84D109D4E374564C760AAB66EE823970EE7BFC1D9DB860840BC4767E4A46F1855526A7D902D4FA954C7F337C7C1205FD4AAA70D7F5D904F1D0CF1DBFB63675991B26B590260714920A7249E75D21199D8C002BD702C5398C45A359965D367FA15A73B83197DB3BF3AE9E987479CD81283419E557F993884EA4F17996CCA39FBA8941EDD70FC86E3A46C84C656F77E9DFA5DB31D8761A8FC1D5A2FE9C1CF67DDA1408A212951A5A1D5E9260BF367FD824ECBE8534AA5C63F3E9E2EE4EC53CB42663A79706088A846614B10EDB58B45BF063ACEF64DBB5ED8808588B51A80EC327B95DB34A2107FA96776F1DD0340C7918D0B846883EED35F5730D67165D4A51DC50533458F045E1266CE5C1CA6A30D931DA81732A876987482F2DB58694C574731E92CE6F9083A5EAD8143F244A8DF04C6DE1B2B07ED86D5593CAFC2A7B3E819C03C70B7B32AC0D576AC2E2E5843A39E4D36EFACBCE679307A1998F9C9DED50BF39CD29A529A82F26B5B4538F9CBBD547B9E4D5F7F31B555A8FCA1F9ABDEF3483640DE77D558735C15A588D944F9D76B06E417B1DA873F38A21321CDACE8D4BDDC49EBA4165D40820BA19A437D65B337B8C037041631D09F8ADD1400524F4A3BC33F9213AC7926548B9C43A4BC0148807D9""") + ), + new DecapsulateTestCase( + xeh(""" +8445C336F3518B298163DCBB6357597983CA2E873DCB49610CF52F14DBCB947C1F3EE9266967276B0C576CF7C30EE6B93DEA5118676CBEE1B1D4794206FB369ABA41167B4393855C84EBA8F32373C05BAE7631C802744AADB6C2DE41250C494315230B52826C34587CB21B183B49B2A5AC04921AC6BFAC1B24A4B37A93A4B168CCE7591BE6111F476260F2762959F5C1640118C2423772E2AD03DC7168A38C6DD39F5F7254264280C8BC10B914168070472FA880ACB8601A8A0837F25FE194687CD68B7DE2340F036DAD891D38D1B0CE9C2633355CF57B50B896036FCA260D2669F85BAC79714FDAFB41EF80B8C30264C31386AE60B05FAA542A26B41EB85F67068F088034FF67AA2E815AAB8BCA6BF71F70ECC3CBCBC45EF701FCD542BD21C7B09568F369C669F396473844FBA14957F51974D852B978014603A210C019036287008994F21255B25099AD82AA132438963B2C0A47CDF5F32BA46B76C7A6559F18BFD555B762E487B6AC992FE20E283CA0B3F6164496955995C3B28A57BBC29826F06FB38B253470AF631BC46C3A8F9CE824321985DD01C05F69B824F916633B40654C75AAEB9385576FFDE2990A6B0A3BE829D6D84E34F1780589C79204C63C798F55D23187E461D48C21E5C047E535B19F458BBA1345B9E41E0CB4A9C2D8C40B490A3BABC553B3026B1672D28CBC8B498A3A99579A832FEAE74610F0B6250CC333E9493EB1621ED34AA4AB175F2CA231152509ACB6AC86B20F6B39108439E5EC12D465A0FEF35003E14277A21812146B2544716D6AB82D1B0726C27A98D589EBDACC4C54BA77B2498F217E14E34E66025A2A143A992520A61C0672CC9CCED7C9450C683E90A3E4651DB623A6DB39AC26125B7FC1986D7B0493B8B72DE7707DC20BBDD43713156AF7D9430EF45399663C2202739168692DD657545B056D9C92385A7F414B34B90C7960D57B35BA7DDE7B81FCA0119D741B12780926018FE4C8030BF038E18B4FA33743D0D3C846417E9D5915C246315938B1E233614501D026959551258B233230D428B181B132F1D0B026067BA816999BC0CD6B547E548B63C9EAA091BAC493DC598DBC2B0E146A2591C2A8C009DD5170AAE027C541A1B5E66E45C65612984C46770493EC896EF25AA9305E9F06692CD0B2F06962E205BEBE113A34EBB1A4830A9B3749641BB935007B23B24BFE576956254D7A35AA496AC446C67A7FEC85A60057E8580617BCB3FAD15C76440FED54CC789394FEA24452CC6B0585B7EB0A88BBA9500D9800E6241AFEB523B55A96A535151D1049573206E59C7FEB070966823634F77D5F1291755A243119621AF8084AB7AC1E22A0568C6201417CBE3655D8A08DD5B513884C98D5A493FD49382EA41860F133CCD601E885966426A2B1F23D42D82E24582D99725192C21777467B1457B1DD429A0C41A5C3D704CEA06278C59941B438C62727097809B4530DBE837EA396B6D31077FAD3733053989A8442AAC4255CB163B8CA2F27501EA967305695ABD659AA02C83EE60BB574203E9937AE1C621C8ECB5CC1D21D556960B5B9161EA96FFFEBAC72E1B8A6154FC4D88B56C04741F090CBB156A737C9E6A22BA8AC704BC304F8E17E5EA845FDE59FBF788CCE0B97C8761F89A242F3052583C6844A632031C964A6C4A85A128A28619BA1BB3D1BEA4B49841FC847614A066841F52ED0EB8AE0B8B096E92B8195405815B231266F36B18C1A53333DAB95D2A9A374B5478A4A41FB8759957C9AB22CAE545AB544BA8DD05B83F3A613A2437ADB073A9635CB4BBC965FB454CF27B298A40CD0DA3B8F9CA99D8CB4286C5EB476416796070BA535AAA58CDB451CD6DB5CBB0CA20F0C71DE97C30DA97EC7906D06B4B939396028C46BA0E7A865BC8308A3810F1212006339F7BC169B1666FDF475911BBC8AAAB41755C9A8AABFA23C0E37F84FE46999E030494B9298EF9934E8A649C0A5CCE2B22F31809AFED23955D87881D99FC1D352896CAC9055BEA0D016CCBA7805A3A50E221630379BD01135221CAD5D9517C8CC42637B9FC0718E9A9BB4945C72D8D11D3D659D83A3C419509AF5B470DD89B7F3ACCF5F35CFC322115FD66A5CD2875651326F9B3168913BE5B9C87AE0B025EC7A2F4A072750946AC61170A7826D9704C5A23A1C0A2325146C3BC1858826C6B39279C2DA7438A370ED8A0AA5169E3BEC29ED88478732758D454143E227F8595883297842E6AF133B17E4811B0F5713AC73B7E347423EB92822D2306FA14500A7207A0672672046544ACC4EA9C16ED7421A069E0D737A98628519C6A29A424A868B46D9A0CC7C6C9DDD8B8BCBF422C8F48A73143D5ABB66BC55499418430802BAC544463CC7319D17998F29411365766D04C847F3129D9077B7D8339BFB96A6739C3F6B74A8F05F9138AB2FE37ACB57634D1820B50176F5A0B6BC2940F1D5938F1936B5F95828B92EB72973C1590AEB7A552CECA10B00C303B7C75D402071A79E2C810AF7C745E3336712492A42043F2903A37C6434CEE20B1D159B057699FF9C1D3BD68029839A08F43E6C1C819913532F911DD370C7021488E11CB504CB9C70570FFF35B4B4601191DC1AD9E6ADC5FA9618798D7CC860C87A939E4CCF8533632268CF1A51AFF0CB811C5545CB1656E65269477430699CCDEA3800630B78CD5810334CCF02E013F3B80244E70ACDB060BBE7A553B063456B2EA807473413165CE57DD563473CFBC90618ADE1F0B888AA48E722BB2751858FE19687442A48E7CA0D2A29CD51BFD8F78C17B9660BFB54A470B2AE9A955C6AB8D6E5CC92AC8ED3C185DAA8BC29F0578EBB812B97C9E5A848A6384DE4E75A31470B53066A8D027BA44B21749C0492465F9072B28376C4E290B30C1863F9E5B79996083422BD8C272C10ECC6EB9A0A8225B31AA0A66E35B9C0B9A79582BA20A3C04CD29914F083A0158288BA4D6EB62D87264B912BCA39732FBDE536A377AD02B8C835D4A2F4E7B1CE115D0C860BEAA7955A49AD689586A89A2B9F9B10D1595D2FC065AD018A7D56C614471F8E946FE8AB49E8226591119FCADB4F9A861631378736B6688B782D58E97E4572753A9664B6B8536812B25911AA76A242375433192738EEE762F6B84315BB3436231E0A9B277ED28AE0050728346457E13405062DB2804B8DA60BB5C793D4CC0E101CBA2D9182FD7124FF52BF4CA28292AC26D678088953971DBA0B6FEC2C9659353291C70C5B9245A0CA253304AFD3C95102BEA66875C6201680B4BDA38687B648C28EB37478E3BC00CA8A3CC27204642B42B68FCBE7B21A366D0668A5029A7DEEF94CDD6A95D7EA8931673BF7112D4042107B1B8B9700C974F9C4E83A8FACD89BFE0CA3CC4C2FCE80A03D3576C222A792B72B1F070AB7F6B6F2B5CA2AF5054AFA70A896990159B45D1003E2A05648675E596016F1B71DD0F7BDA7E2097FC73B3A143D12C726020AC34958AD7062B92B9ABF3CA6BE5AE29F57135E625A367971837E6363D1532094E022A23467CF932E1F89B5B0803C1EC99B585A78B5865096746F32258214ECB38065C97F455E155ACC2DD005A9C76BED59CDA73837D303504E6C976A606A2BE7BBEC5948B91A349E8936688CC0279754B743ABC58666B19B6C3260051F19206BB962BB6633EB0048E32BAACC5B020D02C86CA9770AD469DB54A106AC73A35B8057422B3DB202C5A5B4E3D535F0FC99326C4B8B7B16F1CB5AF96803FA8C195FC0BCEDDAAF012A51728B76489082373C91E92C87ACCA795160782E3B0DD643544BB96ABC2708D49B759CF057AA223BAFD96A330BAF39810FE8671B4343C297DA1E1969C996216AB5106DA668941B160D4477017136CBCA5B5A8D44C4A8B1CF3EF79785E5AA25C3A1AD6C24FD140F79207DE5A499F8A1534FFA804AA7B3889CBE25C0414704AA57897F17862364ECA56258007248813912B836497F0359C2F7238A05D305A0EA152E72B44417A868134E91B3CA7931232FD4C25F8C2A492A339CDC0A138967211451F2562678FA14080A34436C42B07865AC036A81E97A7787A938025CAF813450368BED0C94B1857604526405D27A1C1ABC81B5B6EC13C71930A97D9232CF7021EF87A4D155328E62B583A83B4AF21F9F5750F8575150424F63B899D71CAD267C09E4467146E16E9B6C653F008C311375E2E006D4076A546B82F5314222F7C654317E79EC6035B73FAF491757E61C828326D53044541C4D4537ABD3EA1E67998C3382974CA78AE1B1960E4A9226B0219AB070F0D7AA66D76F9316ADB80C54D6499771B471E8168D47BCAA08324AB6BA92C3A70275F24FA4DC10E251633FB98D162BB5537202C6A553CE7841C4D40B873B85CA03A0A1E1CFADE6BA5180AB1323CCBA9A3E9C53D37575AB1FD9E7316C6FEECB0A14DF6F2DA56C2F56F55A89635CFCFDA47927AF1F0A47B2D4E4E61634B1B51D37A3A307A972420DE1B7A481B83E583B6AF16F63CB00C6"""), + xeh(""" +B36564F2BBECFE4DD315E84612BD765E3F2E84F5D8D86FC0708F72FCAF284A0850708CE6E11D0BE154C00F930D18C0A8D8071B612556238A64B679A083B2FC1A204079EE19A4095E71E0EED695B3CA764F4F4E5D7366430A8933F0356DB074C2D68048E046481E5481E4F5A2F365EA9C4C7A6BEA51CDBF1BF31366F863327126DDD101F8220034FB4A3C68232C5CC84229EB1E35F19AC2016A8E4805A87797F940B72A472F129FF5B751964AEEC96847B0BCA5D7F391CA9053380DE83CBC31F341599FEFE36A1CD83B30A1B7CB588874CCC5F443F73ADFA2CE7E7271A5726272A7E5FC721E85D9755D672F5B2A0EAC8065D2C3835B7F0B2F7C77A27AAC438E345BAA378A572AA676632434737FA59A7E197135BD6AF2619A828AAC865D7F34AFB771BB55B5B7E93B9489AE98C694EAA26C6A86F41D0C53522DA4D90F2AB267675BABFBE963C4C68534A24D1EAEA2BE97702E28CABE5FD080DA6B3C432EB0E55F9FE8C1C0422A44F57002A1F96E6D53E8AB9539E909346D150082DF69F54D27017B9A7633B7BD9F7E6274B1F97D7CB4BF5FC2E34E77ECA1317E7854304C75C388CCD1386C694E93CADC856E136C2C0EE7E113A125C79443C5D1A80A9698BF58248B0903A45961603D1EA0E89E3C0650EA3E82368A6C477CCD1B0180542401BB1DE70E25F64A5DE41D62D0467353EE488E1F692EB60778452B53088473B084D0819B725268AAE752FC8CB56384C7AF9D319CAAEC958FC3EAEF57E0F35F1BFE1BABAA2C64A2D9813EE16F22A94C1C00B29EE82F11C47224A9C5424E647B9883918C9CF2CAF51B7FA825121C5D13ECEB5F66E4EA11526E0C37DBCD464C5BA78A36A31A62B2DECC7DF51C24843EC2325C74A771A7D73D35BF2AC4578932A6C2A7323375A2B7679188CFE804E5EFF4A04B7E14F8851770048F076B32BA4F19F4530364C0529EC3FB2D0DDABDC85DE2257F4DF05686AB498FDBEAE3A1439627DD8885E4C8744156C2B155BD2F965AF0F2017F163A6016C274E8532CA43C784B7AD4747A58253EDFB739D68E376D7ED246E5474454F463F4212090DF4F4D7F88C097B18180B05F2E89EEBB834B9BB6DD9E5F6036ECDD5908CA4962609C208A557A36B7FBC72158A6D86322F4303434F6AFFB34527E47E0599DDC88EAD31814646A81188E79E1B6D562E01FE1EF148FE8825758CFA5BD7B738E3BECDDDCA4C59093CA24581E531667DBA2C295B565951445E410FBC99D795887BD48AB87D6D413B64957993CD7525A0A0A5D393CA1EDF7788E4DFACDFA7B394B6163BB948C9C6779BDDCC8F26BC073BEAD0FC87236704A0DC0D89DEB4F8174E91D249C4DCD9260BC7C86CFB35B985813E1689D83083949927303741550CB782E256E79800F41B5C7D981D68E60978E5190A2C51C812DCC3952AA34212625834B2F8CF8CE8019AD6CE8F00FF910CCCF0CAF5A3596AF8DF947EFDE954F361665458F77787E528937BC52C59950746C783D8C5216570E6F0A944E6BD661F23C7A9AF3C602DF851EA2E5627186A6CCBCC470E07B290E4F754D5A8D6BAD8C34F39B4BA838CB467681B0173C33FA51ABE122BAE3DC06660950CFA5C228CDBA2F5EEF2613D2850DF9B5FEBE7333BE93F90E4DEE219AD18425DEE4006FA3009666C83DF7EDFB2EA4F99902C694248F9D51C7B6FBE53780EB218732C11368C33449D051489FDB01B1A1064FB06DED747ADE38F7A12DCDAA92D64DB4C2C43DFE53068A77339E1479C8C93192793B1C752FA7FB23B57DB5B428622D27CBF608CD7406FDB543FF3BD26FD7ED7269427C6B93491BE6724D071F58AF434FDAD2F0FAD5730A60F3EEF94C59CBC5884F36274C4CD984303EEAAD17E1785914DC804BBAF35406995E3D56094F0FDD71C7650A6C37393C0EF4C167CD2FBC28EB4EDD34B5383CA3D1B89D7BADB0270065B5AE2D461E6DEE53291230ED3CC3B616A7E8A86A4265A98C10A44066301470BBCDB257F35489BA5DCA320A390AF23CEF6ABA8B291538D9C4E965969087E394EDA44C060E28220BF72AB98F1C055159892DFF079D283C52997DCFDC2FD8291FFDF322809BE3CDC113DE9D495EA5F9FA5DDE5052192CA6F26BD510433B197131A7E954AEC5E58F0A341D7E4602BAE46BB1987B5C1D845E6AE5569DC2AFE0C7984DDD9B0B184CD6ABC0AADF5E13E0F110E8876D572200DD837FEF193278119B861C196C7522""") + ), + new DecapsulateTestCase( + xeh(""" +8445C336F3518B298163DCBB6357597983CA2E873DCB49610CF52F14DBCB947C1F3EE9266967276B0C576CF7C30EE6B93DEA5118676CBEE1B1D4794206FB369ABA41167B4393855C84EBA8F32373C05BAE7631C802744AADB6C2DE41250C494315230B52826C34587CB21B183B49B2A5AC04921AC6BFAC1B24A4B37A93A4B168CCE7591BE6111F476260F2762959F5C1640118C2423772E2AD03DC7168A38C6DD39F5F7254264280C8BC10B914168070472FA880ACB8601A8A0837F25FE194687CD68B7DE2340F036DAD891D38D1B0CE9C2633355CF57B50B896036FCA260D2669F85BAC79714FDAFB41EF80B8C30264C31386AE60B05FAA542A26B41EB85F67068F088034FF67AA2E815AAB8BCA6BF71F70ECC3CBCBC45EF701FCD542BD21C7B09568F369C669F396473844FBA14957F51974D852B978014603A210C019036287008994F21255B25099AD82AA132438963B2C0A47CDF5F32BA46B76C7A6559F18BFD555B762E487B6AC992FE20E283CA0B3F6164496955995C3B28A57BBC29826F06FB38B253470AF631BC46C3A8F9CE824321985DD01C05F69B824F916633B40654C75AAEB9385576FFDE2990A6B0A3BE829D6D84E34F1780589C79204C63C798F55D23187E461D48C21E5C047E535B19F458BBA1345B9E41E0CB4A9C2D8C40B490A3BABC553B3026B1672D28CBC8B498A3A99579A832FEAE74610F0B6250CC333E9493EB1621ED34AA4AB175F2CA231152509ACB6AC86B20F6B39108439E5EC12D465A0FEF35003E14277A21812146B2544716D6AB82D1B0726C27A98D589EBDACC4C54BA77B2498F217E14E34E66025A2A143A992520A61C0672CC9CCED7C9450C683E90A3E4651DB623A6DB39AC26125B7FC1986D7B0493B8B72DE7707DC20BBDD43713156AF7D9430EF45399663C2202739168692DD657545B056D9C92385A7F414B34B90C7960D57B35BA7DDE7B81FCA0119D741B12780926018FE4C8030BF038E18B4FA33743D0D3C846417E9D5915C246315938B1E233614501D026959551258B233230D428B181B132F1D0B026067BA816999BC0CD6B547E548B63C9EAA091BAC493DC598DBC2B0E146A2591C2A8C009DD5170AAE027C541A1B5E66E45C65612984C46770493EC896EF25AA9305E9F06692CD0B2F06962E205BEBE113A34EBB1A4830A9B3749641BB935007B23B24BFE576956254D7A35AA496AC446C67A7FEC85A60057E8580617BCB3FAD15C76440FED54CC789394FEA24452CC6B0585B7EB0A88BBA9500D9800E6241AFEB523B55A96A535151D1049573206E59C7FEB070966823634F77D5F1291755A243119621AF8084AB7AC1E22A0568C6201417CBE3655D8A08DD5B513884C98D5A493FD49382EA41860F133CCD601E885966426A2B1F23D42D82E24582D99725192C21777467B1457B1DD429A0C41A5C3D704CEA06278C59941B438C62727097809B4530DBE837EA396B6D31077FAD3733053989A8442AAC4255CB163B8CA2F27501EA967305695ABD659AA02C83EE60BB574203E9937AE1C621C8ECB5CC1D21D556960B5B9161EA96FFFEBAC72E1B8A6154FC4D88B56C04741F090CBB156A737C9E6A22BA8AC704BC304F8E17E5EA845FDE59FBF788CCE0B97C8761F89A242F3052583C6844A632031C964A6C4A85A128A28619BA1BB3D1BEA4B49841FC847614A066841F52ED0EB8AE0B8B096E92B8195405815B231266F36B18C1A53333DAB95D2A9A374B5478A4A41FB8759957C9AB22CAE545AB544BA8DD05B83F3A613A2437ADB073A9635CB4BBC965FB454CF27B298A40CD0DA3B8F9CA99D8CB4286C5EB476416796070BA535AAA58CDB451CD6DB5CBB0CA20F0C71DE97C30DA97EC7906D06B4B939396028C46BA0E7A865BC8308A3810F1212006339F7BC169B1666FDF475911BBC8AAAB41755C9A8AABFA23C0E37F84FE46999E030494B9298EF9934E8A649C0A5CCE2B22F31809AFED23955D87881D99FC1D352896CAC9055BEA0D016CCBA7805A3A50E221630379BD01135221CAD5D9517C8CC42637B9FC0718E9A9BB4945C72D8D11D3D659D83A3C419509AF5B470DD89B7F3ACCF5F35CFC322115FD66A5CD2875651326F9B3168913BE5B9C87AE0B025EC7A2F4A072750946AC61170A7826D9704C5A23A1C0A2325146C3BC1858826C6B39279C2DA7438A370ED8A0AA5169E3BEC29ED88478732758D454143E227F8595883297842E6AF133B17E4811B0F5713AC73B7E347423EB92822D2306FA14500A7207A0672672046544ACC4EA9C16ED7421A069E0D737A98628519C6A29A424A868B46D9A0CC7C6C9DDD8B8BCBF422C8F48A73143D5ABB66BC55499418430802BAC544463CC7319D17998F29411365766D04C847F3129D9077B7D8339BFB96A6739C3F6B74A8F05F9138AB2FE37ACB57634D1820B50176F5A0B6BC2940F1D5938F1936B5F95828B92EB72973C1590AEB7A552CECA10B00C303B7C75D402071A79E2C810AF7C745E3336712492A42043F2903A37C6434CEE20B1D159B057699FF9C1D3BD68029839A08F43E6C1C819913532F911DD370C7021488E11CB504CB9C70570FFF35B4B4601191DC1AD9E6ADC5FA9618798D7CC860C87A939E4CCF8533632268CF1A51AFF0CB811C5545CB1656E65269477430699CCDEA3800630B78CD5810334CCF02E013F3B80244E70ACDB060BBE7A553B063456B2EA807473413165CE57DD563473CFBC90618ADE1F0B888AA48E722BB2751858FE19687442A48E7CA0D2A29CD51BFD8F78C17B9660BFB54A470B2AE9A955C6AB8D6E5CC92AC8ED3C185DAA8BC29F0578EBB812B97C9E5A848A6384DE4E75A31470B53066A8D027BA44B21749C0492465F9072B28376C4E290B30C1863F9E5B79996083422BD8C272C10ECC6EB9A0A8225B31AA0A66E35B9C0B9A79582BA20A3C04CD29914F083A0158288BA4D6EB62D87264B912BCA39732FBDE536A377AD02B8C835D4A2F4E7B1CE115D0C860BEAA7955A49AD689586A89A2B9F9B10D1595D2FC065AD018A7D56C614471F8E946FE8AB49E8226591119FCADB4F9A861631378736B6688B782D58E97E4572753A9664B6B8536812B25911AA76A242375433192738EEE762F6B84315BB3436231E0A9B277ED28AE0050728346457E13405062DB2804B8DA60BB5C793D4CC0E101CBA2D9182FD7124FF52BF4CA28292AC26D678088953971DBA0B6FEC2C9659353291C70C5B9245A0CA253304AFD3C95102BEA66875C6201680B4BDA38687B648C28EB37478E3BC00CA8A3CC27204642B42B68FCBE7B21A366D0668A5029A7DEEF94CDD6A95D7EA8931673BF7112D4042107B1B8B9700C974F9C4E83A8FACD89BFE0CA3CC4C2FCE80A03D3576C222A792B72B1F070AB7F6B6F2B5CA2AF5054AFA70A896990159B45D1003E2A05648675E596016F1B71DD0F7BDA7E2097FC73B3A143D12C726020AC34958AD7062B92B9ABF3CA6BE5AE29F57135E625A367971837E6363D1532094E022A23467CF932E1F89B5B0803C1EC99B585A78B5865096746F32258214ECB38065C97F455E155ACC2DD005A9C76BED59CDA73837D303504E6C976A606A2BE7BBEC5948B91A349E8936688CC0279754B743ABC58666B19B6C3260051F19206BB962BB6633EB0048E32BAACC5B020D02C86CA9770AD469DB54A106AC73A35B8057422B3DB202C5A5B4E3D535F0FC99326C4B8B7B16F1CB5AF96803FA8C195FC0BCEDDAAF012A51728B76489082373C91E92C87ACCA795160782E3B0DD643544BB96ABC2708D49B759CF057AA223BAFD96A330BAF39810FE8671B4343C297DA1E1969C996216AB5106DA668941B160D4477017136CBCA5B5A8D44C4A8B1CF3EF79785E5AA25C3A1AD6C24FD140F79207DE5A499F8A1534FFA804AA7B3889CBE25C0414704AA57897F17862364ECA56258007248813912B836497F0359C2F7238A05D305A0EA152E72B44417A868134E91B3CA7931232FD4C25F8C2A492A339CDC0A138967211451F2562678FA14080A34436C42B07865AC036A81E97A7787A938025CAF813450368BED0C94B1857604526405D27A1C1ABC81B5B6EC13C71930A97D9232CF7021EF87A4D155328E62B583A83B4AF21F9F5750F8575150424F63B899D71CAD267C09E4467146E16E9B6C653F008C311375E2E006D4076A546B82F5314222F7C654317E79EC6035B73FAF491757E61C828326D53044541C4D4537ABD3EA1E67998C3382974CA78AE1B1960E4A9226B0219AB070F0D7AA66D76F9316ADB80C54D6499771B471E8168D47BCAA08324AB6BA92C3A70275F24FA4DC10E251633FB98D162BB5537202C6A553CE7841C4D40B873B85CA03A0A1E1CFADE6BA5180AB1323CCBA9A3E9C53D37575AB1FD9E7316C6FEECB0A14DF6F2DA56C2F56F55A89635CFCFDA47927AF1F0A47B2D4E4E61634B1B51D37A3A307A972420DE1B7A481B83E583B6AF16F63CB00C6"""), + xeh(""" +4B30E5256A941008BAD9BD14060445AD208769EDEA1C5B6E4ED506FB334A2378520B5EDC9217D626E1377839A18F2D21C0CC8902622E4AB79E83DEC449FFFD45A4CBF3AC253142D935DD310B5E4C5D591A9BD61795F8ABF00AA04EBAF96195B6CC7D7C3910FD7D75E25A9D0D79FA453178B06FC6B1E99F189CDA90276D6B69FBEA28D68CC82707A46CBEAB819239BE69BA76D749E27CAC9E5FFE88064B9972DB77C49679D6DDC6E6B03DAA0DDF0106B1A61141DF827E96AC542DC90A69CB316EB4F78C611C0155F9138F527006121DA16DB46531ADEC2FF599378A819CFBE3B079C9FE7E368B91A9E40F97A3E79A4F1F05574CE2AC3A525C206D9E55CE16D42D2F0F4863F896E808FE168B34A102BB81BD607BD02CCFFBA5C189497502A55F3E601F8F61B40A5202BAF9AC87D058E67B9E1CDEA0E4B02FF2DEED7477609A9AE2116512C42079D87AD74B05622E02979EF0A0F1D6375D93576EB6553FB1AC70ABDACBFBDB18735E949EC6D1667E978547A5CEAF2F4DCA6FF5D8346A960CE6925BF2B3F316238D6BC8ACBE67BC1AACD5A9A5D130A3D3B39C3BD7C1B06227A59BF4723AE9656D9922D9228A3404D4856E39702DFDC01C6E8CB6000E0779364BAD4F021BCFD7288CE7049D544E8423B2890C3083FDDB9BC720AC4C6A1A4EEA6BA1927B307E6CB72131B6B831AAD036A50A54608D106EDACD83EBDF104AA80C917314D295E903FDF36CD04EB786CF93AFF1279C2172002F7EE92DFAB3A99BF42C2BE7B7D0EDDD38029AB5AE18F5CFF8A2F1D2EA2EC7F34770FBA8A8BEEB0E1FF6F1C1A036F1BD84030004696BF4FB4161F252436C0401AEC911CBF1D7530D9D801B1B9B3A682329AE2F6930191E48189CD40706256B864D6F016597B4AA86FEE4F0E2362D8BCC743E98531EB2B335DE2DD299F231FAA808F6BC7D8F13DE8EAA30C5698D64E508D3534935B9941C2E40A458BEA82DAE4151ECF6DCD40320E1009BD9FBEE248F4EB6DB4437482BDFD83FDAF8367CC1845E64A23A310F904D5FAAD67241AA7748764C26EC881788D1EE0A39944071E5ACB656AB8CEA285C282545030EBBE6FB595E296E1EA37D7AE529B96CAECED11331D80C92D3DACDD7DC93237D815A9C6CEB9209C0BF3548ED1AD691929B2C1035E80A21477747E313049DEAD43A40B0960A96BF3C3E9BADEBC3B4D424FE7DC4DE5CE7788E31AEA3EC8965740D424CEB66D4A5678260051BFEFF09A3CB24C1AB7782AFBFEDE5EE1ED4EB14AD2A13142E8201CD1B52CE064F05ACFB019E21A73D84A80E30FAA48ABEFECA970BBF17FFA6F3A90AEF80EFA31C494E721231289143416AB9621737FC016380E6079EC6CD962BF7CC0750582EB218F869CE117D399DEF9AA66F7D2F07FD22BEB9E50B94CA5FC758C9DD4D2984A156748C52307731FC78F8539F8264BAD6DD56C0C23937A9A850E66BA298C3D39105ECACA9A573D887C9A4FE33D487F2126097B165594E1F8106C937758AB6EE75EDF39D2BCDE78AB611A034A72FDBEE67A80F3315571AB4DB94C56A19EFB63B8E7708566412F73D4974B160183FB5B6C44C8CED990B29C57BBEEAC5EABDCB11CCED9A17322B6EF197121B4094D7EA4A1B4EC44A68B447FE4C8119A6A33BFB66EA6844DB5B6094119AD1DE89449DE922B9A0D1253EA18C62418EB87330C6B33EEE02D4486F62A4D31CA24F098BE2F187CA6019025AD6E1C2FE69800D8BFA2C646F9FC6BCB3D369A78310084FF163D2065631C41748E7E3B25E8F2C9EDA2E107AA2046FE3F5DCC0A9A39FCE41813C8F1946C3AC07A22A6A56C4AFC626E68FF8CBC4982C1E60C3A9F288D1C4F2B8D7187EF2FAE30B77C4DD73499C2B3793B24014CFFEF6D80063DD1C1F3AC7F14FB61E5E81F850AB865BA873404BEB898FF7A2DCFA3B955DDB161B5781AFE8EF127BA2C8BFDBC2FB1C7D80FC650420214314023F6F65C17FC48927BBAE88D48D2E1976119C2F8310232942DD4C3AD4518D1E4DA9DD588691837122F5E5DE0FF1FA685DE134DFD1348CE3B5BE60B18BBF474074829E7D81AE087F149259122D47B728F369D1D8455EE571F715788C254F2EF438034BFF0A11F2F008E19B370BBEEE135A00DBE7F3C2970208F5F5D0E2765C395CA81B2FD80FC384AD046564229C759315B6CFFAD03A56996556E7714DABDE28F7A9BB5DE2C05B1F3596AF66C747D9A9313673F19AD4BAC6EAA7""") + ), + new DecapsulateTestCase( + xeh(""" +8445C336F3518B298163DCBB6357597983CA2E873DCB49610CF52F14DBCB947C1F3EE9266967276B0C576CF7C30EE6B93DEA5118676CBEE1B1D4794206FB369ABA41167B4393855C84EBA8F32373C05BAE7631C802744AADB6C2DE41250C494315230B52826C34587CB21B183B49B2A5AC04921AC6BFAC1B24A4B37A93A4B168CCE7591BE6111F476260F2762959F5C1640118C2423772E2AD03DC7168A38C6DD39F5F7254264280C8BC10B914168070472FA880ACB8601A8A0837F25FE194687CD68B7DE2340F036DAD891D38D1B0CE9C2633355CF57B50B896036FCA260D2669F85BAC79714FDAFB41EF80B8C30264C31386AE60B05FAA542A26B41EB85F67068F088034FF67AA2E815AAB8BCA6BF71F70ECC3CBCBC45EF701FCD542BD21C7B09568F369C669F396473844FBA14957F51974D852B978014603A210C019036287008994F21255B25099AD82AA132438963B2C0A47CDF5F32BA46B76C7A6559F18BFD555B762E487B6AC992FE20E283CA0B3F6164496955995C3B28A57BBC29826F06FB38B253470AF631BC46C3A8F9CE824321985DD01C05F69B824F916633B40654C75AAEB9385576FFDE2990A6B0A3BE829D6D84E34F1780589C79204C63C798F55D23187E461D48C21E5C047E535B19F458BBA1345B9E41E0CB4A9C2D8C40B490A3BABC553B3026B1672D28CBC8B498A3A99579A832FEAE74610F0B6250CC333E9493EB1621ED34AA4AB175F2CA231152509ACB6AC86B20F6B39108439E5EC12D465A0FEF35003E14277A21812146B2544716D6AB82D1B0726C27A98D589EBDACC4C54BA77B2498F217E14E34E66025A2A143A992520A61C0672CC9CCED7C9450C683E90A3E4651DB623A6DB39AC26125B7FC1986D7B0493B8B72DE7707DC20BBDD43713156AF7D9430EF45399663C2202739168692DD657545B056D9C92385A7F414B34B90C7960D57B35BA7DDE7B81FCA0119D741B12780926018FE4C8030BF038E18B4FA33743D0D3C846417E9D5915C246315938B1E233614501D026959551258B233230D428B181B132F1D0B026067BA816999BC0CD6B547E548B63C9EAA091BAC493DC598DBC2B0E146A2591C2A8C009DD5170AAE027C541A1B5E66E45C65612984C46770493EC896EF25AA9305E9F06692CD0B2F06962E205BEBE113A34EBB1A4830A9B3749641BB935007B23B24BFE576956254D7A35AA496AC446C67A7FEC85A60057E8580617BCB3FAD15C76440FED54CC789394FEA24452CC6B0585B7EB0A88BBA9500D9800E6241AFEB523B55A96A535151D1049573206E59C7FEB070966823634F77D5F1291755A243119621AF8084AB7AC1E22A0568C6201417CBE3655D8A08DD5B513884C98D5A493FD49382EA41860F133CCD601E885966426A2B1F23D42D82E24582D99725192C21777467B1457B1DD429A0C41A5C3D704CEA06278C59941B438C62727097809B4530DBE837EA396B6D31077FAD3733053989A8442AAC4255CB163B8CA2F27501EA967305695ABD659AA02C83EE60BB574203E9937AE1C621C8ECB5CC1D21D556960B5B9161EA96FFFEBAC72E1B8A6154FC4D88B56C04741F090CBB156A737C9E6A22BA8AC704BC304F8E17E5EA845FDE59FBF788CCE0B97C8761F89A242F3052583C6844A632031C964A6C4A85A128A28619BA1BB3D1BEA4B49841FC847614A066841F52ED0EB8AE0B8B096E92B8195405815B231266F36B18C1A53333DAB95D2A9A374B5478A4A41FB8759957C9AB22CAE545AB544BA8DD05B83F3A613A2437ADB073A9635CB4BBC965FB454CF27B298A40CD0DA3B8F9CA99D8CB4286C5EB476416796070BA535AAA58CDB451CD6DB5CBB0CA20F0C71DE97C30DA97EC7906D06B4B939396028C46BA0E7A865BC8308A3810F1212006339F7BC169B1666FDF475911BBC8AAAB41755C9A8AABFA23C0E37F84FE46999E030494B9298EF9934E8A649C0A5CCE2B22F31809AFED23955D87881D99FC1D352896CAC9055BEA0D016CCBA7805A3A50E221630379BD01135221CAD5D9517C8CC42637B9FC0718E9A9BB4945C72D8D11D3D659D83A3C419509AF5B470DD89B7F3ACCF5F35CFC322115FD66A5CD2875651326F9B3168913BE5B9C87AE0B025EC7A2F4A072750946AC61170A7826D9704C5A23A1C0A2325146C3BC1858826C6B39279C2DA7438A370ED8A0AA5169E3BEC29ED88478732758D454143E227F8595883297842E6AF133B17E4811B0F5713AC73B7E347423EB92822D2306FA14500A7207A0672672046544ACC4EA9C16ED7421A069E0D737A98628519C6A29A424A868B46D9A0CC7C6C9DDD8B8BCBF422C8F48A73143D5ABB66BC55499418430802BAC544463CC7319D17998F29411365766D04C847F3129D9077B7D8339BFB96A6739C3F6B74A8F05F9138AB2FE37ACB57634D1820B50176F5A0B6BC2940F1D5938F1936B5F95828B92EB72973C1590AEB7A552CECA10B00C303B7C75D402071A79E2C810AF7C745E3336712492A42043F2903A37C6434CEE20B1D159B057699FF9C1D3BD68029839A08F43E6C1C819913532F911DD370C7021488E11CB504CB9C70570FFF35B4B4601191DC1AD9E6ADC5FA9618798D7CC860C87A939E4CCF8533632268CF1A51AFF0CB811C5545CB1656E65269477430699CCDEA3800630B78CD5810334CCF02E013F3B80244E70ACDB060BBE7A553B063456B2EA807473413165CE57DD563473CFBC90618ADE1F0B888AA48E722BB2751858FE19687442A48E7CA0D2A29CD51BFD8F78C17B9660BFB54A470B2AE9A955C6AB8D6E5CC92AC8ED3C185DAA8BC29F0578EBB812B97C9E5A848A6384DE4E75A31470B53066A8D027BA44B21749C0492465F9072B28376C4E290B30C1863F9E5B79996083422BD8C272C10ECC6EB9A0A8225B31AA0A66E35B9C0B9A79582BA20A3C04CD29914F083A0158288BA4D6EB62D87264B912BCA39732FBDE536A377AD02B8C835D4A2F4E7B1CE115D0C860BEAA7955A49AD689586A89A2B9F9B10D1595D2FC065AD018A7D56C614471F8E946FE8AB49E8226591119FCADB4F9A861631378736B6688B782D58E97E4572753A9664B6B8536812B25911AA76A242375433192738EEE762F6B84315BB3436231E0A9B277ED28AE0050728346457E13405062DB2804B8DA60BB5C793D4CC0E101CBA2D9182FD7124FF52BF4CA28292AC26D678088953971DBA0B6FEC2C9659353291C70C5B9245A0CA253304AFD3C95102BEA66875C6201680B4BDA38687B648C28EB37478E3BC00CA8A3CC27204642B42B68FCBE7B21A366D0668A5029A7DEEF94CDD6A95D7EA8931673BF7112D4042107B1B8B9700C974F9C4E83A8FACD89BFE0CA3CC4C2FCE80A03D3576C222A792B72B1F070AB7F6B6F2B5CA2AF5054AFA70A896990159B45D1003E2A05648675E596016F1B71DD0F7BDA7E2097FC73B3A143D12C726020AC34958AD7062B92B9ABF3CA6BE5AE29F57135E625A367971837E6363D1532094E022A23467CF932E1F89B5B0803C1EC99B585A78B5865096746F32258214ECB38065C97F455E155ACC2DD005A9C76BED59CDA73837D303504E6C976A606A2BE7BBEC5948B91A349E8936688CC0279754B743ABC58666B19B6C3260051F19206BB962BB6633EB0048E32BAACC5B020D02C86CA9770AD469DB54A106AC73A35B8057422B3DB202C5A5B4E3D535F0FC99326C4B8B7B16F1CB5AF96803FA8C195FC0BCEDDAAF012A51728B76489082373C91E92C87ACCA795160782E3B0DD643544BB96ABC2708D49B759CF057AA223BAFD96A330BAF39810FE8671B4343C297DA1E1969C996216AB5106DA668941B160D4477017136CBCA5B5A8D44C4A8B1CF3EF79785E5AA25C3A1AD6C24FD140F79207DE5A499F8A1534FFA804AA7B3889CBE25C0414704AA57897F17862364ECA56258007248813912B836497F0359C2F7238A05D305A0EA152E72B44417A868134E91B3CA7931232FD4C25F8C2A492A339CDC0A138967211451F2562678FA14080A34436C42B07865AC036A81E97A7787A938025CAF813450368BED0C94B1857604526405D27A1C1ABC81B5B6EC13C71930A97D9232CF7021EF87A4D155328E62B583A83B4AF21F9F5750F8575150424F63B899D71CAD267C09E4467146E16E9B6C653F008C311375E2E006D4076A546B82F5314222F7C654317E79EC6035B73FAF491757E61C828326D53044541C4D4537ABD3EA1E67998C3382974CA78AE1B1960E4A9226B0219AB070F0D7AA66D76F9316ADB80C54D6499771B471E8168D47BCAA08324AB6BA92C3A70275F24FA4DC10E251633FB98D162BB5537202C6A553CE7841C4D40B873B85CA03A0A1E1CFADE6BA5180AB1323CCBA9A3E9C53D37575AB1FD9E7316C6FEECB0A14DF6F2DA56C2F56F55A89635CFCFDA47927AF1F0A47B2D4E4E61634B1B51D37A3A307A972420DE1B7A481B83E583B6AF16F63CB00C6"""), + xeh(""" +CA9564B54F15561C8238E6CFD88137EBD4D277FD5D64BAFC33D6E575947F0FF9F93E3B0A4023DDB6FE480D7D6A2B9ABCD6E6E011EF37C0699A6D60D9AB4B05BC685B0A9AF7D3BD999C7AC1CDF017E6AF1DCF0313759CBB21539D7774C31D7ED8C039AC34D0C6A5F7590A3DFE193D73FA96B3458A364DE1555284D85A2BAE7BA9E57ABA00134E6B09C09777F2F1D7125AF858D81D14C71E34E8F668468997334B72E002920FD3FAD8D588355343FA949F1CC0BC263C7F7A7FEA6AD708DB756AF983B16A593EC224F7D69208938A4526400E326CBED532A777301DDEB5E539CFCE60DB8A022AFC52204C71710C204968FD1457919EB71CA15522AD56ED6B60404D62D1DAD0D06E4A2AD6BC746B28859A77226B774BF56BF7F019F2837F51509E9EBE9EB069DA27401CD1D7BF2A74CBE8341A7F213D061619F4E5F52984FE47066D910F1146CCD8DB48210FA2518D6B9FADFF16ED9D389292C07C8A7021F32BCD538AB06A6D5ADB13D7A96F65A4062A17E26B301CC8AD420732126D7CB801DD489AFF2D717D07A2748B4B01D162D228D5F1533CD5FEE8DFF8F032DFB270B61095785E44CEBBD4EA27158362D2A27582CE78594D4D7428B6AD958A9F1604EBA76A8CC0530E1001AC97E5ACC5EE670D5DC6A78AA45300A2BD5F0802CDEE564FA640A19FB554383A4E4CCF2E5BB3A41879C9428CBDB8DE1F4D3FDEFC18C2A8BAE42C096244279E57B307614C843B341BCCF530F6B187121DD83A9A160A3579C3188A98FE2F49A85A2705B9F76DEF04D5D04676D8319F243DFC99A5F90771B34D2A45EFF92C0CA8E4B542B8ED4C2AFBC92C26F8DD20B26B15F9E719AF22F571EE5B9573D5BD1931138D6315C5104BF80AECF830548E98AB23DFA44E5A23C6CF57740926D1E146937AF8D220684919FD89082E260286AB66F66F8A1B81BEE07A85907D07FCCFB9A1002CDD47A33535C9FC0938E3CDDED04D3FABE6326CBF5643373BAE1151704220E49E177C4D0C6168647E5976670DB7F6D0C12F169955E31F553A53A76093DA2A9A0C589F9AFDCCAAD9EC5449ACC01E12A70BCEB389AC104407415782AF2EA3C73D9EB2797CE6D3C005061C5059AB625DD7D273D4D92D1F4EB411A4033492F19921F60D0317AF286866B865E33B6235F0E3528228CF9DB242124F0A6375D50CAB3851DD2A3A022C1E636E332C90D97FBBFC2CF0B971AB1A89014BC2D942FDF015555431ACB3E7A6F258B816BA84892A1DFE3780A0E0C2E6C06149218E70D60D62573BB51856716C0DDA63A983C4008982E842E655E5767DD203DB3490E1E6BDBEC16350296D879F017BA695FC1CB3BBE516B741A67CA6CE09314AE27F718DF68DE698198289B457884FFF1E439F30D9117D19ED7E466084BD5A73E26B5E1567B148D4C7ACD1368B1CE2709B3AF233679E61914202D0DCFC81EF3ACC250DCEA602103C7E529FD6F31A186927E790E3DEE09DCE87DF694ADA7A3B7BB3BEC64456EE983E25DC6CA1CBCD752D72ABE6FDA2FC81A46F81E83AA9738D528C6FA3E69C453346D0C9A0734DF36BB7650D1D2AFA8A5C4C5A936D41258BD4193DA74FFB180CFF582A32D6F6ACB93836E009E8C880592BE61532215F1F6FA50E8FFBB82208A94D8510F70DC6633DC04F9D94C6AC46EDDD4EB36873E064CBBE65D343957CA7B75024EEBB56F589C3DD2253D68D12DC892ABB1FA4BF033B9B732E89A8B89541F04C6462F62F13B09C6705B31036294F1AC38EDC0C2298D7C6F4374C3B5C368D10DA8D371383CBFB4491126A83D1F75DF44F29BCD39349A9BF6526D14B339FCB440647A5FAB63A370089DF162DDBCEAC8966648DDAD6669E1EADC1C8A33E9B7378693E229C6B715F2F0AE54A67455E79FF8970F23E655E7A540D28958E2E102DC99B5CE5772D00831671CC6F7024BBAE8B04173E439054C96AB3BE918C40C5A8D42A9122CA29C56044D340420D2EAAEB738EEF70331D488169FE91B521835297D7326CA272B2614144EAA0B7A75CC7F3849138255B8A1D7DB875BC7C25D28EE5941DE89BF7B063046CA0CFF31A99D7B1846E01B519137B67647F024B3F6DC70045B6950EC6ADBD68F43F67464858D515D6E3EC5F99D9F1C849831BEB4224FEDB01236712E1D715F6A752D0682169A0E83F064FD6F081F338837FE654BCE7C8CAAA8CA90C8505945D9BB3EA58661102FF0ED3F0DE30C4013122D8CF08E0""") + ), + new DecapsulateTestCase( + xeh(""" +8445C336F3518B298163DCBB6357597983CA2E873DCB49610CF52F14DBCB947C1F3EE9266967276B0C576CF7C30EE6B93DEA5118676CBEE1B1D4794206FB369ABA41167B4393855C84EBA8F32373C05BAE7631C802744AADB6C2DE41250C494315230B52826C34587CB21B183B49B2A5AC04921AC6BFAC1B24A4B37A93A4B168CCE7591BE6111F476260F2762959F5C1640118C2423772E2AD03DC7168A38C6DD39F5F7254264280C8BC10B914168070472FA880ACB8601A8A0837F25FE194687CD68B7DE2340F036DAD891D38D1B0CE9C2633355CF57B50B896036FCA260D2669F85BAC79714FDAFB41EF80B8C30264C31386AE60B05FAA542A26B41EB85F67068F088034FF67AA2E815AAB8BCA6BF71F70ECC3CBCBC45EF701FCD542BD21C7B09568F369C669F396473844FBA14957F51974D852B978014603A210C019036287008994F21255B25099AD82AA132438963B2C0A47CDF5F32BA46B76C7A6559F18BFD555B762E487B6AC992FE20E283CA0B3F6164496955995C3B28A57BBC29826F06FB38B253470AF631BC46C3A8F9CE824321985DD01C05F69B824F916633B40654C75AAEB9385576FFDE2990A6B0A3BE829D6D84E34F1780589C79204C63C798F55D23187E461D48C21E5C047E535B19F458BBA1345B9E41E0CB4A9C2D8C40B490A3BABC553B3026B1672D28CBC8B498A3A99579A832FEAE74610F0B6250CC333E9493EB1621ED34AA4AB175F2CA231152509ACB6AC86B20F6B39108439E5EC12D465A0FEF35003E14277A21812146B2544716D6AB82D1B0726C27A98D589EBDACC4C54BA77B2498F217E14E34E66025A2A143A992520A61C0672CC9CCED7C9450C683E90A3E4651DB623A6DB39AC26125B7FC1986D7B0493B8B72DE7707DC20BBDD43713156AF7D9430EF45399663C2202739168692DD657545B056D9C92385A7F414B34B90C7960D57B35BA7DDE7B81FCA0119D741B12780926018FE4C8030BF038E18B4FA33743D0D3C846417E9D5915C246315938B1E233614501D026959551258B233230D428B181B132F1D0B026067BA816999BC0CD6B547E548B63C9EAA091BAC493DC598DBC2B0E146A2591C2A8C009DD5170AAE027C541A1B5E66E45C65612984C46770493EC896EF25AA9305E9F06692CD0B2F06962E205BEBE113A34EBB1A4830A9B3749641BB935007B23B24BFE576956254D7A35AA496AC446C67A7FEC85A60057E8580617BCB3FAD15C76440FED54CC789394FEA24452CC6B0585B7EB0A88BBA9500D9800E6241AFEB523B55A96A535151D1049573206E59C7FEB070966823634F77D5F1291755A243119621AF8084AB7AC1E22A0568C6201417CBE3655D8A08DD5B513884C98D5A493FD49382EA41860F133CCD601E885966426A2B1F23D42D82E24582D99725192C21777467B1457B1DD429A0C41A5C3D704CEA06278C59941B438C62727097809B4530DBE837EA396B6D31077FAD3733053989A8442AAC4255CB163B8CA2F27501EA967305695ABD659AA02C83EE60BB574203E9937AE1C621C8ECB5CC1D21D556960B5B9161EA96FFFEBAC72E1B8A6154FC4D88B56C04741F090CBB156A737C9E6A22BA8AC704BC304F8E17E5EA845FDE59FBF788CCE0B97C8761F89A242F3052583C6844A632031C964A6C4A85A128A28619BA1BB3D1BEA4B49841FC847614A066841F52ED0EB8AE0B8B096E92B8195405815B231266F36B18C1A53333DAB95D2A9A374B5478A4A41FB8759957C9AB22CAE545AB544BA8DD05B83F3A613A2437ADB073A9635CB4BBC965FB454CF27B298A40CD0DA3B8F9CA99D8CB4286C5EB476416796070BA535AAA58CDB451CD6DB5CBB0CA20F0C71DE97C30DA97EC7906D06B4B939396028C46BA0E7A865BC8308A3810F1212006339F7BC169B1666FDF475911BBC8AAAB41755C9A8AABFA23C0E37F84FE46999E030494B9298EF9934E8A649C0A5CCE2B22F31809AFED23955D87881D99FC1D352896CAC9055BEA0D016CCBA7805A3A50E221630379BD01135221CAD5D9517C8CC42637B9FC0718E9A9BB4945C72D8D11D3D659D83A3C419509AF5B470DD89B7F3ACCF5F35CFC322115FD66A5CD2875651326F9B3168913BE5B9C87AE0B025EC7A2F4A072750946AC61170A7826D9704C5A23A1C0A2325146C3BC1858826C6B39279C2DA7438A370ED8A0AA5169E3BEC29ED88478732758D454143E227F8595883297842E6AF133B17E4811B0F5713AC73B7E347423EB92822D2306FA14500A7207A0672672046544ACC4EA9C16ED7421A069E0D737A98628519C6A29A424A868B46D9A0CC7C6C9DDD8B8BCBF422C8F48A73143D5ABB66BC55499418430802BAC544463CC7319D17998F29411365766D04C847F3129D9077B7D8339BFB96A6739C3F6B74A8F05F9138AB2FE37ACB57634D1820B50176F5A0B6BC2940F1D5938F1936B5F95828B92EB72973C1590AEB7A552CECA10B00C303B7C75D402071A79E2C810AF7C745E3336712492A42043F2903A37C6434CEE20B1D159B057699FF9C1D3BD68029839A08F43E6C1C819913532F911DD370C7021488E11CB504CB9C70570FFF35B4B4601191DC1AD9E6ADC5FA9618798D7CC860C87A939E4CCF8533632268CF1A51AFF0CB811C5545CB1656E65269477430699CCDEA3800630B78CD5810334CCF02E013F3B80244E70ACDB060BBE7A553B063456B2EA807473413165CE57DD563473CFBC90618ADE1F0B888AA48E722BB2751858FE19687442A48E7CA0D2A29CD51BFD8F78C17B9660BFB54A470B2AE9A955C6AB8D6E5CC92AC8ED3C185DAA8BC29F0578EBB812B97C9E5A848A6384DE4E75A31470B53066A8D027BA44B21749C0492465F9072B28376C4E290B30C1863F9E5B79996083422BD8C272C10ECC6EB9A0A8225B31AA0A66E35B9C0B9A79582BA20A3C04CD29914F083A0158288BA4D6EB62D87264B912BCA39732FBDE536A377AD02B8C835D4A2F4E7B1CE115D0C860BEAA7955A49AD689586A89A2B9F9B10D1595D2FC065AD018A7D56C614471F8E946FE8AB49E8226591119FCADB4F9A861631378736B6688B782D58E97E4572753A9664B6B8536812B25911AA76A242375433192738EEE762F6B84315BB3436231E0A9B277ED28AE0050728346457E13405062DB2804B8DA60BB5C793D4CC0E101CBA2D9182FD7124FF52BF4CA28292AC26D678088953971DBA0B6FEC2C9659353291C70C5B9245A0CA253304AFD3C95102BEA66875C6201680B4BDA38687B648C28EB37478E3BC00CA8A3CC27204642B42B68FCBE7B21A366D0668A5029A7DEEF94CDD6A95D7EA8931673BF7112D4042107B1B8B9700C974F9C4E83A8FACD89BFE0CA3CC4C2FCE80A03D3576C222A792B72B1F070AB7F6B6F2B5CA2AF5054AFA70A896990159B45D1003E2A05648675E596016F1B71DD0F7BDA7E2097FC73B3A143D12C726020AC34958AD7062B92B9ABF3CA6BE5AE29F57135E625A367971837E6363D1532094E022A23467CF932E1F89B5B0803C1EC99B585A78B5865096746F32258214ECB38065C97F455E155ACC2DD005A9C76BED59CDA73837D303504E6C976A606A2BE7BBEC5948B91A349E8936688CC0279754B743ABC58666B19B6C3260051F19206BB962BB6633EB0048E32BAACC5B020D02C86CA9770AD469DB54A106AC73A35B8057422B3DB202C5A5B4E3D535F0FC99326C4B8B7B16F1CB5AF96803FA8C195FC0BCEDDAAF012A51728B76489082373C91E92C87ACCA795160782E3B0DD643544BB96ABC2708D49B759CF057AA223BAFD96A330BAF39810FE8671B4343C297DA1E1969C996216AB5106DA668941B160D4477017136CBCA5B5A8D44C4A8B1CF3EF79785E5AA25C3A1AD6C24FD140F79207DE5A499F8A1534FFA804AA7B3889CBE25C0414704AA57897F17862364ECA56258007248813912B836497F0359C2F7238A05D305A0EA152E72B44417A868134E91B3CA7931232FD4C25F8C2A492A339CDC0A138967211451F2562678FA14080A34436C42B07865AC036A81E97A7787A938025CAF813450368BED0C94B1857604526405D27A1C1ABC81B5B6EC13C71930A97D9232CF7021EF87A4D155328E62B583A83B4AF21F9F5750F8575150424F63B899D71CAD267C09E4467146E16E9B6C653F008C311375E2E006D4076A546B82F5314222F7C654317E79EC6035B73FAF491757E61C828326D53044541C4D4537ABD3EA1E67998C3382974CA78AE1B1960E4A9226B0219AB070F0D7AA66D76F9316ADB80C54D6499771B471E8168D47BCAA08324AB6BA92C3A70275F24FA4DC10E251633FB98D162BB5537202C6A553CE7841C4D40B873B85CA03A0A1E1CFADE6BA5180AB1323CCBA9A3E9C53D37575AB1FD9E7316C6FEECB0A14DF6F2DA56C2F56F55A89635CFCFDA47927AF1F0A47B2D4E4E61634B1B51D37A3A307A972420DE1B7A481B83E583B6AF16F63CB00C6"""), + xeh(""" +C18D7D95DB69D4FE1E6DB385024D83C01F4790E2BFD25DB3F5DD5A208ABE06551BE0936A84091F081308471E82AC9ED6BAA90824D5525701AE0B638003C21D5EBBCBC17FCA8F522BE4F9FE5ECF38BB66131578163D50994E532D0776B187498C5A85AFF617D4550345F3855F968A8964B4F3CACCFFEC82C92BC8617C78C98E10C91AB505A92CEFE0AD6C8B66406AEA4C3FBC5275047B3E983AD42BCD31838A39B92E1C61E9E62443DF3A45044819D9E289B5514D4F74E08FC3914C0B66D2352CF8B1FABB4AC9B0748A43547BECD29D447D01083803D34E8B7EC89B4F0D78B88AEB33E308989BED2D7A78E1C06A11F3BE808F0B9D9712C80D63DA10475849DDF6CB0DBB1007FCDEDCA3C4220386B78D9EC6E380B4F57731D964470B42CF7D4B4E6D98A12A9021121C8BACC4B132A274941DA57D824FCB60B83565F5CE05D140653DD4C70F385B55D485D24935F3631AC63FA12FF50BCF4E431EE4074B2A05A2A97354C7B4169B13EB225F1727F8424F7CA6317A04C355FE785248E67E053C4D4BDBBC47DC7760AC71DFA2502FBAD1180F2B095425198A26BD5A0F7DFAB70524B8F076E7C7F215B0536B0023F8A9F7784809FF4DA245C2EAC5F9E0AB85D987C5B6FEBDB3DF197347BDFB8D5F1547FD2A59D4B434FA7ECF8D8535903D3892868BA0632F194AD6E4D5A3B30E5A6B92F829642DD4A3031358F9F0D9D46530602A35CE455F0E360C14A754828972D85561AA835D87275AC510856D26192EA319FEB45709346929DA5C5919510CB2A482CBB0F1CB4BF6FCC0343F6DBDFDE734919EF335356ABE82F80786EF0CA22E5B03A05963E7051E1FA7EA4BC3141B5746D264BE1A32CCCD39DFF8F9E5E2AB4C5F51CEFEDE3C1CD118351F9A8ED30649D407FD31F6C4BDA3AF44888ADFC3D118BBD04412FF810A7E106EC32F7524E4750DC5F35A9C55541421B5E412E57BAF24622627F02633F524FF854F71011580598C5CE01190258310BB12D7DB5F95E9EBE5F72C97E89287C2F9007A9332EC51DEF1AA2F2CADA9A8A547C3508B4D294364EAFC858B98C60C5469CC7C3CE3ED659B5A54E889FEFAF825FC777AA74A8896C9447704CA7300FC5DF5810681E3ABE083C1285B3B97EFB0E21F78F45409D00B2E1680DA79439734190AFF0D68E062970F8F6B0F1E84A559B09ACD9938913FC26484DF2125FB6D7FC2E3F0DCBD72D9E5DEDBE7E44CE7D895CC9CF6945BDE0C52F92340F9FAD3009BC90D4C2D3DEF7C1F10A862F9D71681537FE4E2716912DAAB8C9DCBD81A083220F68B05F7502F3911B1B6E3B26DA14EF646DCE67852FAB6145BBE7E21725C21CBB2849C63D01AEAD932F8EE9345D8666786AF06AD0C89B08495A6EA95992301E2D8B6A14426971C7B31626BC93BBE76CF3DB9487B5BFC5BAF298F1A92FC3BE276983E53701F9A550E2961E6E2F07317381364719BF3FC741E2A5A0664D8873120D0C11287E92DB12126332D43F35407C01F7F85DF7916B651EE4A30D602E71227733EC9252EC8346361DEFC23397CEAD0C23AF44C77A4C97242C7FA9065BF0C81983AF3E516C1B8FFF3DD5A6C43B6ED5AD8BB3327A09B6B459168F3E497DCB65FE7593E8AB429B8EB2B31F76DF08A6A8F35EC4CA994037493A8C04A73D8191D682542FCBE16E657D3E477A7D25A1D650450E94FAF485CB76FE7110BAA902D74C335FEE1546D076163B5540D8495E16E909E1D28C15BFB421756B921778A784E16207BAD407B64B9CD83AFB0A602374DE06F5C836F4A1ADFD495012DA8D3FA4B829F735B31BAA6364A2AC11BD18E40628DCF82238D86B0B5EE9DF6D179103E1D12F5191475FE3008A5382CC24648CBB24F2298758823B7F93DF10B380C3179F07DC3277021E9EEA2BE5CED646260165B57A18C26E259F83576938828D4C7617623006682CAA613AAB770791874B55E2D0BB32DDB628919B42C09BB7DAE1FBEE8661CC13F8B6A47CF5D6085A2AED796E305738B508599673DCD03AFC267023814FB1DF7EB928D5762BBAB4515921D81C6CAF551DC6EA16C1D31125B99299ADE63FBFB9BC1CE46331394CE472DE6DCEFB2BF9B3828B0110246419C47D2A1FEF16097B943A310C0664A92A155C8273402E83CB94D7E733E4527E7525E9BAB219B69676804C1F67088184038668D55AC4F6E04CEC0EED4B05DE649A9C2064F241AAF9732B09B0EE4E5BB2C0386E45FBD44""") + ), + new DecapsulateTestCase( + xeh(""" +8445C336F3518B298163DCBB6357597983CA2E873DCB49610CF52F14DBCB947C1F3EE9266967276B0C576CF7C30EE6B93DEA5118676CBEE1B1D4794206FB369ABA41167B4393855C84EBA8F32373C05BAE7631C802744AADB6C2DE41250C494315230B52826C34587CB21B183B49B2A5AC04921AC6BFAC1B24A4B37A93A4B168CCE7591BE6111F476260F2762959F5C1640118C2423772E2AD03DC7168A38C6DD39F5F7254264280C8BC10B914168070472FA880ACB8601A8A0837F25FE194687CD68B7DE2340F036DAD891D38D1B0CE9C2633355CF57B50B896036FCA260D2669F85BAC79714FDAFB41EF80B8C30264C31386AE60B05FAA542A26B41EB85F67068F088034FF67AA2E815AAB8BCA6BF71F70ECC3CBCBC45EF701FCD542BD21C7B09568F369C669F396473844FBA14957F51974D852B978014603A210C019036287008994F21255B25099AD82AA132438963B2C0A47CDF5F32BA46B76C7A6559F18BFD555B762E487B6AC992FE20E283CA0B3F6164496955995C3B28A57BBC29826F06FB38B253470AF631BC46C3A8F9CE824321985DD01C05F69B824F916633B40654C75AAEB9385576FFDE2990A6B0A3BE829D6D84E34F1780589C79204C63C798F55D23187E461D48C21E5C047E535B19F458BBA1345B9E41E0CB4A9C2D8C40B490A3BABC553B3026B1672D28CBC8B498A3A99579A832FEAE74610F0B6250CC333E9493EB1621ED34AA4AB175F2CA231152509ACB6AC86B20F6B39108439E5EC12D465A0FEF35003E14277A21812146B2544716D6AB82D1B0726C27A98D589EBDACC4C54BA77B2498F217E14E34E66025A2A143A992520A61C0672CC9CCED7C9450C683E90A3E4651DB623A6DB39AC26125B7FC1986D7B0493B8B72DE7707DC20BBDD43713156AF7D9430EF45399663C2202739168692DD657545B056D9C92385A7F414B34B90C7960D57B35BA7DDE7B81FCA0119D741B12780926018FE4C8030BF038E18B4FA33743D0D3C846417E9D5915C246315938B1E233614501D026959551258B233230D428B181B132F1D0B026067BA816999BC0CD6B547E548B63C9EAA091BAC493DC598DBC2B0E146A2591C2A8C009DD5170AAE027C541A1B5E66E45C65612984C46770493EC896EF25AA9305E9F06692CD0B2F06962E205BEBE113A34EBB1A4830A9B3749641BB935007B23B24BFE576956254D7A35AA496AC446C67A7FEC85A60057E8580617BCB3FAD15C76440FED54CC789394FEA24452CC6B0585B7EB0A88BBA9500D9800E6241AFEB523B55A96A535151D1049573206E59C7FEB070966823634F77D5F1291755A243119621AF8084AB7AC1E22A0568C6201417CBE3655D8A08DD5B513884C98D5A493FD49382EA41860F133CCD601E885966426A2B1F23D42D82E24582D99725192C21777467B1457B1DD429A0C41A5C3D704CEA06278C59941B438C62727097809B4530DBE837EA396B6D31077FAD3733053989A8442AAC4255CB163B8CA2F27501EA967305695ABD659AA02C83EE60BB574203E9937AE1C621C8ECB5CC1D21D556960B5B9161EA96FFFEBAC72E1B8A6154FC4D88B56C04741F090CBB156A737C9E6A22BA8AC704BC304F8E17E5EA845FDE59FBF788CCE0B97C8761F89A242F3052583C6844A632031C964A6C4A85A128A28619BA1BB3D1BEA4B49841FC847614A066841F52ED0EB8AE0B8B096E92B8195405815B231266F36B18C1A53333DAB95D2A9A374B5478A4A41FB8759957C9AB22CAE545AB544BA8DD05B83F3A613A2437ADB073A9635CB4BBC965FB454CF27B298A40CD0DA3B8F9CA99D8CB4286C5EB476416796070BA535AAA58CDB451CD6DB5CBB0CA20F0C71DE97C30DA97EC7906D06B4B939396028C46BA0E7A865BC8308A3810F1212006339F7BC169B1666FDF475911BBC8AAAB41755C9A8AABFA23C0E37F84FE46999E030494B9298EF9934E8A649C0A5CCE2B22F31809AFED23955D87881D99FC1D352896CAC9055BEA0D016CCBA7805A3A50E221630379BD01135221CAD5D9517C8CC42637B9FC0718E9A9BB4945C72D8D11D3D659D83A3C419509AF5B470DD89B7F3ACCF5F35CFC322115FD66A5CD2875651326F9B3168913BE5B9C87AE0B025EC7A2F4A072750946AC61170A7826D9704C5A23A1C0A2325146C3BC1858826C6B39279C2DA7438A370ED8A0AA5169E3BEC29ED88478732758D454143E227F8595883297842E6AF133B17E4811B0F5713AC73B7E347423EB92822D2306FA14500A7207A0672672046544ACC4EA9C16ED7421A069E0D737A98628519C6A29A424A868B46D9A0CC7C6C9DDD8B8BCBF422C8F48A73143D5ABB66BC55499418430802BAC544463CC7319D17998F29411365766D04C847F3129D9077B7D8339BFB96A6739C3F6B74A8F05F9138AB2FE37ACB57634D1820B50176F5A0B6BC2940F1D5938F1936B5F95828B92EB72973C1590AEB7A552CECA10B00C303B7C75D402071A79E2C810AF7C745E3336712492A42043F2903A37C6434CEE20B1D159B057699FF9C1D3BD68029839A08F43E6C1C819913532F911DD370C7021488E11CB504CB9C70570FFF35B4B4601191DC1AD9E6ADC5FA9618798D7CC860C87A939E4CCF8533632268CF1A51AFF0CB811C5545CB1656E65269477430699CCDEA3800630B78CD5810334CCF02E013F3B80244E70ACDB060BBE7A553B063456B2EA807473413165CE57DD563473CFBC90618ADE1F0B888AA48E722BB2751858FE19687442A48E7CA0D2A29CD51BFD8F78C17B9660BFB54A470B2AE9A955C6AB8D6E5CC92AC8ED3C185DAA8BC29F0578EBB812B97C9E5A848A6384DE4E75A31470B53066A8D027BA44B21749C0492465F9072B28376C4E290B30C1863F9E5B79996083422BD8C272C10ECC6EB9A0A8225B31AA0A66E35B9C0B9A79582BA20A3C04CD29914F083A0158288BA4D6EB62D87264B912BCA39732FBDE536A377AD02B8C835D4A2F4E7B1CE115D0C860BEAA7955A49AD689586A89A2B9F9B10D1595D2FC065AD018A7D56C614471F8E946FE8AB49E8226591119FCADB4F9A861631378736B6688B782D58E97E4572753A9664B6B8536812B25911AA76A242375433192738EEE762F6B84315BB3436231E0A9B277ED28AE0050728346457E13405062DB2804B8DA60BB5C793D4CC0E101CBA2D9182FD7124FF52BF4CA28292AC26D678088953971DBA0B6FEC2C9659353291C70C5B9245A0CA253304AFD3C95102BEA66875C6201680B4BDA38687B648C28EB37478E3BC00CA8A3CC27204642B42B68FCBE7B21A366D0668A5029A7DEEF94CDD6A95D7EA8931673BF7112D4042107B1B8B9700C974F9C4E83A8FACD89BFE0CA3CC4C2FCE80A03D3576C222A792B72B1F070AB7F6B6F2B5CA2AF5054AFA70A896990159B45D1003E2A05648675E596016F1B71DD0F7BDA7E2097FC73B3A143D12C726020AC34958AD7062B92B9ABF3CA6BE5AE29F57135E625A367971837E6363D1532094E022A23467CF932E1F89B5B0803C1EC99B585A78B5865096746F32258214ECB38065C97F455E155ACC2DD005A9C76BED59CDA73837D303504E6C976A606A2BE7BBEC5948B91A349E8936688CC0279754B743ABC58666B19B6C3260051F19206BB962BB6633EB0048E32BAACC5B020D02C86CA9770AD469DB54A106AC73A35B8057422B3DB202C5A5B4E3D535F0FC99326C4B8B7B16F1CB5AF96803FA8C195FC0BCEDDAAF012A51728B76489082373C91E92C87ACCA795160782E3B0DD643544BB96ABC2708D49B759CF057AA223BAFD96A330BAF39810FE8671B4343C297DA1E1969C996216AB5106DA668941B160D4477017136CBCA5B5A8D44C4A8B1CF3EF79785E5AA25C3A1AD6C24FD140F79207DE5A499F8A1534FFA804AA7B3889CBE25C0414704AA57897F17862364ECA56258007248813912B836497F0359C2F7238A05D305A0EA152E72B44417A868134E91B3CA7931232FD4C25F8C2A492A339CDC0A138967211451F2562678FA14080A34436C42B07865AC036A81E97A7787A938025CAF813450368BED0C94B1857604526405D27A1C1ABC81B5B6EC13C71930A97D9232CF7021EF87A4D155328E62B583A83B4AF21F9F5750F8575150424F63B899D71CAD267C09E4467146E16E9B6C653F008C311375E2E006D4076A546B82F5314222F7C654317E79EC6035B73FAF491757E61C828326D53044541C4D4537ABD3EA1E67998C3382974CA78AE1B1960E4A9226B0219AB070F0D7AA66D76F9316ADB80C54D6499771B471E8168D47BCAA08324AB6BA92C3A70275F24FA4DC10E251633FB98D162BB5537202C6A553CE7841C4D40B873B85CA03A0A1E1CFADE6BA5180AB1323CCBA9A3E9C53D37575AB1FD9E7316C6FEECB0A14DF6F2DA56C2F56F55A89635CFCFDA47927AF1F0A47B2D4E4E61634B1B51D37A3A307A972420DE1B7A481B83E583B6AF16F63CB00C6"""), + xeh(""" +E7B361D043C4A0B3A780121E9648DCF38DFC10ED5E47EE4DB5523C1EE1F53552640C89D9D7EFB9DFAA8EBAC7AF137A850AE41A0FF8F8CE31FDFD3E671555180EE46AB58322FE4E5F525146F9D4CDD1D1CA01413C5AC7259E1A2604A5951755F47D1761ED16B26D3DCFF79A263BC38852007BD3F381FC3B79B46A4B372918AF3117180726117BDB33C063BF5EE5D69CB48D267929CEDC890B743DEA43205EAD46FFA69D9B30C1AA5F146CBA3B0B7C4D4A50FA8D120777F1661430DA1B9D1C1DB4E10C5C3C2436D381EB13DDCC61EEB3F9AB46B60D2FB714929139E9C27F8730684EE17B077BDC003500027FAC94DA80870B382EFE41BAAD902A491C29DC95A8F80BB075A4E61C8F100FA738BED869B48F897ABC9CCE08917B5073229A94F3790947FC1AB6C2DEB5B012D60EC156A8A041DE151EED8884EC616089CB08EAEE37C006F5BBD10ACE9596A34FB09345A14FC4EA674E4A74699BA5240FF1282ED1E64360BDC9F7336051A33DD48809CF0011BEB3CE8C681588AB29F5F26175A8A6FD7884CB96CE3964FF10A67FC4A4E14CA516162C16D8127CBC45BCF7C88C89C8602032298B53C19FD099809814BE0504BCFD2407F48F2F24C5ACB89DB4F54A018DD586D871C58CC0D998FB4B0E5F5DAC631BE8367DDE88ED711F069FC8A80EBB573A7DA12AD8F13A4CA1E8A22D9EB53C55B80F700C58E6EADE6CDEB35C262EB42C903AD854F843547B79464524833A05E3FDC46092E41D8E339E7662D1209D338B8A02994D15A10439C1DC02A5B0EDEA58AF197866F43269A57C747DF389EC597F523211770E9C7E4CEFC5E43EEF791897EE43CA6146F3F757B66B9E7592E728565325D1740A1736CD0E678BBAA043F4C355FDE27094F74FAE27AD8C270930DF637C652BC1957F958DB013C146F2A4C5F451AB58A55C2B638A82755C11991B049E82F8D3CD3E7D3571FD5A83B60280E92031B610FADAC9E5F61DA469DC4C51381C970E03F09CA560E5D69D9B32AD6C1DDB6FBE9F8FC0551A909187AD65AFDC067EC6AA01AD684AE4C4F2E1F64046083D3EB347A6B6B23BBBF14668B9650D9364A6A7666593DB86FEB59628A91169F8AE24F67680789D316338B2F27766A83957831D98C88C837215AE3BD49767ADCADE758320ACE76D7F39E2970EDD19657F0EC12583164C325F0A000D065036BA2522F960C87F9852F30BC6BB5419CD8C0A1F9757BD358E748CB244A5E677AB9F9319A43A9BAC847A566052CA42C1C1DB36A0D97F144BED3BC5F11A5C8BEF7A74A4CC67748F1DF53F8B4714E0A04256B36A814B08B78A9737757E3F1347F9E5535DF1AC98B08ACC1409278B925F3B6C7863BC0969520FC6183E216B4E8E449B0FB999F1C65567AE2064774454EFDA67E1749FB24A91B55DFFE7DB75C4E24E8EF2389214EC3E95972CD53234CDAF8958D651A7A95802E65499A8A7811A65ABBA90129D5EC4247D8183316EF818E79BE839BB3379E4B8F4EE9438BFE310105C91F8703AE94D8F9D53096E2341E74E0237DB2665F16954B9713DD9638B05970A9A96261586B04F9FF369028DCC43D35B51F95E69B0323A1CEACC4A5E2EF640CDAF3407BF5F5E14C9042FF299786BC55965EB7C8BB161487FCD7911BDC2FBB65100F2200E16C690F801EA6615F9130EB99DF816B188B06E9A3105B78212B76609DF190FF102CCC451746CBAD16464E8E2F647B75777F664DE86F5089C37E3A54A6AA8B456CB98B42DEB5529C06DA45C2D2A13060BE56A061CE210ECD307FF5AD5BE39CDD8D27B4A3403323D4F53BE35FB4E31670F73CCE74CF73CFBB29A5FC2EECB5F852CA911942066D826404B77251BE5BC5980D0A6E0DB4D753D86490D4250536DACF05D82064A28324B49AD4AD202CD0FC939BB7A3CD9FB1E3E196348EF336DCDBE4BC831DF5847070D0B2BE1C4910FE1C69F58C6A7A2E7FEBD51BE1D0E050D5D721D7537A0325E7ED30AECA75A2A81BBD86EBF91CAFE4483D2729271ABDBB65C2CD9973627D2820DC7ADE3E26CA2F466EB117B2BA98EC868DC728ABC6907D49E2495504133FAA7F8758FD23076D1A65A91C75512F89EE4E2F3E480D6ECB0EE90793F4F93FFB75DF58A7072C91D5A1D9EF0C3B1DDAE79EF576E6A276F78CDC24664897F07B3A20691601EAD2F499C50589BDBCEC74FCADED1A8AFDFC061C2712ED599D48A3ACB3D86515D664D0CF3FA349A1910CB""") + ), + new DecapsulateTestCase( + xeh(""" +8445C336F3518B298163DCBB6357597983CA2E873DCB49610CF52F14DBCB947C1F3EE9266967276B0C576CF7C30EE6B93DEA5118676CBEE1B1D4794206FB369ABA41167B4393855C84EBA8F32373C05BAE7631C802744AADB6C2DE41250C494315230B52826C34587CB21B183B49B2A5AC04921AC6BFAC1B24A4B37A93A4B168CCE7591BE6111F476260F2762959F5C1640118C2423772E2AD03DC7168A38C6DD39F5F7254264280C8BC10B914168070472FA880ACB8601A8A0837F25FE194687CD68B7DE2340F036DAD891D38D1B0CE9C2633355CF57B50B896036FCA260D2669F85BAC79714FDAFB41EF80B8C30264C31386AE60B05FAA542A26B41EB85F67068F088034FF67AA2E815AAB8BCA6BF71F70ECC3CBCBC45EF701FCD542BD21C7B09568F369C669F396473844FBA14957F51974D852B978014603A210C019036287008994F21255B25099AD82AA132438963B2C0A47CDF5F32BA46B76C7A6559F18BFD555B762E487B6AC992FE20E283CA0B3F6164496955995C3B28A57BBC29826F06FB38B253470AF631BC46C3A8F9CE824321985DD01C05F69B824F916633B40654C75AAEB9385576FFDE2990A6B0A3BE829D6D84E34F1780589C79204C63C798F55D23187E461D48C21E5C047E535B19F458BBA1345B9E41E0CB4A9C2D8C40B490A3BABC553B3026B1672D28CBC8B498A3A99579A832FEAE74610F0B6250CC333E9493EB1621ED34AA4AB175F2CA231152509ACB6AC86B20F6B39108439E5EC12D465A0FEF35003E14277A21812146B2544716D6AB82D1B0726C27A98D589EBDACC4C54BA77B2498F217E14E34E66025A2A143A992520A61C0672CC9CCED7C9450C683E90A3E4651DB623A6DB39AC26125B7FC1986D7B0493B8B72DE7707DC20BBDD43713156AF7D9430EF45399663C2202739168692DD657545B056D9C92385A7F414B34B90C7960D57B35BA7DDE7B81FCA0119D741B12780926018FE4C8030BF038E18B4FA33743D0D3C846417E9D5915C246315938B1E233614501D026959551258B233230D428B181B132F1D0B026067BA816999BC0CD6B547E548B63C9EAA091BAC493DC598DBC2B0E146A2591C2A8C009DD5170AAE027C541A1B5E66E45C65612984C46770493EC896EF25AA9305E9F06692CD0B2F06962E205BEBE113A34EBB1A4830A9B3749641BB935007B23B24BFE576956254D7A35AA496AC446C67A7FEC85A60057E8580617BCB3FAD15C76440FED54CC789394FEA24452CC6B0585B7EB0A88BBA9500D9800E6241AFEB523B55A96A535151D1049573206E59C7FEB070966823634F77D5F1291755A243119621AF8084AB7AC1E22A0568C6201417CBE3655D8A08DD5B513884C98D5A493FD49382EA41860F133CCD601E885966426A2B1F23D42D82E24582D99725192C21777467B1457B1DD429A0C41A5C3D704CEA06278C59941B438C62727097809B4530DBE837EA396B6D31077FAD3733053989A8442AAC4255CB163B8CA2F27501EA967305695ABD659AA02C83EE60BB574203E9937AE1C621C8ECB5CC1D21D556960B5B9161EA96FFFEBAC72E1B8A6154FC4D88B56C04741F090CBB156A737C9E6A22BA8AC704BC304F8E17E5EA845FDE59FBF788CCE0B97C8761F89A242F3052583C6844A632031C964A6C4A85A128A28619BA1BB3D1BEA4B49841FC847614A066841F52ED0EB8AE0B8B096E92B8195405815B231266F36B18C1A53333DAB95D2A9A374B5478A4A41FB8759957C9AB22CAE545AB544BA8DD05B83F3A613A2437ADB073A9635CB4BBC965FB454CF27B298A40CD0DA3B8F9CA99D8CB4286C5EB476416796070BA535AAA58CDB451CD6DB5CBB0CA20F0C71DE97C30DA97EC7906D06B4B939396028C46BA0E7A865BC8308A3810F1212006339F7BC169B1666FDF475911BBC8AAAB41755C9A8AABFA23C0E37F84FE46999E030494B9298EF9934E8A649C0A5CCE2B22F31809AFED23955D87881D99FC1D352896CAC9055BEA0D016CCBA7805A3A50E221630379BD01135221CAD5D9517C8CC42637B9FC0718E9A9BB4945C72D8D11D3D659D83A3C419509AF5B470DD89B7F3ACCF5F35CFC322115FD66A5CD2875651326F9B3168913BE5B9C87AE0B025EC7A2F4A072750946AC61170A7826D9704C5A23A1C0A2325146C3BC1858826C6B39279C2DA7438A370ED8A0AA5169E3BEC29ED88478732758D454143E227F8595883297842E6AF133B17E4811B0F5713AC73B7E347423EB92822D2306FA14500A7207A0672672046544ACC4EA9C16ED7421A069E0D737A98628519C6A29A424A868B46D9A0CC7C6C9DDD8B8BCBF422C8F48A73143D5ABB66BC55499418430802BAC544463CC7319D17998F29411365766D04C847F3129D9077B7D8339BFB96A6739C3F6B74A8F05F9138AB2FE37ACB57634D1820B50176F5A0B6BC2940F1D5938F1936B5F95828B92EB72973C1590AEB7A552CECA10B00C303B7C75D402071A79E2C810AF7C745E3336712492A42043F2903A37C6434CEE20B1D159B057699FF9C1D3BD68029839A08F43E6C1C819913532F911DD370C7021488E11CB504CB9C70570FFF35B4B4601191DC1AD9E6ADC5FA9618798D7CC860C87A939E4CCF8533632268CF1A51AFF0CB811C5545CB1656E65269477430699CCDEA3800630B78CD5810334CCF02E013F3B80244E70ACDB060BBE7A553B063456B2EA807473413165CE57DD563473CFBC90618ADE1F0B888AA48E722BB2751858FE19687442A48E7CA0D2A29CD51BFD8F78C17B9660BFB54A470B2AE9A955C6AB8D6E5CC92AC8ED3C185DAA8BC29F0578EBB812B97C9E5A848A6384DE4E75A31470B53066A8D027BA44B21749C0492465F9072B28376C4E290B30C1863F9E5B79996083422BD8C272C10ECC6EB9A0A8225B31AA0A66E35B9C0B9A79582BA20A3C04CD29914F083A0158288BA4D6EB62D87264B912BCA39732FBDE536A377AD02B8C835D4A2F4E7B1CE115D0C860BEAA7955A49AD689586A89A2B9F9B10D1595D2FC065AD018A7D56C614471F8E946FE8AB49E8226591119FCADB4F9A861631378736B6688B782D58E97E4572753A9664B6B8536812B25911AA76A242375433192738EEE762F6B84315BB3436231E0A9B277ED28AE0050728346457E13405062DB2804B8DA60BB5C793D4CC0E101CBA2D9182FD7124FF52BF4CA28292AC26D678088953971DBA0B6FEC2C9659353291C70C5B9245A0CA253304AFD3C95102BEA66875C6201680B4BDA38687B648C28EB37478E3BC00CA8A3CC27204642B42B68FCBE7B21A366D0668A5029A7DEEF94CDD6A95D7EA8931673BF7112D4042107B1B8B9700C974F9C4E83A8FACD89BFE0CA3CC4C2FCE80A03D3576C222A792B72B1F070AB7F6B6F2B5CA2AF5054AFA70A896990159B45D1003E2A05648675E596016F1B71DD0F7BDA7E2097FC73B3A143D12C726020AC34958AD7062B92B9ABF3CA6BE5AE29F57135E625A367971837E6363D1532094E022A23467CF932E1F89B5B0803C1EC99B585A78B5865096746F32258214ECB38065C97F455E155ACC2DD005A9C76BED59CDA73837D303504E6C976A606A2BE7BBEC5948B91A349E8936688CC0279754B743ABC58666B19B6C3260051F19206BB962BB6633EB0048E32BAACC5B020D02C86CA9770AD469DB54A106AC73A35B8057422B3DB202C5A5B4E3D535F0FC99326C4B8B7B16F1CB5AF96803FA8C195FC0BCEDDAAF012A51728B76489082373C91E92C87ACCA795160782E3B0DD643544BB96ABC2708D49B759CF057AA223BAFD96A330BAF39810FE8671B4343C297DA1E1969C996216AB5106DA668941B160D4477017136CBCA5B5A8D44C4A8B1CF3EF79785E5AA25C3A1AD6C24FD140F79207DE5A499F8A1534FFA804AA7B3889CBE25C0414704AA57897F17862364ECA56258007248813912B836497F0359C2F7238A05D305A0EA152E72B44417A868134E91B3CA7931232FD4C25F8C2A492A339CDC0A138967211451F2562678FA14080A34436C42B07865AC036A81E97A7787A938025CAF813450368BED0C94B1857604526405D27A1C1ABC81B5B6EC13C71930A97D9232CF7021EF87A4D155328E62B583A83B4AF21F9F5750F8575150424F63B899D71CAD267C09E4467146E16E9B6C653F008C311375E2E006D4076A546B82F5314222F7C654317E79EC6035B73FAF491757E61C828326D53044541C4D4537ABD3EA1E67998C3382974CA78AE1B1960E4A9226B0219AB070F0D7AA66D76F9316ADB80C54D6499771B471E8168D47BCAA08324AB6BA92C3A70275F24FA4DC10E251633FB98D162BB5537202C6A553CE7841C4D40B873B85CA03A0A1E1CFADE6BA5180AB1323CCBA9A3E9C53D37575AB1FD9E7316C6FEECB0A14DF6F2DA56C2F56F55A89635CFCFDA47927AF1F0A47B2D4E4E61634B1B51D37A3A307A972420DE1B7A481B83E583B6AF16F63CB00C6"""), + xeh(""" +EDD3FAB8AEB1240FB31B836CD1603E1F904BD1F87318DCB02A7DE18B4044385CDB51E343787E583CB043EE23899658420F9DEDB23CAB2BCD1013F573C0C7978521596631F6590105CB7B281AB1591B7056BE068DF838E0B1679F3B88D95208EF4B3019625EEA7704CE79F33AF339AB883B0C48B3C4413921F43AF2515A85023B5D98D06E619238C8D033FB7DD19611CC60CF395A03B0681913B299531B13728B278D353FA093C633710B65000772DD6D7CA59C85DB62196DCCE1B75559ECD3FB42DDD8E57EB4CF3B4E35B57EA3D6063221B81F1B802DD7D76DE308CB0A738C3B5833E9F4427AF3C3D79B521E7E665B052B9A365DCDFE5A688B06EDCDFA2143C938F852E32D6B49808CFFD01A8655B767034F8C638E8AF94BF3EB9EA39AED1D2D22E181888DD608BF9392FD73822303A41996F41D51A924FA6EF76A9C82709A21BEF1DD004693EC9468B335F9BD1FD94D5E6D89D570FC6D23B7F5CAD2975F418B8C4A0EB82EA2A3C979B1C15B0FB0A23F844764DDD49A8B89C0D4BC8C311BB43725EE9BAACC4796F58C0F1180A4F6AFEF45178659B35A74FF34A8E93A64FA4CD003269EC67C5BD528E015B2311B5E2D33472638CD65FC7D5127335EDA862BDEA05F4290EF9B370BE69DC89E7D71DD2522E669700D5D02D8DCD75FE2AD9EDC307225D61C7805CE1EBBC806A08BD360F86FD27B599582B22C57DDE77B08F7537482FB5D75BDB9F3F4EA07DFB0711C25AD1950058EAAA2E17D8F676BE6B72B1687383D8E0DD60A8277F6FDA202D6F8957EE21308AE81ABF72A89924DB44238B262D2FCE733E12E5413C31FDEF94860D5BB0FB0AEDCB1EFA8F87CCC76189FA5D8157FB4FB14652DC188157B2B746B596FE6F2FEB197DE139B80922C2EC14B58E743E3335893ABF85B99BC4566FA1BEED449658C5993CD08BF78F7DBFF808F611D6EB8F0BD7977E854BC195D711C03EA532403547B6ABEAE827481BB5D53C867710215835260097B6CA730FC722A74E230434B08F38EB1ABAF555CD4CC6CB9310E32F93E0ACAC1E915A4B57E0774B013BE7DD435B5C6AF6018944349841F84E8C28260149F266C99FC05E0DB8D5A63DE362CDE45F5BDFB6F30D55A84ACA22E8640A1287DA51714F2C8D4B184A5F671E0E907134E34D875C9A4709ECE3B7FE15713A0DD972505298C18A9D35956149EC9AF45C475016D7C8B5CBFFE2108882B86FFD380A79892BA1909489E016CF9933705E2FA72ACC8569501553401C397648DC47948935C0197D6F162464DE42BA537611CCB67A988030ABF6081946FDD1ED8C6B23691EA160E8543735894839F13C270B3E1F68607A7EECE09AF06A34F4FC9096D4EFFE4905BE56F3EB397C13472F6621F3EE45A59C8001ABF9302E036BEDEB2E0EC92A03FFE0DF52262621728C6791C4E7D8C226D17A04B6E7EB2FF8586585D639B449C85224EEC67E30537ABE85C8F7E2306DB80E968D8585CED3A9E21622BBC38D43A7D79E2457C67307CC208064D3568C476ED79359CD0A4B0BECA02FA702661056E187A51C2D154638F9000DF856ABB82CFE12C47543E46FFDBADD2DC69EBB3FF444E7E1E95235541015E6CC7A0429C82EBD6942C6420AD598C08080DCEC800509C142ED5A642951F491E748B5436148B90ACCBEC35D0D85FAF4E472ED3F1A089113808D3ECDF77EEF3E089FA5A1635B90EF99034AAA49D4D13058EAA5A8797E37C59CEB86C7CCFE1F574E1086DB9BE744BDE5067AD5D6C450FADFF2338DB110736FBBD86B41B29C29D3899CE60E9BEDF775416541350AAA9BD9B5D57573C542375BB0297912863C86AAE39D153CCB29F1811CDE58978951CE8EEFA6F9D10121AD1FB89F02AF8E96AC08DD10E3274E8CA79D910667166797468D3D3BD6D7EF5F2C6FC4F110268A2716CB273F29BBC347050BD98BDD88F30A96E7A9E840A55087F42A09B03D04E612640BA4D86BE87DA6D20ED0ECCCA2523EE7C4E9D2A96E7378BF71308850832769417EB6250FC768B0EDF92FD45216A235435A3E32AE5B22BF913027D81B0D5508D2AF88120A50206DD7837B79C45B21DB4FE59D23F4AB051BF012B13F6EE5B34C83C8D8CC9BB35266D0EF3834F52CE6CC5BCB7C5989198465A9E9DEE1A1F262FAB26FE0D0964E624869DF2607858815418F85A1F503BE5217794CED29D02E19D40C4BC8E65C46FE3815C1E548976649D4332B1841EA03022""") + ), + new DecapsulateTestCase( + xeh(""" +8445C336F3518B298163DCBB6357597983CA2E873DCB49610CF52F14DBCB947C1F3EE9266967276B0C576CF7C30EE6B93DEA5118676CBEE1B1D4794206FB369ABA41167B4393855C84EBA8F32373C05BAE7631C802744AADB6C2DE41250C494315230B52826C34587CB21B183B49B2A5AC04921AC6BFAC1B24A4B37A93A4B168CCE7591BE6111F476260F2762959F5C1640118C2423772E2AD03DC7168A38C6DD39F5F7254264280C8BC10B914168070472FA880ACB8601A8A0837F25FE194687CD68B7DE2340F036DAD891D38D1B0CE9C2633355CF57B50B896036FCA260D2669F85BAC79714FDAFB41EF80B8C30264C31386AE60B05FAA542A26B41EB85F67068F088034FF67AA2E815AAB8BCA6BF71F70ECC3CBCBC45EF701FCD542BD21C7B09568F369C669F396473844FBA14957F51974D852B978014603A210C019036287008994F21255B25099AD82AA132438963B2C0A47CDF5F32BA46B76C7A6559F18BFD555B762E487B6AC992FE20E283CA0B3F6164496955995C3B28A57BBC29826F06FB38B253470AF631BC46C3A8F9CE824321985DD01C05F69B824F916633B40654C75AAEB9385576FFDE2990A6B0A3BE829D6D84E34F1780589C79204C63C798F55D23187E461D48C21E5C047E535B19F458BBA1345B9E41E0CB4A9C2D8C40B490A3BABC553B3026B1672D28CBC8B498A3A99579A832FEAE74610F0B6250CC333E9493EB1621ED34AA4AB175F2CA231152509ACB6AC86B20F6B39108439E5EC12D465A0FEF35003E14277A21812146B2544716D6AB82D1B0726C27A98D589EBDACC4C54BA77B2498F217E14E34E66025A2A143A992520A61C0672CC9CCED7C9450C683E90A3E4651DB623A6DB39AC26125B7FC1986D7B0493B8B72DE7707DC20BBDD43713156AF7D9430EF45399663C2202739168692DD657545B056D9C92385A7F414B34B90C7960D57B35BA7DDE7B81FCA0119D741B12780926018FE4C8030BF038E18B4FA33743D0D3C846417E9D5915C246315938B1E233614501D026959551258B233230D428B181B132F1D0B026067BA816999BC0CD6B547E548B63C9EAA091BAC493DC598DBC2B0E146A2591C2A8C009DD5170AAE027C541A1B5E66E45C65612984C46770493EC896EF25AA9305E9F06692CD0B2F06962E205BEBE113A34EBB1A4830A9B3749641BB935007B23B24BFE576956254D7A35AA496AC446C67A7FEC85A60057E8580617BCB3FAD15C76440FED54CC789394FEA24452CC6B0585B7EB0A88BBA9500D9800E6241AFEB523B55A96A535151D1049573206E59C7FEB070966823634F77D5F1291755A243119621AF8084AB7AC1E22A0568C6201417CBE3655D8A08DD5B513884C98D5A493FD49382EA41860F133CCD601E885966426A2B1F23D42D82E24582D99725192C21777467B1457B1DD429A0C41A5C3D704CEA06278C59941B438C62727097809B4530DBE837EA396B6D31077FAD3733053989A8442AAC4255CB163B8CA2F27501EA967305695ABD659AA02C83EE60BB574203E9937AE1C621C8ECB5CC1D21D556960B5B9161EA96FFFEBAC72E1B8A6154FC4D88B56C04741F090CBB156A737C9E6A22BA8AC704BC304F8E17E5EA845FDE59FBF788CCE0B97C8761F89A242F3052583C6844A632031C964A6C4A85A128A28619BA1BB3D1BEA4B49841FC847614A066841F52ED0EB8AE0B8B096E92B8195405815B231266F36B18C1A53333DAB95D2A9A374B5478A4A41FB8759957C9AB22CAE545AB544BA8DD05B83F3A613A2437ADB073A9635CB4BBC965FB454CF27B298A40CD0DA3B8F9CA99D8CB4286C5EB476416796070BA535AAA58CDB451CD6DB5CBB0CA20F0C71DE97C30DA97EC7906D06B4B939396028C46BA0E7A865BC8308A3810F1212006339F7BC169B1666FDF475911BBC8AAAB41755C9A8AABFA23C0E37F84FE46999E030494B9298EF9934E8A649C0A5CCE2B22F31809AFED23955D87881D99FC1D352896CAC9055BEA0D016CCBA7805A3A50E221630379BD01135221CAD5D9517C8CC42637B9FC0718E9A9BB4945C72D8D11D3D659D83A3C419509AF5B470DD89B7F3ACCF5F35CFC322115FD66A5CD2875651326F9B3168913BE5B9C87AE0B025EC7A2F4A072750946AC61170A7826D9704C5A23A1C0A2325146C3BC1858826C6B39279C2DA7438A370ED8A0AA5169E3BEC29ED88478732758D454143E227F8595883297842E6AF133B17E4811B0F5713AC73B7E347423EB92822D2306FA14500A7207A0672672046544ACC4EA9C16ED7421A069E0D737A98628519C6A29A424A868B46D9A0CC7C6C9DDD8B8BCBF422C8F48A73143D5ABB66BC55499418430802BAC544463CC7319D17998F29411365766D04C847F3129D9077B7D8339BFB96A6739C3F6B74A8F05F9138AB2FE37ACB57634D1820B50176F5A0B6BC2940F1D5938F1936B5F95828B92EB72973C1590AEB7A552CECA10B00C303B7C75D402071A79E2C810AF7C745E3336712492A42043F2903A37C6434CEE20B1D159B057699FF9C1D3BD68029839A08F43E6C1C819913532F911DD370C7021488E11CB504CB9C70570FFF35B4B4601191DC1AD9E6ADC5FA9618798D7CC860C87A939E4CCF8533632268CF1A51AFF0CB811C5545CB1656E65269477430699CCDEA3800630B78CD5810334CCF02E013F3B80244E70ACDB060BBE7A553B063456B2EA807473413165CE57DD563473CFBC90618ADE1F0B888AA48E722BB2751858FE19687442A48E7CA0D2A29CD51BFD8F78C17B9660BFB54A470B2AE9A955C6AB8D6E5CC92AC8ED3C185DAA8BC29F0578EBB812B97C9E5A848A6384DE4E75A31470B53066A8D027BA44B21749C0492465F9072B28376C4E290B30C1863F9E5B79996083422BD8C272C10ECC6EB9A0A8225B31AA0A66E35B9C0B9A79582BA20A3C04CD29914F083A0158288BA4D6EB62D87264B912BCA39732FBDE536A377AD02B8C835D4A2F4E7B1CE115D0C860BEAA7955A49AD689586A89A2B9F9B10D1595D2FC065AD018A7D56C614471F8E946FE8AB49E8226591119FCADB4F9A861631378736B6688B782D58E97E4572753A9664B6B8536812B25911AA76A242375433192738EEE762F6B84315BB3436231E0A9B277ED28AE0050728346457E13405062DB2804B8DA60BB5C793D4CC0E101CBA2D9182FD7124FF52BF4CA28292AC26D678088953971DBA0B6FEC2C9659353291C70C5B9245A0CA253304AFD3C95102BEA66875C6201680B4BDA38687B648C28EB37478E3BC00CA8A3CC27204642B42B68FCBE7B21A366D0668A5029A7DEEF94CDD6A95D7EA8931673BF7112D4042107B1B8B9700C974F9C4E83A8FACD89BFE0CA3CC4C2FCE80A03D3576C222A792B72B1F070AB7F6B6F2B5CA2AF5054AFA70A896990159B45D1003E2A05648675E596016F1B71DD0F7BDA7E2097FC73B3A143D12C726020AC34958AD7062B92B9ABF3CA6BE5AE29F57135E625A367971837E6363D1532094E022A23467CF932E1F89B5B0803C1EC99B585A78B5865096746F32258214ECB38065C97F455E155ACC2DD005A9C76BED59CDA73837D303504E6C976A606A2BE7BBEC5948B91A349E8936688CC0279754B743ABC58666B19B6C3260051F19206BB962BB6633EB0048E32BAACC5B020D02C86CA9770AD469DB54A106AC73A35B8057422B3DB202C5A5B4E3D535F0FC99326C4B8B7B16F1CB5AF96803FA8C195FC0BCEDDAAF012A51728B76489082373C91E92C87ACCA795160782E3B0DD643544BB96ABC2708D49B759CF057AA223BAFD96A330BAF39810FE8671B4343C297DA1E1969C996216AB5106DA668941B160D4477017136CBCA5B5A8D44C4A8B1CF3EF79785E5AA25C3A1AD6C24FD140F79207DE5A499F8A1534FFA804AA7B3889CBE25C0414704AA57897F17862364ECA56258007248813912B836497F0359C2F7238A05D305A0EA152E72B44417A868134E91B3CA7931232FD4C25F8C2A492A339CDC0A138967211451F2562678FA14080A34436C42B07865AC036A81E97A7787A938025CAF813450368BED0C94B1857604526405D27A1C1ABC81B5B6EC13C71930A97D9232CF7021EF87A4D155328E62B583A83B4AF21F9F5750F8575150424F63B899D71CAD267C09E4467146E16E9B6C653F008C311375E2E006D4076A546B82F5314222F7C654317E79EC6035B73FAF491757E61C828326D53044541C4D4537ABD3EA1E67998C3382974CA78AE1B1960E4A9226B0219AB070F0D7AA66D76F9316ADB80C54D6499771B471E8168D47BCAA08324AB6BA92C3A70275F24FA4DC10E251633FB98D162BB5537202C6A553CE7841C4D40B873B85CA03A0A1E1CFADE6BA5180AB1323CCBA9A3E9C53D37575AB1FD9E7316C6FEECB0A14DF6F2DA56C2F56F55A89635CFCFDA47927AF1F0A47B2D4E4E61634B1B51D37A3A307A972420DE1B7A481B83E583B6AF16F63CB00C6"""), + xeh(""" +C72FA15560FEE6B014E73F5F93C307F74EF9C49AA8F7DF578C002AF20419040D6AB6AC46F78FB03F56A9C5C95902D8CBCE34D79853EDF0C319AF5469E32D0B9FC3C41628970E0B3A6C408B509C74DFA218BD23FA7A11DEA2D2277B3522BEF6606E3415D0DD51556440CC1AF59CAE6F23368BCAC3E1509503368354D1E3EC9E91F8B2D377DCC323D578DEB222585E43F97A6D1855B576297F3EC39F5F9EA1B2F72A0E701DB35D633DBCC5FFF76A2D39AE9DF2A3F6326B7671A4C0BB7177897DFF4FAF9FE5CFBCC94966BD298EA2627CF19C1CA866E5927C6E41970F544479D9A6D814AB72E2963F959CBEF37BF905BE98D8C8F3C25FAD3983F71D0C0D27D9FF17E4B34C2F8664406151E92ECA980F6CBE8F8926638398C9BCE9C69A92A30CE82F28CB4FE4110EAC40437BD64D38412030FB8DB3A4242672807737E707E59A0ACFA782127EFCB7BCEC39DFEC55C3109F958E86E0D381C4E9E9FE43110517778C08A140CF440F209011768EE34E5742ECC1E4CED045922D698A29E5557A29C237885D8559F110E4B540FE1298B97920EDF59BC8EBCA11EB91F471B6647864B384AE5A6BB494942BB1F537301B39EDD6F664E4A7877C173614B09D981401D5AA98A8BA4BF1992DD7B7A65BCE7E87FCDFC7B29AB69ADDC9036D71BB9BC08F4E7D9A57B784911CEE7D0EE5A559332981B6475290FB4410D8BA1F00FFC4850031708EB6A83AF524447F491CC25F23FBED71476FBA5C64BCD50D88A3ACD2BE1DF461B11F6D537B2929D073FCFB9E2545E1B097A12F52C411B2AF6C20A27ECD1C084568F4A76A87A4A79F7711012CBEDA777D913CC6B15E6C4E9BCE2C773991946CB9CEFB7F105B15FD2CD3E721E6C1DF69B66BEDF2157ACAD45458FD8C9C1AF910394A13C300696BBBB5B1E1145076BC6B9E3D30A680EA29B6370618B47AF77108EDE6BFCEBFBCFEDDD27FD9F0DA6D289060095C4E309DC3D26DCBFB9E8AF34E12BDD335FAC434663D4D802C8B04AC884352D27739C4DF22F3D7DB38084BAE2C0A15485DF4E356DF2FFBB5BBACA78D0B4886909C4482A6366991776B788C0941437BF858DD83AAA50104D725171C09B7DB521AA65CCCA3CDAFB2E61CDEF66B55D80E201DF44654E7B1FFCA29EFC1E44A8CBA406C8DAC6207C0BD5DA964FBE137ACCD84405A94F5F51D82CE701DD16774BA5F0A7A2BED7F9BB9A4F25C3095D1F8980721A7ECBCE957825A9BE9F4F818E56D35909A3F9DE5487DA0011EBCF9F4D768B72D236042175ED599D731AAFCD45D3D837FB8B64304ED7F22A8C3949BFA25B83A8C05FE9748F63A38201B460E16FFE4329C8464C9BF07D45DF2BA9AE7A84DCFC4CAB7BE42CBD360F61051CD56F68A71FE9E78231986832C9564D02B973EA2D3FCDBAEC374612C1B74DD483F08BAC30F6C9306E7092CC8FE1D20B937AFA4BC605ED4398A8B81A470870E97EA7D51562111D04BF9D09D9BC07533FCDA1E8DA2F2823AD621DB169C99FB112E44FDEFD597B61160815A1776139B685DA9DF6B4C22F6FF6CA3CC46B3264E456E98FF1F301122C88D42928403ED0E0E5F49BB0B450429980ACEFA1A80DA26638B5D2310FCADB0836223CB0894E6FA014D351AE052A70AB5F515641F153509FFB90B8DE495B946AB8C7D7CFEF56D3C66DC871F1D3A38494EF6AB82066E96B9F2782D6B5931B78B7117C389D155759CBC1690897DA66E50D0865209887552C8A6035B8F6911760F8D0A450FB926096721D962877FBFD87D92C37C71836B8BB9FCE92B4637785DC8E8C1D379081C14C73872E676A1C854F1BB68649BD552B48D12F62B17E9A48CCAF63885899C7B781DC3A6D7DE7DA28E286C9FD644D3521F0320B7ECA8FD0AAFFFFF90DAEC85BA80868A2EC69CC73AE00AE29FF5BA37D94510CA19E1EDAA64F30CD79A58B42FC9A6402CE31AF54BAE84DFED8D0C76142A347542265B794A0AEF4A08B4B5DFCADBD56757ECD98F175D80B44121257964293F300FF750107C1B72463D4634EBEDF4705F76C908844763D0D6813FFBE5411FBBFE16C08F32BD1BB3FB8EA5C5339A1B0194DA543E64C1F8065CE526D2754EF95A287DDC97B790FF34EA37863BB166BF0BD99E3A961BC91C1A4F84B63700C9EF5D8D31CEC9E1AE33C554BE638D5C1217CD2DBA13CC143F969DCBF285407A9B608F859812E7F668D4538BE179D11ED767A6971A2AA9CBB545EA01998E""") + ) + }; +}